Exemplo n.º 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 (list[Wires]): the wires ``n`` and ``m`` the circuit acts on
    """

    n, m = wires

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

    # decomposition of C-PhaseShift(2*phi) gate
    PhaseShift(-phi, wires=m)
    CNOT(wires=wires)
    PhaseShift(phi, wires=m)
    CNOT(wires=wires)
    PhaseShift(-phi, wires=n)
Exemplo n.º 2
0
def entangler(par1, par2, wires):
    """Implements a two qubit unitary consisting of a controlled-Z entangler and Pauli-Y rotations.

    Args:
         par1 (float or qml.Variable): parameter of first Pauli-Y rotation
         par2 (float or qml.Variable): parameter of second Pauli-Y rotation
         wires (Wires): two wire indices that unitary acts on
    """

    CZ(wires=wires)
    RY(par1, wires=wires[0])
    RY(par2, wires=wires[1])
Exemplo n.º 3
0
class TestKrausOps:
    """Unit tests for the method `_get_kraus_ops()`"""

    unitary_ops = [
        (PauliX, np.array([[0, 1], [1, 0]])),
        (Hadamard, np.array([[INV_SQRT2, INV_SQRT2], [INV_SQRT2,
                                                      -INV_SQRT2]])),
        (CNOT,
         np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])),
    ]

    @pytest.mark.parametrize("ops", unitary_ops)
    def test_unitary_kraus(self, ops, tol):
        """Tests that matrices of non-diagonal unitary operations are retrieved correctly"""
        dev = qml.device("default.mixed", wires=2)

        assert np.allclose(dev._get_kraus(ops[0]), [ops[1]], atol=tol, rtol=0)

    diagonal_ops = [
        (PauliZ(wires=0), np.array([1, -1])),
        (CZ(wires=[0, 1]), np.array([1, 1, 1, -1])),
    ]

    @pytest.mark.parametrize("ops", diagonal_ops)
    def test_diagonal_kraus(self, ops, tol):
        """Tests that matrices of non-diagonal unitary operations are retrieved correctly"""
        dev = qml.device("default.mixed", wires=2)

        assert np.allclose(dev._get_kraus(ops[0]), ops[1], atol=tol, rtol=0)

    p = 0.5
    K0 = np.sqrt(1 - p) * np.eye(2)
    K1 = np.sqrt(p / 3) * np.array([[0, 1], [1, 0]])
    K2 = np.sqrt(p / 3) * np.array([[0, -1j], [1j, 0]])
    K3 = np.sqrt(p / 3) * np.array([[1, 0], [0, -1]])

    channel_ops = [
        (
            AmplitudeDamping(p, wires=0),
            [
                np.diag([1, np.sqrt(1 - p)]),
                np.sqrt(p) * np.array([[0, 1], [0, 0]])
            ],
        ),
        (DepolarizingChannel(p, wires=0), [K0, K1, K2, K3]),
    ]

    @pytest.mark.parametrize("ops", channel_ops)
    def test_channel_kraus(self, ops, tol):
        """Tests that kraus matrices of non-unitary channels are retrieved correctly"""
        dev = qml.device("default.mixed", wires=1)

        assert np.allclose(dev._get_kraus(ops[0]), ops[1], atol=tol, rtol=0)