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_qubit_management_error_when_loop_tag_supported(): backend = DummyEngine(save_commands=True) def allow_loop_tags(self, meta_tag): return meta_tag == _loop.LoopTag backend.is_meta_tag_handler = types.MethodType(allow_loop_tags, backend) eng = MainEngine(backend=backend, engine_list=[DummyEngine()]) with pytest.raises(_loop.QubitManagementError): with _loop.Loop(eng, 3): qb = eng.allocate_qubit()
def test_empty_loop_when_loop_tag_supported_by_backend(): backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[DummyEngine()]) def allow_loop_tags(self, meta_tag): return meta_tag == _loop.LoopTag backend.is_meta_tag_handler = types.MethodType(allow_loop_tags, backend) qubit = eng.allocate_qubit() assert len(backend.received_commands) == 1 with _loop.Loop(eng, 0): H | qubit assert len(backend.received_commands) == 1
def test_loop_with_supported_loop_tag_depending_on_num(): # Test that if loop has only one iteration, there is no loop tag backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[DummyEngine()]) def allow_loop_tags(self, meta_tag): return meta_tag == _loop.LoopTag backend.is_meta_tag_handler = types.MethodType(allow_loop_tags, backend) qubit = eng.allocate_qubit() with _loop.Loop(eng, 1): H | qubit with _loop.Loop(eng, 2): H | qubit assert len(backend.received_commands[1].tags) == 0 assert len(backend.received_commands[2].tags) == 1
def test_nested_loop(): backend = DummyEngine(save_commands=True) def allow_loop_tags(self, meta_tag): return meta_tag == _loop.LoopTag backend.is_meta_tag_handler = types.MethodType(allow_loop_tags, backend) eng = MainEngine(backend=backend, engine_list=[DummyEngine()]) qubit = eng.allocate_qubit() with _loop.Loop(eng, 3): with _loop.Loop(eng, 4): H | qubit eng.flush(deallocate_qubits=True) assert len(backend.received_commands) == 4 assert backend.received_commands[1].gate == H assert len(backend.received_commands[1].tags) == 2 assert backend.received_commands[1].tags[0].num == 4 assert backend.received_commands[1].tags[1].num == 3 assert (backend.received_commands[1].tags[0].id != backend.received_commands[1].tags[1].id)
def test_basic_engine_is_meta_tag_supported(): eng = _basics.BasicEngine() # BasicEngine needs receive function to function so let's add it: def receive(self, cmd_list): self.send(cmd_list) eng.receive = types.MethodType(receive, eng) backend = DummyEngine() engine0 = DummyEngine() engine1 = DummyEngine() engine2 = DummyEngine() def allow_dirty_qubits(self, meta_tag): if meta_tag == DirtyQubitTag: return True return False engine2.is_meta_tag_handler = types.MethodType(allow_dirty_qubits, engine2) main_engine = MainEngine(backend=backend, engine_list=[engine0, engine1, engine2]) assert not main_engine.is_meta_tag_supported("NotSupported") assert main_engine.is_meta_tag_supported(DirtyQubitTag)
def test_basic_engine_allocate_and_deallocate_qubit_and_qureg(): eng = _basics.BasicEngine() # custom receive function which checks that main_engine does not send # any allocate or deallocate gates cmd_sent_by_main_engine = [] def receive(self, cmd_list): cmd_sent_by_main_engine.append(cmd_list) eng.receive = types.MethodType(receive, eng) # Create test engines: saving_backend = DummyEngine(save_commands=True) main_engine = MainEngine(backend=saving_backend, engine_list=[eng, DummyEngine()]) # Allocate and deallocate qubits qubit = eng.allocate_qubit() # Try to allocate dirty qubit but it should give a non dirty qubit not_dirty_qubit = eng.allocate_qubit(dirty=True) # Allocate an actual dirty qubit def allow_dirty_qubits(self, meta_tag): if meta_tag == DirtyQubitTag: return True return False saving_backend.is_meta_tag_handler = types.MethodType(allow_dirty_qubits, saving_backend) dirty_qubit = eng.allocate_qubit(dirty=True) qureg = eng.allocate_qureg(2) # Test qubit allocation assert isinstance(qubit, list) assert len(qubit) == 1 and isinstance(qubit[0], Qubit) assert qubit[0] in main_engine.active_qubits assert id(qubit[0].engine) == id(eng) # Test non dirty qubit allocation assert isinstance(not_dirty_qubit, list) assert len(not_dirty_qubit) == 1 and isinstance(not_dirty_qubit[0], Qubit) assert not_dirty_qubit[0] in main_engine.active_qubits assert id(not_dirty_qubit[0].engine) == id(eng) # Test dirty_qubit allocation assert isinstance(dirty_qubit, list) assert len(dirty_qubit) == 1 and isinstance(dirty_qubit[0], Qubit) assert dirty_qubit[0] in main_engine.active_qubits assert dirty_qubit[0].id in main_engine.dirty_qubits assert id(dirty_qubit[0].engine) == id(eng) # Test qureg allocation assert isinstance(qureg, list) assert len(qureg) == 2 for tmp_qubit in qureg: assert tmp_qubit in main_engine.active_qubits assert id(tmp_qubit.engine) == id(eng) # Test uniqueness of ids assert len(set([qubit[0].id, not_dirty_qubit[0].id, dirty_qubit[0].id, qureg[0].id, qureg[1].id])) == 5 # Test allocate gates were sent assert len(cmd_sent_by_main_engine) == 0 assert len(saving_backend.received_commands) == 5 for cmd in saving_backend.received_commands: assert cmd.gate == AllocateQubitGate() assert saving_backend.received_commands[2].tags == [DirtyQubitTag()] # Test deallocate gates were sent eng.deallocate_qubit(qubit[0]) eng.deallocate_qubit(not_dirty_qubit[0]) eng.deallocate_qubit(dirty_qubit[0]) eng.deallocate_qubit(qureg[0]) eng.deallocate_qubit(qureg[1]) assert len(cmd_sent_by_main_engine) == 0 assert len(saving_backend.received_commands) == 10 for cmd in saving_backend.received_commands[5:]: assert cmd.gate == DeallocateQubitGate() assert saving_backend.received_commands[7].tags == [DirtyQubitTag()]
def test_compute_uncompute_with_statement(): # Allocating and deallocating qubit within Compute backend = DummyEngine(save_commands=True) compare_engine0 = CompareEngine() # Allow dirty qubits dummy_cengine = DummyEngine() def allow_dirty_qubits(self, meta_tag): return meta_tag == DirtyQubitTag dummy_cengine.is_meta_tag_handler = types.MethodType( allow_dirty_qubits, dummy_cengine) eng = MainEngine(backend=backend, engine_list=[compare_engine0, dummy_cengine]) qubit = eng.allocate_qubit() with _compute.Compute(eng): Rx(0.9) | qubit ancilla = eng.allocate_qubit(dirty=True) # ancilla2 will be deallocated in Uncompute section: ancilla2 = eng.allocate_qubit() # Test that ancilla is registered in MainEngine.active_qubits: assert ancilla[0] in eng.active_qubits H | qubit Rx(0.5) | ancilla CNOT | (ancilla, qubit) Rx(0.7) | qubit Rx(-0.5) | ancilla ancilla[0].__del__() H | qubit _compute.Uncompute(eng) eng.flush(deallocate_qubits=True) assert len(backend.received_commands) == 22 # Test each Command has correct gate assert backend.received_commands[0].gate == Allocate assert backend.received_commands[1].gate == Rx(0.9) assert backend.received_commands[2].gate == Allocate assert backend.received_commands[3].gate == Allocate assert backend.received_commands[4].gate == H assert backend.received_commands[5].gate == Rx(0.5) assert backend.received_commands[6].gate == NOT assert backend.received_commands[7].gate == Rx(0.7) assert backend.received_commands[8].gate == Rx(-0.5) assert backend.received_commands[9].gate == Deallocate assert backend.received_commands[10].gate == H assert backend.received_commands[11].gate == Allocate assert backend.received_commands[12].gate == Rx(0.5) assert backend.received_commands[13].gate == Rx(-0.7) assert backend.received_commands[14].gate == NOT assert backend.received_commands[15].gate == Rx(-0.5) assert backend.received_commands[16].gate == H assert backend.received_commands[17].gate == Deallocate assert backend.received_commands[18].gate == Deallocate assert backend.received_commands[19].gate == Rx(-0.9) assert backend.received_commands[20].gate == Deallocate assert backend.received_commands[21].gate == FlushGate() # Test that each command has correct tags assert backend.received_commands[0].tags == [] assert backend.received_commands[1].tags == [_compute.ComputeTag()] assert backend.received_commands[2].tags == [ DirtyQubitTag(), _compute.ComputeTag() ] for cmd in backend.received_commands[3:9]: assert cmd.tags == [_compute.ComputeTag()] assert backend.received_commands[9].tags == [ DirtyQubitTag(), _compute.ComputeTag() ] assert backend.received_commands[10].tags == [] assert backend.received_commands[11].tags == [ DirtyQubitTag(), _compute.UncomputeTag() ] for cmd in backend.received_commands[12:18]: assert cmd.tags == [_compute.UncomputeTag()] assert backend.received_commands[18].tags == [ DirtyQubitTag(), _compute.UncomputeTag() ] assert backend.received_commands[19].tags == [_compute.UncomputeTag()] assert backend.received_commands[20].tags == [] assert backend.received_commands[21].tags == [] # Test that each command has correct qubits # Note that ancilla qubit in compute should be # different from ancilla qubit in uncompute section qubit_id = backend.received_commands[0].qubits[0][0].id ancilla_compt_id = backend.received_commands[2].qubits[0][0].id ancilla_uncompt_id = backend.received_commands[11].qubits[0][0].id ancilla2_id = backend.received_commands[3].qubits[0][0].id assert backend.received_commands[1].qubits[0][0].id == qubit_id assert backend.received_commands[4].qubits[0][0].id == qubit_id assert backend.received_commands[5].qubits[0][0].id == ancilla_compt_id assert backend.received_commands[6].qubits[0][0].id == qubit_id assert ( backend.received_commands[6].control_qubits[0].id == ancilla_compt_id) assert backend.received_commands[7].qubits[0][0].id == qubit_id assert backend.received_commands[8].qubits[0][0].id == ancilla_compt_id assert backend.received_commands[9].qubits[0][0].id == ancilla_compt_id assert backend.received_commands[10].qubits[0][0].id == qubit_id assert backend.received_commands[12].qubits[0][0].id == ancilla_uncompt_id assert backend.received_commands[13].qubits[0][0].id == qubit_id assert backend.received_commands[14].qubits[0][0].id == qubit_id assert (backend.received_commands[14].control_qubits[0].id == ancilla_uncompt_id) assert backend.received_commands[15].qubits[0][0].id == ancilla_uncompt_id assert backend.received_commands[16].qubits[0][0].id == qubit_id assert backend.received_commands[17].qubits[0][0].id == ancilla2_id assert backend.received_commands[18].qubits[0][0].id == ancilla_uncompt_id assert backend.received_commands[19].qubits[0][0].id == qubit_id assert backend.received_commands[20].qubits[0][0].id == qubit_id # Test that ancilla qubits should have seperate ids assert ancilla_uncompt_id != ancilla_compt_id # Do the same thing with CustomUncompute and compare using the # CompareEngine: backend1 = DummyEngine(save_commands=True) compare_engine1 = CompareEngine() # Allow dirty qubits dummy_cengine1 = DummyEngine() def allow_dirty_qubits(self, meta_tag): return meta_tag == DirtyQubitTag dummy_cengine1.is_meta_tag_handler = types.MethodType( allow_dirty_qubits, dummy_cengine1) eng1 = MainEngine(backend=backend1, engine_list=[compare_engine1, dummy_cengine1]) qubit = eng1.allocate_qubit() with _compute.Compute(eng1): Rx(0.9) | qubit ancilla = eng1.allocate_qubit(dirty=True) # ancilla2 will be deallocated in Uncompute section: ancilla2 = eng1.allocate_qubit() # Test that ancilla is registered in MainEngine.active_qubits: assert ancilla[0] in eng1.active_qubits H | qubit Rx(0.5) | ancilla CNOT | (ancilla, qubit) Rx(0.7) | qubit Rx(-0.5) | ancilla ancilla[0].__del__() H | qubit with _compute.CustomUncompute(eng1): ancilla = eng1.allocate_qubit(dirty=True) Rx(0.5) | ancilla Rx(-0.7) | qubit CNOT | (ancilla, qubit) Rx(-0.5) | ancilla H | qubit assert ancilla[0] in eng1.active_qubits ancilla2[0].__del__() ancilla[0].__del__() Rx(-0.9) | qubit eng1.flush(deallocate_qubits=True) assert compare_engine0 == compare_engine1
def test_loop_with_supported_loop_tag_and_local_qubits(): backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[DummyEngine()]) def allow_loop_tags(self, meta_tag): return meta_tag == _loop.LoopTag backend.is_meta_tag_handler = types.MethodType(allow_loop_tags, backend) qubit = eng.allocate_qubit() H | qubit with _loop.Loop(eng, 6): ancilla = eng.allocate_qubit() ancilla2 = eng.allocate_qubit() H | ancilla2 H | ancilla CNOT | (ancilla, qubit) H | ancilla H | ancilla2 del ancilla2 del ancilla H | qubit eng.flush(deallocate_qubits=True) assert len(backend.received_commands) == 14 assert backend.received_commands[0].gate == Allocate assert backend.received_commands[1].gate == H assert backend.received_commands[2].gate == Allocate assert backend.received_commands[3].gate == Allocate assert backend.received_commands[4].gate == H assert backend.received_commands[5].gate == H assert backend.received_commands[6].gate == X assert backend.received_commands[7].gate == H assert backend.received_commands[8].gate == H assert backend.received_commands[9].gate == Deallocate assert backend.received_commands[10].gate == Deallocate assert backend.received_commands[11].gate == H assert backend.received_commands[12].gate == Deallocate assert backend.received_commands[13].gate == FlushGate() # Test qubit ids qubit_id = backend.received_commands[0].qubits[0][0].id ancilla_id = backend.received_commands[2].qubits[0][0].id ancilla2_id = backend.received_commands[3].qubits[0][0].id assert qubit_id != ancilla_id assert qubit_id != ancilla2_id assert ancilla_id != ancilla2_id assert backend.received_commands[1].qubits[0][0].id == qubit_id assert backend.received_commands[4].qubits[0][0].id == ancilla2_id assert backend.received_commands[5].qubits[0][0].id == ancilla_id assert backend.received_commands[6].qubits[0][0].id == qubit_id assert backend.received_commands[6].control_qubits[0].id == ancilla_id assert backend.received_commands[7].qubits[0][0].id == ancilla_id assert backend.received_commands[8].qubits[0][0].id == ancilla2_id assert backend.received_commands[9].qubits[0][0].id == ancilla2_id assert backend.received_commands[10].qubits[0][0].id == ancilla_id assert backend.received_commands[11].qubits[0][0].id == qubit_id assert backend.received_commands[12].qubits[0][0].id == qubit_id # Tags assert len(backend.received_commands[3].tags) == 1 loop_tag = backend.received_commands[3].tags[0] assert isinstance(loop_tag, _loop.LoopTag) assert loop_tag.num == 6 for ii in [0, 1, 11, 12, 13]: assert backend.received_commands[ii].tags == [] for ii in range(2, 9): assert backend.received_commands[ii].tags == [loop_tag]