def test_vacuum_state(self, tol):
     """Test the vacuum state is correct."""
     wires = 3
     means, cov = vacuum_state(wires, hbar=hbar)
     assert means == pytest.approx(np.zeros([2 * wires]), abs=tol)
     assert cov == pytest.approx(np.identity(2 * wires) * hbar / 2, abs=tol)
Exemplo n.º 2
0
class TestGates:
    """Gate tests."""

    input_state = [vacuum_state(1), coherent_state(a=0.5)]

    @pytest.mark.parametrize("inp_state", input_state)
    def test_identity(self, inp_state, tol):
        inp_cov_mat = inp_state[0]
        inp_means = inp_state[1]

        O = qml.Identity.identity_op()
        out_means = O @ inp_means
        out_cov_mat = O @ inp_cov_mat @ O.T

        assert np.allclose(out_means, inp_means, atol=tol)
        assert np.allclose(
            out_cov_mat, inp_cov_mat,
            atol=tol)  # Identity op shouldn't change means or cov mat

    def test_rotation(self, tol):
        """Test the Fourier transform of a displaced state."""
        # pylint: disable=invalid-unary-operand-type

        alpha = 0.23 + 0.12j
        S = rotation(np.pi / 2)

        # apply to a coherent state. F{x, p} -> {-p, x}
        out = S @ np.array([alpha.real, alpha.imag]) * np.sqrt(2 * hbar)
        expected = np.array([-alpha.imag, alpha.real]) * np.sqrt(2 * hbar)
        assert out == pytest.approx(expected, abs=tol)

    def test_squeezing(self, tol):
        """Test the squeezing symplectic transform."""

        r = 0.543
        phi = 0.123
        S = squeezing(r, phi)

        # apply to an identity covariance matrix
        out = S @ S.T
        expected = rotation(phi / 2) @ np.diag(np.exp(
            [-2 * r, 2 * r])) @ rotation(phi / 2).T
        assert out == pytest.approx(expected, abs=tol)

    def test_quadratic_phase(self, tol):
        """Test the quadratic phase symplectic transform."""

        s = 0.543
        S = quadratic_phase(s)

        # apply to a coherent state. P[x, p] -> [x, p+sx]
        alpha = 0.23 + 0.12j
        out = S @ np.array([alpha.real, alpha.imag]) * np.sqrt(2 * hbar)
        expected = np.array([alpha.real, alpha.imag + s * alpha.real
                             ]) * np.sqrt(2 * hbar)
        assert out == pytest.approx(expected, abs=tol)

    def test_beamsplitter(self, tol):
        """Test the beamsplitter symplectic transform."""

        theta = 0.543
        phi = 0.312
        S = beamsplitter(theta, phi)

        # apply to a coherent state. BS|a1, a2> -> |ta1-r^*a2, ra1+ta2>
        a1 = 0.23 + 0.12j
        a2 = 0.23 + 0.12j
        out = S @ np.array([a1.real, a2.real, a1.imag, a2.imag]) * np.sqrt(
            2 * hbar)

        T = np.cos(theta)
        R = np.exp(1j * phi) * np.sin(theta)
        a1out = T * a1 - R.conj() * a2
        a2out = R * a2 + T * a1
        expected = np.array([a1out.real, a2out.real, a1out.imag, a2out.imag
                             ]) * np.sqrt(2 * hbar)
        assert out == pytest.approx(expected, abs=tol)

    def test_two_mode_squeezing(self, tol):
        """Test the two mode squeezing symplectic transform."""

        r = 0.543
        phi = 0.123
        S = two_mode_squeezing(r, phi)

        # test that S = B^\dagger(pi/4, 0) [S(z) x S(-z)] B(pi/4)
        B = beamsplitter(np.pi / 4, 0)
        Sz = block_diag(squeezing(r, phi),
                        squeezing(-r, phi))[:, [0, 2, 1, 3]][[0, 2, 1, 3]]
        expected = B.conj().T @ Sz @ B
        assert S == pytest.approx(expected, abs=tol)

        # test that S |a1, a2> = |ta1+ra2, ta2+ra1>
        a1 = 0.23 + 0.12j
        a2 = 0.23 + 0.12j
        out = S @ np.array([a1.real, a2.real, a1.imag, a2.imag]) * np.sqrt(
            2 * hbar)

        T = np.cosh(r)
        R = np.exp(1j * phi) * np.sinh(r)
        a1out = T * a1 + R * np.conj(a2)
        a2out = T * a2 + R * np.conj(a1)
        expected = np.array([a1out.real, a2out.real, a1out.imag, a2out.imag
                             ]) * np.sqrt(2 * hbar)
        assert out == pytest.approx(expected, abs=tol)

    def test_controlled_addition(self, tol):
        """Test the CX symplectic transform."""

        s = 0.543
        S = controlled_addition(s)

        # test that S = B(theta+pi/2, 0) [S(z) x S(-z)] B(theta, 0)
        r = np.arcsinh(-s / 2)
        theta = 0.5 * np.arctan2(-1 / np.cosh(r), -np.tanh(r))
        Sz = block_diag(squeezing(r, 0),
                        squeezing(-r, 0))[:, [0, 2, 1, 3]][[0, 2, 1, 3]]

        expected = beamsplitter(theta + np.pi / 2, 0) @ Sz @ beamsplitter(
            theta, 0)
        assert S == pytest.approx(expected, abs=tol)

        # test that S[x1, x2, p1, p2] -> [x1, x2+sx1, p1-sp2, p2]
        x1 = 0.5432
        x2 = -0.453
        p1 = 0.154
        p2 = -0.123
        out = S @ np.array([x1, x2, p1, p2]) * np.sqrt(2 * hbar)
        expected = np.array([x1, x2 + s * x1, p1 - s * p2, p2]) * np.sqrt(
            2 * hbar)
        assert out == pytest.approx(expected, abs=tol)

    def test_controlled_phase(self, tol):
        """Test the CZ symplectic transform."""

        s = 0.543
        S = controlled_phase(s)

        # test that S = R_2(pi/2) CX(s) R_2(pi/2)^\dagger
        R2 = block_diag(np.identity(2),
                        rotation(np.pi / 2))[:, [0, 2, 1, 3]][[0, 2, 1, 3]]
        expected = R2 @ controlled_addition(s) @ R2.conj().T
        assert S == pytest.approx(expected, abs=tol)

        # test that S[x1, x2, p1, p2] -> [x1, x2, p1+sx2, p2+sx1]
        x1 = 0.5432
        x2 = -0.453
        p1 = 0.154
        p2 = -0.123
        out = S @ np.array([x1, x2, p1, p2]) * np.sqrt(2 * hbar)
        expected = np.array([x1, x2, p1 + s * x2, p2 + s * x1]) * np.sqrt(
            2 * hbar)
        assert out == pytest.approx(expected, abs=tol)