Beispiel #1
0
    def get_domain(self,
                   objective: Objective,
                   passive_angles: dict = None) -> typing.List[typing.Dict]:
        """
        return a 'domain' object, for use by GPyOpt.

        This function constructs a list of dictionaries about each variable in objective to optimize over:
        we enforce the domain of 0 to 2 pi, the period of a rotation, since some domain MUST be specified.

        Parameters
        ----------
        objective: Objective:
            the Objective to extract variables from to build the domain.
        passive_angles: dict, optional:
            a dictionary of which angles are passive, in Objective.
            Default: there are none; optimize all angles.



        Returns
        -------
        list of dicts
            the domain object for use by gpyopt.

        """
        op = objective.extract_variables()
        if passive_angles is not None:
            for i, thing in enumerate(op):
                if thing in passive_angles.keys():
                    op.remove(thing)
        return [{
            'name': v,
            'type': 'continuous',
            'domain': (0, 2 * np.pi)
        } for v in op]
Beispiel #2
0
 def __call__(self, objective: Objective,
              maxiter: int,
              passives: typing.Dict[Variable, numbers.Real] = None,
              samples: int = None,
              backend: str = None,
              noise=None,
              method: str = 'lbfgs') -> GPyOptReturnType:
     if self.samples is not None:
         if samples is None:
             samples = self.samples
         else:
             pass
     else:
         pass
     dom = self.get_domain(objective, passives)
     init = {v: np.random.uniform(0, 2 * np.pi) for v in objective.extract_variables()}
     ### O is broken, not using it right now
     O = compile(objective=objective, variables=init, backend=backend, noise=noise, samples=samples)
     f = self.construct_function(O, backend, passives, samples, noise_model=noise)
     opt = self.get_object(f, dom, method)
     opt.run_optimization(maxiter)
     if self.save_history:
         self.history.energies = opt.get_evaluations()[1].flatten()
         self.history.angles = [self.redictify(v, objective, passives) for v in opt.get_evaluations()[0]]
     return GPyOptReturnType(energy=opt.fx_opt, angles=self.redictify(opt.x_opt, objective, passives),
                             history=self.history, opt=opt)
Beispiel #3
0
def minimize(objective: Objective,
             maxiter: int,
             samples: int = None,
             variables: typing.List = None,
             initial_values: typing.Dict = None,
             backend: str = None,
             noise=None,
             method: str = 'lbfgs') -> GPyOptReturnType:
    """

    Parameters
    ----------
    objective: Objective :
        The tequila objective to optimize
    initial_values: typing.Dict[typing.Hashable, numbers.Real]: (Default value = None):
        Initial values as dictionary of Hashable types (variable keys) and floating point numbers. generates FIXED variables! if not provided,
        all variables will be optimized.
    variables: typing.List[typing.Hashable] :
         (Default value = None)
         List of Variables to optimize. If None, all variables optimized, and the passives command is over-ruled.
    samples: int :
         (Default value = None)
         samples/shots to take in every run of the quantum circuits (None activates full wavefunction simulation)
    maxiter: int :
         how many iterations of GPyOpt to run. Note: GPyOpt will override this as it sees fit.
    backend: str :
         (Default value = None)
         Simulator backend, will be automatically chosen if set to None
    noise: NoiseModel :
         (Default value = None)
        a noise model to apply to the circuits of Objective.
    method: str:
         (Default value = 'lbfgs')
         method of acquisition. Allowed arguments are 'lbfgs', 'DIRECT', and 'CMA'

    Returns
    -------

    """

    if variables is None:
        passives = None
    else:
        all_vars = Objective.extract_variables()
        passives = {}
        for k, v in initial_values.items():
            if k not in variables and k in all_vars:
                passives[k] = v
    optimizer = OptimizerGpyOpt()
    return optimizer(objective=objective,
                     samples=samples,
                     backend=backend,
                     passives=passives,
                     maxiter=maxiter,
                     noise=noise,
                     method=method)
