Example #1
0
 def test_two_mode_squeezing_heisenberg(self, phi, mag):
     """ops: Tests the Heisenberg representation of the Beamsplitter gate."""
     r = mag
     matrix = cv.TwoModeSqueezing._heisenberg_rep([r, phi])
     true_matrix = np.array([
         [1, 0, 0, 0, 0],
         [
             0,
             np.cosh(r), 0,
             np.cos(phi) * np.sinh(r),
             np.sin(phi) * np.sinh(r)
         ],
         [
             0, 0,
             np.cosh(r),
             np.sin(phi) * np.sinh(r), -np.cos(phi) * np.sinh(r)
         ],
         [
             0,
             np.cos(phi) * np.sinh(r),
             np.sin(phi) * np.sinh(r),
             np.cosh(r), 0
         ],
         [
             0,
             np.sin(phi) * np.sinh(r), -np.cos(phi) * np.sinh(r), 0,
             np.cosh(r)
         ],
     ])
     assert np.allclose(matrix, true_matrix)
Example #2
0
    def test_finite_diff_squeezed(self, tol):
        """Test that the jacobian of the probability for a squeezed states is
        approximated well with finite differences"""
        cutoff = 5

        dev = qml.device("strawberryfields.gaussian",
                         wires=1,
                         cutoff_dim=cutoff)

        @qml.qnode(dev)
        def circuit(r, phi):
            qml.Squeezing(r, phi, wires=0)
            return qml.probs(wires=[0])

        r = 0.4
        phi = -0.12

        n = np.arange(cutoff)

        # differentiate with respect to parameter r
        res_F = circuit.jacobian([r, phi], wrt={0}, method="F").flatten()
        assert res_F.shape == (cutoff, )

        expected_gradient = (
            np.abs(np.tanh(r))**n * (1 + 2 * n - np.cosh(2 * r)) * fac(n) /
            (2**(n + 1) * np.cosh(r)**2 * np.sinh(r) * fac(n / 2)**2))
        expected_gradient[n % 2 != 0] = 0
        assert np.allclose(res_F, expected_gradient, atol=tol, rtol=0)

        # differentiate with respect to parameter phi
        res_F = circuit.jacobian([r, phi], wrt={1}, method="F").flat
        expected_gradient = 0
        assert np.allclose(res_F, expected_gradient, atol=tol, rtol=0)
Example #3
0
    def test_two_mode_squeezing_heisenberg(self):
        """Tests the Heisenberg representation of the Beamsplitter gate."""
        self.logTestName()

        for r in mags:
            for phi in phis:
                matrix = cv.TwoModeSqueezing._heisenberg_rep([r, phi])
                true_matrix = np.array([[1, 0, 0, 0, 0],
                                        [
                                            0,
                                            np.cosh(r), 0,
                                            np.cos(phi) * np.sinh(r),
                                            np.sin(phi) * np.sinh(r)
                                        ],
                                        [
                                            0, 0,
                                            np.cosh(r),
                                            np.sin(phi) * np.sinh(r),
                                            -np.cos(phi) * np.sinh(r)
                                        ],
                                        [
                                            0,
                                            np.cos(phi) * np.sinh(r),
                                            np.sin(phi) * np.sinh(r),
                                            np.cosh(r), 0
                                        ],
                                        [
                                            0,
                                            np.sin(phi) * np.sinh(r),
                                            -np.cos(phi) * np.sinh(r), 0,
                                            np.cosh(r)
                                        ]])
                self.assertAllAlmostEqual(matrix, true_matrix, delta=self.tol)
    def test_multiple_squeezing_gradient(self, mocker, tol):
        """Test that the gradient of a circuit with two squeeze
        gates is correct."""
        dev = qml.device("default.gaussian", wires=2, hbar=hbar)

        r0, phi0, r1, phi1 = [0.4, -0.3, -0.7, 0.2]

        with qml.tape.JacobianTape() as tape:
            qml.Squeezing(r0, phi0, wires=[0])
            qml.Squeezing(r1, phi1, wires=[0])
            qml.expval(qml.NumberOperator(0))  # second order

        spy2 = mocker.spy(qml.gradients.parameter_shift_cv,
                          "second_order_param_shift")
        tapes, fn = param_shift_cv(tape, dev, force_order2=True)
        grad_A2 = fn(dev.batch_execute(tapes))
        spy2.assert_called()

        # check against the known analytic formula
        expected = np.zeros([4])
        expected[0] = np.cosh(2 * r1) * np.sinh(
            2 * r0) + np.cos(phi0 - phi1) * np.cosh(2 * r0) * np.sinh(2 * r1)
        expected[1] = -0.5 * np.sin(phi0 - phi1) * np.sinh(2 * r0) * np.sinh(
            2 * r1)
        expected[2] = np.cos(phi0 - phi1) * np.cosh(2 * r1) * np.sinh(
            2 * r0) + np.cosh(2 * r0) * np.sinh(2 * r1)
        expected[3] = 0.5 * np.sin(phi0 - phi1) * np.sinh(2 * r0) * np.sinh(
            2 * r1)

        assert np.allclose(grad_A2, expected, atol=tol, rtol=0)
