def target_unitary(self, beta, gamma, symbols_map): target_circuit = Circuit() target_circuit += H(0) target_circuit += H(1) target_circuit += RZ(2 * gamma)(0) target_circuit += RZ(2 * gamma)(1) target_circuit += RX(2 * beta)(0) target_circuit += RX(2 * beta)(1) return target_circuit.bind(symbols_map).to_unitary()
def time_evolution_for_term( term: QubitOperator, time: Union[float, sympy.Expr]) -> circuits.Circuit: """Evolves a Pauli term for a given time and returns a circuit representing it. Based on section 4 from https://arxiv.org/abs/1001.3855 . Args: term: Pauli term to be evolved time: time of evolution Returns: Circuit: Circuit representing evolved term. """ if len(term.terms) != 1: raise ValueError("This function works only on a single term.") term_components = list(term.terms.keys())[0] base_changes = [] base_reversals = [] cnot_gates = [] central_gate = None term_types = [component[1] for component in term_components] qubit_indices = [component[0] for component in term_components] coefficient = list(term.terms.values())[0] circuit = circuits.Circuit() # If constant term, return empty circuit. if not term_components: return circuit for i, (term_type, qubit_id) in enumerate(zip(term_types, qubit_indices)): if term_type == "X": base_changes.append(H(qubit_id)) base_reversals.append(H(qubit_id)) elif term_type == "Y": base_changes.append(RX(np.pi / 2)(qubit_id)) base_reversals.append(RX(-np.pi / 2)(qubit_id)) if i == len(term_components) - 1: central_gate = RZ(2 * time * coefficient)(qubit_id) else: cnot_gates.append(CNOT(qubit_id, qubit_indices[i + 1])) for gate in base_changes: circuit += gate for gate in cnot_gates: circuit += gate circuit += central_gate for gate in reversed(cnot_gates): circuit += gate for gate in base_reversals: circuit += gate return circuit
def create_2_qubit_x_operator(qubit1: int, qubit2: int, param): return Circuit( [ H(qubit1), H(qubit2), CNOT(qubit1, qubit2), RZ(2 * param)(qubit2), CNOT(qubit1, qubit2), H(qubit1), H(qubit2), ] )
def _validate_constant_terms_are_included_in_output( estimator: EstimateExpectationValues, ): estimation_tasks = [ EstimationTask(IsingOperator("Z0"), Circuit([H(0)]), 10000), EstimationTask( IsingOperator("Z0") + IsingOperator("[]", 19.971997), Circuit([H(0)]), 10000, ), ] expectation_values = estimator( backend=_backend, estimation_tasks=estimation_tasks, ) return not np.array_equal(expectation_values[0].values, expectation_values[1].values)
def test_get_wavefunction_seed(self): # Given circuit = Circuit([H(0), CNOT(0, 1), CNOT(1, 2)]) backend1 = ForestSimulator("wavefunction-simulator", seed=5324) backend2 = ForestSimulator("wavefunction-simulator", seed=5324) # When wavefunction1 = backend1.get_wavefunction(circuit) wavefunction2 = backend2.get_wavefunction(circuit) # Then for (ampl1, ampl2) in zip(wavefunction1.amplitudes, wavefunction2.amplitudes): assert ampl1 == ampl2
def test_cvar_estimator_returns_correct_values(self, estimator, backend, operator): # Given estimation_tasks = [EstimationTask(operator, Circuit([H(0)]), 10000)] if estimator.alpha <= 0.5: target_value = -1 else: target_value = (-1 * 0.5 + 1 * (estimator.alpha - 0.5)) / estimator.alpha # When expectation_values = estimator( backend=backend, estimation_tasks=estimation_tasks, ) # Then assert expectation_values[0].values == pytest.approx(target_value, abs=2e-1)
def test_gibbs_estimator_returns_correct_values(self, estimator, backend, operator): # Given estimation_tasks = [EstimationTask(operator, Circuit([H(0)]), 10000)] expval_0 = np.exp(1 * -estimator.alpha) # Expectation value of bitstring 0 expval_1 = np.exp(-1 * -estimator.alpha) # Expectation value of bitstring 1 # Target value is the -log of the mean of the expectation values of the 2 bitstrings target_value = -np.log((expval_1 + expval_0) / 2) # When expectation_values = estimator( backend=backend, estimation_tasks=estimation_tasks, ) # Then assert expectation_values[0].values == pytest.approx(target_value, abs=2e-2)
class TestCreatingUnitaryFromCircuit: @pytest.fixture def cirq_unitaries(self): """ Note: We decided to go with file-based approach after extracting cirq from z-quantum-core and not being able to use `export_to_cirq` anymore. """ path_to_array = ("/".join(__file__.split("/")[:-1]) + "/hardcoded_cirq_unitaries.npy") return np.load(path_to_array, allow_pickle=True) @pytest.mark.parametrize( "circuit, unitary_index", [ # Identity gates in some test cases below are used so that comparable # Cirq circuits have the same number of qubits as Zquantum ones. (Circuit([RX(np.pi / 5)(0)]), 0), (Circuit([RY(np.pi / 2)(0), RX(np.pi / 5)(0)]), 1), ( Circuit( [I(1), I(2), I(3), I(4), RX(np.pi / 5)(0), XX(0.1)(5, 0)]), 2, ), ( Circuit([ XY(np.pi).controlled(1)(3, 1, 4), RZ(0.1 * np.pi).controlled(2)(0, 2, 1), ]), 3, ), ( Circuit( [H(1), YY(0.1).controlled(1)(0, 1, 2), X(2), Y(3), Z(4)]), 4, ), ], ) def test_without_free_params_gives_the_same_result_as_cirq( self, circuit, unitary_index, cirq_unitaries): zquantum_unitary = circuit.to_unitary() assert isinstance( zquantum_unitary, np.ndarray ), "Unitary constructed from non-parameterized circuit is not a numpy array." np.testing.assert_array_almost_equal(zquantum_unitary, cirq_unitaries[unitary_index]) def test_commutes_with_parameter_substitution(self): theta, gamma = sympy.symbols("theta, gamma") circuit = Circuit([ RX(theta / 2)(0), X(1), RY(gamma / 4).controlled(1)(1, 2), YY(0.1)(0, 4) ]) symbols_map = {theta: 0.1, gamma: 0.5} parameterized_unitary = circuit.to_unitary() unitary = circuit.bind(symbols_map).to_unitary() np.testing.assert_array_almost_equal( np.array(parameterized_unitary.subs(symbols_map), dtype=complex), unitary)
assert contract(estimator) """ import numpy as np from openfermion import IsingOperator from zquantum.core.circuits import RX, RY, RZ, Circuit, H from zquantum.core.interfaces.estimation import ( EstimateExpectationValues, EstimationTask, ) from zquantum.core.symbolic_simulator import SymbolicSimulator _backend = SymbolicSimulator(seed=1997) _estimation_tasks = [ EstimationTask(IsingOperator("Z0"), Circuit([H(0)]), 10000), EstimationTask( IsingOperator("Z0") + IsingOperator("Z1") + IsingOperator("Z2"), Circuit([H(0), RX(np.pi / 3)(0), H(2)]), 10000, ), EstimationTask( IsingOperator("Z0") + IsingOperator("Z1", 4), Circuit([ RX(np.pi)(0), RY(0.12)(1), RZ(np.pi / 3)(1), RY(1.9213)(0), ]), 10000, ),
EstimationTask( IsingOperator((), coefficient=2.0), circuit=Circuit([RY(np.pi / 4)(0)]), number_of_shots=30, ), ], [ExpectationValues(np.array([-1])), ExpectationValues(np.array([2]))], ), ] TEST_CASES_NONEIGENSTATES = [ ( [ EstimationTask( IsingOperator("Z0"), circuit=Circuit([H(0)]), number_of_shots=1000, ), EstimationTask( IsingOperator("Z0", coefficient=-2), circuit=Circuit([RY(np.pi / 4)(0)]), number_of_shots=1000, ), ], [ ExpectationValues(np.array([0])), ExpectationValues(np.array([-2 * (np.cos(np.pi / 8)**2 - 0.5) * 2 ])), ], ), ]
def create_x_operator(qubit: int, param): return Circuit([H(qubit), RZ(2 * param)(qubit), H(qubit)])