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 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 create_XZ1_target_unitary(number_of_params, k_body_depth=1): thetas = create_thetas(number_of_params) symbols_map = create_symbols_map(number_of_params) target_circuit = Circuit() target_circuit += create_x_operator(0, thetas[0]) target_circuit += RZ(2 * thetas[1])(0) target_circuit += create_x_operator(1, thetas[2]) target_circuit += RZ(2 * thetas[3])(1) if k_body_depth == 2: target_circuit += create_2_qubit_x_operator(0, 1, thetas[4]) target_circuit += CNOT(0, 1) target_circuit += RZ(2 * thetas[5])(1) target_circuit += CNOT(0, 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 _build_circuit_layer(self, parameters: np.ndarray) -> Circuit: """Build circuit layer for the hardware efficient quantum compiling ansatz Args: parameters: The variational parameters (or symbolic parameters) Returns: Circuit containing a single layer of the Hardware Efficient Quantum Compiling Ansatz """ circuit_layer = Circuit() # Add RZ(theta) RX(pi/2) RZ(theta') RX(pi/2) RZ(theta'') circuit_layer = self._build_rotational_subcircuit( circuit_layer, parameters[:3 * self.number_of_qubits]) qubit_ids = list(range(self.number_of_qubits)) # Add CNOT(x, x+1) for x in even(qubits) for control, target in zip( qubit_ids[::2], qubit_ids[1::2]): # loop over qubits 0, 2, 4... circuit_layer += CNOT(control, target) # Add RZ(theta) RX(pi/2) RZ(theta') RX(pi/2) RZ(theta'') circuit_layer = self._build_rotational_subcircuit( circuit_layer, parameters[3 * self.number_of_qubits:6 * self.number_of_qubits], ) # Add CNOT layer working "inside -> out", skipping every other qubit for qubit_index in qubit_ids[:int(self.number_of_qubits / 2)][::-1][::2]: control = qubit_index target = self.number_of_qubits - qubit_index - 1 circuit_layer += CNOT(control, target) if qubit_index != 0 or self.number_of_qubits % 4 == 0: control = self.number_of_qubits - qubit_index target = qubit_index - 1 circuit_layer += CNOT(control, target) return circuit_layer
class TestDecompositionOfU3Gates: @pytest.mark.parametrize( "gate_to_be_decomposed, target_qubits", [ *[(gate, qubits) for gate in U3_GATES for qubits in [(0,), (2,)]], ], ) def test_gives_the_same_unitary_as_original_gate_up_to_global_phase( self, gate_to_be_decomposed, target_qubits ): circuit = Circuit([gate_to_be_decomposed(*target_qubits)]) decomposed_circuit = decompose_zquantum_circuit(circuit, DECOMPOSITION_RULES) assert _is_scaled_identity( circuit.to_unitary() @ np.linalg.inv(decomposed_circuit.to_unitary()), ) @pytest.mark.parametrize( "operations", [[RY(np.pi / 2)(0)], [X(3), Y(1), Z(0)], [CNOT(3, 11)]], ) def test_leaves_gates_not_matching_predicate_unaffected(self, operations): circuit = Circuit(operations) decomposed_circuit = decompose_zquantum_circuit(circuit, DECOMPOSITION_RULES) assert circuit.operations == decomposed_circuit.operations @pytest.mark.parametrize("target_qubits", [(0,), (2,)]) @pytest.mark.parametrize("gate_to_be_decomposed", U3_GATES) def test_U3_decomposition_comprises_only_rotations( self, gate_to_be_decomposed, target_qubits ): circuit = Circuit([gate_to_be_decomposed(*target_qubits)]) decomposed_circuit = decompose_zquantum_circuit(circuit, DECOMPOSITION_RULES) assert all( isinstance(op, GateOperation) and op.gate.name in ("RZ", "RY") for op in decomposed_circuit.operations )
class SymbolicSimulatorWithNonSupportedOperations(SymbolicSimulator): def is_natively_supported(self, operation: Operation) -> bool: return super().is_natively_supported( operation) and operation.gate.name != "RX" class SymbolicSimulatorWithDefaultSetOfSupportedOperations(SymbolicSimulator): def is_natively_supported(self, operation: Operation) -> bool: return QuantumSimulator.is_natively_supported(self, operation) @pytest.mark.parametrize( "circuit", [ Circuit([RY(0.5)(0), RX(1)(1), CNOT(0, 2), RX(np.pi)(2)]), Circuit([RX(1)(1), CNOT(0, 2), RX(np.pi)(2), RY(0.5)(0)]), Circuit([RX(1)(1), CNOT(0, 2), RX(np.pi)(2), RY(0.5)(0), RX(0.5)(0)]), ], ) def test_quantum_simulator_switches_between_native_and_nonnative_modes_of_execution( circuit, ): simulator = SymbolicSimulatorWithNonSupportedOperations() reference_simulator = SymbolicSimulator() np.testing.assert_array_equal(
def x_cnot_circuit(self): circuit = Circuit([X(0), CNOT(1, 2)]) return circuit