Example #1
0
def decompose_ua(phi, wires=None):
    r"""Implements the circuit decomposing the controlled application of the unitary
    :math:`U_A(\phi)`

    .. math::

        U_A(\phi) = \left(\begin{array}{cc} 0 & e^{-i\phi} \\ e^{-i\phi} & 0 \\ \end{array}\right)

    in terms of the quantum operations supported by PennyLane.

    :math:`U_A(\phi)` is used in `arXiv:1805.04340 <https://arxiv.org/abs/1805.04340>`_,
    to define two-qubit exchange gates required to build particle-conserving
    VQE ansatze for quantum chemistry simulations. See :func:`~.ParticleConservingU1`.

    :math:`U_A(\phi)` is expressed in terms of ``PhaseShift``, ``Rot`` and ``PauliZ`` operations
    :math:`U_A(\phi) = R_\phi(-2\phi) R(-\phi, \pi, \phi) \sigma_z`.

    Args:
        phi (float): angle :math:`\phi` defining the unitary :math:`U_A(\phi)`
        wires (Iterable): the wires ``n`` and ``m`` the circuit acts on
    """

    n, m = wires

    qml.CZ(wires=wires)
    qml.CRot(-phi, np.pi, phi, wires=wires)

    # decomposition of C-PhaseShift(2*phi) gate
    qml.PhaseShift(-phi, wires=m)
    qml.CNOT(wires=wires)
    qml.PhaseShift(phi, wires=m)
    qml.CNOT(wires=wires)
    qml.PhaseShift(-phi, wires=n)
Example #2
0
 def decomposition(wires):
     decomp_ops = [
         qml.PhaseShift(np.pi / 2, wires=wires),
         qml.RX(np.pi / 2, wires=wires),
         qml.PhaseShift(np.pi / 2, wires=wires),
     ]
     return decomp_ops
Example #3
0
    def test_with_qfunc_op(self):
        """Test if the transform works as expected if the operation is a qfunc rather than single
        operation"""
        def op(x, y, wires):
            qml.RX(x, wires=wires)
            qml.PhaseShift(y, wires=wires)

        tape = insert(op, [0.4, 0.5], position="end")(self.tape)

        with QuantumTape() as tape_exp:
            qml.RX(0.9, wires=0)
            qml.RY(0.4, wires=1)
            qml.CNOT(wires=[0, 1])
            qml.RY(0.5, wires=0)
            qml.RX(0.6, wires=1)
            qml.RX(0.4, wires=0)
            qml.PhaseShift(0.5, wires=0)
            qml.RX(0.4, wires=1)
            qml.PhaseShift(0.5, wires=1)
            qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))

        assert all(o1.name == o2.name
                   for o1, o2 in zip(tape.operations, tape_exp.operations))
        assert all(o1.wires == o2.wires
                   for o1, o2 in zip(tape.operations, tape_exp.operations))
        assert all(
            np.allclose(o1.parameters, o2.parameters)
            for o1, o2 in zip(tape.operations, tape_exp.operations))
        assert len(tape.measurements) == 1
        assert tape.observables[0].name == ["PauliZ", "PauliZ"]
        assert tape.observables[0].wires.tolist() == [0, 1]
        assert tape.measurements[0].return_type is Expectation
Example #4
0
 def decomposition(phi, wires):
     return [
         qml.PhaseShift(phi / 2, wires=[wires[0]]),
         qml.PhaseShift(phi / 2, wires=[wires[1]]),
         qml.CNOT(wires=wires),
         qml.PhaseShift(-phi / 2, wires=[wires[1]]),
         qml.CNOT(wires=wires),
     ]
