qml.gradients.hessian_transform¶
-
class
hessian_transform
(*args, **kwargs)[source]¶ Bases:
pennylane.transforms.batch_transform.batch_transform
Decorator for defining quantum Hessian transforms.
Quantum Hessian transforms are a specific case of
gradient_transform
. Hessian transforms compute the second derivative of a quantum function. All quantum Hessian transforms accept a tape, and output a batch of tapes to be independently executed on a quantum device, alongside a post-processing function to return the result.- Parameters
expand_fn (function) – An expansion function (if required) to be applied to the input tape before the Hessian computation takes place. If not provided, the default expansion function simply expands all operations that have
Operation.grad_method=None
until all resulting operations have a defined gradient method.differentiable (bool) – Specifies whether the Hessian transform is differentiable or not. A transform may be non-differentiable if it does not use an autodiff framework for its tensor manipulations. In such a case, setting
differentiable=False
instructs the decorator to mark the output as ‘constant’, reducing potential overhead.hybrid (bool) –
Specifies whether classical processing inside a QNode should be taken into account when transforming a QNode.
If
True
, and classical processing is detected, the Jacobian of the classical processing will be computed and included. When evaluated, the returned Hessian will be with respect to the QNode arguments.If
False
, any internal QNode classical processing will be ignored. When evaluated, the returned Hessian will be with respect to the gate arguments, and not the QNode arguments.
Supported Hessian transforms must be of the following form:
@hessian_transform def my_custom_hessian(tape, **kwargs): ... return hessian_tapes, processing_fn
where:
tape
(QuantumTape): the input quantum tape to compute the Hessian ofhessian_tapes
(list[QuantumTape]): is a list of output tapes to be evaluated. If this list is empty, no quantum evaluations will be made.processing_fn
is a processing function to be applied to the output of the evaluatedhessian_tapes
. It should accept a list of numeric results with lengthlen(hessian_tapes)
, and return the Hessian matrix.
Once defined, the quantum Hessian transform can be used as follows:
>>> hessian_tapes, processing_fn = my_custom_hessian(tape, *hessian_kwargs) >>> res = execute(tapes, dev, interface="autograd", gradient_fn=qml.gradients.param_shift) >>> jacobian = processing_fn(res)
Alternatively, Hessian transforms can be applied directly to QNodes, in which case the execution is implicit:
>>> fn = my_custom_hessian(qnode, *hessian_kwargs) >>> fn(weights) # transformed function takes the same arguments as the QNode 1.2629730888100839
Note
The input tape might have parameters of various types, including NumPy arrays, JAX Arrays, and TensorFlow and PyTorch tensors.
If the Hessian transform is written in a autodiff-compatible manner, either by using a framework such as Autograd or TensorFlow, or by using
qml.math
for tensor manipulation, then higher-order derivatives will also be supported.Alternatively, you may use the
tape.unwrap()
context manager to temporarily convert all tape parameters to NumPy arrays and floats:>>> with tape.unwrap(): ... params = tape.get_parameters() # list of floats
Methods
construct
(tape, *targs, **tkwargs)Applies the batch tape transform to an input tape.
custom_qnode_wrapper
(fn)Register a custom QNode execution wrapper function for the batch transform.
default_qnode_wrapper
(qnode, targs, tkwargs)A wrapper method that takes a QNode and transform arguments, and returns a function that ‘wraps’ the QNode execution.
-
construct
(tape, *targs, **tkwargs)¶ Applies the batch tape transform to an input tape.
- Parameters
tape (QuantumTape) – the tape to be transformed
*args – positional arguments to pass to the tape transform
**kwargs – keyword arguments to pass to the tape transform
- Returns
list of transformed tapes to execute and a post-processing function.
- Return type
tuple[list[tapes], callable]
-
custom_qnode_wrapper
(fn)¶ Register a custom QNode execution wrapper function for the batch transform.
Example
def my_transform(tape, *targs, **tkwargs): ... return tapes, processing_fn @my_transform.custom_qnode_wrapper def my_custom_qnode_wrapper(self, qnode, targs, tkwargs): def wrapper_fn(*args, **kwargs): # construct QNode qnode.construct(args, kwargs) # apply transform to QNode's tapes tapes, processing_fn = self.construct(qnode.qtape, *targs, **tkwargs) # execute tapes and return processed result ... return processing_fn(results) return wrapper_fn
The custom QNode execution wrapper must have arguments
self
(the batch transform object),qnode
(the input QNode to transform and execute),targs
andtkwargs
(the transform arguments and keyword arguments respectively).It should return a callable object that accepts the same arguments as the QNode, and returns the transformed numerical result.
The default
default_qnode_wrapper()
method may be called if only pre- or post-processing dependent on QNode arguments is required:@my_transform.custom_qnode_wrapper def my_custom_qnode_wrapper(self, qnode, targs, tkwargs): transformed_qnode = self.default_qnode_wrapper(qnode) def wrapper_fn(*args, **kwargs): args, kwargs = pre_process(args, kwargs) res = transformed_qnode(*args, **kwargs) ... return ... return wrapper_fn
-
default_qnode_wrapper
(qnode, targs, tkwargs)[source]¶ A wrapper method that takes a QNode and transform arguments, and returns a function that ‘wraps’ the QNode execution.
The returned function should accept the same keyword arguments as the QNode, and return the output of applying the tape transform to the QNode’s constructed tape.