def test_compute_expval_including_identity(self):
        """Test a simple circuit that involves computing the expectation value of the
        Identity operator."""
        dev = qml.device("orquestra.qiskit", wires=3)

        # Skip if not logged in to Orquestra
        try_resp = qe_list_workflow()
        need_login_msg = "token has expired, please log in again\n"

        if need_login_msg in try_resp:
            pytest.skip("Has not logged in to the Orquestra platform.")

        @qml.qnode(dev)
        def circuit():
            qml.PauliX(0)
            qml.PauliX(1)
            qml.PauliX(2)
            return (
                qml.expval(qml.Identity(0)),
                qml.expval(qml.PauliZ(1)),
                qml.expval(qml.Identity(2)),
            )

        assert np.allclose(circuit(), np.array([1, -1, 1]))
示例#2
0
    def test_tensor_number_displaced_squeezed(self, dev, disp_sq_circuit, pars,
                                              tol):
        """Test the variance of the TensorN observable for a squeezed displaced
        state"""

        # Checking the circuit variance and the analytic expression
        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

        var = disp_sq_circuit(pars)

        n0 = np.sinh(rs0)**2 + np.abs(alpha0)**2
        n1 = np.sinh(rs1)**2 + np.abs(alpha1)**2
        expected = (squared_term(alpha0, rs0, phis0) *
                    squared_term(alpha1, rs1, phis1) - n0**2 * n1**2)
        assert np.allclose(var, expected, atol=tol, rtol=0)
示例#3
0
    def test_2q_gate_pauliz_pauliz_tensor_parametric_compilation_off(
            self, a, b):
        """Test that the PauliZ tensor PauliZ observable works correctly, when parametric compilation
        is turned off.

        As the results coming from the qvm are stochastic, a constraint of 3 out of 5 runs was added.
        """

        device = np.random.choice(TEST_QPU_LATTICES)
        dev_qpu = qml.device(
            "forest.qpu",
            device=device,
            load_qc=False,
            readout_error=[0.9, 0.75],
            symmetrize_readout="exhaustive",
            calibrate_readout="plus-eig",
            shots=QVM_SHOTS // 20,
            parametric_compilation=False,
        )

        @qml.qnode(dev_qpu)
        def circuit(x, y):
            qml.RY(x, wires=[0])
            qml.RY(y, wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))

        analytic_value = (np.cos(a / 2)**2 * np.cos(b / 2)**2 +
                          np.cos(b / 2)**2 * np.sin(a / 2)**2 -
                          np.cos(a / 2)**2 * np.sin(b / 2)**2 -
                          np.sin(a / 2)**2 * np.sin(b / 2)**2)

        expt = np.mean([circuit(a, b) for _ in range(20)])
        theory = analytic_value

        assert np.allclose(expt, theory, atol=2e-2)
示例#4
0
    def test_device_wire_expansion(self, tol):
        """Test that the transformation works correctly
        for the case where the transformation applies to more wires
        than the observable."""

        # create a 3-mode symmetric transformation
        wires = qml.wires.Wires([0, "a", 2])
        ndim = 1 + 2 * len(wires)

        Z = np.arange(ndim**2).reshape(ndim, ndim)
        Z = Z.T + Z

        obs = qml.NumberOperator(0)
        res = _transform_observable(obs, Z, device_wires=wires)

        # The Heisenberg representation of the number operator
        # is (X^2 + P^2) / (2*hbar) - 1/2. We use the ordering
        # I, X0, Xa, X2, P0, Pa, P2.
        A = np.diag([-0.5, 0.25, 0.25, 0, 0, 0, 0])
        expected = A @ Z + Z @ A

        assert isinstance(res, qml.PolyXP)
        assert res.wires == wires
        assert np.allclose(res.data[0], expected, atol=tol, rtol=0)
    def test_scalar_jacobian(self, tol):
        """Test scalar jacobian calculation"""
        a = np.array(0.1, requires_grad=True)

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

        dev = qml.device("default.qubit", wires=2)
        res = qml.jacobian(cost)(a, device=dev)
        assert res.shape == (1, )

        # compare to standard tape jacobian
        with QuantumTape() as tape:
            qml.RY(a, wires=0)
            expval(qml.PauliZ(0))

        tape.trainable_params = {0}
        expected = tape.jacobian(dev)
        assert expected.shape == (1, 1)
        assert np.allclose(res, np.squeeze(expected), atol=tol, rtol=0)
