Ejemplo n.º 1
0
    def test_cv_gradients_parameters_inside_array(self, tol):
        """Tests that free parameters inside an array passed to an Operation yield correct gradients."""
        gaussian_dev = qml.device("default.gaussian", wires=2)
        par = [0.4, 1.3]

        def qf(x, y):
            qml.Displacement(0.5, 0, wires=[0])
            qml.Squeezing(x, 0, wires=[0])
            M = np.zeros((5, 5), dtype=object)
            M[1, 1] = y
            M[1, 2] = 1.0
            M[2, 1] = 1.0
            return qml.expval(qml.PolyXP(M, [0, 1]))

        q = CVQNode(qf, gaussian_dev)

        grad_best = q.jacobian(par)
        grad_best2 = q.jacobian(par, options={"force_order2": True})
        grad_F = q.jacobian(par, method="F")

        # par[0] can use the "A" method, par[1] cannot
        assert q.par_to_grad_method == {0: "A", 1: "F"}
        # the different methods agree
        assert grad_best == pytest.approx(grad_F, abs=tol)
        assert grad_best2 == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 2
0
    def test_cv_gradients_multiple_gate_parameters(self, tol):
        """Tests that gates with multiple free parameters yield correct gradients."""

        gaussian_dev = qml.device("default.gaussian", wires=2)

        def qf(r0, phi0, r1, phi1):
            qml.Squeezing(r0, phi0, wires=[0])
            qml.Squeezing(r1, phi1, wires=[0])
            return qml.expval(qml.NumberOperator(0))

        q = CVQNode(qf, gaussian_dev)
        par = [0.4, -0.3, -0.7, 0.2]

        grad_F = q.jacobian(par, method="F")
        grad_A = q.jacobian(par, method="A")
        grad_A2 = q.jacobian(par, method="A", options={'force_order2': True})
        # analytic method works for every parameter
        assert q.par_to_grad_method == {i: "A" for i in range(4)}
        # the different methods agree
        assert grad_A == pytest.approx(grad_F, abs=tol)
        assert grad_A2 == pytest.approx(grad_F, abs=tol)

        # check against the known analytic formula
        r0, phi0, r1, phi1 = par
        dn = np.zeros([4])
        dn[0] = np.cosh(2 * r1) * np.sinh(
            2 * r0) + np.cos(phi0 - phi1) * np.cosh(2 * r0) * np.sinh(2 * r1)
        dn[1] = -0.5 * np.sin(phi0 - phi1) * np.sinh(2 * r0) * np.sinh(2 * r1)
        dn[2] = np.cos(phi0 - phi1) * np.cosh(2 * r1) * np.sinh(
            2 * r0) + np.cosh(2 * r0) * np.sinh(2 * r1)
        dn[3] = 0.5 * np.sin(phi0 - phi1) * np.sinh(2 * r0) * np.sinh(2 * r1)
        assert dn[np.newaxis, :] == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 3
0
    def test_second_order_obs_not_following_gate(self, tol):
        """Parshift differentiation method matches finite diff and analytical result
        when we have order-2 observables that do not follow the parametrized gate.
        """
        num_wires = 2
        dev = qml.device("default.gaussian", wires=2)

        def circuit(params):
            for i in range(num_wires):
                qml.Squeezing(params[i], 0, wires=i)
            return [
                qml.expval(qml.NumberOperator(wires=i))
                for i in range(num_wires)
            ]

        node = CVQNode(circuit, dev)
        par = [0.321, -0.184]

        res = node(par)
        res_true = np.sinh(np.abs(par))**2  # analytical result
        assert res == pytest.approx(res_true, abs=tol)

        grad_A = node.jacobian([par], method="A")
        grad_F = node.jacobian([par], method="F")
        grad_true = np.diag(np.sinh(2 * np.abs(par)) *
                            np.sign(par))  # analytical gradient
        assert grad_A == pytest.approx(grad_F, abs=tol)
        assert grad_A == pytest.approx(grad_true, abs=tol)
