def test_qubit_rotation(self, tol): """Test qubit rotation has the correct QNG value every step, the correct parameter updates, and correct cost after 200 steps""" dev = qml.device("default.qubit", wires=1) @qml.qnode(dev) def circuit(params): qml.RX(params[0], wires=0) qml.RY(params[1], wires=0) return qml.expval(qml.PauliZ(0)) def gradient(params): """Returns the gradient of the above circuit""" da = -np.sin(params[0]) * np.cos(params[1]) db = -np.cos(params[0]) * np.sin(params[1]) return np.array([da, db]) eta = 0.01 init_params = np.array([0.011, 0.012]) num_steps = 200 opt = qml.QNGOptimizer(eta) theta = init_params # optimization for 200 steps total for t in range(num_steps): theta_new = opt.step(circuit, theta) # check metric tensor res = opt.metric_tensor exp = np.diag([0.25, (np.cos(theta[0])**2) / 4]) assert np.allclose(res, exp, atol=tol, rtol=0) # check parameter update dtheta = eta * sp.linalg.pinvh(exp) @ gradient(theta) assert np.allclose(dtheta, theta - theta_new, atol=tol, rtol=0) theta = theta_new # check final cost assert np.allclose(circuit(theta), -0.9963791, atol=tol, rtol=0)
def test_hessian(self, dev_name, diff_method, mode, tol): """Test hessian calculation of a scalar valued QNode""" if diff_method not in {"backprop"}: pytest.skip("Test only supports backprop") dev = qml.device(dev_name, wires=1) @qnode(dev, diff_method=diff_method, interface="jax", mode=mode, max_diff=2) def circuit(x): qml.RY(x[0], wires=0) qml.RX(x[1], wires=0) return qml.expval(qml.PauliZ(0)) x = jnp.array([1.0, 2.0]) res = circuit(x) a, b = x expected_res = np.cos(a) * np.cos(b) assert np.allclose(res, expected_res, atol=tol, rtol=0) grad_fn = jax.grad(circuit) g = grad_fn(x) expected_g = [-np.sin(a) * np.cos(b), -np.cos(a) * np.sin(b)] assert np.allclose(g, expected_g, atol=tol, rtol=0) hess = jax.jacobian(grad_fn)(x) expected_hess = [ [-np.cos(a) * np.cos(b), np.sin(a) * np.sin(b)], [np.sin(a) * np.sin(b), -np.cos(a) * np.cos(b)], ] assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
def test_hermitian_identity_expectation(self, theta, phi, varphi, tol): """Test that a tensor product involving an Hermitian matrix and the identity works correctly""" dev = qml.device("expt.tensornet", wires=2) dev.reset() dev.apply("RY", wires=[0], par=[theta]) dev.apply("RY", wires=[1], par=[phi]) dev.apply("CNOT", wires=[0, 1], par=[]) A = np.array([[1.02789352, 1.61296440 - 0.3498192j], [1.61296440 + 0.3498192j, 1.23920938 + 0j]]) res = dev.expval(["Hermitian", "Identity"], [[0], [1]], [[A], []]) a = A[0, 0] re_b = A[0, 1].real d = A[1, 1] expected = ((a - d) * np.cos(theta) + 2 * re_b * np.sin(theta) * np.sin(phi) + a + d) / 2 assert np.allclose(res, expected, atol=tol, rtol=0)
def test_matrix_parameter(self, execute_kwargs, 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 qml.tape.JacobianTape() as tape: qml.QubitUnitary(U, wires=0) qml.RY(a, wires=0) qml.expval(qml.PauliZ(0)) return execute([tape], device, **execute_kwargs)[0] 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)
def test_one_qubit_wavefunction_circuit(self, tol): """Test that the wavefunction plugin provides correct result for simple circuit""" dev = qml.device("forest.numpy_wavefunction", wires=1) 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(qml.PauliZ(0)) print(circuit(a, b, c)) self.assertAlmostEqual(circuit(a, b, c), np.cos(a) * np.sin(b), delta=tol)
def test_var_expectation_values(self, approx_order, strategy, tol): """Tests correct output shape and evaluation for a tape with expval and var 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.var(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, -2 * np.cos(y) * np.sin(y)]]) assert np.allclose(res, expected, atol=tol, rtol=0)
def test_one_qubit_wavefunction_circuit(self, device): """Test that the wavefunction plugin provides correct result for simple circuit""" shots = 100000 dev = qml.device("forest.qvm", device=device, shots=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))
def test_acting_on_qnodes(self, tol): """Test that a gradient transform acts on QNodes correctly""" dev = qml.device("default.qubit", wires=2) @qml.qnode(dev) def circuit(weights): qml.RX(weights[0], wires=[0]) qml.RY(weights[1], wires=[1]) qml.CNOT(wires=[0, 1]) return qml.expval(qml.PauliZ(0)), qml.var(qml.PauliX(1)) grad_fn = qml.gradients.param_shift(circuit) w = np.array([0.543, -0.654], requires_grad=True) res = grad_fn(w) x, y = w expected = np.array([[-np.sin(x), 0], [0, -2 * np.cos(y) * np.sin(y)]]) assert np.allclose(res, expected, atol=tol, rtol=0)
def test_rx_gradient(self, tol): """Test that the gradient of the RX gate matches the known formula.""" dev = qml.device("default.qubit", wires=2) a = 0.7418 with ReversibleTape() as tape: qml.RX(a, wires=0) qml.expval(qml.PauliZ(0)) circuit_output = tape.execute(dev) expected_output = np.cos(a) assert np.allclose(circuit_output, expected_output, atol=tol, rtol=0) # circuit jacobians circuit_jacobian = tape.jacobian(dev, method="analytic") expected_jacobian = -np.sin(a) assert np.allclose(circuit_jacobian, expected_jacobian, atol=tol, rtol=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) )
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))
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)
def test_squeezed_mean_photon_variance(self, tol): """Test gradient of the photon variance of a displaced thermal state""" dev = qml.device("default.gaussian", wires=1) r = 0.12 phi = 0.105 with qml.tape.JacobianTape() as tape: qml.Squeezing(r, 0, wires=0) qml.Rotation(phi, wires=0) qml.var(qml.X(wires=[0])) tape.trainable_params = {0, 2} tapes, fn = param_shift_cv(tape, dev) grad = fn(dev.batch_execute(tapes)) 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(grad, expected, atol=tol, rtol=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)
def test_second_derivative(self, dev_name, diff_method, mocker, tol): """Test second derivative 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) qml.RX(x[1], wires=0) return qml.expval(qml.PauliZ(0)) x = np.array([1.0, 2.0], requires_grad=True) res = circuit(x) g = qml.grad(circuit)(x) spy = mocker.spy(JacobianTape, "hessian") g2 = qml.grad(lambda x: np.sum(qml.grad(circuit)(x)))(x) if diff_method == "parameter-shift": spy.assert_called_once() elif diff_method == "backprop": spy.assert_not_called() a, b = x expected_res = np.cos(a) * np.cos(b) assert np.allclose(res, expected_res, atol=tol, rtol=0) expected_g = [-np.sin(a) * np.cos(b), -np.cos(a) * np.sin(b)] assert np.allclose(g, expected_g, atol=tol, rtol=0) expected_g2 = [ -np.cos(a) * np.cos(b) + np.sin(a) * np.sin(b), np.sin(a) * np.sin(b) - np.cos(a) * np.cos(b), ] assert np.allclose(g2, expected_g2, atol=tol, rtol=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()
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)
def test_beamsplitter_heisenberg(self, phi, theta): """ops: Tests the Heisenberg representation of the Beamsplitter gate.""" matrix = cv.Beamsplitter._heisenberg_rep([theta, phi]) true_matrix = np.array( [ [1, 0, 0, 0, 0], [ 0, np.cos(theta), 0, -np.cos(phi) * np.sin(theta), -np.sin(phi) * np.sin(theta), ], [ 0, 0, np.cos(theta), np.sin(phi) * np.sin(theta), -np.cos(phi) * np.sin(theta), ], [ 0, np.cos(phi) * np.sin(theta), -np.sin(phi) * np.sin(theta), np.cos(theta), 0, ], [ 0, np.sin(phi) * np.sin(theta), np.cos(phi) * np.sin(theta), 0, np.cos(theta), ], ] ) assert np.allclose(matrix, true_matrix)
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))
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))
def test_multiple_expectation_values(self, 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 = qml.gradients.param_shift(tape) assert len(tapes) == 4 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)
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))
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)
def test_hermitian_hermitian(self, theta, phi, varphi, tol): """Test that a tensor product involving two Hermitian matrices 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=[]) A1 = np.array([[1, 2], [2, 4]]) A2 = 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(["Hermitian", "Hermitian"], [[0], [1, 2]], [[A1], [A2]]) expected = 0.25 * ( -30 + 4 * np.cos(phi) * np.sin(theta) + 3 * np.cos(varphi) * (-10 + 4 * np.cos(phi) * np.sin(theta) - 3 * np.sin(phi)) - 3 * np.sin(phi) - 2 * (5 + np.cos(phi) * (6 + 4 * np.sin(theta)) + (-3 + 8 * np.sin(theta)) * np.sin(phi)) * np.sin(varphi) + np.cos(theta) * ( 18 + 5 * np.sin(phi) + 3 * np.cos(varphi) * (6 + 5 * np.sin(phi)) + 2 * (3 + 10 * np.cos(phi) - 5 * np.sin(phi)) * np.sin(varphi) ) ) assert np.allclose(res, expected, atol=tol, rtol=0)
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)
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))
def test_passing_arguments(self, mocker, tol): """Test that a gradient transform correctly passes arguments""" dev = qml.device("default.qubit", wires=2) spy = mocker.spy(qml.gradients.parameter_shift, "expval_param_shift") @qml.qnode(dev) def circuit(weights): qml.RX(weights[0], wires=[0]) qml.RY(weights[1], wires=[1]) qml.CNOT(wires=[0, 1]) return qml.expval(qml.PauliZ(0)), qml.var(qml.PauliX(1)) grad_fn = qml.gradients.param_shift(circuit, shift=np.pi / 4) w = np.array([0.543, -0.654], requires_grad=True) res = grad_fn(w) x, y = w expected = np.array([[-np.sin(x), 0], [0, -2 * np.cos(y) * np.sin(y)]]) assert np.allclose(res, expected, atol=tol, rtol=0) assert spy.call_args[0][2] == np.pi / 4
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) )
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)
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))