Beispiel #4
0
def preamble(objective: Objective,
             compile_args: dict = None,
             input_vars: list = None):
    """
    Helper function for interfaces to ml backends.
    Parameters
    ----------
    objective: Objective:
        the objective to manipulate and compile.
    compile_args: dict, optional:
        a dictionary of args that can be passed as kwargs to tq.compile
    input_vars: list, optional:
        a list of variables of the objective to specify as input, rather than itnernal weights.

    Returns
    -------
    tuple
        the compiled objective, it's compile arguments, its weight variables, dicts for the weight and input gradients,
        and a dictionary that links positions in an array to each variable (parses parameters).
    """
    def var_sorter(e):
        return hash(e.name)

    all_vars = objective.extract_variables()
    all_vars.sort(key=var_sorter)
    compile_args = check_compiler_args(compile_args)

    weight_vars = []
    if input_vars is None:
        input_vars = []
        weight_vars = all_vars
    else:
        input_vars = [assign_variable(v) for v in input_vars]
        for var in all_vars:
            if var not in input_vars:
                weight_vars.append(assign_variable(var))

    init_vals = compile_args['initial_values']
    if init_vals is not None:
        for k in init_vals.keys():
            if assign_variable(k) in input_vars:
                raise TequilaMLException(
                    'initial_values contained key {},'
                    'which is meant to be an input variable.'.format(k))
        compile_args['initial_values'] = format_variable_dictionary(init_vals)

    comped = compile(objective, **compile_args)
    gradients = get_gradients(objective, compile_args)
    w_grad, i_grad = separate_gradients(gradients,
                                        weight_vars=weight_vars,
                                        input_vars=input_vars)
    first, second = get_variable_orders(weight_vars, input_vars)
    return comped, compile_args, input_vars, weight_vars, i_grad, w_grad, first, second
Beispiel #5
0
def grad(objective: Objective, variable: Variable = None, no_compile=False):
    '''
    wrapper function for getting the gradients of Objectives,ExpectationValues, Unitaries (including single gates), and Transforms.
    :param obj (QCircuit,ParametrizedGateImpl,Objective,ExpectationValue,Transform,Variable): structure to be differentiated
    :param variables (list of Variable): parameter with respect to which obj should be differentiated.
        default None: total gradient.
    return: dictionary of Objectives, if called on gate, circuit, exp.value, or objective; if Variable or Transform, returns number.
    '''

    if variable is None:
        # None means that all components are created
        variables = objective.extract_variables()
        result = {}

        if len(variables) == 0:
            raise TequilaException(
                "Error in gradient: Objective has no variables")

        for k in variables:
            assert (k is not None)
            result[k] = grad(objective, k, no_compile=no_compile)
        return result
    else:
        variable = assign_variable(variable)

    if no_compile:
        compiled = objective
    else:
        compiler = Compiler(multitarget=True,
                            trotterized=True,
                            hadamard_power=True,
                            power=True,
                            controlled_phase=True,
                            controlled_rotation=True)

        compiled = compiler(objective, variables=[variable])

    if variable not in compiled.extract_variables():
        raise TequilaException(
            "Error in taking gradient. Objective does not depend on variable {} "
            .format(variable))

    if isinstance(objective, ExpectationValueImpl):
        return __grad_expectationvalue(E=objective, variable=variable)
    elif objective.is_expectationvalue():
        return __grad_expectationvalue(E=compiled.args[-1], variable=variable)
    elif isinstance(compiled, Objective):
        return __grad_objective(objective=compiled, variable=variable)
    else:
        raise TequilaException(
            "Gradient not implemented for other types than ExpectationValue and Objective."
        )
    def __call__(self, objective: Objective,
                 maxiter=None,
                 variables: typing.List[Variable] = None,
                 initial_values: typing.Dict[Variable, numbers.Real] = None,
                 previous=None,
                 phoenics_config=None,
                 save_to_file=False,
                 file_name=None,
                 *args,
                 **kwargs):

        active_angles, passive_angles, variables = self.initialize_variables(objective,
                                                               initial_values=initial_values,
                                                               variables=variables)

        if maxiter is None:
            maxiter = 10

        obs = []
        bird = self._make_phoenics_object(objective, passive_angles, phoenics_config, *args, **kwargs)
        if previous is not None:
            if type(previous) is str:
                try:
                    obs = pickle.load(open(previous, 'rb'))
                except:
                    print(
                        'failed to load previous observations, which are meant to be a pickle file. Starting fresh.')
            elif type(previous) is list:
                if all([type(k) == dict for k in previous]):
                    obs = previous
                else:
                    print('previous observations were not in the correct format (list of dicts). Starting fresh.')



        if not (type(file_name) == str or file_name == None):
            raise TequilaException('file_name must be a string, or None!')

        best = None
        best_angles = None

        # avoid multiple compilations
        compiled_objective = compile_objective(objective=objective, backend=self.backend,
                                               backend_options=self.backend_options,
                                               samples=self.samples, noise=self.noise)

        if not self.silent:
            print('phoenics has recieved')
            print("objective: \n")
            print(objective)
            print("noise model : {}".format(self.noise))
            print("samples     : {}".format(self.samples))
            print("maxiter     : {}".format(maxiter))
            print("variables   : {}".format(objective.extract_variables()))
            print("passive var : {}".format(passive_angles))
            print("backend options {} ".format(self.backend), self.backend_options)
            print('now lets begin')
        for i in range(0, maxiter):
            with warnings.catch_warnings():
                np.testing.suppress_warnings()
                warnings.simplefilter("ignore")
                warnings.filterwarnings("ignore", category=FutureWarning)

            if len(obs) >= 1:
                precs = bird.recommend(observations=obs)
            else:
                precs = bird.recommend()

            runs = []
            recs = self._process_for_sim(precs, passive_angles=passive_angles)

            start = time.time()
            for j, rec in enumerate(recs):
                En = compiled_objective(variables=rec, samples=self.samples, noise=self.noise,
                                        backend_options=self.backend_options)
                runs.append((rec, En))
                if not self.silent:
                    if self.print_level > 2:
                        print("energy = {:+2.8f} , angles=".format(En), rec)
                    else:
                        print("energy = {:+2.8f}".format(En))
            stop = time.time()
            if not self.silent:
                print("Quantum Objective evaluations: {}s Wall-Time".format(stop-start))

            for run in runs:
                angles = run[0]
                E = run[1]
                if best is None:
                    best = E
                    best_angles = angles
                else:
                    if self._minimize:
                        if E < best:
                            best = E
                            best_angles = angles
                    else:
                        if E > best:
                            best = E
                            best_angles = angles

                if self.save_history:
                    self.history.energies.append(E)
                    self.history.angles.append(angles)
                obs.append(self._process_for_phoenics(angles, E, passive_angles=passive_angles))

        if file_name is not None:
            with open(file_name, 'wb') as file:
                pickle.dump(obs, file)

        if not self.silent:
            print("best energy after {} iterations : {:+2.8f}".format(self.maxiter, best))
        return PhoenicsReturnType(energy=best, angles=best_angles, history=self.history, observations=obs,object=bird)