Ejemplo n.º 4
0
    def test_first_order_cv(self, tol):
        """Test variance of a first order CV expectation value"""
        dev = qml.device("default.gaussian", wires=1)

        def circuit(r, phi):
            qml.Squeezing(r, 0, wires=0)
            qml.Rotation(phi, wires=0)
            return qml.var(qml.X(0))

        circuit = CVQNode(circuit, dev)

        r = 0.543
        phi = -0.654
        var = circuit(r, phi)
        expected = np.exp(2 * r) * np.sin(phi)**2 + np.exp(
            -2 * r) * np.cos(phi)**2
        assert var == pytest.approx(expected, abs=tol)

        # circuit jacobians
        gradA = circuit.jacobian([r, phi], method="A")
        gradF = circuit.jacobian([r, phi], method="F")
        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 gradA == pytest.approx(expected, abs=tol)
        assert gradF == pytest.approx(expected, abs=tol)
Ejemplo n.º 5
0
def test_transform_observable_incorrect_heisenberg_size():
    """The number of dimensions of a CV observable Heisenberg representation does
    not match the ev_order attribute."""
    class P(CVObservable):
        """Dummy CV observable with incorrect ev_order"""
        num_wires = 1
        num_params = 0
        par_domain = None
        ev_order = 2

        @staticmethod
        def _heisenberg_rep(p):
            return np.array([0, 1, 0])

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

    def circuit(x):
        qml.Displacement(x, 0.1, wires=0)
        return qml.expval(P(0))

    node = CVQNode(circuit, dev)

    with pytest.raises(QuantumFunctionError,
                       match="Mismatch between the polynomial order"):
        node.jacobian([0.5])
Ejemplo n.º 6
0
    def test_error_unsupported_grad_recipe(self, monkeypatch):
        """Test exception raised if attempting to use the second order rule for
        computing the gradient analytically of an expectation value that
        contains an operation with an more than two terms in the gradient recipe"""
        class DummyOp(qml.operation.CVOperation):
            num_wires = 1
            num_params = 1
            par_domain = "R"
            grad_method = "A"
            grad_recipe = ([[1, 1, 1], [1, 1, 1], [1, 1, 1]], )

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

        dev._operation_map["DummyOp"] = None

        def circuit(a):
            DummyOp(a, wires=[0])
            return qml.expval(qml.NumberOperator(0))

        with monkeypatch.context() as m:
            circuit = CVQNode(circuit, dev, force_order2=True)

            m.setattr(circuit, "_best_method", lambda arg: "A")
            with pytest.raises(
                    NotImplementedError,
                    match=
                    r"analytic gradient for order-2 operators is unsupported"):
                grad_A = circuit.jacobian(0,
                                          method="A",
                                          options={'force_order2': True})
Ejemplo n.º 7
0
    def test_param_no_observables(self, operable_mock_CV_device_2_wires):
        """Tests that a parameter has 0 gradient if it is not followed by any observables"""
        par = [0.4]

        def qf(x):
            qml.Displacement(x, 0, wires=[0])
            qml.Squeezing(0.3, x, wires=[0])
            qml.Rotation(1.3, wires=[1])
            return qml.expval(qml.X(1))

        q = CVQNode(qf, operable_mock_CV_device_2_wires)
        q._construct(par, {})
        assert q.par_to_grad_method == {0: "0"}
Ejemplo n.º 8
0
    def test_param_not_differentiable(self, operable_mock_CV_device_2_wires):
        """Tests that a parameter is not differentiable if used in an operation
        where grad_method=None"""
        par = [0.4]

        def qf(x):
            qml.FockState(x, wires=[0])
            qml.Rotation(1.3, wires=[0])
            return qml.expval(qml.X(0))

        q = CVQNode(qf, operable_mock_CV_device_2_wires)
        q._construct(par, {})
        assert q.par_to_grad_method == {0: None}
Ejemplo n.º 9
0
    def test_correct_method_non_gaussian_preceeding_one_param(
            self, operable_mock_CV_device_2_wires):
        """Tests that a non-Gaussian preceeding one parameter fallsback to finite-diff"""
        par = [0.4, -2.3]

        def qf(x, y):
            qml.Kerr(y, wires=[1])
            qml.Displacement(x, 0, wires=[0])
            qml.Beamsplitter(0.2, 1.7, wires=[0, 1])
            return qml.expval(qml.X(0)), qml.expval(qml.X(1))

        q = CVQNode(qf, operable_mock_CV_device_2_wires)
        q._construct(par, {})
        assert q.par_to_grad_method == {0: "A", 1: "F"}
