def test_build_ansatz_circuit_with_parameter_values( self, params_filename_and_number_of_layers): # Given params_filename, number_of_layers = params_filename_and_number_of_layers ansatz_specs = { "module_name": "zquantum.core.interfaces.mock_objects", "function_name": "MockAnsatz", "number_of_layers": number_of_layers, "problem_size": 2, } parameters = load_array(params_filename) ansatz = create_object(copy.deepcopy(ansatz_specs)) expected_circuit = ansatz.get_executable_circuit(parameters) # When build_ansatz_circuit(ansatz_specs=ansatz_specs, params=params_filename) # Then try: circuit_filename = "circuit.json" with open(circuit_filename) as f: circuit = new_circuits.circuit_from_dict(json.load(f)) assert circuit == expected_circuit finally: remove_file_if_exists(circuit_filename)
def test_combine_ansatz_params(self, params_filenames): # Given params1_filename, params2_filename = params_filenames # When combine_ansatz_params(params1_filename, params2_filename) # Then try: combined_parameters_filename = "combined-params.json" parameters = load_array(combined_parameters_filename) params1 = load_array(params1_filename) params2 = load_array(params2_filename) assert all(parameters == np.concatenate([params1, params2])) finally: remove_file_if_exists(combined_parameters_filename)
def evaluate_parametrized_circuit( parametrized_circuit: Union[str, Circuit], parameters: Union[str, np.ndarray], ): if isinstance(parametrized_circuit, str): parametrized_circuit = load_circuit(parametrized_circuit) if isinstance(parameters, str): parameters = serialization.load_array(parameters) symbols_map = create_symbols_map(parametrized_circuit.symbolic_params, parameters) bound_circuit = parametrized_circuit.bind(symbols_map) save_circuit(bound_circuit, "evaluated-circuit.json")
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 build_ansatz_circuit(ansatz_specs: Specs, params: Optional[Union[str, List]] = None): ansatz = load_from_specs(ansatz_specs) params_array: np.ndarray if params is not None: if isinstance(params, str): params_array = serialization.load_array(params) else: params_array = np.array(params) circuit = ansatz.get_executable_circuit(params_array) elif ansatz.supports_parametrized_circuits: circuit = ansatz.parametrized_circuit else: raise (Exception( "Ansatz is not parametrizable and no parameters has been provided." )) save_circuit(circuit, "circuit.json")
def test_using_number_of_parameters( self, number_of_parameters, ): # Given seed = RNDSEED filename = "params.json" remove_file_if_exists(filename) # When generate_random_ansatz_params( number_of_parameters=number_of_parameters, seed=seed) # Then try: parameters = load_array(filename) assert len(parameters) == number_of_parameters finally: remove_file_if_exists(filename)
def test_using_mock_ansatz_specs(self, number_of_layers): # Given ansatz_specs = { "module_name": "zquantum.core.interfaces.mock_objects", "function_name": "MockAnsatz", "number_of_layers": number_of_layers, "problem_size": 2, } seed = RNDSEED filename = "params.json" remove_file_if_exists(filename) # When generate_random_ansatz_params(ansatz_specs=ansatz_specs, seed=seed) # Then try: parameters = load_array(filename) assert len(parameters) == number_of_layers finally: remove_file_if_exists(filename)
def build_qaoa_ansatz_circuit( ansatz_specs: Specs, cost_hamiltonian: Union[str, List], mixer_hamiltonian: Union[str, List] = None, params: Optional[Union[str, List]] = None, thetas: Optional[Union[str, List]] = None, ): if isinstance(ansatz_specs, str): DeprecationWarning( "Loading ansatz_specs as a string will be depreciated in future, please change it to a dictionary." ) ansatz_specs = json.loads(ansatz_specs) cost_hamiltonian = load_qubit_operator(cost_hamiltonian) ansatz_specs["cost_hamiltonian"] = cost_hamiltonian if mixer_hamiltonian: mixer_hamiltonian = load_qubit_operator(mixer_hamiltonian) ansatz_specs["mixer_hamiltonian"] = mixer_hamiltonian if thetas: thetas = np.array(load_list(thetas)) ansatz_specs["thetas"] = thetas ansatz = load_from_specs(ansatz_specs) if params is not None: if isinstance(params, str): params = load_array(params) else: params = np.array(params) circuit = ansatz.get_executable_circuit(params) elif ansatz.supports_parametrized_circuits: circuit = ansatz.parametrized_circuit else: raise (Exception( "Ansatz is not parametrizable and no parameters has been provided." )) save_circuit(circuit, "circuit.json")
def combine_ansatz_params(params1: str, params2: str): parameters1 = serialization.load_array(params1) parameters2 = serialization.load_array(params2) combined_params = ansatz_utils.combine_ansatz_params( parameters1, parameters2) serialization.save_array(combined_params, "combined-params.json")
def evaluate_ansatz_based_cost_function( ansatz_specs: Specs, backend_specs: Specs, cost_function_specs: Specs, ansatz_parameters: str, target_operator: Union[str, openfermion.SymbolicOperator], estimation_method_specs: Optional[Specs] = None, estimation_preprocessors_specs: Optional[List[Specs]] = None, noise_model: Optional[str] = None, device_connectivity: Optional[str] = None, prior_expectation_values: Optional[str] = None, estimation_tasks_transformations_kwargs: Optional[Dict] = None, ): # Empty dict as default is bad if estimation_tasks_transformations_kwargs is None: estimation_tasks_transformations_kwargs = {} ansatz_parameters = load_array(ansatz_parameters) # Load qubit op if isinstance(target_operator, str): operator = load_qubit_operator(target_operator) else: operator = target_operator if isinstance(ansatz_specs, str): ansatz_specs = json.loads(ansatz_specs) if ansatz_specs["function_name"] == "QAOAFarhiAnsatz": ansatz = create_object(ansatz_specs, cost_hamiltonian=operator) else: ansatz = create_object(ansatz_specs) if isinstance(backend_specs, str): backend_specs = json.loads(backend_specs) if noise_model is not None: backend_specs["noise_model"] = load_noise_model(noise_model) if device_connectivity is not None: backend_specs["device_connectivity"] = layouts.load_circuit_connectivity( device_connectivity ) backend = create_object(backend_specs) if isinstance(cost_function_specs, str): cost_function_specs = json.loads(cost_function_specs) if ( "estimator-specs" in cost_function_specs.keys() or "estimation-tasks-transformations-specs" in cost_function_specs.keys() ): raise RuntimeError( "Estimation-related specs should be separate arguments and not in " "cost_function_specs" ) if prior_expectation_values is not None: if isinstance(prior_expectation_values, str): prior_expectation_values = load_expectation_values(prior_expectation_values) 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 cost_function_specs["estimation_method"] = estimation_method if estimation_preprocessors_specs is not None: cost_function_specs["estimation_preprocessors"] = [] for estimation_tasks_transformation_specs in estimation_preprocessors_specs: if isinstance(estimation_tasks_transformation_specs, str): estimation_tasks_transformation_specs = json.loads( estimation_tasks_transformation_specs ) if prior_expectation_values is not None: # Since we don't know which estimation task transformation uses # prior_expectation_values, we add it to the kwargs of each one. If not # used by a particular transformer, it will be ignored. estimation_tasks_transformation_specs[ "prior_expectation_values" ] = prior_expectation_values cost_function_specs["estimation_preprocessors"].append( create_object( estimation_tasks_transformation_specs, **estimation_tasks_transformations_kwargs ) ) # cost_function.estimator.prior_expectation_values cost_function_specs["target_operator"] = operator cost_function_specs["ansatz"] = ansatz cost_function_specs["backend"] = backend cost_function = create_object(cost_function_specs) value_estimate = cost_function(ansatz_parameters) save_value_estimate(value_estimate, "value_estimate.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", 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")