示例#6
0
    def test_hermitian(self, theta, phi, varphi, tol):
        """Test that a tensor product involving qml.Hermitian works correctly"""
        dev = qml.device("expt.tensornet", wires=3)
        dev.reset()
        dev.apply("RX", wires=[0], par=[theta])
        dev.apply("RX", wires=[1], par=[phi])
        dev.apply("RX", wires=[2], par=[varphi])
        dev.apply("CNOT", wires=[0, 1], par=[])
        dev.apply("CNOT", wires=[1, 2], par=[])

        A = np.array([
            [-6, 2 + 1j, -3, -5 + 2j],
            [2 - 1j, 0, 2 - 1j, -5 + 4j],
            [-3, 2 + 1j, 0, -4 + 3j],
            [-5 - 2j, -5 - 4j, -4 - 3j, -6],
        ])

        res = dev.expval(["PauliZ", "Hermitian"], [[0], [1, 2]], [[], [A]])
        expected = 0.5 * (-6 * np.cos(theta) *
                          (np.cos(varphi) + 1) - 2 * np.sin(varphi) *
                          (np.cos(theta) + np.sin(phi) - 2 * np.cos(phi)) +
                          3 * np.cos(varphi) * np.sin(phi) + np.sin(phi))

        assert np.allclose(res, expected, atol=tol, rtol=0)
示例#7
0
    def test_with_reps_per_factor(self):
        """Tests if the expected shape is returned when mitigating a circuit with a reps_per_factor
        set not equal to 1"""
        from mitiq.zne.scaling import fold_gates_at_random
        from mitiq.zne.inference import RichardsonFactory

        noise_strength = 0.05

        dev_noise_free = qml.device("default.mixed", wires=2)
        dev = qml.transforms.insert(qml.AmplitudeDamping, noise_strength)(dev_noise_free)

        n_wires = 2
        n_layers = 2

        shapes = qml.SimplifiedTwoDesign.shape(n_wires, n_layers)
        np.random.seed(0)
        w1, w2 = [np.random.random(s) for s in shapes]

        @qml.transforms.mitigate_with_zne(
            [1, 2, 3], fold_gates_at_random, RichardsonFactory.extrapolate, reps_per_factor=2
        )
        @qnode(dev)
        def mitigated_circuit(w1, w2):
            qml.SimplifiedTwoDesign(w1, w2, wires=range(2))
            return qml.expval(qml.PauliZ(0))

        @qnode(dev_noise_free)
        def ideal_circuit(w1, w2):
            qml.SimplifiedTwoDesign(w1, w2, wires=range(2))
            return qml.expval(qml.PauliZ(0))

        res_mitigated = mitigated_circuit(w1, w2)
        res_ideal = ideal_circuit(w1, w2)

        assert res_mitigated.shape == res_ideal.shape
        assert not np.allclose(res_mitigated, res_ideal)
    def test_two_modes_single_real_parameter_gates(self, gate_name, pennylane_gate, tol):
        """Test that gates that take a single real parameter and acts on two
        modes provide the correct result"""
        a = 0.312

        operation = pennylane_gate

        wires = [0, 1]

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

        sf_operation = dev._operation_map[gate_name]

        assert dev.supports_operation(gate_name)

        @qml.qnode(dev)
        def circuit(*args):
            qml.TwoModeSqueezing(0.1, 0, wires=[0, 1])
            operation(*args, wires=wires)
            return qml.expval(qml.NumberOperator(0)), qml.expval(qml.NumberOperator(1))

        res = circuit(a)
        sf_res = SF_gate_reference(sf_operation, wires, a)
        assert np.allclose(res, sf_res, 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)

        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)