Example #5
0
 def decomposition(phi, wires):
     decomp_ops = [
         qml.PhaseShift(phi / 2, wires=wires[0]),
         qml.CNOT(wires=wires),
         qml.PhaseShift(-phi / 2, wires=wires[1]),
         qml.CNOT(wires=wires),
         qml.PhaseShift(phi / 2, wires=wires[1]),
     ]
     return decomp_ops
    def test_construct_subcircuit(self):
        """Test correct subcircuits constructed"""
        dev = qml.device("default.qubit", wires=2)

        with qml.tape.QuantumTape() as tape:
            qml.RX(np.array(1.0, requires_grad=True), wires=0)
            qml.RY(np.array(1.0, requires_grad=True), wires=0)
            qml.CNOT(wires=[0, 1])
            qml.PhaseShift(np.array(1.0, requires_grad=True), wires=1)
            return qml.expval(qml.PauliX(0)), qml.expval(qml.PauliX(1))

        tapes, _ = qml.metric_tensor(tape, approx="block-diag")
        assert len(tapes) == 3

        # first parameter subcircuit
        assert len(tapes[0].operations) == 1
        assert isinstance(tapes[0].operations[0], qml.Hadamard)  # PauliX decomp

        # second parameter subcircuit
        assert len(tapes[1].operations) == 4
        assert isinstance(tapes[1].operations[0], qml.RX)
        # PauliY decomp
        assert isinstance(tapes[1].operations[1], qml.PauliZ)
        assert isinstance(tapes[1].operations[2], qml.S)
        assert isinstance(tapes[1].operations[3], qml.Hadamard)

        # third parameter subcircuit
        assert len(tapes[2].operations) == 4
        assert isinstance(tapes[2].operations[0], qml.RX)
        assert isinstance(tapes[2].operations[1], qml.RY)
        assert isinstance(tapes[2].operations[2], qml.CNOT)
        # Phase shift generator
        assert isinstance(tapes[2].operations[3], qml.QubitUnitary)
Example #7
0
def test_unwrap_tensorflow():
    """Test that unwrapping a tape with TensorFlow parameters
    works as expected"""
    tf = pytest.importorskip("tensorflow")
    p = [tf.Variable(0.1), tf.constant(0.2), np.array(0.5), tf.Variable(0.3)]

    with tf.GradientTape():

        with qml.tape.QuantumTape() as tape:
            qml.RX(p[0], wires=0)
            qml.RY(p[1], wires=0)
            qml.PhaseShift(p[2], wires=0)
            qml.RZ(p[3], wires=0)

        params = tape.get_parameters(trainable_only=False)
        tape.trainable_params = qml.math.get_trainable_indices(params)

        with tape.unwrap() as unwrapped_tape:
            # inside the context manager, all parameters
            # will be unwrapped to NumPy arrays
            params = tape.get_parameters(trainable_only=False)
            assert all(isinstance(i, (float, np.float32)) for i in params)
            assert np.allclose(params, [0.1, 0.2, 0.5, 0.3])
            assert tape.trainable_params == [0, 3]

    # outside the context, the original parameters have been restored.
    assert tape.get_parameters(trainable_only=False) == p
Example #8
0
 def compute_decomposition(phi, wires):
     return [
         qml.SWAP(wires=wires),
         qml.CNOT(wires=wires),
         qml.PhaseShift(phi, wires=[wires[1]]),
         qml.CNOT(wires=wires),
     ]
Example #9
0
    def test_expand_fn_with_kwarg(self, mocker, perform_expansion):
        """Test that kwargs are respected in the expansion."""
        class MyTransform:
            """Dummy class to allow spying to work"""
            def my_transform(self, tape, **kwargs):
                tape1 = tape.copy()
                tape2 = tape.copy()
                return [tape1, tape2], None

        spy_transform = mocker.spy(MyTransform, "my_transform")
        transform_fn = qml.batch_transform(
            MyTransform().my_transform, expand_fn=self.expand_logic_with_kwarg)

        with qml.tape.QuantumTape() as tape:
            qml.PhaseShift(0.5, wires=0)
            qml.expval(qml.PauliX(0))

        spy_expand = mocker.spy(transform_fn, "expand_fn")

        transform_fn(tape, perform_expansion=perform_expansion)

        spy_transform.assert_called()
        spy_expand.assert_called(
        )  # The expand_fn of transform_fn always is called

        input_tape = spy_transform.call_args[0][1]
        assert len(input_tape.operations) == 1
        assert input_tape.operations[0].name == ("RZ" if perform_expansion else
                                                 "PhaseShift")
        assert input_tape.operations[0].parameters == [0.5]