Ejemplo n.º 10
0
    def test_error_analytic_second_order_cv(self):
        """Test exception raised if attempting to use a second
        order observable to compute the variance derivative analytically"""
        dev = qml.device("default.gaussian", wires=1)

        def circuit(a):
            qml.Displacement(a, 0, wires=0)
            return qml.var(qml.NumberOperator(0))

        circuit = CVQNode(circuit, dev)

        with pytest.raises(ValueError,
                           match=r"cannot be used with the parameters \{0\}"):
            circuit.jacobian([1.0], method="A")
Ejemplo n.º 11
0
    def test_non_gaussian_obs_predecessor(self, gaussian_device, tol):
        """Parshift differentiation method is allowed and matches finite diff
        if a non-Gaussian gate precedes an observable but is not preceded by the parametrized gate."""
        def circuit(x):
            qml.Squeezing(x, 0, wires=[0])
            qml.Kerr(0.54, wires=[1])  # nongaussian
            qml.Beamsplitter(1.1, 0, wires=[0, 1])
            return qml.expval(qml.NumberOperator(0))

        node = CVQNode(circuit, gaussian_device)
        par = [0.321]

        grad_A = node.jacobian(par, wrt=[0], method="A")
        grad_F = node.jacobian(par, method="F")
        assert grad_A == pytest.approx(grad_F, abs=tol)
        assert node.par_to_grad_method == {0: "A"}
Ejemplo n.º 12
0
    def test_correct_method_non_gaussian_successor_one_param(
            self, operable_mock_CV_device_2_wires):
        """Tests that a non-Gaussian succeeding a parameter fallsback to finite-diff"""
        par = [0.4, -2.3]

        def qf(x, y):
            qml.Displacement(x, 0, wires=[0])
            qml.CubicPhase(0.2, wires=[0])
            qml.Squeezing(0.3, y, wires=[1])
            qml.Rotation(1.3, wires=[1])
            # nongaussian succeeding x but not y
            return qml.expval(qml.X(0)), qml.expval(qml.X(1))

        q = CVQNode(qf, operable_mock_CV_device_2_wires)
        q._construct(par, {})
        assert q.par_to_grad_method == {0: "F", 1: "A"}
Ejemplo n.º 13
0
    def test_correct_method_non_gaussian_observable(
            self, operable_mock_CV_device_2_wires):
        """Tests that a non-Gaussian observable one parameter fallsback to finite-diff"""
        par = [0.4, -2.3]

        def qf(x, y):
            qml.Displacement(x, 0,
                             wires=[0])  # followed by nongaussian observable
            qml.Beamsplitter(0.2, 1.7, wires=[0, 1])
            qml.Displacement(y, 0, wires=[1])  # followed by order-2 observable
            return qml.expval(qml.FockStateProjector(np.array([2]),
                                                     0)), qml.expval(
                                                         qml.NumberOperator(1))

        q = CVQNode(qf, operable_mock_CV_device_2_wires)
        q._construct(par, {})
        assert q.par_to_grad_method == {0: "F", 1: "A"}
Ejemplo n.º 14
0
    def test_gradient_gate_with_two_parameters(self, tol):
        """Gates with two parameters yield the correct parshift gradient."""

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

        def qf(r0, phi0, r1, phi1):
            qml.Squeezing(r0, phi0, wires=[0])
            qml.Squeezing(r1, phi1, wires=[0])
            return qml.expval(qml.NumberOperator(0))

        q = CVQNode(qf, dev)
        par = [0.543, 0.123, 0.654, -0.629]

        grad_A = q.jacobian(par, method="A")
        grad_F = q.jacobian(par, method="F")
        # the different methods agree
        assert grad_A == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 15
0
    def test_gaussian_successors_fails(self, operable_mock_CV_device_2_wires):
        """Tests that the parameter-shift differentiation method is not allowed
        if a non-gaussian gate is between a differentiable gaussian gate and an observable."""
        def circuit(x):
            qml.Squeezing(x, 0, wires=[0])
            qml.Beamsplitter(np.pi / 4, 0, wires=[0, 1])
            qml.Kerr(0.54, wires=[1])
            return qml.expval(qml.NumberOperator(1))

        node = CVQNode(circuit, operable_mock_CV_device_2_wires)

        with pytest.raises(
                ValueError,
                match="analytic gradient method cannot be used with"):
            node.jacobian([0.321], method="A")

        assert node.par_to_grad_method == {0: "F"}
