qml.qnodes.ReversibleQNode

class ReversibleQNode(func, device, mutable=True, **kwargs)[source]

Bases: pennylane.qnodes.qubit.QubitQNode

Quantum node for reversible analytic differentiation method.

This QNode enables a specific kind of differentiation method unique to simulators.

The ReversibleQNode computes the analytic derivative of the circuit by using the following strategy:

Assume a circuit has a gate \(G(\theta)\) that we want to differentiate. Without loss of generality, we can write the circuit in the form three unitaries: \(UGV\). Starting from the initial state \(\vert 0\rangle\), the quantum state is evolved up to the “pre-measurement” state \(\vert\psi\rangle=UGV\vert 0\rangle\), which is saved (this can be reused for each variable being differentiated).

We then apply the unitary \(V^{-1}\) to evolve this state backwards in time until just after the gate \(G\) (hence the name “reversible”). The generator of \(G\) is then applied as a gate, and we evolve forward using \(V\) again. At this stage, the state of the simulator is proportional to \(\frac{\partial}{\partial\theta}\vert\psi\rangle\). Some further post-processing of this gives the derivative \(\frac{\partial}{\partial\theta} \langle \hat{O} \rangle\) for any observable O.

The reversible approach is similar to backpropagation, but trades off extra computation for enhanced memory efficiency. Where backpropagation caches the state tensors at each step during a forward pass, the reversible method only caches the final pre-measurement state.

Compared to the parameter-shift rule, the reversible method can be faster or slower, depending on the density and location of parametrized gates in a circuit (circuits with higher density of parametrized gates near the end of the circuit will see a benefit).

Parameters
  • func (callable) – The quantum function of the QNode. A Python function containing Operation constructor calls, and returning a tuple of measured Observable instances.

  • device (Device) – computational device to execute the function on

Keyword Arguments
  • mutable (bool) – whether the QNode is mutable or not

  • use_native_type (bool) – If True, return the result in whatever type the device uses internally, otherwise convert it into array[float]. Default: True.

h

step size for the finite difference method

interface

automatic differentiation interface used by the node, if any

order

order for the finite difference method

h

step size for the finite difference method

Type

float

interface

automatic differentiation interface used by the node, if any

Type

str, None

order

order for the finite difference method

Type

float

__call__(*args, **kwargs)

Wrapper for BaseQNode.evaluate().

active_context()

Returns the currently active queuing context.

append(obj, **kwargs)

Append an object to the queue(s).

draw([charset, show_variable_names])

Draw the QNode as a circuit diagram.

evaluate(args, kwargs)

Evaluate the quantum function on the specified device.

evaluate_obs(obs, args, kwargs)

Evaluate the value of the given observables.

get_info(obj)

Returns information of an object in the queue.

get_trainable_args()

Returns the indices of quantum function positional arguments that support differentiability.

jacobian(args[, kwargs, wrt, method, options])

Compute the Jacobian of the QNode.

metric_tensor(args[, kwargs, diag_approx, …])

Evaluate the value of the metric tensor.

print_applied()

Prints the most recently applied operations from the QNode.

remove(obj)

Remove an object from the queue(s) if it is in the queue(s).

set_trainable_args(arg_indices)

Store the indices of quantum function positional arguments that support differentiability.

to_autograd()

Attach the TensorFlow interface to the Jacobian QNode.

to_tf()

Attach the TensorFlow interface to the Jacobian QNode.

to_torch()

Attach the Torch interface to the Jacobian QNode.

unwrap_tensor_kwargs(kwargs)

Unwraps the pennylane.numpy.tensor objects that were passed as keyword arguments so that they can be handled as gate parameters by arbitrary devices.

update_info(obj, **kwargs)

Updates information of an object in the active queue.

__call__(*args, **kwargs)

Wrapper for BaseQNode.evaluate().

classmethod active_context()

Returns the currently active queuing context.

classmethod append(obj, **kwargs)

Append an object to the queue(s).

Parameters

obj – the object to be appended

draw(charset='unicode', show_variable_names=False)

Draw the QNode as a circuit diagram.

Consider the following circuit as an example:

@qml.qnode(dev)
def qfunc(a, w):
    qml.Hadamard(0)
    qml.CRX(a, wires=[0, 1])
    qml.Rot(w[0], w[1], w[2], wires=[1])
    qml.CRX(-a, wires=[0, 1])

    return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))

We can draw the circuit after it has been executed:

>>> result = qfunc(2.3, [1.2, 3.2, 0.7])
>>> print(qfunc.draw())
0: ──H──╭C────────────────────────────╭C─────────╭┤ ⟨Z ⊗ Z⟩
1: ─────╰RX(2.3)──Rot(1.2, 3.2, 0.7)──╰RX(-2.3)──╰┤ ⟨Z ⊗ Z⟩
>>> print(qfunc.draw(charset="ascii"))
0: --H--+C----------------------------+C---------+| <Z @ Z>
1: -----+RX(2.3)--Rot(1.2, 3.2, 0.7)--+RX(-2.3)--+| <Z @ Z>
>>> print(qfunc.draw(show_variable_names=True))
0: ──H──╭C─────────────────────────────╭C─────────╭┤ ⟨Z ⊗ Z⟩
1: ─────╰RX(a)──Rot(w[0], w[1], w[2])──╰RX(-1*a)──╰┤ ⟨Z ⊗ Z⟩
Parameters
  • charset (str, optional) – The charset that should be used. Currently, “unicode” and “ascii” are supported.

  • show_variable_names (bool, optional) – Show variable names instead of values.

