def test_hamiltonian_dif_autograd(self, tol): """Tests that the hamiltonian_expand tape transform is differentiable with the Autograd interface""" H = qml.Hamiltonian( [-0.2, 0.5, 1], [qml.PauliX(1), qml.PauliZ(1) @ qml.PauliY(2), qml.PauliZ(0)]) var = [ np.array(0.1), np.array(0.67), np.array(0.3), np.array(0.4), np.array(-0.5), np.array(0.7), np.array(-0.2), np.array(0.5), np.array(1.0), ] output = 0.42294409781940356 output2 = [ 9.68883500e-02, -2.90832724e-01, -1.04448033e-01, -1.94289029e-09, 3.50307411e-01, -3.41123470e-01, 0.0, -0.43657, 0.64123, ] with qml.tape.JacobianTape() as tape: for i in range(2): qml.RX(np.array(0), wires=0) qml.RX(np.array(0), wires=1) qml.RX(np.array(0), wires=2) qml.CNOT(wires=[0, 1]) qml.CNOT(wires=[1, 2]) qml.CNOT(wires=[2, 0]) qml.expval(H) AutogradInterface.apply(tape) def cost(x): tape.set_parameters(x, trainable_only=False) tapes, fn = qml.transforms.hamiltonian_expand(tape) res = [t.execute(dev) for t in tapes] return fn(res) assert np.isclose(cost(var), output) grad = qml.grad(cost)(var) for g, o in zip(grad, output2): assert np.allclose(g, o, atol=tol)
def cost(a, b, device): with AutogradInterface.apply(JacobianTape()) as tape: qml.RY(a, wires=0) qml.RX(b, wires=0) qml.expval(qml.PauliZ(0)) assert tape.trainable_params == {0} return tape.execute(device)
def to_autograd(self): """Apply the Autograd interface to the internal quantum tape.""" self.dtype = AutogradInterface.dtype if self.interface != "autograd" and self.interface is not None: # Since the interface is changing, need to re-validate the tape class. self._tape, interface, self.device, diff_options = self.get_tape( self._original_device, "autograd", self.diff_method) self.interface = interface self.diff_options.update(diff_options) else: self.interface = "autograd" if self.qtape is not None: AutogradInterface.apply(self.qtape)
def cost(a, U, device): with AutogradInterface.apply(JacobianTape()) as tape: qml.QubitUnitary(U, wires=0) qml.RY(a, wires=0) qml.expval(qml.PauliZ(0)) assert tape.trainable_params == [1] return tape.execute(device)
def cost_fn(x): with AutogradInterface.apply(qml.tape.CVParamShiftTape()) 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) return fn([t.execute(dev) for t in tapes])[0, 1]
def cost(x, device): with AutogradInterface.apply(JacobianTape()) as tape: qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) qml.sample(qml.PauliZ(0)) qml.sample(qml.PauliX(1)) return tape.execute(device)
def test_interface_str(self): """Test that the interface string is correctly identified as autograd""" with AutogradInterface.apply(JacobianTape()) as tape: qml.RX(0.5, wires=0) qml.expval(qml.PauliX(0)) assert tape.interface == "autograd" assert isinstance(tape, AutogradInterface)
def cost(a, device): with AutogradInterface.apply(JacobianTape()) as qtape: qml.RY(a[0], wires=0) qml.RX(a[1], wires=0) qml.expval(qml.PauliZ(0)) qtape.jacobian_options = {"h": 1e-8, "order": 2} return qtape.execute(dev)
def cost(a, b, c, device): with AutogradInterface.apply(JacobianTape()) as tape: qml.RY(a * c, wires=0) qml.RZ(b, wires=0) qml.RX(c + c ** 2 + np.sin(a), wires=0) qml.expval(qml.PauliZ(0)) assert tape.trainable_params == [0, 2] return tape.execute(device)
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.expval(qml.PauliZ(0)) qml.probs(wires=[1]) return tape.execute(device)
def cost_fn(a, p, device): tape = JacobianTape() with tape: qml.RX(a, wires=0) U3(*p, wires=0) qml.expval(qml.PauliX(0)) tape = AutogradInterface.apply(tape.expand()) assert tape.trainable_params == [1, 2, 3, 4] assert [i.name for i in tape.operations] == ["RX", "Rot", "PhaseShift"] assert np.all(np.array(tape.get_parameters()) == [p[2], p[0], -p[2], p[1] + p[2]]) return tape.execute(device=device)
def test_get_parameters(self): """Test that the get_parameters function correctly gets the trainable parameters and all parameters, depending on the trainable_only argument""" a = np.array(0.1, requires_grad=True) b = np.array(0.2, requires_grad=False) c = np.array(0.3, requires_grad=True) d = np.array(0.4, requires_grad=False) with AutogradInterface.apply(JacobianTape()) as tape: qml.Rot(a, b, c, wires=0) qml.RX(d, wires=1) qml.CNOT(wires=[0, 1]) qml.expval(qml.PauliX(0)) assert tape.trainable_params == [0, 2] assert np.all(tape.get_parameters(trainable_only=True) == [a, c]) assert np.all(tape.get_parameters(trainable_only=False) == [a, b, c, d])
def test_reusing_quantum_tape(self, tol): """Test re-using a quantum tape by passing new parameters""" a = np.array(0.1, requires_grad=True) b = np.array(0.2, requires_grad=True) dev = qml.device("default.qubit", wires=2) with AutogradInterface.apply(JacobianTape()) as tape: qml.RY(a, wires=0) qml.RX(b, wires=1) qml.CNOT(wires=[0, 1]) qml.expval(qml.PauliZ(0)) qml.expval(qml.PauliY(1)) assert tape.trainable_params == [0, 1] def cost(a, b): tape.set_parameters([a, b]) return tape.execute(dev) jac_fn = qml.jacobian(cost) jac = jac_fn(a, b) a = np.array(0.54, requires_grad=True) b = np.array(0.8, requires_grad=True) res2 = cost(2 * a, b) expected = [np.cos(2 * a), -np.cos(2 * a) * np.sin(b)] assert np.allclose(res2, expected, atol=tol, rtol=0) jac_fn = qml.jacobian(lambda a, b: cost(2 * a, b)) jac = jac_fn(a, b) assert isinstance(jac, tuple) and len(jac) == 2 expected = ( [-2 * np.sin(2 * a), 2 * np.sin(2 * a) * np.sin(b)], [0, -np.cos(2 * a) * np.cos(b)], ) assert np.allclose(jac[0], expected[0], atol=tol, rtol=0) assert np.allclose(jac[1], expected[1], atol=tol, rtol=0)