Ejemplo n.º 16
0
    def test_correct_method_non_gaussian_successor_all_params(
            self, operable_mock_CV_device_2_wires):
        """Tests that a non-Gaussian succeeding all parameters fallsback to finite-diff"""
        par = [0.4, -2.3]

        def qf(x, y):
            qml.Displacement(x, 0, wires=[0])
            qml.Displacement(1.2, y, wires=[1])
            qml.Beamsplitter(0.2, 1.7, wires=[0, 1])
            qml.Rotation(1.9, wires=[0])
            qml.Kerr(0.3, wires=[
                1
            ])  # nongaussian succeeding both x and y due to the beamsplitter
            return qml.expval(qml.X(0)), qml.expval(qml.X(1))

        q = CVQNode(qf, operable_mock_CV_device_2_wires)
        q._construct(par, {})
        assert q.par_to_grad_method == {0: "F", 1: "F"}
Ejemplo n.º 17
0
    def test_CVOperation_with_heisenberg_and_no_parshift(self, name, tol):
        """An integration test for Gaussian CV gates that have a Heisenberg representation
        but cannot be differentiated using the parameter-shift method themselves
        (for example, they may accept no parameters, or have no gradient recipe).

        Tests that the parameter-shift method can still be used with other gates in the circuit.
        """
        gaussian_dev = qml.device("default.gaussian", wires=2)

        cls = getattr(qml.ops, name)
        if cls.supports_heisenberg and (not cls.supports_parameter_shift):
            U = np.array(
                [[0.51310276 + 0.81702166j, 0.13649626 + 0.22487759j],
                 [0.26300233 + 0.00556194j, -0.96414101 - 0.03508489j]])

            if cls.num_wires <= 0:
                w = list(range(2))
            else:
                w = list(range(cls.num_wires))

            def circuit(x):
                qml.Displacement(x, 0, wires=0)

                if cls.par_domain == "A":
                    cls(U, wires=w)
                else:
                    cls(wires=w)
                return qml.expval(qml.X(0))

            qnode = CVQNode(circuit, gaussian_dev)
            grad_F = qnode.jacobian(0.5, method="F")
            grad_A = qnode.jacobian(0.5, method="A")
            grad_A2 = qnode.jacobian(0.5,
                                     method="A",
                                     options={'force_order2': True})

            # par[0] can use the "A" method
            assert qnode.par_to_grad_method == {0: "A"}

            # the different methods agree
            assert grad_A == pytest.approx(grad_F, abs=tol)
            assert grad_A2 == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 18
0
    def test_keywordarg_second_order_cv(self, tol):
        """Non-differentiable keyword arguments with a second order CV expectation value."""

        dev = qml.device("default.gaussian", wires=3)

        def circuit(x, *, k=0.0):
            qml.Displacement(x, 0, wires=0)
            qml.Rotation(k, wires=0)
            return qml.expval(qml.PolyXP(np.diag([0, 1, 0]), wires=0))  # X^2

        node = CVQNode(circuit, dev)
        par = [0.62]
        aux = {'k': 0.4}

        # circuit jacobians
        grad_A = node.jacobian(par, aux, method="A")
        grad_F = node.jacobian(par, aux, method="F")
        expected = np.array([[8 * par[0] * np.cos(aux['k'])**2]])
        assert grad_A == pytest.approx(grad_F, abs=tol)
        assert grad_A == pytest.approx(expected, abs=tol)
Ejemplo n.º 19
0
    def test_cv_gradients_repeated_gate_parameters(self, tol):
        """Tests that repeated use of a free parameter in a multi-parameter gate yield correct gradients."""
        gaussian_dev = qml.device("default.gaussian", wires=2)
        par = [0.2, 0.3]

        def qf(x, y):
            qml.Displacement(x, 0, wires=[0])
            qml.Squeezing(y, -1.3 * y, wires=[0])
            return qml.expval(qml.X(0))

        q = CVQNode(qf, gaussian_dev)
        grad_F = q.jacobian(par, method="F")
        grad_A = q.jacobian(par, method="A")
        grad_A2 = q.jacobian(par, method="A", options={'force_order2': True})

        # analytic method works for every parameter
        assert q.par_to_grad_method == {0: "A", 1: "A"}
        # the different methods agree
        assert grad_A == pytest.approx(grad_F, abs=tol)
        assert grad_A2 == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 20
