def qft(eng, circuit, qubits): m = len(qubits) for i in range(m - 1, -1, -1): circuit.apply_single_qubit_gate(Rz(np.pi / 2), qubits[i]) circuit.apply_single_qubit_gate(Rx(np.pi / 2), qubits[i]) circuit.apply_single_qubit_gate(Rz(np.pi / 2), qubits[i]) for j in range(2, i + 2): circuit.apply_single_qubit_gate(Rz(-np.pi / 2), qubits[i - j + 1]) circuit.apply_single_qubit_gate(Rx(np.pi / 2), qubits[i]) circuit.apply_single_qubit_gate(Rz(np.pi / 2), qubits[i]) circuit.apply_ld_two_qubit_gate(ISwap, qubits[i - j + 1], qubits[i]) circuit.apply_single_qubit_gate(Rx(np.pi / 2), qubits[i - j + 1]) circuit.apply_ld_two_qubit_gate(ISwap, qubits[i - j + 1], qubits[i]) circuit.apply_single_qubit_gate(Rz(np.pi / 2), qubits[i]) circuit.apply_single_qubit_gate(R(-calculate_phase(i) / 4), qubits[i]) circuit.apply_single_qubit_gate(Rz(-np.pi / 2), qubits[i - j + 1]) circuit.apply_single_qubit_gate(Rx(np.pi / 2), qubits[i]) circuit.apply_single_qubit_gate(Rz(np.pi / 2), qubits[i]) circuit.apply_ld_two_qubit_gate(ISwap, qubits[i - j + 1], qubits[i]) circuit.apply_single_qubit_gate(Rx(np.pi / 2), qubits[i - j + 1]) circuit.apply_ld_two_qubit_gate(ISwap, qubits[i - j + 1], qubits[i]) circuit.apply_single_qubit_gate(Rz(np.pi / 2), qubits[i]) circuit.apply_single_qubit_gate(Rz(calculate_phase(i) / 4), qubits[i - j + 1]) circuit.apply_single_qubit_gate(Rz(calculate_phase(i) / 4), qubits[i])
def _decompose_time_evolution_individual_terms(cmd): """ Implements a TimeEvolution gate with a hamiltonian having only one term. To implement exp(-i * t * hamiltonian), where the hamiltonian is only one term, e.g., hamiltonian = X0 x Y1 X Z2, we first perform local transformations to in order that all Pauli operators in the hamiltonian are Z. We then implement exp(-i * t * (Z1 x Z2 x Z3) and transform the basis back to the original. For more details see, e.g., James D. Whitfield, Jacob Biamonte & Aspuru-Guzik Simulation of electronic structure Hamiltonians using quantum computers, Molecular Physics, 109:5, 735-750 (2011). or Nielsen and Chuang, Quantum Computation and Information. """ assert len(cmd.qubits) == 1 qureg = cmd.qubits[0] eng = cmd.engine time = cmd.gate.time hamiltonian = cmd.gate.hamiltonian assert len(hamiltonian.terms) == 1 term = list(hamiltonian.terms)[0] coefficient = hamiltonian.terms[term] check_indices = set() # Check that hamiltonian is not identity term, # Previous or operator should have apply a global phase instead: assert not term == () # hamiltonian has only a single local operator if len(term) == 1: with Control(eng, cmd.control_qubits): if term[0][1] == 'X': Rx(time * coefficient * 2.) | qureg[term[0][0]] elif term[0][1] == 'Y': Ry(time * coefficient * 2.) | qureg[term[0][0]] else: Rz(time * coefficient * 2.) | qureg[term[0][0]] # hamiltonian has more than one local operator else: with Control(eng, cmd.control_qubits): with Compute(eng): # Apply local basis rotations for index, action in term: check_indices.add(index) if action == 'X': H | qureg[index] elif action == 'Y': Rx(math.pi / 2.) | qureg[index] # Check that qureg had exactly as many qubits as indices: assert check_indices == set((range(len(qureg)))) # Compute parity for i in range(len(qureg) - 1): CNOT | (qureg[i], qureg[i + 1]) Rz(time * coefficient * 2.) | qureg[-1] # Uncompute parity and basis change Uncompute(eng)
def test_decomposition(angle): for basis_state in ([1, 0], [0, 1]): correct_dummy_eng = DummyEngine(save_commands=True) correct_eng = MainEngine(backend=Simulator(), engine_list=[correct_dummy_eng]) rule_set = DecompositionRuleSet(modules=[rx2rz]) test_dummy_eng = DummyEngine(save_commands=True) test_eng = MainEngine( backend=Simulator(), engine_list=[ AutoReplacer(rule_set), InstructionFilter(rx_decomp_gates), test_dummy_eng, ], ) correct_qb = correct_eng.allocate_qubit() Rx(angle) | correct_qb correct_eng.flush() test_qb = test_eng.allocate_qubit() Rx(angle) | test_qb test_eng.flush() assert correct_dummy_eng.received_commands[1].gate == Rx(angle) assert test_dummy_eng.received_commands[1].gate != Rx(angle) for fstate in ['0', '1']: test = test_eng.backend.get_amplitude(fstate, test_qb) correct = correct_eng.backend.get_amplitude(fstate, correct_qb) assert correct == pytest.approx(test, rel=1e-12, abs=1e-12) Measure | test_qb Measure | correct_qb
def test_dagger_with_dirty_qubits(): backend = DummyEngine(save_commands=True) def allow_dirty_qubits(self, meta_tag): return meta_tag == DirtyQubitTag backend.is_meta_tag_handler = types.MethodType(allow_dirty_qubits, backend) eng = MainEngine(backend=backend, engine_list=[DummyEngine()]) qubit = eng.allocate_qubit() with _dagger.Dagger(eng): ancilla = eng.allocate_qubit(dirty=True) Rx(0.6) | ancilla CNOT | (ancilla, qubit) H | qubit Rx(-0.6) | ancilla del ancilla[0] eng.flush(deallocate_qubits=True) assert len(backend.received_commands) == 9 assert backend.received_commands[0].gate == Allocate assert backend.received_commands[1].gate == Allocate assert backend.received_commands[2].gate == Rx(0.6) assert backend.received_commands[3].gate == H assert backend.received_commands[4].gate == X assert backend.received_commands[5].gate == Rx(-0.6) assert backend.received_commands[6].gate == Deallocate assert backend.received_commands[7].gate == Deallocate assert backend.received_commands[1].tags == [DirtyQubitTag()] assert backend.received_commands[6].tags == [DirtyQubitTag()]
def test_compute_uncompute_no_additional_qubits(): # No ancilla qubit created in compute section backend0 = DummyEngine(save_commands=True) compare_engine0 = CompareEngine() eng0 = MainEngine(backend=backend0, engine_list=[compare_engine0]) qubit = eng0.allocate_qubit() with _compute.Compute(eng0): Rx(0.5) | qubit H | qubit _compute.Uncompute(eng0) eng0.flush(deallocate_qubits=True) assert backend0.received_commands[0].gate == Allocate assert backend0.received_commands[1].gate == Rx(0.5) assert backend0.received_commands[2].gate == H assert backend0.received_commands[3].gate == Rx(-0.5) assert backend0.received_commands[4].gate == Deallocate assert backend0.received_commands[0].tags == [] assert backend0.received_commands[1].tags == [_compute.ComputeTag()] assert backend0.received_commands[2].tags == [] assert backend0.received_commands[3].tags == [_compute.UncomputeTag()] assert backend0.received_commands[4].tags == [] # Same using CustomUncompute and test using CompareEngine backend1 = DummyEngine(save_commands=True) compare_engine1 = CompareEngine() eng1 = MainEngine(backend=backend1, engine_list=[compare_engine1]) qubit = eng1.allocate_qubit() with _compute.Compute(eng1): Rx(0.5) | qubit H | qubit with _compute.CustomUncompute(eng1): Rx(-0.5) | qubit eng1.flush(deallocate_qubits=True) assert compare_engine0 == compare_engine1
def run(self, type): """ construct the prob dist according to the parameters trained using born machine. :param type: str, forward or backward :return: """ if type == 'forward': for dep_index in range(self.depth + 1): for i in range(self.num_qubits): Rz(self.theta[dep_index, i, 0]) | self.qureg[i] Rx(self.theta[dep_index, i, 1]) | self.qureg[i] Rz(self.theta[dep_index, i, 2]) | self.qureg[i] # entanglement if dep_index == self.depth: pass else: for ctrl_pair in self.ctrl_pairs: CNOT | (self.qureg[ctrl_pair[0]], self.qureg[ctrl_pair[1]]) elif type == 'backward': for dep_index in range(self.depth, -1, -1): # entanglement if dep_index != self.depth: for ctrl_pair in self.ctrl_pairs[::-1]: CNOT | (self.qureg[ctrl_pair[0]], self.qureg[ctrl_pair[1]]) for i in range(self.num_qubits): Rz(self.theta[dep_index, i, 2]).get_inverse() | self.qureg[i] Rx(self.theta[dep_index, i, 1]).get_inverse() | self.qureg[i] Rz(self.theta[dep_index, i, 0]).get_inverse() | self.qureg[i]
def test_command_get_merged(main_engine): qubit = main_engine.allocate_qubit() ctrl_qubit = main_engine.allocate_qubit() cmd = _command.Command(main_engine, Rx(0.5), (qubit,)) cmd.tags = ["TestTag"] cmd.add_control_qubits(ctrl_qubit) # Merge two commands cmd2 = _command.Command(main_engine, Rx(0.5), (qubit,)) cmd2.add_control_qubits(ctrl_qubit) cmd2.tags = ["TestTag"] merged_cmd = cmd.get_merged(cmd2) expected_cmd = _command.Command(main_engine, Rx(1.0), (qubit,)) expected_cmd.add_control_qubits(ctrl_qubit) expected_cmd.tags = ["TestTag"] assert merged_cmd == expected_cmd # Don't merge commands as different control qubits cmd3 = _command.Command(main_engine, Rx(0.5), (qubit,)) cmd3.tags = ["TestTag"] with pytest.raises(NotMergeable): cmd.get_merged(cmd3) # Don't merge commands as different tags cmd4 = _command.Command(main_engine, Rx(0.5), (qubit,)) cmd4.add_control_qubits(ctrl_qubit) with pytest.raises(NotMergeable): cmd.get_merged(cmd4)
def test_aqt_retrieve(monkeypatch): # patch send def mock_retrieve(*args, **kwargs): return [0, 6, 0, 6, 0, 0, 0, 6, 0, 6] monkeypatch.setattr(_aqt, "retrieve", mock_retrieve) backend = _aqt.AQTBackend( retrieve_execution="a3877d18-314f-46c9-86e7-316bc4dbe968", verbose=True) eng = MainEngine(backend=backend, engine_list=[]) unused_qubit = eng.allocate_qubit() qureg = eng.allocate_qureg(2) # entangle the qureg Ry(math.pi / 2) | qureg[0] Rx(math.pi / 2) | qureg[0] Rx(math.pi / 2) | qureg[0] Ry(math.pi / 2) | qureg[0] Rxx(math.pi / 2) | (qureg[0], qureg[1]) Rx(7 * math.pi / 2) | qureg[0] Ry(7 * math.pi / 2) | qureg[0] Rx(7 * math.pi / 2) | qureg[1] del unused_qubit # measure; should be all-0 or all-1 All(Measure) | qureg # run the circuit eng.flush() prob_dict = eng.backend.get_probabilities([qureg[0], qureg[1]]) assert prob_dict['11'] == pytest.approx(0.4) assert prob_dict['00'] == pytest.approx(0.6) # Unknown qubit and no mapper invalid_qubit = [Qubit(eng, 10)] with pytest.raises(RuntimeError): eng.backend.get_probabilities(invalid_qubit)
def test_local_optimizer_caching(): local_optimizer = _optimize.LocalOptimizer(m=4) backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[local_optimizer]) # Test that it caches for each qubit 3 gates qb0 = eng.allocate_qubit() qb1 = eng.allocate_qubit() assert len(backend.received_commands) == 0 H | qb0 H | qb1 CNOT | (qb0, qb1) assert len(backend.received_commands) == 0 Rx(0.5) | qb0 assert len(backend.received_commands) == 1 assert backend.received_commands[0].gate == AllocateQubitGate() H | qb0 assert len(backend.received_commands) == 2 assert backend.received_commands[1].gate == H # Another gate on qb0 means it needs to send CNOT but clear pipeline of qb1 Rx(0.6) | qb0 for cmd in backend.received_commands: print(cmd) assert len(backend.received_commands) == 5 assert backend.received_commands[2].gate == AllocateQubitGate() assert backend.received_commands[3].gate == H assert backend.received_commands[3].qubits[0][0].id == qb1[0].id assert backend.received_commands[4].gate == X assert backend.received_commands[4].control_qubits[0].id == qb0[0].id assert backend.received_commands[4].qubits[0][0].id == qb1[0].id
def CNOT(eng, circuit, b1, b2): circuit.apply_single_qubit_gate(Rz(-np.pi / 2), b1) circuit.apply_single_qubit_gate(Rx(np.pi / 2), b2) circuit.apply_single_qubit_gate(Rz(np.pi / 2), b2) circuit.apply_ld_two_qubit_gate(ISwap, b1, b2) circuit.apply_single_qubit_gate(Rx(np.pi / 2), b1) circuit.apply_ld_two_qubit_gate(ISwap, b1, b2) circuit.apply_single_qubit_gate(Rz(np.pi / 2), b2)
def Swap(eng, circuit, b1, b2): # circuit.apply_ld_two_qubit_gate(ops.Swap, b1, b2) circuit.apply_ld_two_qubit_gate(ISwap, b1, b2) circuit.apply_single_qubit_gate(Rx(-np.pi / 2), b2) circuit.apply_ld_two_qubit_gate(ISwap, b1, b2) circuit.apply_single_qubit_gate(Rx(-np.pi / 2), b1) circuit.apply_ld_two_qubit_gate(ISwap, b1, b2) circuit.apply_single_qubit_gate(Rx(-np.pi / 2), b2)
def test_decomposition(): for basis_state_index in range(0, 16): basis_state = [0] * 16 basis_state[basis_state_index] = 1.0 correct_dummy_eng = DummyEngine(save_commands=True) correct_eng = MainEngine(backend=Simulator(), engine_list=[correct_dummy_eng]) rule_set = DecompositionRuleSet(modules=[cnu2toffoliandcu]) test_dummy_eng = DummyEngine(save_commands=True) test_eng = MainEngine( backend=Simulator(), engine_list=[ AutoReplacer(rule_set), InstructionFilter(_decomp_gates), test_dummy_eng, ], ) test_sim = test_eng.backend correct_sim = correct_eng.backend correct_qb = correct_eng.allocate_qubit() correct_ctrl_qureg = correct_eng.allocate_qureg(3) correct_eng.flush() test_qb = test_eng.allocate_qubit() test_ctrl_qureg = test_eng.allocate_qureg(3) test_eng.flush() correct_sim.set_wavefunction(basis_state, correct_qb + correct_ctrl_qureg) test_sim.set_wavefunction(basis_state, test_qb + test_ctrl_qureg) with Control(test_eng, test_ctrl_qureg[:2]): Rx(0.4) | test_qb with Control(test_eng, test_ctrl_qureg): Ry(0.6) | test_qb with Control(test_eng, test_ctrl_qureg): X | test_qb with Control(correct_eng, correct_ctrl_qureg[:2]): Rx(0.4) | correct_qb with Control(correct_eng, correct_ctrl_qureg): Ry(0.6) | correct_qb with Control(correct_eng, correct_ctrl_qureg): X | correct_qb test_eng.flush() correct_eng.flush() assert len(correct_dummy_eng.received_commands) == 9 assert len(test_dummy_eng.received_commands) == 25 for fstate in range(16): binary_state = format(fstate, '04b') test = test_sim.get_amplitude(binary_state, test_qb + test_ctrl_qureg) correct = correct_sim.get_amplitude(binary_state, correct_qb + correct_ctrl_qureg) assert correct == pytest.approx(test, rel=1e-12, abs=1e-12) All(Measure) | test_qb + test_ctrl_qureg All(Measure) | correct_qb + correct_ctrl_qureg test_eng.flush(deallocate_qubits=True) correct_eng.flush(deallocate_qubits=True)
def inversed_full_rotation(wavefunction, qsubset, parameter): """ The inversed operation of full_rotation() of the same parameter """ n_qubit = len(qsubset) for i in range(len(qsubset)): Rx(-parameter[2 * n_qubit + i]) | wavefunction[qsubset[i]] Rz(-parameter[n_qubit + i]) | wavefunction[qsubset[i]] Rx(-parameter[i]) | wavefunction[qsubset[i]]
def full_rotation(wavefunction, qsubset, parameter): """ Apply Rx(t1)Ry(t2)Rx(t3) rotation to all the qubits with different angle """ n_qubit = len(qsubset) for i in range(len(qsubset)): Rx(parameter[i]) | wavefunction[qsubset[i]] Rz(parameter[n_qubit + i]) | wavefunction[qsubset[i]] Rx(parameter[2 * n_qubit + i]) | wavefunction[qsubset[i]]
def test_is_identity(): # Choose gate which is not an identity gate: non_identity_gate = Rx(0.5) assert not non_identity_gate.is_identity() assert not _metagates.is_identity(non_identity_gate) # Choose gate which is an identity gate: identity_gate = Rx(0.0) assert identity_gate.is_identity() assert _metagates.is_identity(identity_gate)
def initializeState(qreg, theta): Rx(np.pi) | qreg[0] Ry(np.pi / 2.0) | qreg[1] Rx(2.5*np.pi) | qreg[0] CNOT | (qreg[1], qreg[0]) Rz(theta) | qreg[0] CNOT | (qreg[1], qreg[0]) Ry(2.5*np.pi) | qreg[1] Rx(np.pi/2) | qreg[0]
def test_aqt_backend_functional_test(monkeypatch): correct_info = { 'circuit': '[["Y", 0.5, [1]], ["X", 0.5, [1]], ["X", 0.5, [1]], ' '["Y", 0.5, [1]], ["MS", 0.5, [1, 2]], ["X", 3.5, [1]], ' '["Y", 3.5, [1]], ["X", 3.5, [2]]]', 'nq': 3, 'shots': 10, 'backend': {'name': 'simulator'}, } def mock_send(*args, **kwargs): assert args[0] == correct_info return [0, 6, 0, 6, 0, 0, 0, 6, 0, 6] monkeypatch.setattr(_aqt, "send", mock_send) backend = _aqt.AQTBackend(verbose=True, num_runs=10) # no circuit has been executed -> raises exception with pytest.raises(RuntimeError): backend.get_probabilities([]) mapper = BasicMapperEngine() res = {} for i in range(4): res[i] = i mapper.current_mapping = res eng = MainEngine(backend=backend, engine_list=[mapper]) unused_qubit = eng.allocate_qubit() qureg = eng.allocate_qureg(2) # entangle the qureg Ry(math.pi / 2) | qureg[0] Rx(math.pi / 2) | qureg[0] Rx(math.pi / 2) | qureg[0] Ry(math.pi / 2) | qureg[0] Rxx(math.pi / 2) | (qureg[0], qureg[1]) Rx(7 * math.pi / 2) | qureg[0] Ry(7 * math.pi / 2) | qureg[0] Rx(7 * math.pi / 2) | qureg[1] All(Barrier) | qureg del unused_qubit # measure; should be all-0 or all-1 All(Measure) | qureg # run the circuit eng.flush() prob_dict = eng.backend.get_probabilities([qureg[0], qureg[1]]) assert prob_dict['11'] == pytest.approx(0.4) assert prob_dict['00'] == pytest.approx(0.6) # Unknown qubit and no mapper invalid_qubit = [WeakQubitRef(eng, 10)] with pytest.raises(RuntimeError): eng.backend.get_probabilities(invalid_qubit) with pytest.raises(RuntimeError): eng.backend.get_probabilities(eng.allocate_qubit())
def test_command_str(): qubit = Qureg([Qubit(main_engine, 0)]) ctrl_qubit = Qureg([Qubit(main_engine, 1)]) cmd = _command.Command(main_engine, Rx(0.5), (qubit, )) cmd.tags = ["TestTag"] cmd.add_control_qubits(ctrl_qubit) assert str(cmd) == "CRx(0.5) | ( Qureg[1], Qureg[0] )" cmd2 = _command.Command(main_engine, Rx(0.5), (qubit, )) assert str(cmd2) == "Rx(0.5) | Qureg[0]"
def swap(self, node1, node2): self.gates_applied += 6 self.single_applied += 3 self.two_applied += 3 ISwap | (node1.qubit.qubit, node2.qubit.qubit) Rx(-np.pi / 2) | node2.qubit.qubit ISwap | (node1.qubit.qubit, node2.qubit.qubit) Rx(-np.pi / 2) | node1.qubit.qubit ISwap | (node1.qubit.qubit, node2.qubit.qubit) Rx(-np.pi / 2) | node2.qubit.qubit
def _decompose_cnot2rxx_P(cmd): """ Decompose CNOT gate into Rxx gate. """ # Labelled 'P' for 'plus' because decomposition ends with a Ry(+pi/2) ctrl = cmd.control_qubits Ry(-math.pi / 2) | ctrl[0] Ph(math.pi / 4) | ctrl[0] Rx(-math.pi / 2) | ctrl[0] Rx(math.pi / 2) | cmd.qubits[0][0] Rxx(math.pi / 2) | (ctrl[0], cmd.qubits[0][0]) Ry(math.pi / 2) | ctrl[0]
def _decompose_cnot2rxx_M(cmd): # pylint: disable=invalid-name """Decompose CNOT gate into Rxx gate.""" # Labelled 'M' for 'minus' because decomposition ends with a Ry(-pi/2) ctrl = cmd.control_qubits Ry(math.pi / 2) | ctrl[0] Ph(7 * math.pi / 4) | ctrl[0] Rx(-math.pi / 2) | ctrl[0] Rx(-math.pi / 2) | cmd.qubits[0][0] Rxx(math.pi / 2) | (ctrl[0], cmd.qubits[0][0]) Ry(-1 * math.pi / 2) | ctrl[0]
def test_command_is_identity(main_engine): qubit = main_engine.allocate_qubit() qubit2 = main_engine.allocate_qubit() cmd = _command.Command(main_engine, Rx(0.0), (qubit,)) cmd2 = _command.Command(main_engine, Rx(0.5), (qubit2,)) inverse_cmd = cmd.get_inverse() inverse_cmd2 = cmd2.get_inverse() assert inverse_cmd.gate.is_identity() assert cmd.gate.is_identity() assert not inverse_cmd2.gate.is_identity() assert not cmd2.gate.is_identity()
def test_recognize_correct_gates(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend) qubit = eng.allocate_qubit() ctrl_qubit = eng.allocate_qubit() eng.flush() Rx(0.3) | qubit with Control(eng, ctrl_qubit): Rx(0.4) | qubit eng.flush(deallocate_qubits=True) assert rx2rz._recognize_RxNoCtrl(saving_backend.received_commands[3]) assert not rx2rz._recognize_RxNoCtrl(saving_backend.received_commands[4])
def test_local_optimizer_mergeable_gates(): local_optimizer = _optimize.LocalOptimizer(m=4) backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[local_optimizer]) # Test that it merges mergeable gates such as Rx qb0 = eng.allocate_qubit() for _ in range(10): Rx(0.5) | qb0 assert len(backend.received_commands) == 0 eng.flush() # Expect allocate, one Rx gate, and flush gate assert len(backend.received_commands) == 3 assert backend.received_commands[1].gate == Rx(10 * 0.5)
def test_command_str(main_engine): qubit = Qureg([Qubit(main_engine, 0)]) ctrl_qubit = Qureg([Qubit(main_engine, 1)]) cmd = _command.Command(main_engine, Rx(0.5 * math.pi), (qubit,)) cmd.tags = ["TestTag"] cmd.add_control_qubits(ctrl_qubit) cmd2 = _command.Command(main_engine, Rx(0.5 * math.pi), (qubit,)) if sys.version_info.major == 3: assert cmd.to_string(symbols=False) == "CRx(1.570796326795) | ( Qureg[1], Qureg[0] )" assert str(cmd2) == "Rx(1.570796326795) | Qureg[0]" else: assert cmd.to_string(symbols=False) == "CRx(1.5707963268) | ( Qureg[1], Qureg[0] )" assert str(cmd2) == "Rx(1.5707963268) | Qureg[0]"
def generalized_rotation(wavefunction, qsubset, pauliword, evolution_time): """Apply e^{iPt} on the wavefunction Args: qsubset: The subset of qubits in the wavefunction that the operation applies on pauliword: The Pauli word P in e^{iPt} 1:X,2:Y,3:Z evolution_time: t in e^{iPt} """ HALF_PI = math.pi / 2 n_qubit = len(qsubset) # Exponentiating each Pauli string requires five parts # 1. Perform basis rotations for p in range(0, n_qubit): pop = pauliword[p] # Pauli op if pop == 1: H | wavefunction[qsubset[p]] # Hadamard elif pop == 2: Rx(HALF_PI) | wavefunction[qsubset[p]] # 2. First set CNOTs prev_index = None for p in range(0, n_qubit): pop = pauliword[p] # Pauli op if pop == 0: continue if prev_index is not None: CNOT | (wavefunction[prev_index], wavefunction[qsubset[p]]) prev_index = qsubset[p] # 3. Rotation (Note kexp & Ntrot) Rz(evolution_time * 2) | wavefunction[prev_index] # 4. Second set of CNOTs prev_index = None for p in reversed(range(0, n_qubit)): pop = pauliword[p] # Pauli op if pop == 0: continue if prev_index is not None: CNOT | (wavefunction[qsubset[p]], wavefunction[prev_index]) prev_index = qsubset[p] # 5. Rotate back to Z basis for p in range(0, len(pauliword)): pop = pauliword[p] # Pauli op if pop == 1: H | wavefunction[qsubset[p]] # Hadamard elif pop == 2: Rx(-HALF_PI) | wavefunction[qsubset[p]]
def test_unitary_is_available(): sim = UnitarySimulator() qb0 = WeakQubitRef(engine=None, idx=0) qb1 = WeakQubitRef(engine=None, idx=1) qb2 = WeakQubitRef(engine=None, idx=2) qb3 = WeakQubitRef(engine=None, idx=2) qb4 = WeakQubitRef(engine=None, idx=2) qb5 = WeakQubitRef(engine=None, idx=2) qb6 = WeakQubitRef(engine=None, idx=2) assert sim.is_available(Command(None, Allocate, qubits=([qb0], ))) assert sim.is_available(Command(None, Deallocate, qubits=([qb0], ))) assert sim.is_available(Command(None, Measure, qubits=([qb0], ))) assert sim.is_available(Command(None, X, qubits=([qb0], ))) assert sim.is_available(Command(None, Rx(1.2), qubits=([qb0], ))) assert sim.is_available(Command(None, Rxx(1.2), qubits=([qb0, qb1], ))) assert sim.is_available(Command(None, X, qubits=([qb0], ), controls=[qb1])) assert sim.is_available( Command(None, X, qubits=([qb0], ), controls=[qb1], control_state='1')) assert not sim.is_available(Command(None, BasicGate(), qubits=([qb0], ))) assert not sim.is_available( Command(None, X, qubits=([qb0], ), controls=[qb1], control_state='0')) with pytest.warns(UserWarning): assert sim.is_available( Command( None, MatrixGate(np.identity(2**7)), qubits=([qb0, qb1, qb2, qb3, qb4, qb5, qb6], ), ))
def test_store_returns_correct_qasm(self): angle = 0.1 self.__store_function_assert_equal(0, NOT, "\nx q[0]") self.__store_function_assert_equal(1, NOT, "\ncnot q[0], q[1]", count=1) self.__store_function_assert_equal(0, Swap, "\nswap q[0], q[1]") self.__store_function_assert_equal(1, X, "\ntoffoli q[0], q[1], q[1]", count=2) self.__store_function_assert_equal(1, Z, "\ncz q[0], q[1]", count=1) self.__store_function_assert_equal(0, Barrier, "\n# barrier gate q[0], q[1];") self.__store_function_assert_equal( 1, Rz(angle), "\ncr q[0],q[1],{0:.12f}".format(angle), count=1) self.__store_function_assert_equal( 1, R(angle), "\ncr q[0],q[1],{0:.12f}".format(angle), count=1) self.__store_function_assert_equal(1, Rx(angle), "\nrx q[1],{0}".format(angle)) self.__store_function_assert_equal(1, Ry(angle), "\nry q[1],{0}".format(angle)) self.__store_function_assert_equal(1, Rz(angle), "\nrz q[1],{0}".format(angle)) self.__store_function_assert_equal(0, X, "\nx q[0]") self.__store_function_assert_equal(0, Y, "\ny q[0]") self.__store_function_assert_equal(0, Z, "\nz q[0]") self.__store_function_assert_equal(0, H, "\nh q[0]") self.__store_function_assert_equal(0, S, "\ns q[0]") self.__store_function_assert_equal(0, Sdag, "\nsdag q[0]") self.__store_function_assert_equal(0, T, "\nt q[0]") self.__store_function_assert_equal(0, Tdag, "\ntdag q[0]")
def test_tensor_or(): saving_backend = DummyEngine(save_commands=True) main_engine = MainEngine(backend=saving_backend, engine_list=[DummyEngine()]) gate = Rx(0.6) qubit0 = Qubit(main_engine, 0) qubit1 = Qubit(main_engine, 1) qubit2 = Qubit(main_engine, 2) # Option 1: _metagates.Tensor(gate) | ([qubit0, qubit1, qubit2], ) # Option 2: _metagates.Tensor(gate) | [qubit0, qubit1, qubit2] received_commands = [] # Remove Allocate and Deallocate gates for cmd in saving_backend.received_commands: if not (isinstance(cmd.gate, FastForwardingGate) or isinstance(cmd.gate, ClassicalInstructionGate)): received_commands.append(cmd) # Check results assert len(received_commands) == 6 qubit_ids = [] for cmd in received_commands: assert len(cmd.qubits) == 1 assert cmd.gate == gate qubit_ids.append(cmd.qubits[0][0].id) assert sorted(qubit_ids) == [0, 0, 1, 1, 2, 2]
def test_controlled_gate_or(): saving_backend = DummyEngine(save_commands=True) main_engine = MainEngine(backend=saving_backend, engine_list=[DummyEngine()]) gate = Rx(0.6) qubit0 = Qubit(main_engine, 0) qubit1 = Qubit(main_engine, 1) qubit2 = Qubit(main_engine, 2) qubit3 = Qubit(main_engine, 3) expected_cmd = Command(main_engine, gate, ([qubit3], )) expected_cmd.add_control_qubits([qubit0, qubit1, qubit2]) received_commands = [] # Option 1: _metagates.ControlledGate(gate, 3) | ([qubit1], [qubit0], [qubit2 ], [qubit3]) # Option 2: _metagates.ControlledGate(gate, 3) | (qubit1, qubit0, qubit2, qubit3) # Option 3: _metagates.ControlledGate(gate, 3) | ([qubit1, qubit0], qubit2, qubit3) # Option 4: _metagates.ControlledGate(gate, 3) | (qubit1, [qubit0, qubit2], qubit3) # Wrong option 5: with pytest.raises(_metagates.ControlQubitError): _metagates.ControlledGate(gate, 3) | (qubit1, [qubit0, qubit2, qubit3]) # Remove Allocate and Deallocate gates for cmd in saving_backend.received_commands: if not (isinstance(cmd.gate, FastForwardingGate) or isinstance(cmd.gate, ClassicalInstructionGate)): received_commands.append(cmd) assert len(received_commands) == 4 for cmd in received_commands: assert cmd == expected_cmd