示例#10
0
    def test_interface_torch(self, dev):
        """Test if gradients agree between the adjoint and finite-diff methods when using the
        Torch interface"""

        torch = pytest.importorskip("torch")

        def f(params1, params2):
            qml.RX(0.4, wires=[0])
            qml.RZ(params1 * torch.sqrt(params2), wires=[0])
            qml.RY(torch.cos(params2), wires=[0])
            return qml.expval(qml.PauliZ(0))

        params1 = torch.tensor(0.3, requires_grad=True)
        params2 = torch.tensor(0.4, requires_grad=True)

        h = 2e-3 if dev.R_DTYPE == np.float32 else 1e-7
        tol = 1e-3 if dev.R_DTYPE == np.float32 else 1e-7

        qnode1 = QNode(f, dev, interface="torch", diff_method="adjoint")
        qnode2 = QNode(f,
                       dev,
                       interface="torch",
                       diff_method="finite-diff",
                       h=h)

        res1 = qnode1(params1, params2)
        res1.backward()

        grad_adjoint = params1.grad, params2.grad

        res2 = qnode2(params1, params2)
        res2.backward()

        grad_fd = params1.grad, params2.grad

        assert np.allclose(grad_adjoint, grad_fd)
示例#11
0
    def test_compile_template(self):
        """Test that functions with templates are correctly expanded and compiled."""

        # Push commuting gates to the right and merging rotations gives a circuit
        # with alternating RX and CNOT gates
        def qfunc(x, params):
            qml.templates.AngleEmbedding(x, wires=range(3))
            qml.templates.BasicEntanglerLayers(params, wires=range(3))
            return qml.expval(qml.PauliZ(wires=2))

        dev = qml.device("default.qubit", wires=3)
        qnode = qml.QNode(qfunc, dev)

        pipeline = [commute_controlled, merge_rotations]
        transformed_qfunc = compile(pipeline=pipeline)(qfunc)
        transformed_qnode = qml.QNode(transformed_qfunc, dev)

        x = np.array([0.1, 0.2, 0.3])
        params = np.ones((2, 3))

        original_result = qnode(x, params)
        transformed_result = transformed_qnode(x, params)
        assert np.allclose(original_result, transformed_result)

        names_expected = ["RX", "CNOT"] * 6
        wires_expected = [
            Wires(0),
            Wires([0, 1]),
            Wires(1),
            Wires([1, 2]),
            Wires(2),
            Wires([2, 0]),
        ] * 2

        compare_operation_lists(transformed_qnode.qtape.operations,
                                names_expected, wires_expected)
示例#12
0
    def test_gradient_gate_with_multiple_parameters_hermitian(self, dev):
        """Tests that gates with multiple free parameters yield correct gradients."""
        x, y, z = [0.5, 0.3, -0.7]

        with qml.tape.QuantumTape() as tape:
            qml.RX(0.4, wires=[0])
            qml.Rot(x, y, z, wires=[0])
            qml.RY(-0.2, wires=[0])
            qml.expval(qml.Hermitian([[0, 1], [1, 1]], wires=0))

        tape.trainable_params = {1, 2, 3}

        h = 2e-3 if dev.R_DTYPE == np.float32 else 1e-7
        tol = 1e-3 if dev.R_DTYPE == np.float32 else 1e-7

        grad_D = dev.adjoint_jacobian(tape)
        tapes, fn = qml.gradients.finite_diff(tape, h=h)
        grad_F = fn(qml.execute(tapes, dev, None))

        # gradient has the correct shape and every element is nonzero
        assert grad_D.shape == (1, 3)
        assert np.count_nonzero(grad_D) == 3
        # the different methods agree
        assert np.allclose(grad_D, grad_F, atol=tol, rtol=0)
示例#13
0
    def test_multiple_rx_gradient_expval_hermitian(self, tol, dev):
        """Tests that the gradient of multiple RX gates in a circuit yields the correct result
        with Hermitian observable
        """
        params = np.array([np.pi / 3, np.pi / 4, np.pi / 5])

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

            qml.expval(
                qml.Hermitian(
                    [[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]],
                    wires=[0, 2]))

        tape.trainable_params = {0, 1, 2}
        dev_jacobian = dev.adjoint_jacobian(tape)
        expected_jacobian = np.array([
            -np.sin(params[0]) * np.cos(params[2]), 0,
            -np.cos(params[0]) * np.sin(params[2])
        ])

        assert np.allclose(dev_jacobian, expected_jacobian, atol=tol, rtol=0)
