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]))
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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))
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
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
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)
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)
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)
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
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)
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)
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, )
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)