Beispiel #7
0
def minimize(objective: Objective,
             maxiter: int = None,
             samples: int = None,
             variables: typing.List = None,
             initial_values: typing.Dict = None,
             backend: str = None,
             noise=None,
             previous: typing.Union[str, list] = None,
             phoenics_config: typing.Union[str, typing.Dict] = None,
             save_to_file: bool = False,
             file_name: str = None,
             silent: bool = False,
             *args,
             **kwargs):
    """

    Parameters
    ----------
    objective: Objective :
        The tequila objective to optimize
    initial_values: typing.Dict[typing.Hashable, numbers.Real]: (Default value = None):
        Initial values as dictionary of Hashable types (variable keys) and floating point numbers. If given None they will all be set to zero
    variables: typing.List[typing.Hashable] :
         (Default value = None)
         List of Variables to optimize
    samples: int :
         (Default value = None)
         samples/shots to take in every run of the quantum circuits (None activates full wavefunction simulation)
    maxiter: int :
         how many iterations of phoenics to run. Note that this is NOT identical to the number of times the circuit will run.
    backend: str :
         (Default value = None)
         Simulator backend, will be automatically chosen if set to None
    noise: NoiseModel :
         (Default value = None)
         a noise model to apply to the circuits of Objective.
    previous:
        (Default value = None)
        Previous phoenics observations. If string, the name of a file from which to load them. Else, a list.
    phoenics_config:
        (Default value = None)
        a pre-made phoenics configuration. if str, the name of a file from which to load it; Else, a dictionary.
        Individual keywords of the 'general' sections can also be passed down as kwargs
    save_to_file: bool:
        (Default value = False)
        whether or not to save the output of the optimization to an external file
    file_name: str:
        (Default value = None)
        where to save output to, if save_to_file is True.
    kwargs: dict:
        Send down more keywords for single replacements in the phoenics config 'general' section, like e.g. batches=5, boosted=True etc
    Returns
    -------

    """

    if variables is None:
        passives = None
    else:
        all_vars = Objective.extract_variables()
        passives = {}
        for k, v in initial_values.items():
            if k not in variables and k in all_vars:
                passives[k] = v
    optimizer = OptimizerPhoenics(samples=samples, backend=backend, maxiter=maxiter, silent=silent)
    return optimizer(objective=objective, backend=backend, passives=passives, previous=previous,
                     maxiter=maxiter, noise=noise, samples=samples,
                     phoenics_config=phoenics_config, save_to_file=save_to_file, file_name=file_name, *args, **kwargs)
