def test_unknown_gradient_method(self, operable_mock_device_2_wires): """ The gradient method is unknown.""" def circuit(x): qml.Rot(0.3, x, -0.2, wires=[0]) return qml.expval(qml.PauliZ(0)) node = JacobianQNode(circuit, operable_mock_device_2_wires) with pytest.raises(ValueError, match="Unknown gradient method"): node.jacobian(0.5, method="unknown")
def test_wrong_order_in_finite_difference(self, operable_mock_device_2_wires): """Finite difference are attempted with wrong order.""" def circuit(x): qml.Rot(0.3, x, -0.2, wires=[0]) return qml.expval(qml.PauliZ(0)) node = JacobianQNode(circuit, operable_mock_device_2_wires) with pytest.raises(ValueError, match="Order must be 1 or 2"): node.jacobian(0.5, method="F", options={'order': 3})
def test_indices_not_unique(self, operable_mock_device_2_wires): """The Jacobian is requested for non-unique indices.""" def circuit(x): qml.Rot(0.3, x, -0.2, wires=[0]) return qml.expval(qml.PauliZ(0)) node = JacobianQNode(circuit, operable_mock_device_2_wires) with pytest.raises(ValueError, match="Parameter indices must be unique."): node.jacobian(0.5, wrt=[0, 0])
def test_operator_not_supporting_pd_analytic(self, operable_mock_device_2_wires): """Differentiating wrt. a parameter that appears as an argument to an operation that does not support parameter-shift derivatives.""" def circuit(x): qml.RX(x, wires=[0]) return qml.expval(qml.Hermitian(np.diag([x, 0]), 0)) node = JacobianQNode(circuit, operable_mock_device_2_wires) with pytest.raises(ValueError, match="analytic gradient method cannot be used with"): node.jacobian(0.5, method="A")
def test_gradient_of_sample(self, operable_mock_device_2_wires): """Differentiation of a sampled output.""" def circuit(x): qml.RX(x, wires=[0]) return qml.sample(qml.PauliZ(0)), qml.sample(qml.PauliX(1)) node = JacobianQNode(circuit, operable_mock_device_2_wires) with pytest.raises(QuantumFunctionError, match="Circuits that include sampling can not be differentiated."): node.jacobian(1.0)
def test_nondifferentiable_operator(self, operable_mock_device_2_wires): """Differentiating wrt. a parameter that appears as an argument to a nondifferentiable operator.""" def circuit(x): qml.BasisState(np.array([x, 0]), wires=[0, 1]) # not differentiable qml.RX(x, wires=[0]) return qml.expval(qml.PauliZ(0)) node = JacobianQNode(circuit, operable_mock_device_2_wires) with pytest.raises(ValueError, match="Cannot differentiate with respect to the parameters"): node.jacobian(0.5)
def test_indices_nonexistant(self, operable_mock_device_2_wires): """ The Jacobian is requested for non-existant parameters.""" def circuit(x): qml.Rot(0.3, x, -0.2, wires=[0]) return qml.expval(qml.PauliZ(0)) node = JacobianQNode(circuit, operable_mock_device_2_wires) with pytest.raises(ValueError, match="Tried to compute the gradient with respect to"): node.jacobian(0.5, wrt=[0, 6]) with pytest.raises(ValueError, match="Tried to compute the gradient with respect to"): node.jacobian(0.5, wrt=[1, -1])
def test_bogus_gradient_method_set(self, operable_mock_device_2_wires): """The gradient method set is bogus.""" def circuit(x): qml.RX(x, wires=[0]) return qml.expval(qml.PauliZ(0)) # in mutable mode, the grad method would be # recomputed and overwritten from the # bogus value 'J'. Caching stops this from happening. node = JacobianQNode(circuit, operable_mock_device_2_wires, mutable=False) node.evaluate([0.0], {}) node.par_to_grad_method[0] = "J" with pytest.raises(ValueError, match="Unknown gradient method"): node.jacobian(0.5)
def test_finite_difference_options(qubit_device_1_wire, order, h, monkeypatch): """Test that the _pd_finite_diff method for calculating the finite difference gradient correctly receives the options set when the JacobianQNode was instantiated.""" def circuit(x): qml.RX(x, wires=0) return qml.expval(qml.PauliZ(0)) q = JacobianQNode(circuit, qubit_device_1_wire, order=order, h=h) _pd_finite_diff = mock.MagicMock(return_value=0) with monkeypatch.context() as m: m.setattr("pennylane.qnodes.jacobian.JacobianQNode._pd_finite_diff", _pd_finite_diff) q.jacobian(0.2) call_kwargs = _pd_finite_diff.call_args[1] assert call_kwargs["order"] == order assert call_kwargs["h"] == h