def test_load_optimization_results_successfully_loads_optimization_result_from_file(): result_to_serialize = EXAMPLE_OPTIMIZATION_RESULT optimization_result_filename = "test-optimization-result-io.json" save_optimization_results(result_to_serialize, optimization_result_filename) loaded_data = load_optimization_results(optimization_result_filename) assert optimization_results_equal(result_to_serialize, loaded_data) os.remove(optimization_result_filename)
def optimize_variational_qcbm_circuit( distance_measure_specs, distance_measure_parameters, n_layers, n_qubits, n_samples, topology, backend_specs, optimizer_specs, initial_parameters, target_distribution, keep_history, gradient_type = "finite_difference", gradient_kwargs = None, ): if isinstance(distance_measure_specs, str): distance_measure_specs = json.loads(distance_measure_specs) distance_measure = get_func_from_specs(distance_measure_specs) ansatz = QCBMAnsatz(n_layers, n_qubits, topology) if isinstance(backend_specs, str): backend_specs = json.loads(backend_specs) backend = create_object(backend_specs) if isinstance(optimizer_specs, str): optimizer_specs = json.loads(optimizer_specs) optimizer = create_object(optimizer_specs) initial_parameters = load_array(initial_parameters) target_distribution = load_bitstring_distribution(target_distribution) if isinstance(distance_measure_parameters, str): distance_measure_parameters = json.loads(distance_measure_parameters) cost_function = QCBMCostFunction( ansatz, backend, n_samples, distance_measure, distance_measure_parameters, target_distribution, gradient_type, gradient_kwargs ) opt_results = optimizer.minimize(cost_function, initial_parameters, keep_history) save_optimization_results(opt_results, "qcbm-optimization-results.json") save_array(opt_results.opt_params, "optimized-parameters.json")
def test_save_optimization_results_successfully_saves_optimization_result(): result_to_serialize = EXAMPLE_OPTIMIZATION_RESULT expected_deserialized_result = EXPECTED_DESERIALIZED_RESULT optimization_result_filename = "test-optimization-result-io.json" # When save_optimization_results(result_to_serialize, optimization_result_filename) # Then with open(optimization_result_filename, "r") as f: loaded_data = json.load(f) assert loaded_data == expected_deserialized_result os.remove(optimization_result_filename)
def optimize_variational_qcbm_circuit( distance_measure_specs, distance_measure_parameters, n_layers, n_qubits, topology, backend_specs, optimizer_specs, initial_parameters, target_distribution, ): if isinstance(distance_measure_specs, str): distance_measure_specs = json.loads(distance_measure_specs) distance_measure = get_func_from_specs(distance_measure_specs) ansatz = QCBMAnsatz(n_layers, n_qubits, topology) if isinstance(backend_specs, str): backend_specs = json.loads(backend_specs) backend = create_object(backend_specs) if isinstance(optimizer_specs, str): optimizer_specs = json.loads(optimizer_specs) optimizer = create_object(optimizer_specs) initial_parameters = load_circuit_template_params(initial_parameters) target_distribution = load_bitstring_distribution(target_distribution) if isinstance(distance_measure_parameters, str): distance_measure_parameters = json.loads(distance_measure_parameters) cost_function = QCBMCostFunction( ansatz, backend, distance_measure, distance_measure_parameters, target_distribution, ) opt_results = optimizer.minimize(cost_function, initial_parameters) save_optimization_results(opt_results, "qcbm-optimization-results.json") save_circuit_template_params(opt_results.opt_params, "optimized-parameters.json")
def optimize_parametrized_circuit_for_ground_state_of_operator( optimizer_specs: Specs, target_operator: Union[SymbolicOperator, str], parametrized_circuit: Union[Circuit, str], backend_specs: Specs, estimator_specs: Optional[Specs] = None, estimator_kwargs: Optional[Union[Dict, str]] = None, initial_parameters: Union[str, np.ndarray, List[float]] = None, fixed_parameters: Optional[Union[np.ndarray, str]] = None, parameter_precision: Optional[float] = None, parameter_precision_seed: Optional[int] = None, ): """Optimize the parameters of a parametrized quantum circuit to prepare the ground state of a target operator. Args: optimizer_specs (Union[Dict, str]): The specs of the optimizer to use to refine the parameter values target_operator (Union[SymbolicOperator, str]): The operator of which to prepare the ground state parametrized_circuit (Union[Circuit, str]): The parametrized quantum circuit that prepares trial states backend_specs (Union[Dict, str]): The specs of the quantum backend (or simulator) to use to run the circuits estimator_specs (Union[Dict, str]): The estimator to use to estimate the expectation value of the operator. The default is the BasicEstimator. estimator_kwargs (dict): kwargs required to run get_estimated_expectation_values method of the estimator. initial_parameters (Union[str, np.ndarray, List[float]]): The initial parameter values to begin optimization fixed_parameters (Optional[Union[np.ndarray, str]]): values for the circuit parameters that should be fixed. parameter_precision (float): the standard deviation of the Gaussian noise to add to each parameter, if any. parameter_precision_seed (int): seed for randomly generating parameter deviation if using parameter_precision initial_parameters (Union[str, np.ndarray, List[float]] = None, """ if estimator_kwargs is not None: if isinstance(estimator_kwargs, str): estimator_kwargs = json.loads(estimator_kwargs) estimator = create_object(estimator_kwargs) else: estimator_kwargs = {} if isinstance(optimizer_specs, str): optimizer_specs = json.loads(optimizer_specs) optimizer = create_object(optimizer_specs) if isinstance(target_operator, str): with open(target_operator, "r") as f: target_operator = json.loads(f.read()) if isinstance(parametrized_circuit, str): parametrized_circuit = load_circuit(parametrized_circuit) if isinstance(backend_specs, str): backend_specs = json.loads(backend_specs) backend = create_object(backend_specs) if estimator_specs is not None: if isinstance(estimator_specs, str): estimator_specs = json.loads(estimator_specs) estimator = create_object(estimator_specs) else: estimator = BasicEstimator() if initial_parameters is not None: if isinstance(initial_parameters, str): initial_parameters = load_circuit_template_params( initial_parameters) if fixed_parameters is not None: if isinstance(fixed_parameters, str): fixed_parameters = load_circuit_template_params(fixed_parameters) cost_function = get_ground_state_cost_function( target_operator, parametrized_circuit, backend, estimator=estimator, estimator_kwargs=estimator_kwargs, fixed_parameters=fixed_parameters, parameter_precision=parameter_precision, parameter_precision_seed=parameter_precision_seed, ) optimization_results = optimizer.minimize(cost_function, initial_parameters) save_optimization_results(optimization_results, "optimization_results.json")
def optimize_parametrized_circuit_for_ground_state_of_operator( optimizer_specs: Specs, target_operator: Union[SymbolicOperator, str], parametrized_circuit: Union[Circuit, str], backend_specs: Specs, estimation_method_specs: Optional[Specs] = None, estimation_preprocessors_specs: Optional[List[Specs]] = None, initial_parameters: Union[str, np.ndarray, List[float]] = None, fixed_parameters: Optional[Union[np.ndarray, str]] = None, parameter_precision: Optional[float] = None, parameter_precision_seed: Optional[int] = None, keep_history: bool = True, **kwargs, ): """Optimize the parameters of a parametrized quantum circuit to prepare the ground state of a target operator. Args: optimizer_specs: The specs of the optimizer to use to refine the parameter values target_operator: The operator of which to prepare the ground state parametrized_circuit: The parametrized quantum circuit that prepares trial states backend_specs: The specs of the quantum backend (or simulator) to use to run the circuits estimation_method_specs: A reference to a callable to use to estimate the expectation value of the operator. The default is the estimate_expectation_values_by_averaging function. estimation_preprocessors_specs: A list of Specs that describe callable functions that adhere to the EstimationPreprocessor protocol. initial_parameters: The initial parameter values to begin optimization fixed_parameters: values for the circuit parameters that should be fixed. parameter_precision: the standard deviation of the Gaussian noise to add to each parameter, if any. parameter_precision_seed: seed for randomly generating parameter deviation if using parameter_precision keep_history: flag indicating whether to store optimization history. kwargs: unused, exists for compatibility """ if isinstance(optimizer_specs, str): optimizer_specs = json.loads(optimizer_specs) optimizer = create_object(optimizer_specs) if isinstance(target_operator, str): target_operator = load_qubit_operator(target_operator) if isinstance(parametrized_circuit, str): with open(parametrized_circuit) as f: parametrized_circuit = new_circuits.circuit_from_dict(json.load(f)) if isinstance(backend_specs, str): backend_specs = json.loads(backend_specs) backend = create_object(backend_specs) if estimation_method_specs is not None: if isinstance(estimation_method_specs, str): estimation_method_specs = json.loads(estimation_method_specs) estimation_method = create_object(estimation_method_specs) else: estimation_method = estimate_expectation_values_by_averaging estimation_preprocessors = [] if estimation_preprocessors_specs is not None: for estimation_preprocessor_specs in estimation_preprocessors_specs: if isinstance(estimation_preprocessor_specs, str): estimation_preprocessor_specs = json.loads( estimation_preprocessor_specs) estimation_preprocessors.append( create_object(estimation_preprocessor_specs)) if initial_parameters is not None: if isinstance(initial_parameters, str): initial_parameters = load_array(initial_parameters) if fixed_parameters is not None: if isinstance(fixed_parameters, str): fixed_parameters = load_array(fixed_parameters) cost_function = get_ground_state_cost_function( target_operator, parametrized_circuit, backend, estimation_method=estimation_method, estimation_preprocessors=estimation_preprocessors, fixed_parameters=fixed_parameters, parameter_precision=parameter_precision, parameter_precision_seed=parameter_precision_seed, ) optimization_results = optimizer.minimize(cost_function, initial_parameters, keep_history) save_optimization_results(optimization_results, "optimization-results.json") save_array(optimization_results.opt_params, "optimized-parameters.json")
def optimize_ansatz_based_cost_function( optimizer_specs: Specs, target_operator: Union[SymbolicOperator, str], ansatz_specs: Specs, backend_specs: Specs, estimation_method_specs: Optional[Specs] = None, estimation_preprocessors_specs: Optional[List[Specs]] = None, initial_parameters: Union[str, np.ndarray, List[float]] = None, fixed_parameters: Optional[Union[np.ndarray, str]] = None, parameter_precision: Optional[float] = None, parameter_precision_seed: Optional[int] = None, keep_history: bool = False, **kwargs, ): """Optimize the parameters of an ansatz circuit to prepare the ground state of a target operator. Args: optimizer_specs: The specs of the optimizer to use to refine the parameter values target_operator: The operator of which to prepare the ground state ansatz_specs: The specs describing an Ansatz which will prepare the quantum circuit backend_specs: The specs of the quantum backend (or simulator) to use to run the circuits estimation_method_specs: A reference to a callable to use to estimate the expectation value of the operator. The default is the estimate_expectation_values_by_averaging function. estimation_preprocessors_specs: A list of Specs that describe callable functions that adhere to the EstimationPreprocessor protocol. initial_parameters: The initial parameter values to begin optimization fixed_parameters: values for the circuit parameters that should be fixed. parameter_precision: the standard deviation of the Gaussian noise to add to each parameter, if any. parameter_precision_seed: seed for randomly generating parameter deviation if using parameter_precision keep_history: flag indicating whether to store optimization history. kwargs: The following key word arguments are handled explicitly when appropriate: - thetas: A list of thetas used to initialize the WarmStartQAOAAnsatz """ if isinstance(optimizer_specs, str): optimizer_specs = json.loads(optimizer_specs) optimizer = create_object(optimizer_specs) if isinstance(target_operator, str): target_operator = load_qubit_operator(target_operator) if isinstance(ansatz_specs, str): ansatz_specs = json.loads(ansatz_specs) if "WarmStartQAOAAnsatz" in ansatz_specs["function_name"]: ansatz_specs["thetas"] = np.array(load_list(kwargs.pop("thetas"))) ansatz_specs["cost_hamiltonian"] = target_operator elif "QAOA" in ansatz_specs["function_name"]: ansatz_specs["cost_hamiltonian"] = target_operator ansatz = create_object(ansatz_specs) if isinstance(backend_specs, str): backend_specs = json.loads(backend_specs) backend = create_object(backend_specs) if estimation_method_specs is not None: if isinstance(estimation_method_specs, str): estimation_method_specs = json.loads(estimation_method_specs) estimation_method = create_object(estimation_method_specs) else: estimation_method = estimate_expectation_values_by_averaging estimation_preprocessors = [] if estimation_preprocessors_specs is not None: for estimation_preprocessor_specs in estimation_preprocessors_specs: if isinstance(estimation_preprocessor_specs, str): estimation_preprocessor_specs = json.loads( estimation_preprocessor_specs) estimation_preprocessors.append( create_object(estimation_preprocessor_specs)) if initial_parameters is not None: if isinstance(initial_parameters, str): initial_parameters = load_array(initial_parameters) if fixed_parameters is not None: if isinstance(fixed_parameters, str): fixed_parameters = load_array(fixed_parameters) cost_function = AnsatzBasedCostFunction( target_operator, ansatz, backend, estimation_method=estimation_method, estimation_preprocessors=estimation_preprocessors, fixed_parameters=fixed_parameters, parameter_precision=parameter_precision, parameter_precision_seed=parameter_precision_seed, ) optimization_results = optimizer.minimize(cost_function, initial_parameters, keep_history) save_optimization_results(optimization_results, "optimization-results.json") save_array(optimization_results.opt_params, "optimized-parameters.json")
def optimize_variational_circuit( ansatz_specs, backend_specs, optimizer_specs, cost_function_specs, qubit_operator, initial_parameters="None", fixed_parameters="None", noise_model="None", device_connectivity="None", parameter_grid="None", constraint_operator="None", ): if initial_parameters != "None": initial_params = load_circuit_template_params(initial_parameters) else: initial_params = None if fixed_parameters != "None": fixed_params = load_circuit_template_params(fixed_parameters) else: fixed_params = None # Load qubit operator operator = load_qubit_operator(qubit_operator) if isinstance(ansatz_specs, str): ansatz_specs_dict = yaml.load(ansatz_specs, Loader=yaml.SafeLoader) else: ansatz_specs_dict = ansatz_specs if ansatz_specs_dict["function_name"] == "QAOAFarhiAnsatz": ansatz = create_object(ansatz_specs_dict, cost_hamiltonian=operator) else: ansatz = create_object(ansatz_specs_dict) # Load parameter grid if parameter_grid != "None": grid = load_parameter_grid(parameter_grid) else: grid = None # Load optimizer specs if isinstance(optimizer_specs, str): optimizer_specs_dict = yaml.load(optimizer_specs, Loader=yaml.SafeLoader) else: optimizer_specs_dict = optimizer_specs if (grid is not None and optimizer_specs_dict["function_name"] == "GridSearchOptimizer"): optimizer = create_object(optimizer_specs_dict, grid=grid) else: optimizer = create_object(optimizer_specs_dict) # Load backend specs if isinstance(backend_specs, str): backend_specs_dict = yaml.load(backend_specs, Loader=yaml.SafeLoader) else: backend_specs_dict = backend_specs if noise_model != "None": backend_specs_dict["noise_model"] = load_noise_model(noise_model) if device_connectivity != "None": backend_specs_dict["device_connectivity"] = load_circuit_connectivity( device_connectivity) backend = create_object(backend_specs_dict) # Load cost function specs if isinstance(cost_function_specs, str): cost_function_specs_dict = yaml.load(cost_function_specs, Loader=yaml.SafeLoader) else: cost_function_specs_dict = cost_function_specs estimator_specs = cost_function_specs_dict.pop("estimator-specs", None) if estimator_specs is not None: cost_function_specs_dict["estimator"] = create_object(estimator_specs) cost_function_specs_dict["target_operator"] = operator cost_function_specs_dict["ansatz"] = ansatz cost_function_specs_dict["backend"] = backend cost_function_specs_dict["fixed_parameters"] = fixed_params cost_function = create_object(cost_function_specs_dict) if constraint_operator != "None": constraint_op = load_qubit_operator(constraint_operator) constraints_cost_function_specs = yaml.load(cost_function_specs, Loader=yaml.SafeLoader) constraints_estimator_specs = constraints_cost_function_specs.pop( "estimator-specs", None) if constraints_estimator_specs is not None: constraints_cost_function_specs["estimator"] = create_object( constraints_estimator_specs) constraints_cost_function_specs["ansatz"] = ansatz constraints_cost_function_specs["backend"] = backend constraints_cost_function_specs["target_operator"] = constraint_op constraint_cost_function = create_object( constraints_cost_function_specs) constraint_cost_function_wrapper = ( lambda params: constraint_cost_function.evaluate(params).value) constraint_functions = ({ "type": "eq", "fun": constraint_cost_function_wrapper }, ) optimizer.constraints = constraint_functions opt_results = optimizer.minimize(cost_function, initial_params) save_optimization_results(opt_results, "optimization-results.json") save_circuit_template_params(opt_results.opt_params, "optimized-parameters.json")
def optimize_variational_circuit( ansatz_specs, backend_specs, optimizer_specs, cost_function_specs, qubit_operator, initial_parameters="None", fixed_parameters="None", noise_model="None", device_connectivity="None", parameter_grid="None", parameter_values_list=None, constraint_operator="None", prior_expectation_values: Optional[str] = None, keep_history=False, thetas=None, ): warnings.warn( "optimize_variational_circuit will be depreciated in favor of optimize_ansatz_based_cost_function in steps/optimize.py in z-quantum-core.", DeprecationWarning, ) if initial_parameters != "None": initial_params = load_array(initial_parameters) else: initial_params = None if fixed_parameters != "None": fixed_params = load_array(fixed_parameters) else: fixed_params = None # Load qubit operator operator = load_qubit_operator(qubit_operator) if isinstance(ansatz_specs, str): ansatz_specs_dict = yaml.load(ansatz_specs, Loader=yaml.SafeLoader) else: ansatz_specs_dict = ansatz_specs if "WarmStartQAOAAnsatz" in ansatz_specs_dict["function_name"]: thetas = np.array(load_list(thetas)) ansatz = create_object(ansatz_specs_dict, cost_hamiltonian=operator, thetas=thetas) elif "QAOA" in ansatz_specs_dict["function_name"]: ansatz = create_object(ansatz_specs_dict, cost_hamiltonian=operator) else: ansatz = create_object(ansatz_specs_dict) # Load parameter grid if parameter_grid != "None": grid = load_parameter_grid(parameter_grid) else: grid = None # Load parameter values list if parameter_values_list is not None: parameter_values_list = load_array(parameter_values_list) # Load optimizer specs if isinstance(optimizer_specs, str): optimizer_specs_dict = yaml.load(optimizer_specs, Loader=yaml.SafeLoader) else: optimizer_specs_dict = optimizer_specs if (grid is not None and optimizer_specs_dict["function_name"] == "GridSearchOptimizer"): optimizer = create_object(optimizer_specs_dict, grid=grid) elif (parameter_values_list is not None and optimizer_specs_dict["function_name"] == "SearchPointsOptimizer"): optimizer = create_object(optimizer_specs_dict, parameter_values_list=parameter_values_list) else: optimizer = create_object(optimizer_specs_dict) # Load backend specs if isinstance(backend_specs, str): backend_specs_dict = yaml.load(backend_specs, Loader=yaml.SafeLoader) else: backend_specs_dict = backend_specs if noise_model != "None": backend_specs_dict["noise_model"] = load_noise_model(noise_model) if device_connectivity != "None": backend_specs_dict["device_connectivity"] = load_circuit_connectivity( device_connectivity) backend = create_object(backend_specs_dict) # Load cost function specs if isinstance(cost_function_specs, str): cost_function_specs_dict = yaml.load(cost_function_specs, Loader=yaml.SafeLoader) else: cost_function_specs_dict = cost_function_specs estimation_method_specs = cost_function_specs_dict.pop( "estimation_method_specs", None) if estimation_method_specs is not None: if isinstance(estimation_method_specs, str): estimation_method_specs = yaml.loads(estimation_method_specs) estimation_method = create_object(estimation_method_specs) else: estimation_method = estimate_expectation_values_by_averaging cost_function_specs_dict["estimation_method"] = estimation_method estimation_preprocessors_specs_list = cost_function_specs_dict.pop( "estimation_preprocessors_specs", None) if estimation_preprocessors_specs_list is not None: estimation_preprocessors = [] for estimation_preprocessor_specs in estimation_preprocessors_specs_list: if isinstance(estimation_preprocessor_specs, str): estimation_preprocessor_specs = yaml.loads( estimation_preprocessor_specs) estimation_preprocessors.append( create_object(estimation_preprocessor_specs)) cost_function_specs_dict[ "estimation_preprocessors"] = estimation_preprocessors cost_function_specs_dict["target_operator"] = operator cost_function_specs_dict["ansatz"] = ansatz cost_function_specs_dict["backend"] = backend cost_function_specs_dict["fixed_parameters"] = fixed_params cost_function = create_object(cost_function_specs_dict) if prior_expectation_values is not None: if isinstance(prior_expectation_values, str): cost_function.estimator.prior_expectation_values = load_expectation_values( prior_expectation_values) if constraint_operator != "None": constraint_op = load_qubit_operator(constraint_operator) constraints_cost_function_specs = yaml.load(cost_function_specs, Loader=yaml.SafeLoader) constraints_estimator_specs = constraints_cost_function_specs.pop( "estimator-specs", None) if constraints_estimator_specs is not None: constraints_cost_function_specs["estimator"] = create_object( constraints_estimator_specs) constraints_cost_function_specs["ansatz"] = ansatz constraints_cost_function_specs["backend"] = backend constraints_cost_function_specs["target_operator"] = constraint_op constraint_cost_function = create_object( constraints_cost_function_specs) constraint_cost_function_wrapper = ( lambda params: constraint_cost_function.evaluate(params).value) constraint_functions = ({ "type": "eq", "fun": constraint_cost_function_wrapper }, ) optimizer.constraints = constraint_functions opt_results = optimizer.minimize(cost_function, initial_params, keep_history) save_optimization_results(opt_results, "optimization-results.json") save_array(opt_results.opt_params, "optimized-parameters.json")