Beispiel #1
0
 def test_QFT(self, inverse):
     """Test if the QFT matrix is equal to a manually-calculated version for 3 qubits"""
     op = qml.QFT(wires=range(3)).inv() if inverse else qml.QFT(
         wires=range(3))
     res = op.matrix
     exp = QFT.conj().T if inverse else QFT
     assert np.allclose(res, exp)
Beispiel #2
0
    def test_expected_tape(self):
        """Tests if QuantumPhaseEstimation populates the tape as expected for a fixed example"""

        m = qml.RX(0.3, wires=0).matrix

        op = qml.QuantumPhaseEstimation(m,
                                        target_wires=[0],
                                        estimation_wires=[1, 2])
        tape = op.expand()

        with qml.tape.QuantumTape() as tape2:
            qml.Hadamard(1),
            qml.ControlledQubitUnitary(m @ m, control_wires=[1], wires=[0]),
            qml.Hadamard(2),
            qml.ControlledQubitUnitary(m, control_wires=[2], wires=[0]),
            qml.QFT(wires=[1, 2]).inv()

        assert len(tape2.queue) == len(tape.queue)
        assert all([
            op1.name == op2.name for op1, op2 in zip(tape.queue, tape2.queue)
        ])
        assert all([
            op1.wires == op2.wires for op1, op2 in zip(tape.queue, tape2.queue)
        ])
        assert np.allclose(tape.queue[1].matrix, tape2.queue[1].matrix)
        assert np.allclose(tape.queue[3].matrix, tape2.queue[3].matrix)
Beispiel #3
0
 def circuit(x, z):
     qml.QFT(wires=(0, 1, 2, 3))
     qml.Toffoli(wires=(0, 1, 2))
     qml.CSWAP(wires=(0, 2, 3))
     qml.RX(x, wires=0)
     qml.CRZ(z, wires=(3, 0))
     return qml.expval(qml.PauliZ(0))
Beispiel #4
0
    def test_QFT_adjoint_decomposition(self, n_qubits):  # tol
        """Test if the QFT adjoint operation has the right decomposition"""

        # QFT adjoint has right decompositions
        qft = qml.QFT(wires=range(n_qubits))
        qft_dec = qft.expand().operations

        expected_op = [x.adjoint() for x in qft_dec]
        expected_op.reverse()

        adj = qml.QFT(wires=range(n_qubits)).adjoint()
        op = adj.expand().operations

        for j in range(0, len(op)):
            assert op[j].name == expected_op[j].name
            assert op[j].wires == expected_op[j].wires
            assert op[j].parameters == expected_op[j].parameters
Beispiel #5
0
    def test_notches(self, wires, n):
        """Test notches are included when non-active wires exist."""

        with QuantumTape() as tape:
            qml.QFT(wires=wires)

        _, ax = tape_mpl(tape, show_all_wires=True, wire_order=[0, 1, 2])
        assert len(ax.patches) == (n + 1)
        plt.close()
Beispiel #6
0
    def test_QFT_decomposition(self, n_qubits):
        """Test if the QFT operation is correctly decomposed"""
        op = qml.QFT(wires=range(n_qubits))
        decomp = op.decompose()

        dev = qml.device("default.qubit", wires=n_qubits)

        out_states = []
        for state in np.eye(2**n_qubits):
            dev.reset()
            ops = [qml.QubitStateVector(state, wires=range(n_qubits))] + decomp
            dev.apply(ops)
            out_states.append(dev.state)

        reconstructed_unitary = np.array(out_states).T
        expected_unitary = qml.QFT(wires=range(n_qubits)).matrix

        assert np.allclose(reconstructed_unitary, expected_unitary)
Beispiel #7
0
def qfunc_adder(m, wires):
    """Quantum function capable of adding m units to a basic state given as input.

    Args:
        - m (int): units to add.
        - wires (list(int)): list of wires in which the function will be executed on.
    """

    qml.QFT(wires=wires)

    # QHACK #

    nwires = len(wires)
    for i in range(nwires):
        qml.RZ(2**i / 2**nwires * 2 * np.pi * m, wires=(nwires - i - 1))

    # QHACK #

    qml.QFT(wires=wires).inv()