Example #10
0
def local_hadamard_test(weights, l=None, lp=None, j=None, part=None):

    # First Hadamard gate applied to the ancillary qubit.
    qml.Hadamard(wires=ancilla_idx)

    # For estimating the imaginary part of the coefficient "mu", we must add a "-i" phase gate.
    if part == "Im" or part == "im":
        qml.PhaseShift(-np.pi / 2, wires=ancilla_idx)

    # Variational circuit generating a guess for the solution vector |x>
    variational_block(weights)

    # Controlled application of the unitary component A_l of the problem matrix A.
    CA(l)

    # Adjoint of the unitary U_b associated to the problem vector |b>.
    # In this specific example Adjoint(U_b) = U_b.
    U_b()

    # Controlled Z operator at position j. If j = -1, apply the identity.
    if j != -1:
        qml.CZ(wires=[ancilla_idx, j])

    # Unitary U_b associated to the problem vector |b>.
    U_b()

    # Controlled application of Adjoint(A_lp).
    # In this specific example Adjoint(A_lp) = A_lp.
    CA(lp)

    # Second Hadamard gate applied to the ancillary qubit.
    qml.Hadamard(wires=ancilla_idx)

    # Expectation value of Z for the ancillary qubit.
    return qml.expval(qml.PauliZ(wires=ancilla_idx))
def apply_single_clifford(clifford_string, inverse=False):
    for gate in clifford_string:
        if gate == 'H':
            qml.Hadamard(wires=0)
        else:
            sign = -1 if inverse else 1
            qml.PhaseShift(sign * np.pi / 2, wires=0)
Example #12
0
def test_unwrap_torch():
    """Test that unwrapping a tape with Torch parameters
    works as expected"""
    torch = pytest.importorskip("torch")

    p = [
        torch.tensor(0.1, requires_grad=True),
        torch.tensor(0.2),
        np.array(0.5),
        torch.tensor(0.3, requires_grad=True),
    ]

    with qml.tape.QuantumTape() as tape:
        qml.RX(p[0], wires=0)
        qml.RY(p[1], wires=0)
        qml.PhaseShift(p[2], wires=0)
        qml.RZ(p[3], wires=0)

    with tape.unwrap() as unwrapped_tape:
        # inside the context manager, all parameters
        # will be unwrapped to NumPy arrays
        params = tape.get_parameters(trainable_only=False)
        assert all(isinstance(i, float) for i in params)
        assert np.allclose(params, [0.1, 0.2, 0.5, 0.3])
        assert tape.trainable_params == {0, 3}

    # outside the context, the original parameters have been restored.
    assert tape.get_parameters(trainable_only=False) == p
Example #13
0
    def test_expand_fn(self, mocker):
        """Test that if an expansion function is provided,
        that the input tape is expanded before being transformed."""
        class MyTransform:
            """Dummy class to allow spying to work"""
            def my_transform(self, tape):
                tape1 = tape.copy()
                tape2 = tape.copy()
                return [tape1, tape2], None

        spy_transform = mocker.spy(MyTransform, "my_transform")
        transform_fn = qml.batch_transform(MyTransform().my_transform,
                                           expand_fn=self.phaseshift_expand)

        with qml.tape.QuantumTape() as tape:
            qml.PhaseShift(0.5, wires=0)
            qml.expval(qml.PauliX(0))

        spy_expand = mocker.spy(transform_fn, "expand_fn")

        transform_fn(tape)

        spy_transform.assert_called()
        spy_expand.assert_called()

        input_tape = spy_transform.call_args[0][1]
        assert len(input_tape.operations) == 1
        assert input_tape.operations[0].name == "RZ"
        assert input_tape.operations[0].parameters == [0.5]
