예제 #1
0
    def test_one_qubit_wavefunction_circuit(self, device, qvm, compiler):
        """Test that the wavefunction plugin provides correct result for simple circuit.

        As the results coming from the qvm are stochastic, a constraint of 2 out of 5 runs was added.
        """
        shots = 100_000
        dev = qml.device("forest.qvm", device=device, shots=QVM_SHOTS)

        a = 0.543
        b = 0.123
        c = 0.987

        @qml.qnode(dev)
        def circuit(x, y, z):
            """Reference QNode"""
            qml.BasisState(np.array([1]), wires=0)
            qml.Hadamard(wires=0)
            qml.Rot(x, y, z, wires=0)
            return qml.expval(qml.PauliZ(0))

        self.assertAlmostEqual(circuit(a, b, c), np.cos(a) * np.sin(b), delta=3 / np.sqrt(shots))
예제 #2
0
    def test_state_differentiability(self, tol):
        """Test that the device state can be differentiated"""
        dev = qml.device("default.qubit.autograd", wires=1)

        @qml.qnode(dev, diff_method="backprop", interface="autograd")
        def circuit(a):
            qml.RY(a, wires=0)
            return qml.expval(qml.PauliZ(0))

        a = np.array(0.54, requires_grad=True)

        def cost(a):
            """A function of the device quantum state, as a function
            of input QNode parameters."""
            circuit(a)
            res = np.abs(dev.state)**2
            return res[1] - res[0]

        grad = qml.grad(cost)(a)
        expected = np.sin(a)
        assert np.allclose(grad, expected, atol=tol, rtol=0)
예제 #3
0
    def test_beamsplitter(self):
        """Test the beamsplitter symplectic transform."""
        self.logTestName()

        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)
        self.assertAllAlmostEqual(out, expected, delta=self.tol)
예제 #4
0
    def test_matrix_parameter(self, mocker, tol):
        """Test jacobian computation when the tape includes a matrix parameter"""
        spy = mocker.spy(QuantumTape, "jacobian")
        U = np.array([[0, 1], [1, 0]], requires_grad=False)
        a = np.array(0.1, requires_grad=True)

        def cost(a, U, device):
            with QuantumTape() as tape:
                qml.QubitUnitary(U, wires=0)
                qml.RY(a, wires=0)
                expval(qml.PauliZ(0))
            return tape.execute(device)

        dev = qml.device("default.qubit.autograd", wires=2)
        res = cost(a, U, device=dev)
        assert np.allclose(res, -np.cos(a), atol=tol, rtol=0)

        jac_fn = qml.jacobian(cost)
        res = jac_fn(a, U, device=dev)
        assert np.allclose(res, np.sin(a), atol=tol, rtol=0)
        spy.assert_not_called()