Beispiel #8
0
def op(op_name):
    ops_list = {
        "RX": qml.RX(0.123, wires=0),
        "RY": qml.RY(1.434, wires=0),
        "RZ": qml.RZ(2.774, wires=0),
        "S": qml.S(wires=0),
        "SX": qml.SX(wires=0),
        "T": qml.T(wires=0),
        "CNOT": qml.CNOT(wires=[0, 1]),
        "CZ": qml.CZ(wires=[0, 1]),
        "CY": qml.CY(wires=[0, 1]),
        "SWAP": qml.SWAP(wires=[0, 1]),
        "ISWAP": qml.ISWAP(wires=[0, 1]),
        "SISWAP": qml.SISWAP(wires=[0, 1]),
        "SQISW": qml.SQISW(wires=[0, 1]),
        "CSWAP": qml.CSWAP(wires=[0, 1, 2]),
        "PauliRot": qml.PauliRot(0.123, "Y", wires=0),
        "IsingXX": qml.IsingXX(0.123, wires=[0, 1]),
        "IsingXY": qml.IsingXY(0.123, wires=[0, 1]),
        "IsingYY": qml.IsingYY(0.123, wires=[0, 1]),
        "IsingZZ": qml.IsingZZ(0.123, wires=[0, 1]),
        "Identity": qml.Identity(wires=0),
        "Rot": qml.Rot(0.123, 0.456, 0.789, wires=0),
        "Toffoli": qml.Toffoli(wires=[0, 1, 2]),
        "PhaseShift": qml.PhaseShift(2.133, wires=0),
        "ControlledPhaseShift": qml.ControlledPhaseShift(1.777, wires=[0, 2]),
        "CPhase": qml.CPhase(1.777, wires=[0, 2]),
        "MultiRZ": qml.MultiRZ(0.112, wires=[1, 2, 3]),
        "CRX": qml.CRX(0.836, wires=[2, 3]),
        "CRY": qml.CRY(0.721, wires=[2, 3]),
        "CRZ": qml.CRZ(0.554, wires=[2, 3]),
        "Hadamard": qml.Hadamard(wires=0),
        "PauliX": qml.PauliX(wires=0),
        "PauliY": qml.PauliY(wires=0),
        "PauliZ": qml.PauliZ(wires=0),
        "CRot": qml.CRot(0.123, 0.456, 0.789, wires=[0, 1]),
        "DiagonalQubitUnitary": qml.DiagonalQubitUnitary(np.array([1.0, 1.0j]), wires=1),
        "ControlledQubitUnitary": qml.ControlledQubitUnitary(
            np.eye(2) * 1j, wires=[0], control_wires=[2]
        ),
        "MultiControlledX": qml.MultiControlledX(wires=(0, 1, 2), control_values="01"),
        "SingleExcitation": qml.SingleExcitation(0.123, wires=[0, 3]),
        "SingleExcitationPlus": qml.SingleExcitationPlus(0.123, wires=[0, 3]),
        "SingleExcitationMinus": qml.SingleExcitationMinus(0.123, wires=[0, 3]),
        "DoubleExcitation": qml.DoubleExcitation(0.123, wires=[0, 1, 2, 3]),
        "DoubleExcitationPlus": qml.DoubleExcitationPlus(0.123, wires=[0, 1, 2, 3]),
        "DoubleExcitationMinus": qml.DoubleExcitationMinus(0.123, wires=[0, 1, 2, 3]),
        "QFT": qml.QFT(wires=0),
        "QubitSum": qml.QubitSum(wires=[0, 1, 2]),
        "QubitCarry": qml.QubitCarry(wires=[0, 1, 2, 3]),
        "QubitUnitary": qml.QubitUnitary(np.eye(2) * 1j, wires=0),
    }
    return ops_list.get(op_name)
Beispiel #9
0
    def test_active_wire_notches_False(self):
        """Test active wire notches are disable with active_wire_notches=False."""

        with QuantumTape() as tape:
            qml.QFT(wires=(0, 3))

        _, ax = tape_mpl(tape,
                         show_all_wires=True,
                         wire_order=[0, 1, 2, 3],
                         active_wire_notches=False)

        assert len(ax.patches) == 1
Beispiel #10
0
    def test_QFT_adjoint_method(self, num_inversions):
        """Test the adjoint method of the QFT class"""
        op = qml.QFT(wires=range(3))

        for _ in range(num_inversions):
            op = op.adjoint()

        res = op.matrix
        inverse = num_inversions % 2 == 1
        exp = QFT.conj().T if inverse else QFT
        assert np.allclose(res, exp)
        assert op.inverse is inverse
Beispiel #11
0
    def expand(self):
        unitary = self.parameters[0]
        unitary_powers = [unitary]

        for _ in range(len(self.estimation_wires) - 1):
            new_power = unitary_powers[-1] @ unitary_powers[-1]
            unitary_powers.append(new_power)

        with qml.tape.QuantumTape() as tape:
            for wire in self.estimation_wires:
                qml.Hadamard(wire)
                qml.ControlledQubitUnitary(unitary_powers.pop(),
                                           control_wires=wire,
                                           wires=self.target_wires)

            qml.QFT(wires=self.estimation_wires).inv()

        return tape