Example #5
0
 def squared_term(a, r, phi):
     """Analytic expression for <N^2>"""
     magnitude_squared = np.abs(a)**2
     squared_term = (
         -magnitude_squared + magnitude_squared**2 +
         2 * magnitude_squared * np.cosh(2 * r) -
         np.exp(-1j * phi) * a**2 * np.cosh(r) * np.sinh(r) -
         np.exp(1j * phi) * np.conj(a)**2 * np.cosh(r) * np.sinh(r) +
         np.sinh(r)**4 + np.cosh(r) * np.sinh(r) * np.sinh(2 * r))
     return squared_term
Example #6
0
    def test_jax(self, tol):
        """Tests that the output of the parameter-shift CV transform
        can be differentiated using JAX, yielding second derivatives."""
        jax = pytest.importorskip("jax")
        from jax import numpy as jnp
        from jax.config import config

        config.update("jax_enable_x64", True)

        dev = qml.device("default.gaussian", wires=2)
        params = jnp.array([0.543, -0.654])

        def cost_fn(x):
            with qml.tape.JacobianTape() as tape:
                qml.Squeezing(params[0], 0, wires=0)
                qml.Rotation(params[1], wires=0)
                qml.var(qml.X(wires=[0]))

            tape.trainable_params = {0, 2}
            tapes, fn = qml.gradients.param_shift_cv(tape, dev)
            jac = fn(
                qml.execute(tapes,
                            dev,
                            param_shift_cv,
                            gradient_kwargs={"dev": dev},
                            interface="jax"))
            return jac

        r, phi = params
        res = cost_fn(params)
        expected = np.array([
            2 * np.exp(2 * r) * np.sin(phi)**2 -
            2 * np.exp(-2 * r) * np.cos(phi)**2,
            2 * np.sinh(2 * r) * np.sin(2 * phi),
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)

        pytest.xfail(
            "The CV Operation methods have not been updated to support autodiff"
        )

        res = jax.jacobian(cost_fn)(params)
        expected = np.array([
            [
                4 * np.exp(-2 * r) *
                (np.cos(phi)**2 + np.exp(4 * r) * np.sin(phi)**2),
                4 * np.cosh(2 * r) * np.sin(2 * phi),
            ],
            [
                4 * np.cosh(2 * r) * np.sin(2 * phi),
                4 * np.cos(2 * phi) * np.sinh(2 * r)
            ],
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)
 def expected_grad(r, p):
     return np.array([
         np.cosh(2 * r[1]) * np.sinh(2 * r[0]) +
         np.cos(p[0] - p[1]) * np.cosh(2 * r[0]) * np.sinh(2 * r[1]),
         -0.5 * np.sin(p[0] - p[1]) * np.sinh(2 * r[0]) *
         np.sinh(2 * r[1]),
         np.cos(p[0] - p[1]) * np.cosh(2 * r[1]) * np.sinh(2 * r[0]) +
         np.cosh(2 * r[0]) * np.sinh(2 * r[1]),
         0.5 * np.sin(p[0] - p[1]) * np.sinh(2 * r[0]) *
         np.sinh(2 * r[1]),
     ])
 def setUp(self):
     self.fnames = ['test_function_1', 'test_function_2', 'test_function_3']
     self.univariate_funcs = [
         np.sin, lambda x: np.exp(x / 10.), lambda x: x**2
     ]
     self.grad_uni_fns = [
         np.cos, lambda x: np.exp(x / 10.) / 10., lambda x: 2 * x
     ]
     self.multivariate_funcs = [
         lambda x: np.sin(x[0]) + np.cos(x[1]),
         lambda x: np.exp(x[0] / 3) * np.tanh(x[1]),
         lambda x: np.sum(x_**2 for x_ in x)
     ]
     self.grad_multi_funcs = [
         lambda x: np.array([np.cos(x[0]), -np.sin(x[1])]),
         lambda x: np.array([
             np.exp(x[0] / 3) / 3 * np.tanh(x[1]),
             np.exp(x[0] / 3) * (1 - np.tanh(x[1])**2)
         ]), lambda x: np.array([2 * x_ for x_ in x])
     ]
     self.mvar_mdim_funcs = [
         lambda x: np.sin(x[0, 0]) + np.cos(x[1, 0]),
         lambda x: np.exp(x[0, 0] / 3) * np.tanh(x[1, 0]),
         lambda x: np.sum(x_[0]**2 for x_ in x)
     ]
     self.grad_mvar_mdim_funcs = [
         lambda x: np.array([[np.cos(x[0, 0])], [-np.sin(x[[1]])]]),
         lambda x: np.array([[np.exp(x[0, 0] / 3) / 3 * np.tanh(x[
             1, 0])], [np.exp(x[0, 0] / 3) * (1 - np.tanh(x[1, 0])**2)]]),
         lambda x: np.array([[2 * x_[0]] for x_ in x])
     ]
     self.margs_fns = [
         lambda x, y: np.sin(x) + np.cos(y),
         lambda x, y: np.exp(x / 3) * np.tanh(y),
         lambda x, y: np.sum(x_**2 for x_ in [x, y])
     ]
     self.grad_margs_funcs = [
         lambda x, y: (np.cos(x), -np.sin(y)), lambda x, y:
         (np.exp(x / 3) / 3 * np.tanh(y), np.exp(x / 3) *
          (1 - np.tanh(y)**2)), lambda x, y: (2 * x, 2 * y)
     ]
     self.margs_mdim_fns = [
         lambda x, y: (np.sin(x), np.cos(y)), lambda x, y:
         (np.exp(x / 3) * np.tanh(y), np.sinh(x * y)), lambda x, y:
         (x**2 + y**2, x * y)
     ]
     self.grad_margs_mdim_funcs = [
         lambda x, y: np.diag([np.cos(x), -np.sin(y)]),
         lambda x, y: np.array([[
             np.exp(x / 3) / 3 * np.tanh(y),
             np.exp(x / 3) * np.sech(y)**2
         ], [np.cosh(x * y) * y, np.cosh(x * y) * x]]),
         lambda x, y: np.array([[2 * x, 2 * y], [y, x]])
     ]
Example #9
0
def test_squeezing_heisenberg(phi, mag):
    """ops: Tests the Heisenberg representation of the Squeezing gate."""
    r = mag
    matrix = cv.Squeezing._heisenberg_rep([r, phi])
    true_matrix = np.array([
        [1, 0, 0],
        [0,
         np.cosh(r) - np.cos(phi) * np.sinh(r), -np.sin(phi) * np.sinh(r)],
        [0, -np.sin(phi) * np.sinh(r),
         np.cosh(r) + np.cos(phi) * np.sinh(r)],
    ])
    assert np.allclose(matrix, true_matrix)
Example #10
0
    def test_fock_state(self):
        """Test that FockStateProjector works as expected"""
        self.logTestName()

        cutoff_dim = 12
        a = 0.54321
        r = 0.123

        hbar = 2
        dev = qml.device('strawberryfields.fock',
                         wires=2,
                         hbar=hbar,
                         cutoff_dim=cutoff_dim)

        # test correct number state expectation |<n|a>|^2
        @qml.qnode(dev)
        def circuit(x):
            qml.Displacement(x, 0, wires=0)
            return qml.expval(qml.FockStateProjector(np.array([2]), wires=0))

        expected = np.abs(np.exp(-np.abs(a)**2 / 2) * a**2 / np.sqrt(2))**2
        self.assertAlmostEqual(circuit(a), expected)

        # test correct number state expectation |<n|S(r)>|^2
        @qml.qnode(dev)
        def circuit(x):
            qml.Squeezing(x, 0, wires=0)
            return qml.expval(
                qml.FockStateProjector(np.array([2, 0]), wires=[0, 1]))

        expected = np.abs(
            np.sqrt(2) / (2) * (-np.tanh(r)) / np.sqrt(np.cosh(r)))**2
        self.assertAlmostEqual(circuit(r), expected)
Example #11
0
    def test_autograd_gradient(self, tol):
        """Tests that the output of the parameter-shift CV transform
        can be differentiated using autograd, yielding second derivatives."""
        dev = qml.device("default.gaussian", wires=1)

        r = 0.12
        phi = 0.105

        def cost_fn(x):
            with qml.tape.JacobianTape() as tape:
                qml.Squeezing(x[0], 0, wires=0)
                qml.Rotation(x[1], wires=0)
                qml.var(qml.X(wires=[0]))

            tapes, fn = param_shift_cv(tape, dev)
            jac = fn(
                qml.execute(tapes,
                            dev,
                            param_shift_cv,
                            gradient_kwargs={"dev": dev}))
            return jac[0, 2]

        params = np.array([r, phi], requires_grad=True)
        grad = qml.jacobian(cost_fn)(params)
        expected = np.array([
            4 * np.cosh(2 * r) * np.sin(2 * phi),
            4 * np.cos(2 * phi) * np.sinh(2 * r)
        ])
        assert np.allclose(grad, expected, atol=tol, rtol=0)
Example #12
0
    def test_controlled_addition(self):
        """Test the CX symplectic transform."""
        self.logTestName()

        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)
        self.assertAllAlmostEqual(S, expected, delta=self.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)
        self.assertAllAlmostEqual(out, expected, delta=self.tol)
Example #13
0
    def test_two_mode_squeezing(self):
        """Test the two mode squeezing symplectic transform."""
        self.logTestName()

        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
        self.assertAllAlmostEqual(S, expected, delta=self.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)
        self.assertAllAlmostEqual(out, expected, delta=self.tol)
    def test_tf(self, tol):
        """Tests that the output of the parameter-shift CV transform
        can be executed using TF"""
        tf = pytest.importorskip("tensorflow")
        from pennylane.interfaces.tf import TFInterface

        dev = qml.device("default.gaussian", wires=1)
        params = tf.Variable([0.543, -0.654], dtype=tf.float64)

        with tf.GradientTape() as t:
            with TFInterface.apply(qml.tape.CVParamShiftTape()) as tape:
                qml.Squeezing(params[0], 0, wires=0)
                qml.Rotation(params[1], wires=0)
                qml.var(qml.X(wires=[0]))

            tapes, fn = qml.gradients.param_shift_cv(tape, dev)
            jac = fn([tp.execute(dev) for tp in tapes])
            res = jac[0, 1]

        r, phi = 1.0 * params

        expected = np.array([
            2 * np.exp(2 * r) * np.sin(phi)**2 -
            2 * np.exp(-2 * r) * np.cos(phi)**2,
            2 * np.sinh(2 * r) * np.sin(2 * phi),
        ])
        assert np.allclose(jac, expected, atol=tol, rtol=0)

        grad = t.jacobian(res, params)
        expected = np.array([
            4 * np.cosh(2 * r) * np.sin(2 * phi),
            4 * np.cos(2 * phi) * np.sinh(2 * r)
        ])
        assert np.allclose(grad, expected, atol=tol, rtol=0)
Example #15
0
    def test_number_state(self):
        """Test that NumberState works as expected"""
        self.logTestName()

        a = 0.54321
        r = 0.123

        hbar = 2
        dev = qml.device('strawberryfields.gaussian', wires=2, hbar=hbar)

        # test correct number state expectation |<n|a>|^2
        @qml.qnode(dev)
        def circuit(x):
            qml.Displacement(x, 0, 0)
            return qml.expval.NumberState(np.array([2]), wires=0)

        expected = np.abs(np.exp(-np.abs(a)**2 / 2) * a**2 / np.sqrt(2))**2
        self.assertAlmostEqual(circuit(a), expected)

        # test correct number state expectation |<n|S(r)>|^2
        @qml.qnode(dev)
        def circuit(x):
            qml.Squeezing(x, 0, 0)
            return qml.expval.NumberState(np.array([2, 0]), wires=[0, 1])

        expected = np.abs(
            np.sqrt(2) / (2) * (-np.tanh(r)) / np.sqrt(np.cosh(r)))**2
        self.assertAlmostEqual(circuit(r), expected)
    def test_squeezed_number_state_gradient(self, mocker, tol):
        """Test the numerical gradient of the squeeze gate with
        with number state expectation is correct"""
        dev = qml.device("default.gaussian", wires=2, hbar=hbar)

        r = 0.23354

        with qml.tape.JacobianTape() as tape:
            qml.Squeezing(r, 0.0, wires=[0])
            # the fock state projector is a 'non-Gaussian' observable
            qml.expval(qml.FockStateProjector(np.array([2, 0]), wires=[0, 1]))

        tape.trainable_params = {0}

        spy = mocker.spy(qml.gradients.parameter_shift_cv,
                         "second_order_param_shift")

        tapes, fn = param_shift_cv(tape, dev)
        grad = fn(dev.batch_execute(tapes))
        assert tape._par_info[0]["grad_method"] == "F"

        spy.assert_not_called()

        # (d/dr) |<2|S(r)>|^2 = 0.5 tanh(r)^3 (2 csch(r)^2 - 1) sech(r)
        expected = 0.5 * np.tanh(r)**3 * (2 / (np.sinh(r)**2) - 1) / np.cosh(r)
        assert np.allclose(grad, expected, atol=tol, rtol=0)
    def test_autograd_gradient(self, tol):
        """Tests that the output of the parameter-shift CV transform
        can be differentiated using autograd, yielding second derivatives."""
        dev = qml.device("default.gaussian", wires=1)
        from pennylane.interfaces.autograd import AutogradInterface

        r = 0.12
        phi = 0.105

        def cost_fn(x):
            with AutogradInterface.apply(qml.tape.CVParamShiftTape()) as tape:
                qml.Squeezing(x[0], 0, wires=0)
                qml.Rotation(x[1], wires=0)
                qml.var(qml.X(wires=[0]))

            tapes, fn = param_shift_cv(tape, dev)
            return fn([t.execute(dev) for t in tapes])[0, 1]

        params = np.array([r, phi], requires_grad=True)
        grad = qml.jacobian(cost_fn)(params)
        expected = np.array([
            4 * np.cosh(2 * r) * np.sin(2 * phi),
            4 * np.cos(2 * phi) * np.sinh(2 * r)
        ])
        assert np.allclose(grad, expected, atol=tol, rtol=0)
Example #18
0
    def test_fock_state_projector(self, tol):
        """Test that FockStateProjector works as expected"""
        cutoff_dim = 12
        a = 0.54321
        r = 0.123

        hbar = 2
        dev = qml.device("strawberryfields.fock", wires=2, hbar=hbar, cutoff_dim=cutoff_dim)

        # test correct number state expectation |<n|a>|^2
        @qml.qnode(dev)
        def circuit(x):
            qml.Displacement(x, 0, wires=0)
            return qml.expval(qml.FockStateProjector(np.array([2]), wires=0))

        expected = np.abs(np.exp(-np.abs(a) ** 2 / 2) * a**2 / np.sqrt(2)) ** 2
        assert np.allclose(circuit(a), expected, atol=tol, rtol=0)

        # test correct number state expectation |<n|S(r)>|^2
        @qml.qnode(dev)
        def circuit(x):
            qml.Squeezing(x, 0, wires=0)
            return qml.expval(qml.FockStateProjector(np.array([2, 0]), wires=[0, 1]))

        expected = np.abs(np.sqrt(2) / (2) * (-np.tanh(r)) / np.sqrt(np.cosh(r))) ** 2
        assert np.allclose(circuit(r), expected, atol=tol, rtol=0)
Example #19
0
    def test_finite_diff_squeezed(self, tol):
        """Test that the jacobian of the probability for a squeezed states is
        approximated well with finite differences"""
        cutoff = 5

        dev = qml.device("strawberryfields.fock", wires=1, cutoff_dim=cutoff)

        @qml.qnode(dev)
        def circuit(r, phi):
            qml.Squeezing(r, phi, wires=0)
            return qml.probs(wires=[0])

        r = 0.4
        phi = -0.12

        n = np.arange(cutoff)

        # construct tape
        circuit.construct([r, phi], {})

        # differentiate with respect to parameter a
        circuit.qtape.trainable_params = {0}
        tapes, fn = qml.gradients.finite_diff(circuit.qtape)
        res_F = fn(dev.batch_execute(tapes)).flatten()
        assert res_F.shape == (cutoff,)

        expected_gradient = (
            np.abs(np.tanh(r)) ** n
            * (1 + 2 * n - np.cosh(2 * r))
            * fac(n)
            / (2 ** (n + 1) * np.cosh(r) ** 2 * np.sinh(r) * fac(n / 2) ** 2)
        )
        expected_gradient[n % 2 != 0] = 0
        assert np.allclose(res_F, expected_gradient, atol=tol, rtol=0)

        # re-construct tape to reset trainable_params
        circuit.construct([r, phi], {})

        # differentiate with respect to parameter phi
        circuit.qtape.trainable_params = {1}

        tapes, fn = qml.gradients.finite_diff(circuit.qtape)
        res_F = fn(dev.batch_execute(tapes)).flatten()
        expected_gradient = 0
        assert np.allclose(res_F, expected_gradient, atol=tol, rtol=0)
Example #20
0
 def pd_sr(rs0, phis0, rd0, phid0, rs1, phis1, rd1, phid1):
     """Analytic expression for the partial derivative with respect to
     the r argument of the first squeezing operation (rs0)"""
     return (
         (
             0.25
             + rd0 ** 2 * (-0.25 - 2 * rd1 ** 2 + 2 * rd1 ** 4)
             + (-(rd1 ** 2) + rd0 ** 2 * (-1 + 6 * rd1 ** 2)) * np.cosh(2 * rs1)
             + (-0.25 + 1.25 * rd0 ** 2) * np.cosh(4 * rs1)
         )
         * np.sinh(2 * rs0)
         + (
             -(rd1 ** 2)
             + rd1 ** 4
             + (-0.5 + 2.5 * rd1 ** 2) * np.cosh(2 * rs1)
             + 0.5 * np.cosh(4 * rs1)
         )
         * np.sinh(4 * rs0)
         + rd1 ** 2
         * np.cos(2 * phid1 - phis1)
         * ((1 - 4 * rd0 ** 2) * np.sinh(2 * rs0) - 1.5 * np.sinh(4 * rs0))
         * np.sinh(2 * rs1)
         + rd0 ** 2
         * np.cos(2 * phid0 - phis0)
         * np.cosh(2 * rs0)
         * (
             -0.25
             + 2 * rd1 ** 2
             - 2 * rd1 ** 4
             + (1 - 4 * rd1 ** 2) * np.cosh(2 * rs1)
             - 0.75 * np.cosh(4 * rs1)
             + 2 * rd1 ** 2 * np.cos(2 * phid1 - phis1) * np.sinh(2 * rs1)
         )
     )
Example #21
0
 def pd_dr(rs0, phis0, rd0, phid0, rs1, phis1, rd1, phid1):
     """Analytic expression for the partial derivative with respect to
     the r argument of the first displacement operation (rd0)"""
     return rd0 * (
         0.5
         - rd0 ** 2
         + (-2 + 4 * rd0 ** 2) * rd1 ** 2 * np.cosh(2 * rs1)
         + (-0.5 + rd0 ** 2) * np.cosh(4 * rs1)
         + (2 - 4 * rd0 ** 2) * rd1 ** 2 * np.cos(2 * phid1 - phis1) * np.sinh(2 * rs1)
         + np.cosh(2 * rs0)
         * (
             -0.25
             - 2 * rd1 ** 2
             + 2 * rd1 ** 4
             + (-1 + 6 * rd1 ** 2) * np.cosh(2 * rs1)
             + 1.25 * np.cosh(4 * rs1)
             - 4 * rd1 ** 2 * np.cos(2 * phid1 - phis1) * np.sinh(2 * rs1)
         )
         + np.cos(2 * phid0 - phis0)
         * np.sinh(2 * rs0)
         * (
             -0.25
             + 2 * rd1 ** 2
             - 2 * rd1 ** 4
             + (1 - 4 * rd1 ** 2) * np.cosh(2 * rs1)
             - 0.75 * np.cosh(4 * rs1)
             + 2 * rd1 ** 2 * np.cos(2 * phid1 - phis1) * np.sinh(2 * rs1)
         )
     )
Example #22
0
    def test_expectation(self):
        """Test that expectation values are calculated correctly"""
        self.logTestName()

        dev = qml.device('default.gaussian', wires=1, hbar=hbar)

        # test correct mean and variance for <n> of a displaced thermal state
        nbar = 0.5431
        alpha = 0.324 - 0.59j
        dev.apply('ThermalState', wires=[0], par=[nbar])
        dev.apply('Displacement', wires=[0], par=[alpha, 0])
        mean = dev.expval('MeanPhoton', [0], [])
        self.assertAlmostEqual(mean, np.abs(alpha)**2 + nbar, delta=self.tol)
        # self.assertAlmostEqual(var, nbar**2+nbar+np.abs(alpha)**2*(1+2*nbar), delta=self.tol)

        # test correct mean and variance for Homodyne P measurement
        alpha = 0.324 - 0.59j
        dev.apply('CoherentState', wires=[0], par=[alpha])
        mean = dev.expval('P', [0], [])
        self.assertAlmostEqual(mean,
                               alpha.imag * np.sqrt(2 * hbar),
                               delta=self.tol)
        # self.assertAlmostEqual(var, hbar/2, delta=self.tol)

        # test correct mean and variance for Homodyne measurement
        mean = dev.expval('Homodyne', [0], [np.pi / 2])
        self.assertAlmostEqual(mean,
                               alpha.imag * np.sqrt(2 * hbar),
                               delta=self.tol)
        # self.assertAlmostEqual(var, hbar/2, delta=self.tol)

        # test correct mean and variance for number state expectation |<n|alpha>|^2
        # on a coherent state
        for n in range(3):
            mean = dev.expval('NumberState', [0], [np.array([n])])
            expected = np.abs(
                np.exp(-np.abs(alpha)**2 / 2) * alpha**n / np.sqrt(fac(n)))**2
            self.assertAlmostEqual(mean, expected, delta=self.tol)

        # test correct mean and variance for number state expectation |<n|S(r)>|^2
        # on a squeezed state
        n = 1
        r = 0.4523
        dev.apply('SqueezedState', wires=[0], par=[r, 0])
        mean = dev.expval('NumberState', [0], [np.array([2 * n])])
        expected = np.abs(
            np.sqrt(fac(2 * n)) / (2**n * fac(n)) * (-np.tanh(r))**n /
            np.sqrt(np.cosh(r)))**2
        self.assertAlmostEqual(mean, expected, delta=self.tol)
Example #23
0
    def test_variance_squeezed_numberstate(self):
        """test correct variance for number state expectation |<n|S(r)>|^2
        on a squeezed state
        """
        self.logTestName()
        dev = qml.device('default.gaussian', wires=1, hbar=hbar)

        n = 1
        r = 0.4523
        dev.apply('SqueezedState', wires=[0], par=[r, 0])
        var = dev.var('FockStateProjector', [0], [np.array([2 * n])])
        mean = np.abs(
            np.sqrt(fac(2 * n)) / (2**n * fac(n)) * (-np.tanh(r))**n /
            np.sqrt(np.cosh(r)))**2
        self.assertAlmostEqual(var, mean * (1 - mean), delta=self.tol)
Example #24
0
    def test_torch(self, tol):
        """Tests that the output of the parameter-shift CV transform
        can be executed using Torch."""
        torch = pytest.importorskip("torch")

        dev = qml.device("default.gaussian", wires=1)
        params = torch.tensor([0.543, -0.654],
                              dtype=torch.float64,
                              requires_grad=True)

        with qml.tape.JacobianTape() as tape:
            qml.Squeezing(params[0], 0, wires=0)
            qml.Rotation(params[1], wires=0)
            qml.var(qml.X(wires=[0]))

        tape.trainable_params = {0, 2}
        tapes, fn = qml.gradients.param_shift_cv(tape, dev)
        jac = fn(
            qml.execute(tapes,
                        dev,
                        param_shift_cv,
                        gradient_kwargs={"dev": dev},
                        interface="torch"))

        r, phi = params.detach().numpy()

        expected = np.array([
            2 * np.exp(2 * r) * np.sin(phi)**2 -
            2 * np.exp(-2 * r) * np.cos(phi)**2,
            2 * np.sinh(2 * r) * np.sin(2 * phi),
        ])
        assert np.allclose(jac.detach().numpy(), expected, atol=tol, rtol=0)

        cost = jac[0, 1]
        cost.backward()
        hess = params.grad
        expected = np.array([
            4 * np.cosh(2 * r) * np.sin(2 * phi),
            4 * np.cos(2 * phi) * np.sinh(2 * r)
        ])
        assert np.allclose(hess.detach().numpy(), expected, atol=0.1, rtol=0)
Example #25
0
    def test_tf(self, tol):
        """Tests that the output of the parameter-shift CV transform
        can be executed using TF"""
        tf = pytest.importorskip("tensorflow")

        dev = qml.device("default.gaussian", wires=1)
        params = tf.Variable([0.543, -0.654], dtype=tf.float64)

        with tf.GradientTape() as t:
            with qml.tape.JacobianTape() as tape:
                qml.Squeezing(params[0], 0, wires=0)
                qml.Rotation(params[1], wires=0)
                qml.var(qml.X(wires=[0]))

            tape.trainable_params = {0, 2}
            tapes, fn = param_shift_cv(tape, dev)
            jac = fn(
                qml.execute(tapes,
                            dev,
                            param_shift_cv,
                            gradient_kwargs={"dev": dev},
                            interface="tf"))
            res = jac[0, 1]

        r, phi = 1.0 * params

        expected = np.array([
            2 * np.exp(2 * r) * np.sin(phi)**2 -
            2 * np.exp(-2 * r) * np.cos(phi)**2,
            2 * np.sinh(2 * r) * np.sin(2 * phi),
        ])
        assert np.allclose(jac, expected, atol=tol, rtol=0)

        grad = t.jacobian(res, params)
        expected = np.array([
            4 * np.cosh(2 * r) * np.sin(2 * phi),
            4 * np.cos(2 * phi) * np.sinh(2 * r)
        ])
        assert np.allclose(grad, expected, atol=tol, rtol=0)
    def test_torch(self, tol):
        """Tests that the output of the parameter-shift CV transform
        can be executed using Torch."""
        torch = pytest.importorskip("torch")
        from pennylane.interfaces.torch import TorchInterface

        dev = qml.device("default.gaussian", wires=1)
        params = torch.tensor([0.543, -0.654],
                              dtype=torch.float64,
                              requires_grad=True)

        with TorchInterface.apply(qml.tape.CVParamShiftTape()) as tape:
            qml.Squeezing(params[0], 0, wires=0)
            qml.Rotation(params[1], wires=0)
            qml.var(qml.X(wires=[0]))

        tapes, fn = qml.gradients.param_shift_cv(tape, dev)
        jac = fn([t.execute(dev) for t in tapes])

        r, phi = params.detach().numpy()

        expected = np.array([
            2 * np.exp(2 * r) * np.sin(phi)**2 -
            2 * np.exp(-2 * r) * np.cos(phi)**2,
            2 * np.sinh(2 * r) * np.sin(2 * phi),
        ])
        assert np.allclose(jac.detach().numpy(), expected, atol=tol, rtol=0)

        cost = jac[0, 1]
        cost.backward()
        hess = params.grad
        expected = np.array([
            4 * np.cosh(2 * r) * np.sin(2 * phi),
            4 * np.cos(2 * phi) * np.sinh(2 * r)
        ])
        assert np.allclose(hess.detach().numpy(), expected, atol=0.1, rtol=0)