示例#14
0
    def test_involutory_and_noninvolutory_variance(self, tol):
        """Tests a qubit Hermitian observable that is not involutory alongside
        an involutory observable."""
        dev = qml.device("default.qubit", wires=2)
        A = np.array([[4, -1 + 6j], [-1 - 6j, 2]])
        a = 0.54

        with qml.tape.JacobianTape() as tape:
            qml.RX(a, wires=0)
            qml.RX(a, wires=1)
            qml.var(qml.PauliZ(0))
            qml.var(qml.Hermitian(A, 1))

        tape.trainable_params = {0, 1}

        res = tape.execute(dev)
        expected = [
            1 - np.cos(a)**2,
            (39 / 2) - 6 * np.sin(2 * a) + (35 / 2) * np.cos(2 * a)
        ]
        assert np.allclose(res, expected, atol=tol, rtol=0)

        # circuit jacobians
        tapes, fn = qml.gradients.param_shift(tape)
        gradA = fn(dev.batch_execute(tapes))
        assert len(tapes) == 1 + 2 * 4

        tapes, fn = qml.gradients.finite_diff(tape)
        gradF = fn(dev.batch_execute(tapes))
        assert len(tapes) == 1 + 2

        expected = [
            2 * np.sin(a) * np.cos(a), -35 * np.sin(2 * a) - 12 * np.cos(2 * a)
        ]
        assert np.diag(gradA) == pytest.approx(expected, abs=tol)
        assert np.diag(gradF) == pytest.approx(expected, abs=tol)
示例#15
0
    def test_hermitian_expectation(self, device, shots, tol):
        """Test that arbitrary Hermitian expectation values are correct"""
        dev = device(2)

        theta = 0.432
        phi = 0.123

        @qml.qnode(dev)
        def circuit():
            qml.RY(theta, wires=[0])
            qml.RY(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            return [qml.expval(qml.Hermitian(A, i)) for i in range(2)]

        a = A[0, 0]
        re_b = A[0, 1].real
        d = A[1, 1]
        ev1 = ((a - d) * np.cos(theta) +
               2 * re_b * np.sin(theta) * np.sin(phi) + a + d) / 2
        ev2 = ((a - d) * np.cos(theta) * np.cos(phi) + 2 * re_b * np.sin(phi) +
               a + d) / 2
        expected = np.array([ev1, ev2])

        assert np.allclose(circuit(), expected, **tol)
    def test_multiple_qnode_arguments_mixed(self):
        """Test that the correct Hessian is calculated with multiple mixed-shape QNode arguments"""

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

        @qml.qnode(dev, diff_method="parameter-shift", max_diff=2)
        def circuit(x, y, z):
            qml.RX(x, wires=0)
            qml.RY(z[0] + z[1], wires=0)
            qml.CNOT(wires=[0, 1])
            qml.RX(y[1, 0], wires=0)
            qml.RY(y[0, 1], wires=0)
            return qml.probs(wires=0), qml.probs(wires=1)

        x = np.array(0.1, requires_grad=True)
        y = np.array([[0.5, 0.6], [0.2, 0.1]], requires_grad=True)
        z = np.array([0.3, 0.4], requires_grad=True)

        expected = tuple(
            qml.jacobian(qml.jacobian(circuit, argnum=i), argnum=i)(x, y, z)
            for i in range(3))
        hessian = qml.gradients.param_shift_hessian(circuit)(x, y, z)

        assert all(np.allclose(expected[i], hessian[i]) for i in range(3))
示例#17
0
    def test_single_expectation_value(self, tol):
        """Tests correct output shape and evaluation for a tape
        with a single expval output"""
        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.PauliX(1))

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

        tapes, fn = qml.gradients.vjp(tape, dy, param_shift)
        assert len(tapes) == 4

        res = fn(dev.batch_execute(tapes))
        assert res.shape == (2, )

        expected = np.array([-np.sin(y) * np.sin(x), np.cos(y) * np.cos(x)])
        assert np.allclose(res, expected, atol=tol, rtol=0)
    def test_fewer_device_invocations_scalar_input(self):
        """Test that the hessian invokes less hardware executions than double differentiation
        (0d -> 0d)"""

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

        @qml.qnode(dev, diff_method="parameter-shift", max_diff=2)
        def circuit(x):
            qml.RX(x, wires=0)
            qml.CNOT(wires=[0, 1])
            return qml.expval(qml.PauliZ(1))

        x = np.array(0.1, requires_grad=True)

        with qml.Tracker(dev) as tracker:
            hessian = qml.gradients.param_shift_hessian(circuit)(x)
            hessian_qruns = tracker.totals["executions"]
            expected = qml.jacobian(qml.jacobian(circuit))(x)
            jacobian_qruns = tracker.totals["executions"] - hessian_qruns

        assert np.allclose(hessian, expected)
        assert hessian_qruns < jacobian_qruns
        assert hessian_qruns <= 2**2 * 1  # 1 = (1+2-1)C(2)
        assert hessian_qruns <= 3**1