Beispiel #12
0
def QuantumPhaseEstimation(unitary, target_wires, estimation_wires):
    r"""Performs the
    `quantum phase estimation <https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm>`__
    circuit.

    Given a unitary matrix :math:`U`, this template applies the circuit for quantum phase
    estimation. The unitary is applied to the qubits specified by ``target_wires`` and :math:`n`
    qubits are used for phase estimation as specified by ``estimation_wires``.

    .. figure:: ../../_static/templates/subroutines/qpe.svg
        :align: center
        :width: 60%
        :target: javascript:void(0);

    This circuit can be used to perform the standard quantum phase estimation algorithm, consisting
    of the following steps:

    #. Prepare ``target_wires`` in a given state. If ``target_wires`` are prepared in an eigenstate
       of :math:`U` that has corresponding eigenvalue :math:`e^{2 \pi i \theta}` with phase
       :math:`\theta \in [0, 1)`, this algorithm will measure :math:`\theta`. Other input states can
       be prepared more generally.
    #. Apply the ``QuantumPhaseEstimation`` circuit.
    #. Measure ``estimation_wires`` using :func:`~.probs`, giving a probability distribution over
       measurement outcomes in the computational basis.
    #. Find the index of the largest value in the probability distribution and divide that number by
       :math:`2^{n}`. This number will be an estimate of :math:`\theta` with an error that decreases
       exponentially with the number of qubits :math:`n`.

    Note that if :math:`\theta \in (-1, 0]`, we can estimate the phase by again finding the index
    :math:`i` found in step 4 and calculating :math:`\theta \approx \frac{1 - i}{2^{n}}`. The
    usage details below give an example of this case.

    Args:
        unitary (array): the phase estimation unitary, specified as a matrix
        target_wires (Union[Wires, Sequence[int], or int]): the target wires to apply the unitary
        estimation_wires (Union[Wires, Sequence[int], or int]): the wires to be used for phase
            estimation

    Raises:
        QuantumFunctionError: if the ``target_wires`` and ``estimation_wires`` share a common
            element

    .. UsageDetails::

        Consider the matrix corresponding to a rotation from an :class:`~.RX` gate:

        .. code-block:: python

            import pennylane as qml
            from pennylane.templates import QuantumPhaseEstimation
            from pennylane import numpy as np

            phase = 5
            target_wires = [0]
            unitary = qml.RX(phase, wires=0).matrix

        The ``phase`` parameter can be estimated using ``QuantumPhaseEstimation``. An example is
        shown below using a register of five phase-estimation qubits:

        .. code-block:: python

            n_estimation_wires = 5
            estimation_wires = range(1, n_estimation_wires + 1)

            dev = qml.device("default.qubit", wires=n_estimation_wires + 1)

            @qml.qnode(dev)
            def circuit():
                # Start in the |+> eigenstate of the unitary
                qml.Hadamard(wires=target_wires)

                QuantumPhaseEstimation(
                    unitary,
                    target_wires=target_wires,
                    estimation_wires=estimation_wires,
                )

                return qml.probs(estimation_wires)

            phase_estimated = np.argmax(circuit()) / 2 ** n_estimation_wires

            # Need to rescale phase due to convention of RX gate
            phase_estimated = 4 * np.pi * (1 - phase_estimated)
    """

    target_wires = Wires(target_wires)
    estimation_wires = Wires(estimation_wires)

    if len(Wires.shared_wires([target_wires, estimation_wires])) != 0:
        raise qml.QuantumFunctionError(
            "The target wires and estimation wires must be different")

    unitary_powers = [unitary]

    for _ in range(len(estimation_wires) - 1):
        new_power = unitary_powers[-1] @ unitary_powers[-1]
        unitary_powers.append(new_power)

    for wire in estimation_wires:
        qml.Hadamard(wire)
        qml.ControlledQubitUnitary(unitary_powers.pop(),
                                   control_wires=wire,
                                   wires=target_wires)

    qml.QFT(wires=estimation_wires).inv()
Beispiel #13
0
 def temp_circ():
     qml.QFT(wires=(0, 1.23))
     return qml.probs(0)
Beispiel #14
0
 def qfunc1():
     qml.RX(2, wires=0)
     qml.RY(-3, wires=1)
     qml.QFT(wires=[0, 1, 2])
     qml.SWAP(wires=[1, 2])
     return qml.state()
Beispiel #15
0
 def circ(n_qubits):
     qml.adjoint(qml.QFT)(wires=range(n_qubits))
     qml.QFT(wires=range(n_qubits))
     return qml.state()