예제 #5
0
    def test_pauliy_expectation(self, shots, qvm, compiler):
        """Test that PauliY expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)
        dev.apply("RX", wires=[0], par=[theta])
        dev.apply("RX", wires=[1], par=[phi])
        dev.apply("CNOT", wires=[0, 1], par=[])

        O = qml.PauliY
        name = "PauliY"

        dev._obs_queue = [O(wires=[0], do_queue=False), O(wires=[1], do_queue=False)]
        dev.pre_measure()

        # below are the analytic expectation values for this circuit
        res = np.array([dev.expval(name, [0], []), dev.expval(name, [1], [])])
        self.assertAllAlmostEqual(
            res, np.array([0, -np.cos(theta) * np.sin(phi)]), delta=3 / np.sqrt(shots)
        )
예제 #6
0
    def test_matrix_parameter(self, tol):
        """Test that the autograd interface works correctly
        with a matrix parameter"""
        U = np.array([[0, 1], [1, 0]], requires_grad=False)
        a = np.array(0.1, requires_grad=True)

        def cost(a, U, device):
            with AutogradInterface.apply(QuantumTape()) as tape:
                qml.QubitUnitary(U, wires=0)
                qml.RY(a, wires=0)
                expval(qml.PauliZ(0))
            assert tape.trainable_params == {1}
            return tape.execute(device)

        dev = qml.device("default.qubit", wires=2)
        res = cost(a, U, device=dev)
        assert np.allclose(res, -np.cos(a), atol=tol, rtol=0)

        jac_fn = qml.jacobian(cost)
        res = jac_fn(a, U, device=dev)
        assert np.allclose(res, np.sin(a), atol=tol, rtol=0)
예제 #7
0
    def test_matrix_parameter(self, dev_name, diff_method, tol):
        """Test that the autograd interface works correctly
        with a matrix parameter"""
        U = np.array([[0, 1], [1, 0]], requires_grad=False)
        a = np.array(0.1, requires_grad=True)

        dev = qml.device(dev_name, wires=2)

        @qnode(dev, diff_method=diff_method, interface="autograd")
        def circuit(U, a):
            qml.QubitUnitary(U, wires=0)
            qml.RY(a, wires=0)
            return qml.expval(qml.PauliZ(0))

        res = circuit(U, a)

        if diff_method == "finite-diff":
            assert circuit.qtape.trainable_params == {1}

        res = qml.grad(circuit)(U, a)
        assert np.allclose(res, np.sin(a), atol=tol, rtol=0)
예제 #8
0
    def test_parameter_shift_hessian(self, params, tol, recwarn):
        """Tests that the output of the parameter-shift transform
        can be differentiated using autograd, yielding second derivatives."""
        dev = qml.device("default.qubit.autograd", wires=2)
        params = np.array([0.543, -0.654], requires_grad=True)

        def cost_fn(x):
            with qml.tape.JacobianTape() as tape1:
                qml.RX(x[0], wires=[0])
                qml.RY(x[1], wires=[1])
                qml.CNOT(wires=[0, 1])
                qml.var(qml.PauliZ(0) @ qml.PauliX(1))

            with qml.tape.JacobianTape() as tape2:
                qml.RX(x[0], wires=0)
                qml.RY(x[0], wires=1)
                qml.CNOT(wires=[0, 1])
                qml.probs(wires=1)

            result = execute([tape1, tape2],
                             dev,
                             gradient_fn=param_shift,
                             max_diff=2)
            return result[0] + result[1][0, 0]

        res = cost_fn(params)
        x, y = params
        expected = 0.5 * (3 + np.cos(x)**2 * np.cos(2 * y))
        assert np.allclose(res, expected, atol=tol, rtol=0)

        res = qml.grad(cost_fn)(params)
        expected = np.array([
            -np.cos(x) * np.cos(2 * y) * np.sin(x),
            -np.cos(x)**2 * np.sin(2 * y)
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)

        res = qml.jacobian(qml.grad(cost_fn))(params)
        expected = np.array([
            [-np.cos(2 * x) * np.cos(2 * y),
             np.sin(2 * x) * np.sin(2 * y)],
            [np.sin(2 * x) * np.sin(2 * y), -2 * np.cos(x)**2 * np.cos(2 * y)],
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)

        # Check that no deprecation warnigns are emitted due to trainable
        # parameters with the Autograd interface
        assert len(recwarn) == 0
예제 #9
0
    def test_multiple_expectation_values(self, tol, dev):
        """Tests correct output shape and evaluation for a tape
        with multiple expval outputs"""
        x = 0.543
        y = -0.654

        with qml.tape.QuantumTape() as tape:
            qml.RX(x, wires=[0])
            qml.RY(y, wires=[1])
            qml.CNOT(wires=[0, 1])
            qml.expval(qml.PauliZ(0))
            qml.expval(qml.PauliX(1))

        tape.trainable_params = {0, 1}
        dy = np.array([1.0, 2.0])

        fn = dev.vjp(tape.measurements, dy)
        vjp = fn(tape)

        expected = np.array([-np.sin(x), 2 * np.cos(y)])
        assert np.allclose(vjp, expected, atol=tol, rtol=0)
예제 #10
0
    def test_hessian_unused_parameter(self, dev_name, diff_method, mocker,
                                      tol):
        """Test hessian calculation of a scalar valued QNode"""
        if diff_method not in {"parameter-shift", "backprop"}:
            pytest.skip("Test only supports parameter-shift or backprop")

        dev = qml.device(dev_name, wires=1)

        @qnode(dev, diff_method=diff_method, interface="autograd")
        def circuit(x):
            qml.RY(x[0], wires=0)
            return qml.expval(qml.PauliZ(0))

        x = np.array([1.0, 2.0], requires_grad=True)
        res = circuit(x)

        a, b = x

        expected_res = np.cos(a)
        assert np.allclose(res, expected_res, atol=tol, rtol=0)

        grad_fn = qml.grad(circuit)
        g = grad_fn(x)

        expected_g = [-np.sin(a), 0]
        assert np.allclose(g, expected_g, atol=tol, rtol=0)

        spy = mocker.spy(JacobianTape, "hessian")
        hess = qml.jacobian(grad_fn)(x)

        if diff_method == "backprop":
            spy.assert_not_called()
        elif diff_method == "parameter-shift":
            spy.assert_called_once()

        expected_hess = [
            [-np.cos(a), 0],
            [0, 0],
        ]
        assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
예제 #11
0
    def test_probability_differentiation(self, execute_kwargs, tol):
        """Tests correct output shape and evaluation for a tape
        with prob outputs"""

        if execute_kwargs["gradient_fn"] == "device":
            pytest.skip(
                "Adjoint differentiation does not yet support probabilities")

        def cost(x, y, device):
            with qml.tape.JacobianTape() as tape:
                qml.RX(x, wires=[0])
                qml.RY(y, wires=[1])
                qml.CNOT(wires=[0, 1])
                qml.probs(wires=[0])
                qml.probs(wires=[1])

            return execute([tape], device, **execute_kwargs)[0]

        dev = qml.device("default.qubit", wires=2)
        x = np.array(0.543, requires_grad=True)
        y = np.array(-0.654, requires_grad=True)

        res = cost(x, y, device=dev)
        expected = np.array([
            [np.cos(x / 2)**2, np.sin(x / 2)**2],
            [(1 + np.cos(x) * np.cos(y)) / 2, (1 - np.cos(x) * np.cos(y)) / 2],
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)

        jac_fn = qml.jacobian(cost)
        res = jac_fn(x, y, device=dev)
        assert res.shape == (2, 2, 2)

        expected = np.array([
            [[-np.sin(x) / 2, 0], [np.sin(x) / 2, 0]],
            [
                [-np.sin(x) * np.cos(y) / 2, -np.cos(x) * np.sin(y) / 2],
                [np.cos(y) * np.sin(x) / 2,
                 np.cos(x) * np.sin(y) / 2],
            ],
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)
예제 #12
0
    def test_probability_differentiation(self, mocker, tol):
        """Tests correct output shape and evaluation for a tape
        with prob and expval outputs"""
        spy = mocker.spy(QuantumTape, "jacobian")

        def cost(x, y, device):
            with QuantumTape() as tape:
                qml.RX(x, wires=[0])
                qml.RY(y, wires=[1])
                qml.CNOT(wires=[0, 1])
                probs(wires=[0])
                probs(wires=[1])

            return tape.execute(device)

        dev = qml.device("default.qubit.autograd", wires=2)
        x = np.array(0.543, requires_grad=True)
        y = np.array(-0.654, requires_grad=True)

        res = cost(x, y, device=dev)
        expected = np.array([
            [np.cos(x / 2)**2, np.sin(x / 2)**2],
            [(1 + np.cos(x) * np.cos(y)) / 2, (1 - np.cos(x) * np.cos(y)) / 2],
        ])

        assert np.allclose(res, expected, atol=tol, rtol=0)

        jac_fn = qml.jacobian(cost)
        res = jac_fn(x, y, device=dev)
        assert res.shape == (2, 2, 2)

        expected = np.array([
            [[-np.sin(x) / 2, 0],
             [-np.sin(x) * np.cos(y) / 2, -np.cos(x) * np.sin(y) / 2]],
            [
                [np.sin(x) / 2, 0],
                [np.cos(y) * np.sin(x) / 2,
                 np.cos(x) * np.sin(y) / 2],
            ],
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)
        spy.assert_not_called()
예제 #13
0
    def test_multiple_expectation_values(self, approx_order, strategy, tol):
        """Tests correct output shape and evaluation for a tape
        with multiple expval outputs"""
        dev = qml.device("default.qubit", wires=2)
        x = 0.543
        y = -0.654

        with qml.tape.JacobianTape() as tape:
            qml.RX(x, wires=[0])
            qml.RY(y, wires=[1])
            qml.CNOT(wires=[0, 1])
            qml.expval(qml.PauliZ(0))
            qml.expval(qml.PauliX(1))

        tapes, fn = finite_diff(tape,
                                approx_order=approx_order,
                                strategy=strategy)
        res = fn(dev.batch_execute(tapes))
        assert res.shape == (2, 2)

        expected = np.array([[-np.sin(x), 0], [0, np.cos(y)]])
        assert np.allclose(res, expected, atol=tol, rtol=0)
예제 #14
0
def test_get_unitary_matrix_tensorflow_differentiable(v):

    tf = pytest.importorskip("tensorflow")

    def circuit(theta):
        qml.RX(theta, wires=0)
        qml.PauliZ(wires=0)
        qml.CNOT(wires=[0, 1])

    def loss(theta):
        U = qml.transforms.get_unitary_matrix(circuit)(theta)
        return qml.math.real(qml.math.trace(U))

    x = tf.Variable(v)
    with tf.GradientTape() as tape:
        l = loss(x)
    dl = tape.gradient(l, x)
    matrix = qml.transforms.get_unitary_matrix(circuit)(x)

    assert isinstance(matrix, tf.Tensor)
    assert np.allclose(l, 2 * np.cos(v / 2))
    assert np.allclose(dl, -np.sin(v / 2))
예제 #15
0
def test_get_unitary_matrix_torch_differentiable(v):

    torch = pytest.importorskip("torch")

    def circuit(theta):
        qml.RX(theta, wires=0)
        qml.PauliZ(wires=0)
        qml.CNOT(wires=[0, 1])

    def loss(theta):
        U = qml.transforms.get_unitary_matrix(circuit)(theta)
        return qml.math.real(qml.math.trace(U))

    x = torch.tensor(v, requires_grad=True)
    l = loss(x)
    l.backward()
    dl = x.grad
    matrix = qml.transforms.get_unitary_matrix(circuit)(x)

    assert isinstance(matrix, torch.Tensor)
    assert np.allclose(l.detach(), 2 * np.cos(v / 2))
    assert np.allclose(dl.detach(), -np.sin(v / 2))
예제 #16
0
def test_get_unitary_matrix_jax_differentiable(v):

    jax = pytest.importorskip("jax")

    def circuit(theta):
        qml.RX(theta, wires=0)
        qml.PauliZ(wires=0)
        qml.CNOT(wires=[0, 1])

    def loss(theta):
        U = qml.transforms.get_unitary_matrix(circuit)(theta)
        return qml.math.real(qml.math.trace(U))

    x = jax.numpy.array(v)

    l = loss(x)
    dl = jax.grad(loss)(x)
    matrix = qml.transforms.get_unitary_matrix(circuit)(x)

    assert isinstance(matrix, jax.numpy.ndarray)
    assert np.allclose(l, 2 * np.cos(v / 2))
    assert np.allclose(dl, -np.sin(v / 2))
예제 #17
0
    def test_multiple_rx_gradient(self, tol):
        """Tests that the gradient of multiple RX gates in a circuit
        yeilds the correct result."""
        dev = qml.device("default.qubit", wires=3)
        params = np.array([np.pi, np.pi / 2, np.pi / 3])

        with ReversibleTape() as tape:
            qml.RX(params[0], wires=0)
            qml.RX(params[1], wires=1)
            qml.RX(params[2], wires=2)

            for idx in range(3):
                qml.expval(qml.PauliZ(idx))

        circuit_output = tape.execute(dev)
        expected_output = np.cos(params)
        assert np.allclose(circuit_output, expected_output, atol=tol, rtol=0)

        # circuit jacobians
        circuit_jacobian = tape.jacobian(dev, method="analytic")
        expected_jacobian = -np.diag(np.sin(params))
        assert np.allclose(circuit_jacobian, expected_jacobian, atol=tol, rtol=0)
예제 #18
0
    def test_multiple_probability_differentiation(self, dev_name, diff_method,
                                                  tol):
        """Tests correct output shape and evaluation for a tape
        with multiple prob outputs"""

        if diff_method == "adjoint":
            pytest.skip(
                "The adjoint method does not currently support returning probabilities"
            )

        dev = qml.device(dev_name, wires=2)
        x = np.array(0.543, requires_grad=True)
        y = np.array(-0.654, requires_grad=True)

        @qnode(dev, diff_method=diff_method, interface="autograd")
        def circuit(x, y):
            qml.RX(x, wires=[0])
            qml.RY(y, wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.probs(wires=[0]), qml.probs(wires=[1])

        res = circuit(x, y)

        expected = np.array([
            [np.cos(x / 2)**2, np.sin(x / 2)**2],
            [(1 + np.cos(x) * np.cos(y)) / 2, (1 - np.cos(x) * np.cos(y)) / 2],
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)

        res = qml.jacobian(circuit)(x, y)
        expected = np.array([
            [[-np.sin(x) / 2, 0],
             [-np.sin(x) * np.cos(y) / 2, -np.cos(x) * np.sin(y) / 2]],
            [
                [np.sin(x) / 2, 0],
                [np.cos(y) * np.sin(x) / 2,
                 np.cos(x) * np.sin(y) / 2],
            ],
        ])

        assert np.allclose(res, expected, atol=tol, rtol=0)
예제 #19
0
    def test_classical_processing_arguments(self, mocker, tol):
        """Test that a gradient transform acts on QNodes
        correctly when the QNode arguments are classically processed"""
        dev = qml.device("default.qubit", wires=2)
        spy = mocker.spy(qml.transforms, "classical_jacobian")

        @qml.qnode(dev)
        def circuit(weights):
            qml.RX(weights[0] ** 2, wires=[0])
            qml.RY(weights[1], wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.expval(qml.PauliZ(0))

        w = np.array([0.543, -0.654], requires_grad=True)
        res = qml.gradients.param_shift(circuit)(w)

        classical_jac = spy.spy_return(w)
        assert isinstance(classical_jac, np.ndarray)
        assert np.allclose(classical_jac, np.array([[2 * w[0], 0], [0, 1]]))

        x, y = w
        expected = [-2 * x * np.sin(x ** 2), 0]
        assert np.allclose(res, expected, atol=tol, rtol=0)
예제 #20
0
    def test_classical_processing(self, dev_name, diff_method, tol):
        """Test classical processing within the quantum tape"""
        a = np.array(0.1, requires_grad=True)
        b = np.array(0.2, requires_grad=False)
        c = np.array(0.3, requires_grad=True)

        dev = qml.device(dev_name, wires=1)

        @qnode(dev, diff_method=diff_method, interface="autograd")
        def circuit(a, b, c):
            qml.RY(a * c, wires=0)
            qml.RZ(b, wires=0)
            qml.RX(c + c ** 2 + np.sin(a), wires=0)
            return qml.expval(qml.PauliZ(0))

        res = qml.jacobian(circuit)(a, b, c)

        if diff_method == "finite-diff":
            assert circuit.qtape.trainable_params == {0, 2}
            tape_params = np.array(circuit.qtape.get_parameters())
            assert np.all(tape_params == [a * c, c + c ** 2 + np.sin(a)])

        assert res.shape == (2,)
    def test_nonzero_shots(self, qvm, compiler):
        """Test that the wavefunction plugin provides correct result for high shot number"""
        shots = 10**2
        dev = qml.device('forest.wavefunction', wires=1, shots=shots)

        a = 0.543
        b = 0.123
        c = 0.987

        @qml.qnode(dev)
        def circuit(x, y, z):
            """Test QNode"""
            qml.BasisState(np.array([1]), wires=0)
            qml.Hadamard(wires=0)
            qml.Rot(x, y, z, wires=0)
            return qml.expval.PauliZ(0)

        runs = []
        for _ in range(100):
            runs.append(circuit(a, b, c))

        expected_var = np.sqrt(1/shots)
        self.assertAlmostEqual(np.mean(runs), np.cos(a)*np.sin(b), delta=expected_var)
예제 #22
0
    def test_probability_differentiation(self, tol):
        """Tests correct output shape and evaluation for a tape
        with prob outputs"""

        def cost(x, y, device):
            with AutogradInterface.apply(JacobianTape()) as tape:
                qml.RX(x, wires=[0])
                qml.RY(y, wires=[1])
                qml.CNOT(wires=[0, 1])
                qml.probs(wires=[0])
                qml.probs(wires=[1])

            return tape.execute(device)

        dev = qml.device("default.qubit", wires=2)
        x = np.array(0.543, requires_grad=True)
        y = np.array(-0.654, requires_grad=True)

        res = cost(x, y, device=dev)
        expected = np.array(
            [
                [np.cos(x / 2) ** 2, np.sin(x / 2) ** 2],
                [(1 + np.cos(x) * np.cos(y)) / 2, (1 - np.cos(x) * np.cos(y)) / 2],
            ]
        )
        assert np.allclose(res, expected, atol=tol, rtol=0)

        jac_fn = qml.jacobian(cost)
        res = jac_fn(x, y, device=dev)
        assert res.shape == (2, 2, 2)
        expected = np.array(
            [
                [[-np.sin(x) / 2, 0], [-np.sin(x) * np.cos(y) / 2, -np.cos(x) * np.sin(y) / 2]],
                [
                    [np.sin(x) / 2, 0],
                    [np.cos(y) * np.sin(x) / 2, np.cos(x) * np.sin(y) / 2],
                ],
            ]
        )
        assert np.allclose(res, expected, atol=tol, rtol=0)
예제 #23
0
    def test_pauliy_expectation(self, shots, qvm, compiler):
        """Test that PauliY expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.PauliY(wires=[0]))
            O2 = qml.expval(qml.PauliY(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])

        # below are the analytic expectation values for this circuit
        self.assertAllAlmostEqual(res,
                                  np.array([0, -np.cos(theta) * np.sin(phi)]),
                                  delta=3 / np.sqrt(shots))
