Пример #1
0
def test_gate_filter():
    # BasicGate with no get_inverse used for testing:
    with pytest.raises(NotInvertible):
        TestGate.get_inverse()
    # Loading of decomposition rules:
    def decompose_test1(cmd):
        qb = cmd.qubits
        X | qb

    def recognize_test(cmd):
        return True

    register_decomposition(TestGate.__class__, decompose_test1, recognize_test)

    def decompose_test2(cmd):
        qb = cmd.qubits
        H | qb

    register_decomposition(TestGate.__class__, decompose_test2, recognize_test)

    assert len(decompositions[TestGate.__class__.__name__]) == 2

    # Filter which doesn't allow TestGate
    def test_gate_filter_func(self, cmd):
        if cmd.gate == TestGate:
            return False
        return True

    return _replacer.InstructionFilter(test_gate_filter_func)
Пример #2
0
def test_auto_replacer_use_inverse_decomposition():
    # Check that if there is no decomposition for the gate, that
    # AutoReplacer runs the decomposition for the inverse gate in reverse

    # Create test gate and inverse
    class NoMagicGate(BasicGate):
        pass

    class MagicGate(BasicGate):
        def get_inverse(self):
            return NoMagicGate()

    def decompose_no_magic_gate(cmd):
        qb = cmd.qubits
        Rx(0.6) | qb
        H | qb

    def recognize_no_magic_gate(cmd):
        return True

    register_decomposition(NoMagicGate, decompose_no_magic_gate,
                           recognize_no_magic_gate)

    def magic_filter(self, cmd):
        if cmd.gate == MagicGate():
            return False
        return True

    backend = DummyEngine(save_commands=True)
    eng = MainEngine(backend=backend,
                     engine_list=[
                         _replacer.AutoReplacer(),
                         _replacer.InstructionFilter(magic_filter)
                     ])
    assert len(backend.received_commands) == 0
    qb = eng.allocate_qubit()
    MagicGate() | qb
    eng.flush()
    for cmd in backend.received_commands:
        print(cmd)
    assert len(backend.received_commands) == 4
    assert backend.received_commands[1].gate == H
    assert backend.received_commands[2].gate == Rx(-0.6)
Пример #3
0
from ._gates import (AddConstant, SubConstant, AddConstantModN,
                     SubConstantModN, MultiplyByConstantModN)
from ._constantmath import (add_constant, add_constant_modN,
                            mul_by_constant_modN)


def _replace_addconstant(cmd):
    eng = cmd.engine
    c = cmd.gate.a
    quint = cmd.qubits[0]

    with Control(eng, cmd.control_qubits):
        add_constant(eng, c, quint)


register_decomposition(AddConstant, _replace_addconstant)


def _replace_addconstmodN(cmd):
    eng = cmd.engine
    c = cmd.gate.a
    N = cmd.gate.N
    quint = cmd.qubits[0]

    with Control(eng, cmd.control_qubits):
        add_constant_modN(eng, c, N, quint)


register_decomposition(AddConstantModN, _replace_addconstmodN)

Пример #4
0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
"""
Registers a decomposition to achieve a Swap gate.

Decomposes a Swap gate using 3 CNOT gates, where the one in the middle
features as many control qubits as the Swap gate has control qubits.
"""

from projectq.cengines import register_decomposition
from projectq.meta import Compute, Uncompute, Control, get_control_count
from projectq.ops import Swap, CNOT


def _decompose_swap(cmd):
    """ Decompose (controlled) swap gates. """
    ctrl = cmd.control_qubits
    eng = cmd.engine
    with Compute(eng):
        CNOT | (cmd.qubits[0], cmd.qubits[1])
    with Control(eng, ctrl):
        CNOT | (cmd.qubits[1], cmd.qubits[0])
    Uncompute(eng)


register_decomposition(Swap.__class__, _decompose_swap)
Пример #5
0
#   See the License for the specific language governing permissions and
#   limitations under the License.
"""
Registers a decomposition for the controlled global phase gate.

Turns the controlled global phase gate into a (controlled) phase-shift gate.
Each time this rule is applied, one control can be shaved off.
"""

from projectq.cengines import register_decomposition
from projectq.meta import Control, get_control_count
from projectq.ops import Ph, R


def _decompose_Ph(cmd):
    """ Decompose the controlled phase gate (C^nPh(phase)). """
    ctrl = cmd.control_qubits
    gate = cmd.gate
    eng = cmd.engine

    with Control(eng, ctrl[1:]):
        R(gate._angle) | ctrl[0]


def _recognize_Ph(cmd):
    """ Recognize the controlled phase gate. """
    return get_control_count(cmd) >= 1