Example #14
0
def test_unwrap_autograd():
    """Test that unwrapping a tape with Autograd parameters
    works as expected"""
    from pennylane import numpy as anp

    p = [
        anp.tensor(0.1, requires_grad=True),
        anp.tensor(0.2, requires_grad=False),
        0.5,
        anp.tensor(0.3, requires_grad=True),
    ]

    with qml.tape.QuantumTape() as tape:
        qml.RX(p[0], wires=0)
        qml.RY(p[1], wires=0)
        qml.PhaseShift(p[2], wires=0)
        qml.RZ(p[3], wires=0)

    with tape.unwrap() as unwrapped_tape:
        # inside the context manager, all parameters
        # will be unwrapped to NumPy arrays
        params = tape.get_parameters(trainable_only=False)
        assert all(isinstance(i, float) for i in params)
        assert np.allclose(params, [0.1, 0.2, 0.5, 0.3])
        assert tape.trainable_params == {0, 2, 3}

    # outside the context, the original parameters have been restored.
    assert tape.get_parameters(trainable_only=False) == p
    def qfunc(a, b, c, angles):
        qml.RX(a, wires=0)
        qml.RX(b, wires=1)
        qml.PauliZ(1)
        qml.CNOT(wires=[0, 1]).inv()
        qml.CRY(b, wires=[3, 1])
        qml.RX(angles[0], wires=0)
        qml.RX(4 * angles[1], wires=1)
        qml.PhaseShift(17 / 9 * c, wires=2)
        qml.RZ(b, wires=3)
        qml.RX(angles[2], wires=2).inv()
        qml.CRY(0.3589, wires=[3, 1]).inv()
        qml.CSWAP(wires=[4, 2, 1]).inv()
        qml.QubitUnitary(np.eye(2), wires=[2])
        qml.Toffoli(wires=[0, 2, 1])
        qml.CNOT(wires=[0, 2])
        qml.PauliZ(wires=[1])
        qml.PauliZ(wires=[1]).inv()
        qml.CZ(wires=[0, 1])
        qml.CZ(wires=[0, 2]).inv()
        qml.CNOT(wires=[2, 1])
        qml.CNOT(wires=[0, 2])
        qml.SWAP(wires=[0, 2]).inv()
        qml.CNOT(wires=[1, 3])
        qml.RZ(b, wires=3)
        qml.CSWAP(wires=[4, 0, 1])

        return [
            qml.expval(qml.PauliY(0)),
            qml.var(qml.Hadamard(wires=1)),
            qml.sample(qml.PauliX(2)),
            qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])),
        ]
Example #16
0
class TestOperations:
    """Tests for the operations"""
    @pytest.mark.parametrize(
        "op",
        [
            (qml.Hadamard(wires=0)),
            (qml.PauliX(wires=0)),
            (qml.PauliY(wires=0)),
            (qml.PauliZ(wires=0)),
            (qml.S(wires=0)),
            (qml.T(wires=0)),
            (qml.SX(wires=0)),
            (qml.RX(0.3, wires=0)),
            (qml.RY(0.3, wires=0)),
            (qml.RZ(0.3, wires=0)),
            (qml.PhaseShift(0.3, wires=0)),
            (qml.Rot(0.3, 0.4, 0.5, wires=0)),
        ],
    )
    def test_single_qubit_rot_angles(self, op):
        """Tests that the Rot gates yielded by single_qubit_rot_angles
        are equivalent to the true operations up to a global phase."""
        angles = op.single_qubit_rot_angles()
        obtained_mat = qml.Rot(*angles, wires=0).matrix

        # Check whether the two matrices are each others conjugate transposes
        mat_product = qml.math.dot(op.matrix, qml.math.conj(obtained_mat.T))
        mat_product /= mat_product[0, 0]

        assert qml.math.allclose(mat_product, I)
Example #17
0
def test_unwrap_jax():
    """Test that unwrapping a tape with JAX parameters
    works as expected"""
    jax = pytest.importorskip("jax")
    from jax import numpy as jnp

    p = [
        jnp.array(0.1),
        jnp.array(0.2),
        0.5,
        jnp.array(0.3),
    ]

    with qml.tape.QuantumTape() as tape:
        qml.RX(p[0], wires=0)
        qml.RY(p[1], wires=0)
        qml.PhaseShift(p[2], wires=0)
        qml.RZ(p[3], wires=0)

    with tape.unwrap() as unwrapped_tape:
        # inside the context manager, all parameters
        # will be unwrapped to NumPy arrays
        params = tape.get_parameters(trainable_only=False)
        assert all(isinstance(i, float) for i in params)
        assert np.allclose(params, [0.1, 0.2, 0.5, 0.3])

        # During the forward pass, JAX has no concept of trainable
        # arrays.
        assert tape.trainable_params == set()

    # outside the context, the original parameters have been restored.
    assert tape.get_parameters(trainable_only=False) == p