0
    def test_expval_and_variance_cv(self, tol):
        """Test that the qnode works for a combination of CV expectation
        values and variances"""
        dev = qml.device("default.gaussian", wires=3)

        def circuit(a, b):
            qml.Displacement(0.5, 0, wires=0)
            qml.Squeezing(a, 0, wires=0)
            qml.Squeezing(b, 0, wires=1)
            qml.Beamsplitter(0.6, -0.3, wires=[0, 1])
            qml.Squeezing(-0.3, 0, wires=2)
            qml.Beamsplitter(1.4, 0.5, wires=[1, 2])
            return qml.var(qml.X(0)), qml.expval(qml.X(1)), qml.var(qml.X(2))

        node = CVQNode(circuit, dev)
        par = [0.54, -0.423]

        # jacobians must match
        gradA = node.jacobian(par, method="A")
        gradF = node.jacobian(par, method="F")
        assert gradA == pytest.approx(gradF, abs=tol)
Ejemplo n.º 21
0
    def test_second_order_cv(self, tol):
        """Test variance of a second order CV expectation value"""
        dev = qml.device("default.gaussian", wires=1)

        def circuit(n, a):
            qml.ThermalState(n, wires=0)
            qml.Displacement(a, 0, wires=0)
            return qml.var(qml.NumberOperator(0))

        circuit = CVQNode(circuit, dev)

        n = 0.12
        a = 0.765
        var = circuit(n, a)
        expected = n**2 + n + np.abs(a)**2 * (1 + 2 * n)
        assert var == pytest.approx(expected, abs=tol)

        # circuit jacobians
        gradF = circuit.jacobian([n, a], method="F")
        expected = np.array([[2 * a**2 + 2 * n + 1, 2 * a * (2 * n + 1)]])
        assert gradF == pytest.approx(expected, abs=tol)
Ejemplo n.º 22
0
    def test_quadoperator(self, tol):
        """Test the differentiation of CV observables that depend on positional qfunc parameters."""
        def circuit(a):
            qml.Displacement(1.0, 0, wires=0)
            return qml.expval(qml.QuadOperator(a, 0))

        gaussian_dev = qml.device("default.gaussian", wires=1)
        qnode = CVQNode(circuit, gaussian_dev)

        par = [0.6]
        grad_F = qnode.jacobian(par, method='F')
        grad_A = qnode.jacobian(par, method='A')
        grad_A2 = qnode.jacobian(par,
                                 method='A',
                                 options={'force_order2': True})

        # par 0 can use the 'A' method
        assert qnode.par_to_grad_method == {0: 'A'}
        # the different methods agree
        assert grad_A == pytest.approx(grad_F, abs=tol)
        assert grad_A2 == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 23
0
    def test_cv_gradients_gaussian_circuit(self, G, O, tol):
        """Tests that the gradients of circuits of gaussian gates match between the finite difference and analytic methods."""
        gaussian_dev = qml.device("default.gaussian", wires=2)

        tol = 1e-5
        par = [0.4]

        def circuit(x):
            args = [0.3] * G.num_params
            args[0] = x
            qml.Displacement(0.5, 0, wires=0)
            G(*args, wires=range(G.num_wires))
            qml.Beamsplitter(1.3, -2.3, wires=[0, 1])
            qml.Displacement(-0.5, 0.1, wires=0)
            qml.Squeezing(0.5, -1.5, wires=0)
            qml.Rotation(-1.1, wires=0)
            return qml.expval(O(wires=0))

        q = CVQNode(circuit, gaussian_dev)
        val = q.evaluate(par, {})

        grad_F = q.jacobian(par, method="F")
        grad_A2 = q.jacobian(par, method="A", options={'force_order2': True})
        if O.ev_order == 1:
            grad_A = q.jacobian(par, method="A")
            # the different methods agree
            assert grad_A == pytest.approx(grad_F, abs=tol)

        # analytic method works for every parameter
        assert q.par_to_grad_method == {0: "A"}
        # the different methods agree
        assert grad_A2 == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 24
0
    def test_cv_gradient_fanout(self, tol):
        """Tests that CV qnodes can compute the correct gradient when the same parameter is used
        in multiple gates."""
        gaussian_dev = qml.device("default.gaussian", wires=2)
        par = [0.5, 1.3]

        def circuit(x, y):
            qml.Displacement(x, 0, wires=[0])
            qml.Rotation(y, wires=[0])
            qml.Displacement(0, x, wires=[0])
            return qml.expval(qml.X(0))

        q = CVQNode(circuit, gaussian_dev)
        grad_F = q.jacobian(par, method="F")
        grad_A = q.jacobian(par, method="A")
        grad_A2 = q.jacobian(par, method="A", options={'force_order2': True})

        # analytic method works for every parameter
        assert q.par_to_grad_method == {0: "A", 1: "A"}
        # the different methods agree
        assert grad_A == pytest.approx(grad_F, abs=tol)
        assert grad_A2 == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 25