示例#19
0
    def test_hermitian(self, theta, phi, varphi, tol):
        """Test that a tensor product involving qml.Hermitian works correctly"""
        dev = qml.device("expt.tensornet", wires=3)
        dev.reset()
        dev.apply("RX", wires=[0], par=[theta])
        dev.apply("RX", wires=[1], par=[phi])
        dev.apply("RX", wires=[2], par=[varphi])
        dev.apply("CNOT", wires=[0, 1], par=[])
        dev.apply("CNOT", wires=[1, 2], par=[])

        A = np.array([
            [-6, 2 + 1j, -3, -5 + 2j],
            [2 - 1j, 0, 2 - 1j, -5 + 4j],
            [-3, 2 + 1j, 0, -4 + 3j],
            [-5 - 2j, -5 - 4j, -4 - 3j, -6],
        ])

        res = dev.var(["PauliZ", "Hermitian"], [[0], [1, 2]], [[], [A]])

        expected = (
            1057 - np.cos(2 * phi) + 12 *
            (27 + np.cos(2 * phi)) * np.cos(varphi) -
            2 * np.cos(2 * varphi) * np.sin(phi) *
            (16 * np.cos(phi) + 21 * np.sin(phi)) + 16 * np.sin(2 * phi) - 8 *
            (-17 + np.cos(2 * phi) + 2 * np.sin(2 * phi)) * np.sin(varphi) -
            8 * np.cos(2 * theta) *
            (3 + 3 * np.cos(varphi) + np.sin(varphi))**2 - 24 * np.cos(phi) *
            (np.cos(phi) + 2 * np.sin(phi)) * np.sin(2 * varphi) -
            8 * np.cos(theta) *
            (4 * np.cos(phi) *
             (4 + 8 * np.cos(varphi) + np.cos(2 * varphi) -
              (1 + 6 * np.cos(varphi)) * np.sin(varphi)) + np.sin(phi) *
             (15 + 8 * np.cos(varphi) - 11 * np.cos(2 * varphi) +
              42 * np.sin(varphi) + 3 * np.sin(2 * varphi)))) / 16

        assert np.allclose(res, expected, atol=tol, rtol=0)
    def test_f0_argument(self):
        """Test that we can provide the results of a QNode to save on quantum invocations"""

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

        @qml.qnode(dev, diff_method="parameter-shift", max_diff=2)
        def circuit(x):
            qml.RX(x[0], wires=0)
            qml.RY(x[1], wires=0)
            qml.CNOT(wires=[0, 1])
            return qml.probs(wires=1)

        x = np.array([0.1, 0.2], requires_grad=True)

        res = circuit(x)

        with qml.Tracker(dev) as tracker:
            hessian1 = qml.gradients.param_shift_hessian(circuit, f0=res)(x)
            qruns1 = tracker.totals["executions"]
            hessian2 = qml.gradients.param_shift_hessian(circuit)(x)
            qruns2 = tracker.totals["executions"] - qruns1

        assert np.allclose(hessian1, hessian2)
        assert qruns1 < qruns2