register_decomposition(Ph, _decompose_Ph, _recognize_Ph)
Пример #6
0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
"""
Registers a decomposition rule for the phase-shift gate.

Decomposes the (controlled) phase-shift gate using z-rotation and a global
phase gate.
"""

from projectq.cengines import register_decomposition
from projectq.meta import Control
from projectq.ops import Ph, Rz, R


def _decompose_R(cmd):
    """ Decompose the (controlled) phase-shift gate, denoted by R(phase). """
    ctrl = cmd.control_qubits
    eng = cmd.engine
    gate = cmd.gate

    with Control(eng, ctrl):
        Ph(.5 * gate._angle) | cmd.qubits
        Rz(gate._angle) | cmd.qubits


register_decomposition(R, _decompose_R)
Пример #7
0
    ctrl = cmd.control_qubits
    eng = cmd.engine

    target = cmd.qubits[0]
    c1 = ctrl[0]
    c2 = ctrl[1]

    H | target
    CNOT | (c1, target)
    T | c1
    Tdag | target
    CNOT | (c2, target)
    CNOT | (c2, c1)
    Tdag | c1
    T | target
    CNOT | (c2, c1)
    CNOT | (c1, target)
    Tdag | target
    CNOT | (c2, target)
    T | target
    T | c2
    H | target


def _recognize_toffoli(cmd):
    """ Recognize the Toffoli gate. """
    return get_control_count(cmd) == 2


register_decomposition(NOT.__class__, _decompose_toffoli, _recognize_toffoli)
Пример #8
0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
"""
Registers a decomposition for the Entangle gate.

Applies a Hadamard gate to the first qubit and then, conditioned on this first
qubit, CNOT gates to all others.
"""

from projectq.cengines import register_decomposition
from projectq.meta import Control, get_control_count
from projectq.ops import X, H, Entangle, All


def _decompose_entangle(cmd):
    """ Decompose the entangle gate. """
    qr = cmd.qubits[0]
    eng = cmd.engine

    with Control(eng, cmd.control_qubits):
        H | qr[0]
        with Control(eng, qr[0]):
            All(X) | qr[1:]


register_decomposition(Entangle.__class__, _decompose_entangle)
Пример #9
0
#   limitations under the License.
"""
Registers a decomposition rule for the quantum Fourier transform.

Decomposes the QFT gate into Hadamard and controlled phase-shift gates (R).

Warning:
	The final Swaps are not included, as those are simply a re-indexing of
	quantum registers.
"""

import math

from projectq.cengines import register_decomposition
from projectq.ops import H, R, QFT
from projectq.meta import Control


def _decompose_QFT(cmd):
    qb = cmd.qubits[0]
    eng = cmd.engine
    with Control(eng, cmd.control_qubits):
        for i in range(len(qb)):
            H | qb[-1 - i]
            for j in range(len(qb) - 1 - i):
                with Control(eng, qb[-1 - (j + i + 1)]):
                    R(math.pi / (1 << (1 + j))) | qb[-1 - i]


register_decomposition(QFT.__class__, _decompose_QFT)
Пример #10
0
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
"""
Registers a decomposition rule for global phases.

Deletes global phase gates (which can be ignored).
"""

from projectq.cengines import register_decomposition
from projectq.meta import get_control_count
from projectq.ops import Ph


def _decompose_PhNoCtrl(cmd):
    """ Throw out global phases (no controls). """
    pass


def _recognize_PhNoCtrl(cmd):
    """ Recognize global phases (no controls). """
    return get_control_count(cmd) == 0


register_decomposition(Ph, _decompose_PhNoCtrl, _recognize_PhNoCtrl)
Пример #11
0
"""
Registers a decomposition for controlled z-rotation gates.

It uses 2 z-rotations and 2 C^n NOT gates to achieve this gate.
"""

from projectq.cengines import register_decomposition
from projectq.meta import get_control_count
from projectq.ops import NOT, Rz, C


def _decompose_CRz(cmd):
    """ Decompose the controlled Rz gate (into CNOT and Rz). """
    qubit = cmd.qubits[0]
    ctrl = cmd.control_qubits
    gate = cmd.gate
    n = get_control_count(cmd)

    Rz(0.5 * gate._angle) | qubit
    C(NOT, n) | (ctrl, qubit)
    Rz(-0.5 * gate._angle) | qubit
    C(NOT, n) | (ctrl, qubit)


def _recognize_CRz(cmd):
    """ Recognize the controlled Rz gate. """
    return get_control_count(cmd) >= 1


register_decomposition(Rz, _decompose_CRz, _recognize_CRz)