Example #18
0
 def circuit():
     qml.CRZ(0.0, wires=[0, 1])
     qml.CRX(0.0, wires=[0, 1])
     qml.PhaseShift(0.0, wires=0)
     qml.ControlledPhaseShift(0.0, wires=[1, 0])
     qml.CRot(1.0, 0.0, 0.0, wires=[0, 1])
     qml.CRY(0.0, wires=[0, 1])
     return qml.sample(qml.PauliZ(wires=0))
Example #19
0
    def test_phase(self):
        """Test if the function correctly returns the derivative of PhaseShift"""
        p = 0.3
        op = qml.PhaseShift(p, wires=0)

        derivative = operation_derivative(op)
        expected_derivative = np.array([[0, 0], [0, 1j * np.exp(1j * p)]])
        assert np.allclose(derivative, expected_derivative)
def Turing():
    # distinct fun names in functional placeholders=
    # []
    qml.Hadamard(0)
    qml.PauliX(1)
    qml.PauliY(1)
    qml.PauliZ(1)
    qml.CNOT(wires=[0, 1])
    qml.CZ(wires=[0, 1])
    qml.SWAP(wires=[1, 0])
    qml.RX(-6.283185307179586, wires=2)
    qml.RY(-6.283185307179586, wires=2)
    qml.RZ(-6.283185307179586, wires=2)
    qml.PhaseShift(3.141592653589793, wires=1)

    def rot(rad_ang_x, rad_ang_y, rad_ang_z):
        """
        Returns
    
        exp(1j*(rad_ang_x*sig_x + rad_ang_y*sig_y + rad_ang_z*sig_z))
    
        where rad_ang_x is an angle in radians and sig_x is the x Pauli
        matrix, etc.
    
        Parameters
        ----------
        rad_ang_x : float
        rad_ang_y : float
        rad_ang_z : float
    
        Returns
        -------
        np.ndarray
    
        """
        ty = np.complex128
        mat = np.zeros([2, 2], dtype=ty)
        vec = np.array([rad_ang_x, rad_ang_y, rad_ang_z])
        n = np.linalg.norm(vec)  # sqrt(dot(vec, vec.conj))
        if abs(n) < 1e-8:
            mat[0, 0] = 1
            mat[1, 1] = 1
        else:
            nx = rad_ang_x / n
            ny = rad_ang_y / n
            nz = rad_ang_z / n
            c = np.cos(n)
            s = np.sin(n)
            mat[0, 0] = c + 1j * s * nz
            mat[0, 1] = s * ny + 1j * s * nx
            mat[1, 0] = -s * ny + 1j * s * nx
            mat[1, 1] = c - 1j * s * nz
        return mat

    qml.QubitUnitary(rot(-6.283185307179586, -6.283185307179586,
                         -6.283185307179586),
                     wires=0)
    return qml.expval.Hermitian(hamil)
Example #21
0
 def qfunc():
     qml.RZ(0.3, wires="a")
     qml.RY(0.5, wires="a")
     qml.Rot(0.1, 0.2, 0.3, wires="b")
     qml.RX(0.1, wires="a")
     qml.CNOT(wires=["b", "a"])
     qml.SX(wires="b")
     qml.S(wires="b")
     qml.PhaseShift(0.3, wires="b")
Example #22
0
        def expand(self):
            theta, phi, lam = self.data
            wires = self.wires

            with JacobianTape() as tape:
                qml.Rot(lam, theta, -lam, wires=wires)
                qml.PhaseShift(phi + lam, wires=wires)

            return tape