示例#21
0
    def test_integration(self, weights, ph, pphh, expected, tol):
        """Test integration with PennyLane and gradient calculations"""

        N = 4
        wires = range(N)
        dev = qml.device('default.qubit', wires=N)

        w_ph_0 = weights[0]
        w_ph_1 = weights[1]
        w_pphh = weights[2]

        @qml.qnode(dev)
        def circuit(w_ph_0, w_ph_1, w_pphh):
        	UCCSD(weights, wires, ph=ph, pphh=pphh, init_state=np.array([1, 1, 0, 0]))

        return [qml.expval(qml.PauliZ(w)) for w in range(N)]

        res = circuit(w_ph_0, w_ph_1, w_pphh)
        assert np.allclose(res, np.array(expected), atol=tol)

        # compare the two methods of computing the Jacobian
        jac_A = circuit.jacobian((w_ph_0, w_ph_1, w_pphh), method="A")
        jac_F = circuit.jacobian((w_ph_0, w_ph_1, w_pphh), method="F")
        assert jac_A == pytest.approx(jac_F, abs=tol)
    def test_hessian_transform_is_differentiable_tensorflow(self):
        """Test that the 3rd derivate can be calculated via auto-differentiation in Tensorflow
        (1d -> 1d)"""
        tf = pytest.importorskip("tensorflow")

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

        @qml.qnode(dev, diff_method="parameter-shift", max_diff=3)
        def circuit(x):
            qml.RX(x[1], wires=0)
            qml.RY(x[0], wires=0)
            qml.CNOT(wires=[0, 1])
            return qml.probs(wires=[0, 1])

        x = np.array([0.1, 0.2], requires_grad=True)
        x_tf = tf.Variable([0.1, 0.2], dtype=tf.float64)

        expected = qml.jacobian(qml.jacobian(qml.jacobian(circuit)))(x)
        circuit.interface = "tf"
        with tf.GradientTape() as tf_tape:
            hessian = qml.gradients.param_shift_hessian(circuit)(x_tf)[0]
        tensorflow_deriv = tf_tape.jacobian(hessian, x_tf)

        assert np.allclose(expected, tensorflow_deriv)
    def test_scalar_jacobian(self, tol, mocker):
        """Test scalar jacobian calculation"""
        spy = mocker.spy(QuantumTape, "jacobian")
        a = np.array(0.1, requires_grad=True)

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

        dev = qml.device("default.qubit.autograd", wires=2)
        res = qml.jacobian(cost)(a, device=dev)
        spy.assert_not_called()
        assert res.shape == (1, )

        # compare to standard tape jacobian
        with QuantumTape() as tape:
            qml.RY(a, wires=0)
            expval(qml.PauliZ(0))

        expected = tape.jacobian(dev)
        assert expected.shape == (1, 1)
        assert np.allclose(res, np.squeeze(expected), atol=tol, rtol=0)
示例#24
0
    def test_integration(self, tol):
        """Test integration with PennyLane to compute expectation values"""

        N = 4
        wires = range(N)
        layers = 2
        weights = np.array(
            [
                [[-0.09009989, -0.00090317], [-0.16034551, -0.13278097], [-0.02926428, 0.05175079]],
                [[-0.07988132, 0.11315495], [-0.16079166, 0.09439518], [-0.04321269, 0.13678911]],
            ]
        )

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

        @qml.qnode(dev)
        def circuit(weights):
            ParticleConservingU1(weights, wires, init_state=np.array([1, 1, 0, 0]))
            return [qml.expval(qml.PauliZ(w)) for w in range(N)]

        res = circuit(weights)

        exp = np.array([-0.99993177, -0.9853332, 0.98531251, 0.99995246])
        assert np.allclose(res, np.array(exp), atol=tol)
示例#25
0
    def test_execution(self, tol):
        """Tests the StronglyEntanglingLayers for various parameters."""
        np.random.seed(0)
        outcomes = []

        for num_wires in range(2, 4):
            for num_layers in range(1, 3):

                dev = qml.device('default.qubit', wires=num_wires)
                weights = np.random.randn(num_layers, num_wires, 3)

                @qml.qnode(dev)
                def circuit(weights, x=None):
                    qml.BasisState(x, wires=range(num_wires))
                    StronglyEntanglingLayers(weights, wires=range(num_wires))
                    return qml.expval.PauliZ(0)

                outcomes.append(
                    circuit(weights,
                            x=np.array(np.random.randint(0, 1, num_wires))))

        res = np.array(outcomes)
        expected = np.array([-0.29242496, 0.22129055, 0.07540091, -0.77626557])
        assert np.allclose(res, expected, atol=tol)
