finite_diff(tape, argnum=None, h=1e-07, approx_order=1, n=1, strategy='forward', f0=None, validate_params=True)[source]

Transform a QNode to compute the finite-difference gradient of all gate parameters with respect to its inputs.

Parameters
• qnode (pennylane.QNode or QuantumTape) – quantum tape or QNode to differentiate

• argnum (int or list[int] or None) – Trainable parameter indices to differentiate with respect to. If not provided, the derivatives with respect to all trainable parameters are returned.

• h (float) – finite difference method step size

• approx_order (int) – The approximation order of the finite-difference method to use.

• n (int) – compute the $$n$$-th derivative

• strategy (str) – The strategy of the finite difference method. Must be one of "forward", "center", or "backward". For the "forward" strategy, the finite-difference shifts occur at the points $$x_0, x_0+h, x_0+2h,\dots$$, where $$h$$ is some small stepsize. The "backwards" strategy is similar, but in reverse: $$x_0, x_0-h, x_0-2h, \dots$$. Finally, the "center" strategy results in shifts symmetric around the unshifted point: $$\dots, x_0-2h, x_0-h, x_0, x_0+h, x_0+2h,\dots$$.

• f0 (tensor_like[float] or None) – Output of the evaluated input tape. If provided, and the gradient recipe contains an unshifted term, this value is used, saving a quantum evaluation.

• validate_params (bool) – Whether to validate the tape parameters or not. If True, the Operation.grad_method attribute and the circuit structure will be analyzed to determine if the trainable parameters support the finite-difference method. If False, the finite-difference method will be applied to all parameters.

Returns

• If the input is a QNode, a tensor representing the output Jacobian matrix of size (number_outputs, number_gate_parameters) is returned.

• If the input is a tape, a tuple containing a list of generated tapes, in addition to a post-processing function to be applied to the evaluated tapes.

Return type

tensor_like or tuple[list[QuantumTape], function]

Example

This transform can be registered directly as the quantum gradient transform to use during autodifferentiation:

>>> dev = qml.device("default.qubit", wires=2)
... def circuit(params):
...     qml.RX(params, wires=0)
...     qml.RY(params, wires=0)
...     qml.RX(params, wires=0)
...     return qml.expval(qml.PauliZ(0)), qml.var(qml.PauliZ(0))
>>> params = np.array([0.1, 0.2, 0.3], requires_grad=True)
>>> qml.jacobian(circuit)(params)
tensor([[-0.38751725, -0.18884792, -0.38355708],


This gradient transform can also be applied directly to QNode objects:

>>> @qml.qnode(dev)
... def circuit(params):
...     qml.RX(params, wires=0)
...     qml.RY(params, wires=0)
...     qml.RX(params, wires=0)
...     return qml.expval(qml.PauliZ(0)), qml.var(qml.PauliZ(0))
tensor([[-0.38751725, -0.18884792, -0.38355708],


This quantum gradient transform can also be applied to low-level QuantumTape objects. This will result in no implicit quantum device evaluation. Instead, the processed tapes, and post-processing function, which together define the gradient are directly returned:

>>> with qml.tape.QuantumTape() as tape:
...     qml.RX(params, wires=0)
...     qml.RY(params, wires=0)
...     qml.RX(params, wires=0)
...     qml.expval(qml.PauliZ(0))
...     qml.var(qml.PauliZ(0))
[<QuantumTape: wires=, params=3>,
<QuantumTape: wires=, params=3>,
<QuantumTape: wires=, params=3>,
<QuantumTape: wires=, params=3>]


This can be useful if the underlying circuits representing the gradient computation need to be analyzed.

The output tapes can then be evaluated and post-processed to retrieve the gradient:

>>> dev = qml.device("default.qubit", wires=2)