예제 #24
0
    def cost(*p):
        with qml.tape.QuantumTape() as tape:
            qml.RX(p[0][0], wires=0)
            qml.RY(p[1], wires=0)
            qml.PhaseShift(p[0][1], wires=0)
            qml.RZ(p[0][2], 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) 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.
        params = tape.get_parameters(trainable_only=False)
        assert any(isinstance(i, ArrayBox) for i in params)

        return p[0][0] * p[1]**2 * anp.sin(p[0][1]) * anp.exp(-0.5 * p[0][2])
예제 #25
0
    def test_torch(self, tol):
        """Test that a gradient transform remains differentiable
        with PyTorch"""
        torch = pytest.importorskip("torch")
        dev = qml.device("default.qubit", wires=2)

        @qml.gradients.param_shift
        @qml.qnode(dev, interface="torch")
        def circuit(x):
            qml.RY(x, wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.var(qml.PauliX(1))

        x_ = -0.654
        x = torch.tensor(x_, dtype=torch.float64, requires_grad=True)
        res = circuit(x)[0]

        expected = -2 * np.cos(x_) * np.sin(x_)
        assert np.allclose(res.detach(), expected, atol=tol, rtol=0)

        res.backward()
        expected = -2 * np.cos(2 * x_)
        assert np.allclose(x.grad.detach(), expected, atol=tol, rtol=0)
예제 #26
0
    def test_multiple_probability_differentiation(self, dev_name, diff_method, mode, tol):
        """Tests correct output shape and evaluation for a tape
        with multiple prob outputs"""
        if diff_method != "backprop":
            pytest.skip("JAX interface does not support vector-valued QNodes")

        dev = qml.device(dev_name, wires=2)
        x = jnp.array(0.543)
        y = jnp.array(-0.654)

        @qnode(dev, diff_method=diff_method, interface="jax", mode=mode)
        def circuit(x, y):
            qml.RX(x, wires=[0])
            qml.RY(y, wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.probs(wires=[0]), qml.probs(wires=[1])

        res = circuit(x, y)

        expected = np.array(
            [
                [np.cos(x / 2) ** 2, np.sin(x / 2) ** 2],
                [(1 + np.cos(x) * np.cos(y)) / 2, (1 - np.cos(x) * np.cos(y)) / 2],
            ]
        )
        assert np.allclose(res, expected, atol=tol, rtol=0)

        res = jax.jacobian(circuit, argnums=[0, 1])(x, y)
        expected = np.array(
            [
                [[-np.sin(x) / 2, 0], [-np.sin(x) * np.cos(y) / 2, -np.cos(x) * np.sin(y) / 2]],
                [
                    [np.sin(x) / 2, 0],
                    [np.cos(y) * np.sin(x) / 2, np.cos(x) * np.sin(y) / 2],
                ],
            ]
        )

        assert np.allclose(res, expected.T, atol=tol, rtol=0)
예제 #27
0
    def test_pauliy_expectation(self, shots):
        """Test that PauliY expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device='2q-pyqvm', shots=shots)
        dev.apply('RX', wires=[0], par=[theta])
        dev.apply('RX', wires=[1], par=[phi])
        dev.apply('CNOT', wires=[0, 1], par=[])

        O = qml.expval.PauliY
        name = 'PauliY'

        dev._expval_queue = [
            O(wires=[0], do_queue=False),
            O(wires=[1], do_queue=False)
        ]
        dev.pre_expval()

        # below are the analytic expectation values for this circuit
        res = np.array([dev.expval(name, [0], []), dev.expval(name, [1], [])])
        self.assertAllAlmostEqual(res,
                                  np.array([0, -np.cos(theta) * np.sin(phi)]),
                                  delta=3 / np.sqrt(shots))
예제 #28
0
    def test_parametrized_transform_qnode(self, mocker):
        """Test that a parametrized transform can be applied
        to a QNode"""

        a = 0.1
        b = 0.4
        x = 0.543

        dev = qml.device("default.qubit", wires=2)

        @qml.qnode(dev)
        def circuit(x):
            qml.Hadamard(wires=0)
            qml.RX(x, wires=0)
            return qml.expval(qml.PauliX(0))

        transform_fn = self.my_transform(circuit, a, b)

        spy = mocker.spy(self.my_transform, "construct")
        res = transform_fn(x)

        spy.assert_called()
        tapes, fn = spy.spy_return

        assert len(tapes[0].operations) == 2
        assert tapes[0].operations[0].name == "Hadamard"
        assert tapes[0].operations[1].name == "RY"
        assert tapes[0].operations[1].parameters == [a * np.abs(x)]

        assert len(tapes[1].operations) == 2
        assert tapes[1].operations[0].name == "Hadamard"
        assert tapes[1].operations[1].name == "RZ"
        assert tapes[1].operations[1].parameters == [b * np.sin(x)]

        expected = fn(dev.batch_execute(tapes))
        assert res == expected
예제 #29
0
    def test_parametrized_transform_tape_decorator(self):
        """Test that a parametrized transform can be applied
        to a tape"""

        a = 0.1
        b = 0.4
        x = 0.543

        with qml.tape.QuantumTape() as tape:
            qml.Hadamard(wires=0)
            qml.RX(x, wires=0)
            qml.expval(qml.PauliX(0))

        tapes, fn = self.my_transform(a, b)(tape)

        assert len(tapes[0].operations) == 2
        assert tapes[0].operations[0].name == "Hadamard"
        assert tapes[0].operations[1].name == "RY"
        assert tapes[0].operations[1].parameters == [a * np.abs(x)]

        assert len(tapes[1].operations) == 2
        assert tapes[1].operations[0].name == "Hadamard"
        assert tapes[1].operations[1].name == "RZ"
        assert tapes[1].operations[1].parameters == [b * np.sin(x)]
예제 #30
0
    def test_pauliy_expectation(self, shots):
        """Test that PauliY expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-pyqvm", shots=shots)
        O1 = qml.expval(qml.PauliY(wires=[0]))
        O2 = qml.expval(qml.PauliY(wires=[1]))

        circuit_graph = CircuitGraph(
            [qml.RX(theta, wires=[0]), qml.RX(phi, wires=[1]), qml.CNOT(wires=[0, 1])] + [O1, O2],
            {},
        )

        dev.apply(circuit_graph.operations, rotations=circuit_graph.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1), dev.expval(O2)])

        # below are the analytic expectation values for this circuit
        self.assertAllAlmostEqual(
            res, np.array([0, -np.cos(theta) * np.sin(phi)]), delta=3 / np.sqrt(shots)
        )