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_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)
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_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_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_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_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)
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
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_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)
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)
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()
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)
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_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_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_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)
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)
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)
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)
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 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])
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)
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)
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))
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
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)]
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) )