Beispiel #8
0
    def __call__(self, objective: Objective,
                 maxiter: int = None,
                 passives: typing.Dict[Variable, numbers.Real] = None,
                 samples: int = None,
                 backend: str = None,
                 noise=None,
                 previous=None,
                 phoenics_config=None,
                 save_to_file=False,
                 file_name=None,
                 *args,
                 **kwargs):

        backend_options = {}
        if 'backend_options' in kwargs:
            backend_options = kwargs['backend_options']

        if maxiter is None:
            maxiter = 10

        bird = self._make_phoenics_object(objective, passives, phoenics_config, *args, **kwargs)
        if previous is not None:
            if type(previous) is str:
                try:
                    obs = pickle.load(open(previous, 'rb'))
                except:
                    print(
                        'failed to load previous observations, which are meant to be a pickle file. Please try again or seek assistance. Starting fresh.')
                    obs = []
            elif type(previous) is list:
                if all([type(k) == dict for k in previous]):
                    obs = previous
                else:
                    print(
                        'previous observations were not in the correct format (list of dicts). Are you sure you gave me the right info? Starting fresh.')
                    obs = []

        else:
            obs = []

        if save_to_file is True:
            if type(file_name) is str:
                pass
            elif file_name is None:
                raise TequilaException(
                    'You have asked me to save phoenics observations without telling me where to do so! please provide a file_name')
            else:
                raise TequilaException('file_name must be a string!')

        ### this line below just gets the damn compiler to run, since that argument is necessary
        init = {key: np.pi for key in objective.extract_variables()}

        best = None
        best_angles = None

        # avoid multiple compilations
        compiled_objective = compile_objective(objective=objective, backend=backend, samples=samples, noise=noise)

        if not self.silent:
            print('phoenics has recieved')
            print("objective: \n")
            print(objective)
            print("noise model : {}".format(noise))
            print("samples     : {}".format(samples))
            print("maxiter     : {}".format(maxiter))
            print("variables   : {}".format(objective.extract_variables()))
            print("passive var : {}".format(passives))
            print("backend options {} ".format(backend), backend_options)
            print('now lets begin')
        for i in range(0, maxiter):
            with warnings.catch_warnings():
                np.testing.suppress_warnings()
                warnings.simplefilter("ignore")
                warnings.filterwarnings("ignore", category=FutureWarning)

            if len(obs) >= 1:
                precs = bird.recommend(observations=obs)
            else:
                precs = bird.recommend()

            runs = []
            recs = self._process_for_sim(precs, passives=passives)

            start = time.time()
            for i, rec in enumerate(recs):
                En = compiled_objective(variables=rec, samples=samples, noise=noise, **backend_options)
                runs.append((rec, En))
                if not self.silent:
                    print("energy = {:+2.8f} , angles=".format(En), rec)
            stop = time.time()
            if not self.silent:
                print("Quantum Objective evaluations: {}s Wall-Time".format(stop-start))

            for run in runs:
                angles = run[0]
                E = run[1]
                if best is None:
                    best = E
                    best_angles = angles
                else:
                    if self._minimize:
                        if E < best:
                            best = E
                            best_angles = angles
                    else:
                        if E > best:
                            best = E
                            best_angles = angles

                if self.save_history:
                    self.history.energies.append(E)
                    self.history.angles.append(angles)
                obs.append(self._process_for_phoenics(angles, E, passives=passives))

        if save_to_file is True:
            with open(file_name, 'wb') as file:
                pickle.dump(obs, file)

        if not self.silent:
            print("best energy after {} iterations : {:+2.8f}".format(self.maxiter, best))
        return PhoenicsReturnType(energy=best, angles=best_angles, history=self.history, observations=obs)
    def __call__(self,
                 objective: Objective,
                 maxiter=None,
                 variables: typing.List[Variable] = None,
                 initial_values: typing.Dict[Variable, numbers.Real] = None,
                 previous=None,
                 phoenics_config=None,
                 file_name=None,
                 *args,
                 **kwargs):
        """
        Perform optimization with phoenics.

        Parameters
        ----------
        objective: Objective
            the objective to optimize.
        maxiter: int:
            (Default value = None)
            if not None, overwrite the init maxiter with new number.
        variables: list:
            (Default value = None)
            which variables to optimize over. If None: all of the variables in objective are used.
        initial_values: dict:
            (Default value = None)
            an initial point to begin optimization from. Random, if None.
        previous:
            previous observations, formatted for phoenics, to use in optimization. For use by advanced users.
        phoenics_config:
            a config for a phoenics object.
        file_name:
            a file
        args
        kwargs

        Returns
        -------
        PhoenicsResults:
            the results of optimization by phoenics.

        """

        objective = objective.contract()
        active_angles, passive_angles, variables = self.initialize_variables(
            objective, initial_values=initial_values, variables=variables)

        if maxiter is None:
            maxiter = 10

        obs = []
        bird = self._make_phoenics_object(objective, passive_angles,
                                          phoenics_config, *args, **kwargs)
        if previous is not None:
            if type(previous) is str:
                try:
                    obs = pickle.load(open(previous, 'rb'))
                except:
                    print(
                        'failed to load previous observations, which are meant to be a pickle file. Starting fresh.'
                    )
            elif type(previous) is list:
                if all([type(k) == dict for k in previous]):
                    obs = previous
                else:
                    print(
                        'previous observations were not in the correct format (list of dicts). Starting fresh.'
                    )

        if not (type(file_name) == str or file_name == None):
            raise TequilaException(
                'file_name must be a string, or None. Recieved {}'.format(
                    type(file_name)))

        best = None
        best_angles = None

        # avoid multiple compilations
        compiled_objective = compile_objective(objective=objective,
                                               backend=self.backend,
                                               device=self.device,
                                               samples=self.samples,
                                               noise=self.noise)

        if not self.silent:
            print('phoenics has recieved')
            print("objective: \n")
            print(objective)
            print("noise model : {}".format(self.noise))
            print("samples     : {}".format(self.samples))
            print("maxiter     : {}".format(maxiter))
            print("variables   : {}".format(objective.extract_variables()))
            print("passive var : {}".format(passive_angles))
            print('now lets begin')
        for i in range(0, maxiter):
            with warnings.catch_warnings():
                np.testing.suppress_warnings()
                warnings.simplefilter("ignore")
                warnings.filterwarnings("ignore", category=FutureWarning)

            precs = bird.recommend(observations=obs)

            runs = []
            recs = self._process_for_sim(precs, passive_angles=passive_angles)

            start = time.time()
            for j, rec in enumerate(recs):
                En = compiled_objective(variables=rec,
                                        samples=self.samples,
                                        noise=self.noise)
                runs.append((rec, En))
                if not self.silent:
                    if self.print_level > 2:
                        print("energy = {:+2.8f} , angles=".format(En), rec)
                    else:
                        print("energy = {:+2.8f}".format(En))
            stop = time.time()
            if not self.silent:
                print("Quantum Objective evaluations: {}s Wall-Time".format(
                    stop - start))

            for run in runs:
                angles = run[0]
                E = run[1]
                if best is None:
                    best = E
                    best_angles = angles
                else:
                    if self._minimize:
                        if E < best:
                            best = E
                            best_angles = angles
                    else:
                        if E > best:
                            best = E
                            best_angles = angles

                if self.save_history:
                    self.history.energies.append(E)
                    self.history.angles.append(angles)
                obs.append(
                    self._process_for_phoenics(angles,
                                               E,
                                               passive_angles=passive_angles))

        if file_name is not None:
            with open(file_name, 'wb') as file:
                pickle.dump(obs, file)

        if not self.silent:
            print("best energy after {} iterations : {:+2.8f}".format(
                self.maxiter, best))
        return PhoenicsResults(energy=best,
                               variables=best_angles,
                               history=self.history,
                               observations=obs,
                               phoenics_instance=bird)