def run_circuitset_and_measure( backend_specs: Specs, circuitset: str, n_samples: Optional[int] = None, noise_model: Optional[str] = None, device_connectivity: Optional[str] = None, ): 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 ) circuit_set = circuits.load_circuitset(circuitset) backend = create_object(backend_specs) n_samples_list = [n_samples for _ in circuit_set] measurements_set = backend.run_circuitset_and_measure( circuit_set, n_samples=n_samples_list ) list_of_measurements = [measurement.bitstrings for measurement in measurements_set] save_list(list_of_measurements, "measurements-set.json")
def generate_random_list_of_integers(seed: Union[None, int] = None, **kwargs): """Generate a random list of integers. Docs can be found at the link below, but the keyword argument "low" is mandatory. https://numpy.org/devdocs/reference/random/generated/numpy.random.Generator.integers.html#numpy.random.Generator.integers """ rng = np.random.default_rng(seed=seed) generated_integers = rng.integers(**kwargs).tolist() save_list(generated_integers, "integers.json")
def solve_relaxed_qubo( qubo, optimizer_specs=None, number_of_trials=10, symmetrize_matrix=True, ): qubo = load_qubo(qubo) qubo_matrix = qubo.to_numpy_matrix().astype(float) if symmetrize_matrix: qubo_matrix = (qubo_matrix + qubo_matrix.T) / 2 if is_matrix_positive_semidefinite(qubo_matrix): solution, optimal_value = solve_qp_problem_for_psd_matrix( qubo_matrix, symmetrize_matrix) else: if optimizer_specs is None: raise ValueError( "For qubo with semipositive definite matrix, an optimizer must be provided." ) optimizer = create_object(optimizer_specs) solution, optimal_value = solve_qp_problem_with_optimizer( qubo_matrix, optimizer, number_of_trials, symmetrize_matrix) save_list(solution.tolist(), "solution.json") save_value_estimate(ValueEstimate(optimal_value), "energy.json")
def test_list_io(self): # Given initial_list = [0.1, 0.3, -0.3] # When save_list(initial_list, "list.json") loaded_list = load_list("list.json") # Then assert initial_list == loaded_list remove_file_if_exists("list.json")
def test_named_list_io(self): # Given initial_list = [0.1, 0.3, -0.3] # When save_list(initial_list, "list.json", "number") loaded_list = load_list("list.json") # Then assert initial_list == loaded_list # And # After manually loading json if isinstance("list.json", str): with open("list.json", "r") as f: data = json.load(f) else: data = json.load("list.json") # Check that assert data["schema"] == SCHEMA_VERSION + "-number-list" remove_file_if_exists("list.json")
def run_circuit_and_get_expval( backend_specs: dict, circuit: str, operators: str, ): """Takes a circuit to obtain the expectation value of an operator on a given backend. All backend calls used in this function are defined as ``QuantumBackend`` and ``QuantumSimulator`` interface standard methods implemented are defined in the ``z-quantum-core`` repository. There are two computation modes: sampling and exact. Expectation values are computed by post-processing samples when an Orquestra ``QuantumBackend`` is used or the number of samples was specified for a ``QuantumSimulator`` backend. When the number of samples was not specified, ``QuantumSimulator`` backends run in exact mode. Args: backend_specs (dict): the parsed Orquestra backend specifications circuit (str): the circuit represented as an OpenQASM 2.0 program operators (str): the operator in an ``openfermion.QubitOperator`` or ``openfermion.IsingOperator`` representation """ backend_specs = json.loads(backend_specs) operators = json.loads(operators) backend = create_object(backend_specs) # 1. Parse circuit qc = QuantumCircuit.from_qasm_str(circuit) # 2. Create operators ops = [] for op in operators: if backend.n_samples is not None: # Operator for Backend/Simulator in sampling mode ops.append(IsingOperator(op)) else: # Operator for Simulator exact mode ops.append(QubitOperator(op)) # 2.+1 # Activate the qubits that are measured but were not acted on # By applying the identity # Note: this is a temporary logic subject to be removed once supported by # Orquestra # Get the active qubits of the circuit active_qubits = [] for instr in qc.data: instruction_qubits = [qubit.index for qubit in instr[1]] active_qubits.extend(instruction_qubits) active_qubits = set(active_qubits) # Get the qubits we'd like to measure # Data for identities is not stored, need to account for empty terms op_qubits = [term[0][0] for op in ops for term in op.terms if term] need_to_activate = set(op_qubits) - active_qubits if not need_to_activate == set(): for qubit in need_to_activate: # Apply the identity qc.id(qubit) # If there are still no instructions, apply identity to the first qubit # Can happen for an empty circuit when measuring the identity operator if not qc.data: qc.id(qc.qubits[0]) # Convert to zquantum.core.circuit.Circuit circuit = Circuit(qc) # 3. Expval results = _get_expval(backend, circuit, ops) save_list(results, "expval.json")
def convert_relaxed_solution_to_angles(solution, epsilon=0.5): solution = np.array(load_list(solution)) thetas = warm_start_ansatz.convert_relaxed_solution_to_angles( solution, epsilon) save_list(thetas.tolist(), "thetas.json")
def run_circuit_and_get_expval( backend_specs: str, circuit: str, operators: str, ): """Executes a circuit to obtain the expectation value of an operator on a given backend. All Orquestra backend interface calls used in this function are standard methods of the ``QuantumBackend`` and ``QuantumSimulator`` interfaces as defined in the ``z-quantum-core`` repository. There are two computation modes: sampling and exact. Expectation values are computed by post-processing samples when an Orquestra ``QuantumBackend`` is used or the number of samples was specified for a ``QuantumSimulator`` backend. When the number of samples isn't specified, ``QuantumSimulator`` backends run in exact mode. Args: backend_specs (str): the Orquestra backend specification in a json representation circuit (str): the circuit represented as an OpenQASM 2.0 program operators (str): the operator in an ``openfermion.QubitOperator`` or ``openfermion.IsingOperator`` representation """ backend_specs = json.loads(backend_specs) n_samples = backend_specs.pop("n_samples", None) operators = json.loads(operators) backend = create_object(backend_specs) # 1. Parse circuit qc = QuantumCircuit.from_qasm_str(circuit) # 2. Create operators ops = [] if n_samples is not None: # Operators for Backend/Simulator in sampling mode for op in operators: ops.append(IsingOperator(op)) else: # Operators for Simulator exact mode for op in operators: ops.append(QubitOperator(op)) # 2.+1 # Activate the qubits that are measured but were not acted on # by applying the identity # Note: this is a temporary logic subject to be removed once supported by # Orquestra # Get the active qubits of the circuit active_qubits = [] for instr in qc.data: instruction_qubits = [qubit.index for qubit in instr[1]] active_qubits.extend(instruction_qubits) need_to_activate = set(range(len(qc.qubits))) - set(active_qubits) if need_to_activate: # We activate all the qubits for convenience for qubit in need_to_activate: # Apply the identity qc.id(qubit) # Convert to zquantum.core.circuits.Circuit circuit = import_from_qiskit(qc) # 3. Expval results = _get_expval(backend, circuit, ops, n_samples) save_list(results, "expval.json")