0
    def test_keywordarg_with_positional_arg_immutable_second_order_cv(
            self, tol):
        """Non-differentiable keyword arguments appear in the same op with differentiable arguments,
        qfunc is immutable so kwargs are passed as Variables."""

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

        def circuit(x, *, k=0.0):
            qml.Displacement(0.5, 0, wires=0)
            qml.Squeezing(x, k, wires=0)
            return qml.expval(qml.X(0))

        node = CVQNode(circuit, dev, mutable=False)
        par = [0.39]
        aux = {'k': -0.7}

        # circuit jacobians
        grad_A = node.jacobian(par,
                               aux,
                               method="A",
                               options={'force_order2': True})
        grad_F = node.jacobian(par, aux, method="F")
        assert grad_A == pytest.approx(grad_F, abs=tol)
Ejemplo n.º 26
0
    def test_number_state_gradient(self, r, tol):
        """Tests that the automatic gradient of a squeezed state with number state expectation is correct."""

        def circuit(y):
            qml.Squeezing(y, 0., wires=[0])
            return qml.expval(qml.FockStateProjector(np.array([2, 0]), wires=[0, 1]))

        dev = qml.device('default.gaussian', wires=2)
        circuit = to_autograd(CVQNode(circuit, dev))
        grad_fn = autograd.grad(circuit)

        # (d/dr) |<2|S(r)>|^2 = 0.5 tanh(r)^3 (2 csch(r)^2 - 1) sech(r)
        autograd_val = grad_fn(r)
        manualgrad_val = 0.5*np.tanh(r)**3 * (2/(np.sinh(r)**2)-1) / np.cosh(r)
        assert autograd_val == pytest.approx(manualgrad_val, abs=tol)
Ejemplo n.º 27
0
    def test_squeeze_gradient(self, r, tol):
        """Tests that the automatic gradient of a phase space squeezing is correct."""
        def circuit(y):
            qml.Displacement(alpha, 0., wires=[0])
            qml.Squeezing(y, 0., wires=[0])
            return qml.expval(qml.X(0))

        dev = qml.device('default.gaussian', wires=1)
        circuit = to_autograd(CVQNode(circuit, dev))
        grad_fn = autograd.grad(circuit)

        autograd_val = grad_fn(r)
        # qfunc evaluates to -exp(-r) * hbar * Re(alpha)
        manualgrad_val = -np.exp(-r) * hbar * alpha
        assert autograd_val == pytest.approx(manualgrad_val, abs=tol)
Ejemplo n.º 28
0
    def test_beamsplitter_gradient(self, theta, tol):
        """Tests that the automatic gradient of a beamsplitter is correct."""
        def circuit(y):
            qml.Displacement(alpha, 0., wires=[0])
            qml.Beamsplitter(y, 0, wires=[0, 1])
            return qml.expval(qml.X(0))

        dev = qml.device('default.gaussian', wires=2)
        circuit = to_autograd(CVQNode(circuit, dev))
        grad_fn = autograd.grad(circuit)

        autograd_val = grad_fn(theta)
        # qfunc evalutes to hbar * alpha * cos(theta)
        manualgrad_val = -hbar * alpha * np.sin(theta)
        assert autograd_val == pytest.approx(manualgrad_val, abs=tol)
Ejemplo n.º 29
0
    def test_displacement_gradient(self, mag, theta, tol):
        """Tests that the automatic gradient of a phase space displacement is correct."""
        def circuit(r, phi):
            qml.Displacement(r, phi, wires=[0])
            return qml.expval(qml.X(0))

        dev = qml.device('default.gaussian', wires=1)
        circuit = to_autograd(CVQNode(circuit, dev))
        grad_fn = autograd.grad(circuit)

        #alpha = mag * np.exp(1j * theta)
        autograd_val = grad_fn(mag, theta)
        # qfunc evalutes to hbar * Re(alpha)
        manualgrad_val = hbar * np.cos(theta)
        assert autograd_val == pytest.approx(manualgrad_val, abs=tol)