Beispiel #16
0
 def qfunc2():
     qml.RX(2, wires=0)
     qml.RY(-3, wires=2)
     qml.QFT(wires=[0, 2, 1])
     return qml.state()
Beispiel #17
0
        # two wire labels, so CRX is third text object
        assert ax.texts[2].get_text() == "RX\n(1.23)"
        plt.close()


general_op_data = [
    qml.RX(1.234, wires=0),
    qml.Hadamard(0),
    qml.S(wires=0),
    qml.IsingXX(1.234, wires=(0, 1)),
    qml.U3(1.234, 2.345, 3.456, wires=0),
    # State Prep
    qml.BasisState([0, 1, 0], wires=(0, 1, 2)),
    ### Templates
    qml.QFT(wires=range(3)),
    qml.Permute([4, 2, 0, 1, 3], wires=(0, 1, 2, 3, 4)),
    qml.GroverOperator(wires=(0, 1, 2, 3, 4, 5)),
    ### Continuous Variable
    qml.Kerr(1.234, wires=0),
    qml.Beamsplitter(1.234, 2.345, wires=(0, 1)),
    qml.Rotation(1.234, wires=0),
]


class TestGeneralOperations:
    """Tests general operations."""

    width = 0.75 - 2 * 0.2

    @pytest.mark.parametrize("op", general_op_data)
Beispiel #18
0
    "PhaseShift": qml.PhaseShift(0, wires=[0]),
    "ControlledPhaseShift": qml.ControlledPhaseShift(0, wires=[0, 1]),
    "QubitStateVector": qml.QubitStateVector(np.array([1.0, 0.0]), wires=[0]),
    "QubitUnitary": qml.QubitUnitary(np.eye(2), wires=[0]),
    "ControlledQubitUnitary": qml.ControlledQubitUnitary(np.eye(2), control_wires=[1], wires=[0]),
    "MultiControlledX": qml.MultiControlledX(control_wires=[1, 2], wires=[0]),
    "RX": qml.RX(0, wires=[0]),
    "RY": qml.RY(0, wires=[0]),
    "RZ": qml.RZ(0, wires=[0]),
    "Rot": qml.Rot(0, 0, 0, wires=[0]),
    "S": qml.S(wires=[0]),
    "SWAP": qml.SWAP(wires=[0, 1]),
    "T": qml.T(wires=[0]),
    "SX": qml.SX(wires=[0]),
    "Toffoli": qml.Toffoli(wires=[0, 1, 2]),
    "QFT": qml.QFT(wires=[0, 1, 2]),
    "SingleExcitation": qml.SingleExcitation(0, wires=[0, 1]),
    "SingleExcitationPlus": qml.SingleExcitationPlus(0, wires=[0, 1]),
    "SingleExcitationMinus": qml.SingleExcitationMinus(0, wires=[0, 1]),
    "DoubleExcitation": qml.DoubleExcitation(0, wires=[0, 1, 2, 3]),
    "DoubleExcitationPlus": qml.DoubleExcitationPlus(0, wires=[0, 1, 2, 3]),
    "DoubleExcitationMinus": qml.DoubleExcitationMinus(0, wires=[0, 1, 2, 3]),
    "QubitCarry": qml.QubitCarry(wires=[0, 1, 2, 3]),
    "QubitSum:": qml.QubitSum(wires=[0, 1, 2]),
}

all_ops = ops.keys()

# non-parametrized qubit gates
I = np.identity(2)
X = np.array([[0, 1], [1, 0]])
Beispiel #19
0
    fig.suptitle("My Circuit", fontsize="xx-large")

    options = {'facecolor': "white", 'edgecolor': "#f57e7e", "linewidth": 6, "zorder": -1}
    box1 = plt.Rectangle((-0.5, -0.5), width=3.0, height=4.0, **options)
    ax.add_patch(box1)

    ax.annotate("CSWAP", xy=(3, 2.5), xycoords='data', xytext=(3.8,1.5), textcoords='data',
                arrowprops={'facecolor': 'black'}, fontsize=14)

    plt.savefig(folder / "postprocessing.png")
    plt.close()

if __name__ == "__main__":

    with qml.tape.QuantumTape() as tape:
        qml.QFT(wires=(0,1,2,3))
        qml.IsingXX(1.234, wires=(0,2))
        qml.Toffoli(wires=(0,1,2))
        qml.CSWAP(wires=(0,2,3))
        qml.RX(1.2345, wires=0)
        qml.CRZ(1.2345, wires=(3,0))
        qml.expval(qml.PauliZ(0))

    default(tape)
    decimals()
    wire_order(tape)
    show_all_wires(tape)
    use_style(tape)
    rcparams(tape)
    wires_and_labels(tape)
    postprocessing(tape)