示例#26
0
    def simplify(self):
        r"""Simplifies the Hamiltonian by combining like-terms.

        **Example**

        >>> ops = [qml.PauliY(2), qml.PauliX(0) @ qml.Identity(1), qml.PauliX(0)]
        >>> H = qml.Hamiltonian([1, 1, -2], ops)
        >>> H.simplify()
        >>> print(H)
          (-1) [X0]
        + (1) [Y2]
        """

        coeffs = []
        ops = []

        for c, op in zip(self.coeffs, self.ops):
            op = op if isinstance(op, Tensor) else Tensor(op)

            ind = None
            for i, other in enumerate(ops):
                if op.compare(other):
                    ind = i
                    break

            if ind is not None:
                coeffs[ind] += c
                if np.allclose([coeffs[ind]], [0]):
                    del coeffs[ind]
                    del ops[ind]
            else:
                ops.append(op.prune())
                coeffs.append(c)

        self._coeffs = coeffs
        self._ops = ops
示例#27
0
    def test_2q_gate(self):
        """Test that the two qubit gate with the PauliZ observable works correctly.

        As the results coming from the qvm are stochastic, a constraint of 3 out of 5 runs was added.
        """

        device = np.random.choice(TEST_QPU_LATTICES)
        dev_qpu = qml.device(
            "forest.qpu",
            device=device,
            load_qc=False,
            readout_error=[0.9, 0.75],
            symmetrize_readout="exhaustive",
            calibrate_readout="plus-eig",
            shots=QVM_SHOTS,
        )

        @qml.qnode(dev_qpu)
        def circuit():
            qml.RY(np.pi / 2, wires=[0])
            qml.CNOT(wires=[0, 1])
            return qml.expval(qml.PauliZ(0))

        assert np.allclose(circuit(), 0.0, atol=2e-2)
示例#28
0
def test_jax_jit(diff_method, tol):
    """Test derivatives when using JAX and JIT."""
    jax = pytest.importorskip("jax")
    jnp = jax.numpy
    dev = qml.device("default.qubit", wires=2)

    @qml.batch_params
    @qml.qnode(dev, interface="jax", diff_method=diff_method)
    def circuit(x):
        qml.RX(x, wires=0)
        qml.RY(0.1, wires=1)
        qml.CNOT(wires=[0, 1])
        return qml.expval(qml.PauliZ(0) @ qml.PauliX(1))

    @jax.jit
    def cost(x):
        return jnp.sum(circuit(x))

    batch_size = 3
    x = jnp.linspace(0.1, 0.5, batch_size)

    res = jax.grad(cost)(x)
    expected = -np.sin(0.1) * np.sin(x)
    assert np.allclose(res, expected, atol=tol, rtol=0)
示例#29
0
def test_multiple_steps(fun, x_min, param, num_freq):
    """Tests that repeated steps execute as expected."""
    param = tuple(np.array(p, requires_grad=True) for p in param)
    substep_optimizer = "brute"
    substep_kwargs = None
    opt = RotosolveOptimizer(substep_optimizer, substep_kwargs)

    for _ in range(3):
        param = opt.step(
            fun,
            *param,
            nums_frequency=num_freq,
        )
        # The following accounts for the unpacking functionality for length-one param
        if len(x_min) == 1:
            param = (param, )

    assert (np.isscalar(x_min)
            and np.isscalar(param)) or len(x_min) == len(param)
    assert np.allclose(
        np.fromiter(_flatten(x_min), dtype=float),
        np.fromiter(_flatten(param), dtype=float),
        atol=1e-5,
    )
示例#30
0
    def test_adjoint_hessian(self, tol):
        """Since the adjoint hessian is not a differentiable transform,
        higher-order derivatives are not supported."""
        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 tape:
                qml.RX(x[0], wires=[0])
                qml.RY(x[1], wires=[1])
                qml.CNOT(wires=[0, 1])
                qml.expval(qml.PauliZ(0))

            return execute(
                [tape],
                dev,
                gradient_fn="device",
                gradient_kwargs={"method": "adjoint_jacobian", "use_device_state": True},
            )[0]

        with pytest.warns(UserWarning, match="Output seems independent"):
            res = qml.jacobian(qml.grad(cost_fn))(params)

        assert np.allclose(res, np.zeros([2, 2]), atol=tol, rtol=0)