Ejemplo n.º 1
0
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()]
Ejemplo n.º 2
0
def test_control_engine_has_compute_tag():
    eng = MainEngine(backend=DummyEngine(), engine_list=[DummyEngine()])
    qubit = eng.allocate_qubit()
    test_cmd0 = Command(eng, H, (qubit,))
    test_cmd1 = Command(eng, H, (qubit,))
    test_cmd2 = Command(eng, H, (qubit,))
    test_cmd0.tags = [DirtyQubitTag(), ComputeTag(), DirtyQubitTag()]
    test_cmd1.tags = [DirtyQubitTag(), UncomputeTag(), DirtyQubitTag()]
    test_cmd2.tags = [DirtyQubitTag()]
    assert _control._has_compute_uncompute_tag(test_cmd0)
    assert _control._has_compute_uncompute_tag(test_cmd1)
    assert not _control._has_compute_uncompute_tag(test_cmd2)
Ejemplo n.º 3
0
    def deallocate_qubit(self, qubit):
        """
        Deallocate a qubit (and sends the deallocation command down the
        pipeline). If the qubit was allocated as a dirty qubit, add
        DirtyQubitTag() to Deallocate command.

        Args:
            qubit (BasicQubit): Qubit to deallocate.
        Raises:
            ValueError: Qubit already deallocated. Caller likely has a bug.
        """
        if qubit.id == -1:
            raise ValueError("Already deallocated.")

        is_dirty = qubit.id in self.dirty_qubits
        weak_copy = WeakQubitRef(qubit.engine, qubit.id)

        if not isinstance(qubit, WeakQubitRef):
            if qubit in self.active_qubits:
                self.active_qubits.remove(qubit)
                qubit.id = -1

        from projectq.meta import DirtyQubitTag
        self.send([
            Command(self,
                    Deallocate, (Qureg([weak_copy]), ),
                    tags=[DirtyQubitTag()] if is_dirty else [])
        ])
Ejemplo n.º 4
0
    def allocate_qubit(self, dirty=False):
        """
        Return a new qubit as a list containing 1 qubit object (quantum register of size 1).

        Allocates a new qubit by getting a (new) qubit id from the MainEngine, creating the qubit object, and then
        sending an AllocateQubit command down the pipeline. If dirty=True, the fresh qubit can be replaced by a
        pre-allocated one (in an unknown, dirty, initial state). Dirty qubits must be returned to their initial states
        before they are deallocated / freed.

        All allocated qubits are added to the MainEngine's set of active qubits as weak references. This allows proper
        clean-up at the end of the Python program (using atexit), deallocating all qubits which are still alive. Qubit
        ids of dirty qubits are registered in MainEngine's dirty_qubits set.

        Args:
            dirty (bool): If True, indicates that the allocated qubit may be
                dirty (i.e., in an arbitrary initial state).

        Returns:
            Qureg of length 1, where the first entry is the allocated qubit.
        """
        new_id = self.main_engine.get_new_qubit_id()
        qb = Qureg([Qubit(self, new_id)])
        cmd = Command(self, Allocate, (qb, ))
        if dirty:
            from projectq.meta import (  # pylint: disable=import-outside-toplevel
                DirtyQubitTag, )

            if self.is_meta_tag_supported(DirtyQubitTag):
                cmd.tags += [DirtyQubitTag()]
                self.main_engine.dirty_qubits.add(qb[0].id)
        self.main_engine.active_qubits.add(qb[0])
        self.send([cmd])
        return qb
Ejemplo n.º 5
0
    def deallocate_qubit(self, qubit):
        """
        Deallocate a qubit (and sends the deallocation command down the pipeline).

        If the qubit was allocated as a dirty qubit, add DirtyQubitTag() to Deallocate command.

        Args:
            qubit (BasicQubit): Qubit to deallocate.
        Raises:
            ValueError: Qubit already deallocated. Caller likely has a bug.
        """
        if qubit.id == -1:
            raise ValueError("Already deallocated.")

        from projectq.meta import (  # pylint: disable=import-outside-toplevel
            DirtyQubitTag, )

        is_dirty = qubit.id in self.main_engine.dirty_qubits
        self.send([
            Command(
                self,
                Deallocate,
                ([WeakQubitRef(engine=qubit.engine, idx=qubit.id)], ),
                tags=[DirtyQubitTag()] if is_dirty else [],
            )
        ])
        # Mark qubit as deallocated
        qubit.id = -1
Ejemplo n.º 6
0
    def deallocate_qubit(self, qubit):
        """
        Deallocate a qubit (and sends the deallocation command down the
        pipeline). If the qubit was allocated as a dirty qubit, add
        DirtyQubitTag() to Deallocate command.

        Args:
            qubit (BasicQubit): Qubit to deallocate.
        Raises:
            ValueError: Qubit already deallocated. Caller likely has a bug.
        """
        if qubit.id == -1:
            raise ValueError("Already deallocated.")

        from projectq.meta import DirtyQubitTag
        is_dirty = qubit.id in self.main_engine.dirty_qubits
        self.send([Command(self,
                           Deallocate,
                           (Qureg([qubit]),),
                           tags=[DirtyQubitTag()] if is_dirty else [])])
Ejemplo n.º 7
0
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()]
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
 def cmd_modifier(cmd):
     assert (cmd.gate == Deallocate)
     cmd.tags += [DirtyQubitTag()]
     return cmd