Example #23
0
 def expand(self):
     tape = JacobianTape()
     theta, phi, lam = self.data
     wires = self.wires
     tape._ops += [
         qml.Rot(lam, theta, -lam, wires=wires),
         qml.PhaseShift(phi + lam, wires=wires),
     ]
     return tape
 def circuit(a, b):
     # The classical processing function is
     #     f: ([a0, a1], b) -> (a1, a0, b)
     # So the classical Jacobians will be a permutation matrix and an identity matrix:
     #     classical_jacobian(circuit)(a, b) == ([[0, 1], [1, 0]], [[1]])
     qml.RX(a[1], wires=0)
     qml.RY(a[0], wires=0)
     qml.CNOT(wires=[0, 1])
     qml.PhaseShift(b, wires=1)
     return qml.expval(qml.PauliX(0)), qml.expval(qml.PauliX(1))
def qfunc(theta):
    qml.PauliX(wires=2)
    qml.S(wires=0)
    qml.CNOT(wires=[0, 1])
    qml.PauliY(wires=1)
    qml.CRY(theta[0], wires=[2, 1])
    qml.PhaseShift(theta[1], wires=0)
    qml.T(wires=0)
    qml.Toffoli(wires=[0, 1, 2])
    return qml.expval(qml.PauliZ(0))
Example #26
0
def test_multiple_unwrap():
    """Test that unwrapping multiple tapes at once works correctly"""
    torch = pytest.importorskip("torch")

    p = [
        torch.tensor(0.1, requires_grad=True),
        torch.tensor(0.2),
        np.array(0.5),
        torch.tensor(0.3, requires_grad=True),
    ]

    with qml.tape.QuantumTape() as tape1:
        qml.RX(p[0], wires=0)
        qml.RY(p[1], wires=0)
        qml.PhaseShift(p[2], wires=0)
        qml.RZ(p[3], wires=0)

    with qml.tape.QuantumTape() as tape2:
        qml.RX(p[1], wires=0)
        qml.RY(p[3], wires=0)
        qml.PhaseShift(p[0], wires=0)
        qml.RZ(p[2], wires=0)

    for t in [tape1, tape2]:
        params = t.get_parameters(trainable_only=False)
        t.trainable_params = qml.math.get_trainable_indices(params)

    with qml.tape.Unwrap(tape1, tape2):
        # inside the context manager, all parameters
        # will be unwrapped to NumPy arrays
        params = tape1.get_parameters(trainable_only=False)
        assert all(isinstance(i, float) for i in params)
        assert tape1.trainable_params == [0, 3]

        params = tape2.get_parameters(trainable_only=False)
        assert all(isinstance(i, float) for i in params)
        assert tape2.trainable_params == [1, 2]

    # outside the context, the original parameters have been restored.
    assert tape1.get_parameters(trainable_only=False) == p
    assert tape2.get_parameters(trainable_only=False) == [
        p[1], p[3], p[0], p[2]
    ]
Example #27
0
    def test_inclusion_after_addition(self):
        """Test that we can add operators to the set in multiple ways."""
        new_attribute.add("RX")
        new_attribute.add(qml.PhaseShift(0.5, wires=0))
        new_attribute.add(qml.RY)

        assert "RX" in new_attribute
        assert "PhaseShift" in new_attribute
        assert "RY" in new_attribute
        assert len(new_attribute) == 8
Example #28
0
 def test_append_qubit_gates(self):
     """Test that gates are successfully appended to the queue."""
     with qml.beta.queuing.AnnotatedQueue() as q:
         ops = [
             qml.RX(0.5, wires=0),
             qml.RY(-10.1, wires=1),
             qml.CNOT(wires=[0, 1]),
             qml.PhaseShift(-1.1, wires=18),
             qml.T(wires=99),
         ]
     assert q.queue == ops
        def qfunc():
            qml.PauliZ(wires=2)
            qml.S(wires=0)
            qml.CZ(wires=[0, 2])

            qml.CNOT(wires=[0, 1])

            qml.PhaseShift(0.2, wires=2)
            qml.T(wires=0)
            qml.PauliZ(wires=0)
            qml.CRZ(0.5, wires=[0, 1])
Example #30
0
    def circuit(x, y, z):
        for i in range(w):
            qml.RX(x, wires=i)
            qml.PhaseShift(z, wires=i)
            qml.RY(y, wires=i)

        qml.CNOT(wires=[0, 1])
        qml.CNOT(wires=[1, 2])
        qml.CNOT(wires=[2, 3])

        return qml.probs(wires=[1, 3])