def evaluate_operator_for_parameter_grid( ansatz_specs, backend_specs, grid, operator, fixed_parameters="None", ): ansatz = create_object(json.loads(ansatz_specs)) backend = create_object(json.loads(backend_specs)) grid = load_parameter_grid(grid) operator = load_qubit_operator(operator) if fixed_parameters != "None": if type(fixed_parameters) == str: if os.path.exists(fixed_parameters): fixed_parameters = load_circuit_template_params(fixed_parameters) else: fixed_parameters = [] ( parameter_grid_evaluation, optimal_parameters, ) = _evaluate_operator_for_parameter_grid( ansatz, grid, backend, operator, previous_layer_params=fixed_parameters ) save_parameter_grid_evaluation( parameter_grid_evaluation, "parameter-grid-evaluation.json" ) save_circuit_template_params(optimal_parameters, "/app/optimal-parameters.json")
def test_unsuccessful_post_result_body_None(self): connection = http.client.HTTPConnection(self.ipaddress+":"+str(self.listening_port), timeout=2) # POST argument values to allow proxy to verify that argument values that come in with # Value POST are correct params = np.random.random((2,2)) save_circuit_template_params(params, 'proxy_test_current_argument_values_artifact.json') with open('proxy_test_current_argument_values_artifact.json', 'r') as f: arg_val_data = json.load(f) # set status to be OPTIMIZING in order to POST argument values connection.request('POST', '/status', body="OPTIMIZING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) # POST argument values connection.request('POST', '/cost-function-argument-values', body=json.JSONEncoder().encode(arg_val_data)) response = connection.getresponse() self.assertEqual(response.getcode(), 200) # set status to be EVALUATING connection.request('POST', '/status', body="EVALUATING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) # POST cost function result connection.request('POST', '/cost-function-results', body=None) response = connection.getresponse() self.assertEqual(response.getcode(), 400) response_lower = response.read().decode("utf-8").lower() self.assertTrue(response_lower.find('error') != -1) self.assertTrue(response_lower.find('format') != -1)
def test_post_current_argument_values(self): params = np.random.random((2,2)) save_circuit_template_params(params, 'proxy_test_current_argument_values_artifact.json') with open('proxy_test_current_argument_values_artifact.json', 'r') as f: data = json.load(f) connection = http.client.HTTPConnection(self.ipaddress+":"+str(self.listening_port), timeout=2) # set status to be OPTIMIZING connection.request('POST', '/status', body="OPTIMIZING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) connection.request('POST', '/cost-function-argument-values', body=json.JSONEncoder().encode(data)) response = connection.getresponse() self.assertEqual(response.getcode(), 200) # decode id from response id_from_argument_value_post = response.read().decode("utf-8") connection.request('GET', '/cost-function-argument-values') response = connection.getresponse() self.assertEqual(response.getcode(), 200) # remove id from response and verify it is correct response_json = json.loads(response.read().decode("utf-8")) response_id = response_json.pop("optimization-evaluation-id") self.assertEqual(id_from_argument_value_post, response_id) # assert argument values are same as above with open('proxy_test_current_argument_values_artifact_from_proxy.json', 'w') as f: f.write(json.dumps(response_json)) new_data_loaded_from_file = load_circuit_template_params('proxy_test_current_argument_values_artifact_from_proxy.json') np.testing.assert_array_equal(params, new_data_loaded_from_file)
def __call__(self, parameters) -> ValueEstimate: """Evaluates the value of the cost function for given parameters by communicating with client. Args: parameters (np.ndarray): parameters for which the evaluation should occur Returns: value: cost function value for given parameters, either int or float. """ # Encode params to json string save_circuit_template_params(parameters, "current_optimization_params.json") with open("current_optimization_params.json", "r") as f: current_params_string = f.read() # POST params to proxy evaluation_id = self.client.post_argument_values(current_params_string) # POST status to EVALUATING self.client.post_status("EVALUATING") # WAIT for status to be OPTIMIZING while self.client.get_status() != "OPTIMIZING": time.sleep(1) # GET cost function evaluation from proxy evaluation_string = self.client.get_evaluation_result(evaluation_id) value_estimate = load_value_estimate(io.StringIO(evaluation_string)) return value_estimate
def test_save_parameter_grid_evaluation(self): # Given ansatz = MockAnsatz(2, 2) grid = build_uniform_param_grid(1, 2, 0, np.pi, np.pi / 10) backend = create_object({ "module_name": "zquantum.core.interfaces.mock_objects", "function_name": "MockQuantumSimulator", }) op = QubitOperator("0.5 [] + 0.5 [Z1]") ( parameter_grid_evaluation, optimal_parameters, ) = evaluate_operator_for_parameter_grid(ansatz, grid, backend, op) # When save_parameter_grid_evaluation(parameter_grid_evaluation, "parameter-grid-evaluation.json") save_circuit_template_params(optimal_parameters, "optimal-parameters.json") # Then # TODO files_to_remove = ("parameter-grid-evaluation.json", "optimal-parameters.json") failed_to_remove = [] for path in files_to_remove: try: os.remove(path) except OSError: failed_to_remove.append(path) if failed_to_remove: raise RuntimeError(f"Failed to remove files: {failed_to_remove}")
def params_filename_and_number_of_layers(self, number_of_layers): params = np.random.uniform(low=0, high=np.pi, size=number_of_layers) params_filename = "params.json" save_circuit_template_params(np.array(params), params_filename) yield params_filename, number_of_layers remove_file_if_exists(params_filename)
def test_post_result(self): connection = http.client.HTTPConnection(self.ipaddress+":"+str(self.listening_port), timeout=2) # POST argument values to allow proxy to verify that id that comes in with # result POST are correct params = np.random.random((2,2)) save_circuit_template_params(params, 'proxy_test_current_argument_values_artifact.json') with open('proxy_test_current_argument_values_artifact.json', 'r') as f: arg_val_data = json.load(f) # set status to be OPTIMIZING in order to POST argument values connection.request('POST', '/status', body="OPTIMIZING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) # POST argument values connection.request('POST', '/cost-function-argument-values', body=json.JSONEncoder().encode(arg_val_data)) response = connection.getresponse() self.assertEqual(response.getcode(), 200) # decode id from response id_from_argument_value_post = response.read().decode("utf-8") # set status to be EVALUATING connection.request('POST', '/status', body="EVALUATING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) # make cost function result result = ValueEstimate(1.5,10.0) save_value_estimate(result, 'proxy_test_results_artifact.json') with open('proxy_test_results_artifact.json', 'r') as f: result_data = json.load(f) result_data["optimization-evaluation-id"] = id_from_argument_value_post # POST cost function result connection.request('POST', '/cost-function-results', body=json.JSONEncoder().encode(result_data)) response = connection.getresponse() self.assertEqual(response.getcode(), 204) # GET cost function result connection.request('GET', '/cost-function-results', body=id_from_argument_value_post) response = connection.getresponse() self.assertEqual(response.getcode(), 200) # remove id from response and verify it is correct response_string = response.read().decode("utf-8") response_json = json.loads(response_string) response_id = response_json.pop("optimization-evaluation-id") self.assertEqual(id_from_argument_value_post, response_id) # assert result is same as above with open('proxy_test_results_artifact_from_proxy.json', 'w') as f: f.write(json.dumps(response_json)) new_data_loaded_from_file = load_value_estimate('proxy_test_results_artifact_from_proxy.json') self.assertEqual(result.value, new_data_loaded_from_file.value) self.assertEqual(result.precision, new_data_loaded_from_file.precision)
def params_filenames(self, request): params1_filename = "params1.json" save_circuit_template_params(np.array(request.param[0]), params1_filename) params2_filename = "params2.json" save_circuit_template_params(np.array(request.param[1]), params2_filename) yield (params1_filename, params2_filename) remove_file_if_exists(params1_filename) remove_file_if_exists(params2_filename)
def evaluate_operator_for_parameter_grid( ansatz_specs: Specs, backend_specs: Specs, grid: Union[str, ParameterGrid], operator: Union[str, SymbolicOperator], fixed_parameters: Union[List[float], np.ndarray, str] = None, ): """Measure the expection values of the terms in an input operator with respect to the states prepared by the input ansatz circuits when set to the different parameters in the input parameter grid on the backend described by the backend_specs. The results are serialized into a JSON under the files: "parameter-grid-evaluation.json" and "optimal-parameters.json" ARGS: ansatz_specs (Union[dict, str]): The ansatz producing the parameterized quantum circuits backend_specs (Union[dict, str]): The backend on which to run the quantum circuit grid (Union[str, ParameterGrid]): The parameter grid describing the different ansatz parameters to use operator (Union[str, SymbolicOperator]): The operator to measure fixed_parameters (Union[List[float], np.ndarray, str]): Any fixed parameter values that the ansatz should be evaluated to that are not described by the parameter grid """ if isinstance(ansatz_specs, str): ansatz_specs = json.loads(ansatz_specs) ansatz = create_object(ansatz_specs) if isinstance(backend_specs, str): backend_specs = json.loads(backend_specs) backend = create_object(backend_specs) if isinstance(grid, str): grid = load_parameter_grid(grid) if isinstance(operator, str): operator = load_qubit_operator(operator) if fixed_parameters is not None: if isinstance(fixed_parameters, str): fixed_parameters = load_circuit_template_params(fixed_parameters) else: fixed_parameters = [] ( parameter_grid_evaluation, optimal_parameters, ) = _evaluate_operator_for_parameter_grid( ansatz, grid, backend, operator, previous_layer_params=fixed_parameters) save_parameter_grid_evaluation(parameter_grid_evaluation, "parameter-grid-evaluation.json") save_circuit_template_params(optimal_parameters, "optimal-parameters.json")
def test_unsuccessful_post_result_wrong_status(self): connection = http.client.HTTPConnection(self.ipaddress+":"+str(self.listening_port), timeout=2) # POST argument values to allow proxy to verify that argument values that come in with # Value POST are correct params = np.random.random((2,2)) save_circuit_template_params(params, 'proxy_test_current_argument_values_artifact.json') with open('proxy_test_current_argument_values_artifact.json', 'r') as f: arg_val_data = json.load(f) # set status to be OPTIMIZING in order to POST argument values connection.request('POST', '/status', body="OPTIMIZING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) # POST argument values connection.request('POST', '/cost-function-argument-values', body=json.JSONEncoder().encode(arg_val_data)) response = connection.getresponse() self.assertEqual(response.getcode(), 200) # decode id from response id_from_argument_value_post = response.read().decode("utf-8") # set status to be EVALUATING connection.request('POST', '/status', body="EVALUATING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) # make cost function result result = ValueEstimate(1.5,10.0) save_value_estimate(result, 'proxy_test_results_artifact.json') with open('proxy_test_results_artifact.json', 'r') as f: result_data = json.load(f) result_data["optimization-evaluation-id"] = id_from_argument_value_post # set status to be OPTIMIZING - new results should not be able to # be posted while that is the status connection.request('POST', '/status', body="OPTIMIZING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) # POST cost function result connection.request('POST', '/cost-function-results', body=json.JSONEncoder().encode(result_data)) response = connection.getresponse() self.assertEqual(response.getcode(), 409) response_lower = response.read().decode("utf-8").lower() self.assertTrue(response_lower.find('error') != -1) self.assertTrue(response_lower.find('status') != -1) self.assertTrue(response_lower.find('evaluating') != -1)
def generate_random_ansatz_params( ansatz_specs: Dict, number_of_parameters: Union[str, int] = "None", min_value: float = -np.pi * 0.5, max_value: float = np.pi * 0.5, seed: Union[str, int] = "None", ): if ansatz_specs != "None": # TODO None issue in workflow v1 ansatz_specs_dict = json.loads(ansatz_specs) ansatz = create_object(ansatz_specs_dict) number_of_params = ansatz.number_of_params elif number_of_parameters != "None": number_of_params = number_of_parameters if seed != "None": np.random.seed(seed) params = np.random.uniform(min_value, max_value, number_of_params) save_circuit_template_params(params, "params.json")
def test_save_parameter_grid_evaluation(self): # Given ansatz = MockAnsatz(2, 2) grid = build_uniform_param_grid(1, 2, 0, np.pi, np.pi / 10) backend = create_object({ "module_name": "zquantum.core.interfaces.mock_objects", "function_name": "MockQuantumSimulator", }) op = QubitOperator("0.5 [] + 0.5 [Z1]") ( parameter_grid_evaluation, optimal_parameters, ) = evaluate_operator_for_parameter_grid(ansatz, grid, backend, op) # When save_parameter_grid_evaluation(parameter_grid_evaluation, "parameter-grid-evaluation.json") save_circuit_template_params(optimal_parameters, "optimal-parameters.json")
def test_build_ansatz_circuit_raises_exception_on_invalid_inputs(self): params_filename = "params.json" save_circuit_template_params(np.array([1.0]), params_filename) ansatz_specs = { "module_name": "zquantum.core.interfaces.mock_objects", "function_name": "MockAnsatz", "number_of_layers": 0, "problem_size": 2, } try: circuit_filename = "circuit.json" with pytest.raises(Exception): build_ansatz_circuit(ansatz_specs=ansatz_specs, params=params_filename) finally: remove_file_if_exists(params_filename) remove_file_if_exists(circuit_filename)
def generate_random_ansatz_params( ansatz_specs: Optional[Specs] = None, number_of_parameters: Optional[int] = None, min_value: float = -np.pi * 0.5, max_value: float = np.pi * 0.5, seed: Optional[int] = None, ): assert (ansatz_specs is None) != (number_of_parameters is None) if ansatz_specs is not None: ansatz = load_from_specs(ansatz_specs) number_of_parameters = ansatz.number_of_params if seed is not None: np.random.seed(seed) params = np.random.uniform(min_value, max_value, number_of_parameters) save_circuit_template_params(params, "params.json")
def _evaluate(self, parameters): """ Evaluates the value of the cost function for given parameters by communicating with client. Args: parameters (np.ndarray): parameters for which the evaluation should occur Returns: value: cost function value for given parameters, either int or float. """ # Encode params to json string save_circuit_template_params(parameters, 'current_optimization_params.json') with open('current_optimization_params.json', 'r') as f: current_params_string = f.read() # POST params to proxy evaluation_id = self.client.post_argument_values(current_params_string) # POST status to EVALUATING self.client.post_status("EVALUATING") # WAIT for status to be OPTIMIZING while self.client.get_status() != "OPTIMIZING": time.sleep(1) # GET cost function evaluation from proxy evaluation_string = self.client.get_evaluation_result(evaluation_id) value_estimate = load_value_estimate(io.StringIO(evaluation_string)) # SAVE ID to optimization result['history'] if self.save_evaluation_history: if len(self.evaluations_history) < self.current_iteration + 1: self.evaluations_history.append( {'optimization-evaluation-ids': []}) self.evaluations_history[self.current_iteration][ 'optimization-evaluation-ids'].append(evaluation_id) self.evaluations_history[ self.current_iteration]["params"] = parameters self.evaluations_history[ self.current_iteration]["value"] = value_estimate.value return value_estimate.value
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 test_unsuccessful_post_current_argument_values_wrong_status(self): params = np.random.random((2,2)) save_circuit_template_params(params, 'proxy_test_current_argument_values_artifact.json') with open('proxy_test_current_argument_values_artifact.json', 'r') as f: data = json.load(f) connection = http.client.HTTPConnection(self.ipaddress+":"+str(self.listening_port), timeout=2) # set status to be EVALUATING - new argument values should not be able to # be posted while that is the status connection.request('POST', '/status', body="EVALUATING") response = connection.getresponse() self.assertEqual(response.getcode(), 204) connection.request('POST', '/cost-function-argument-values', body=json.JSONEncoder().encode(data)) response = connection.getresponse() self.assertEqual(response.getcode(), 409) response_lower = response.read().decode("utf-8").lower() self.assertTrue(response_lower.find('error') != -1) self.assertTrue(response_lower.find('status') != -1)
def combine_ansatz_params(params1: str, params2: str): parameters1 = load_circuit_template_params(params1) parameters2 = load_circuit_template_params(params2) combined_params = _combine_ansatz_params(parameters1, parameters2) save_circuit_template_params(combined_params, "combined-params.json")
def extract_xfav_params_from_cma_es_opt_results(optimization_results): opt_results = load_optimization_results(optimization_results) save_circuit_template_params(np.array(opt_results.cma_xfavorite), "fav-params.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")