Raises
  • ValueError – If the given charset is not supported

  • pennylane.QuantumFunctionError – Drawing is impossible because the underlying CircuitGraph has not yet been constructed

Returns

The circuit representation of the QNode

Return type

str

evaluate(args, kwargs)

Evaluate the quantum function on the specified device.

Parameters
  • args (tuple[Any]) – positional arguments to the quantum function (differentiable)

  • kwargs (dict[str, Any]) – auxiliary arguments (not differentiable)

Keyword Arguments

use_native_type (bool) – If True, return the result in whatever type the device uses internally, otherwise convert it into array[float]. Default: False.

Returns

output measured value(s)

Return type

float or array[float]

evaluate_obs(obs, args, kwargs)

Evaluate the value of the given observables.

Assumes construct() has already been called.

Parameters
  • obs (Iterable[Observable]) – observables to measure

  • args (tuple[Any]) – positional arguments to the quantum function (differentiable)

  • kwargs (dict[str, Any]) – auxiliary arguments (not differentiable)

Returns

measured values

Return type

array[float]

classmethod get_info(obj)

Returns information of an object in the queue.

get_trainable_args()

Returns the indices of quantum function positional arguments that support differentiability.

Returns

Differentiable positional argument indices. A

value of None means that all argument indices are differentiable.

Return type

None or Set[int]

jacobian(args, kwargs=None, *, wrt=None, method='best', options=None)

Compute the Jacobian of the QNode.

Returns the Jacobian of the parametrized quantum circuit encapsulated in the QNode. The Jacobian is returned as a two-dimensional array. The (possibly nested) input arguments of the QNode are flattened so the QNode can be interpreted as a simple \(\mathbb{R}^m \to \mathbb{R}^n\) function.

The Jacobian can be computed using several methods:

  • Finite differences ('F'). The first-order method evaluates the circuit at \(n+1\) points of the parameter space, the second-order method at \(2n\) points, where n = len(wrt).

  • Analytic method ('A'). Analytic, if implemented by the inheriting QNode.

  • Best known method for each parameter ('best'): uses the analytic method if possible, otherwise finite difference.

  • Device method ('device'): Delegates the computation of the Jacobian to the device executing the circuit. Only supported by devices that provide their own method for computing derivatives; support can be checked by querying the device capabilities: dev.capabilities()['provides_jacobian'] must return True. Examples of supported devices include the experimental "default.tensor.tf" device.

Note

The finite difference method is sensitive to statistical noise in the circuit output, since it compares the output at two points infinitesimally close to each other. Hence the ‘F’ method requires exact expectation values, i.e., analytic=True in simulator devices.

Parameters
  • args (nested Iterable[float] or float) – positional arguments to the quantum function (differentiable)

  • kwargs (dict[str, Any]) – auxiliary arguments to the quantum function (not differentiable)

  • wrt (Sequence[int] or None) – Indices of the flattened positional parameters with respect to which to compute the Jacobian. None means all the parameters. Note that you cannot compute the Jacobian with respect to the kwargs.

  • method (str) – Jacobian computation method, in {'F', 'A', 'best', 'device'}, see above

  • options (dict[str, Any]) –

    additional options for the computation methods

    • h (float): finite difference method step size

    • order (int): finite difference method order, 1 or 2

Returns

Jacobian, shape (n, len(wrt)), where n is the number of outputs returned by the QNode

Return type

array[float]

metric_tensor(args, kwargs=None, *, diag_approx=False, only_construct=False)

Evaluate the value of the metric tensor.

Parameters
  • args (tuple[Any]) – positional (differentiable) arguments

  • kwargs (dict[str, Any]) – auxiliary arguments

  • diag_approx (bool) – iff True, use the diagonal approximation

  • only_construct (bool) – Iff True, construct the circuits used for computing the metric tensor but do not execute them, and return None.

Returns

metric tensor

Return type

array[float]

print_applied()

Prints the most recently applied operations from the QNode.

classmethod remove(obj)

Remove an object from the queue(s) if it is in the queue(s).

Parameters

obj – the object to be removed

set_trainable_args(arg_indices)

Store the indices of quantum function positional arguments that support differentiability.

Parameters

args (None or Set[int]) – Differentiable positional argument indices. A value of None means that all argument indices are differentiable.

to_autograd()

Attach the TensorFlow interface to the Jacobian QNode.

Raises

QuantumFunctionError – if Autograd is not installed

to_tf()

Attach the TensorFlow interface to the Jacobian QNode.

Raises

QuantumFunctionError – if TensorFlow >= 1.12 is not installed

to_torch()

Attach the Torch interface to the Jacobian QNode.

Raises

QuantumFunctionError – if PyTorch is not installed

static unwrap_tensor_kwargs(kwargs)

Unwraps the pennylane.numpy.tensor objects that were passed as keyword arguments so that they can be handled as gate parameters by arbitrary devices.

Parameters

kwargs (dict[str, Any]) – Auxiliary arguments passed to the quantum function.

Returns

Auxiliary arguments passed to the quantum function in an unwrapped form (if applicable).

Return type

dict[str, Any]

classmethod update_info(obj, **kwargs)

Updates information of an object in the active queue.