qml.capture¶
This module implements PennyLane’s capturing mechanism for hybrid quantum-classical programs.
Warning
This module is experimental and will change significantly in the future.
|
Disable the capturing mechanism of hybrid quantum-classical programs in a PennyLane Program Representation (plxpr). |
|
Enable the capturing mechanism of hybrid quantum-classical programs in a PennyLane Program Representation (plxpr). |
|
Return whether the capturing mechanism of hybrid quantum-classical programs in a PennyLane Program Representation (plxpr) is enabled. |
|
Create a primitive corresponding to an operator type. |
Create a primitive corresponding to the input type where the abstract inputs are an operator. |
|
Create a primitive corresponding to the input type where the abstract inputs are the wires. |
|
Create a primitive corresponding to the input type where the abstract inputs are classical mid circuit measurement results. |
|
|
A capture compatible call to a QNode. |
To activate and deactivate the new PennyLane program capturing mechanism, use
the switches qml.capture.enable
and qml.capture.disable
.
Whether or not the capturing mechanism is currently being used can be
queried with qml.capture.enabled
.
By default, the mechanism is disabled:
>>> import pennylane as qml
>>> qml.capture.enabled()
False
>>> qml.capture.enable()
>>> qml.capture.enabled()
True
>>> qml.capture.disable()
>>> qml.capture.enabled()
False
Custom Operator Behaviour
Any operator that inherits from Operator
gains a default ability to be captured
in a Jaxpr. Any positional argument is bound as a tracer, wires are processed out into individual tracers,
and any keyword arguments are passed as keyword metadata.
class MyOp1(qml.operation.Operator):
def __init__(self, arg1, wires, key=None):
super().__init__(arg1, wires=wires)
def qfunc(a):
MyOp1(a, wires=(0,1), key="a")
qml.capture.enable()
print(jax.make_jaxpr(qfunc)(0.1))
{ lambda ; a:f32[]. let
_:AbstractOperator() = MyOp1[key=a n_wires=2] a 0 1
in () }
But an operator developer may need to override custom behavior for calling cls._primitive.bind
(where cls
indicates the class) if:
The operator does not accept wires, like
SymbolicOp
orCompositeOp
.The operator needs to enforce a data / metadata distinction, like
PauliRot
.
In such cases, the operator developer can override cls._primitive_bind_call
, which
will be called when constructing a new class instance instead of type.__call__
. For example,
class JustMetadataOp(qml.operation.Operator):
def __init__(self, metadata):
super().__init__(wires=[])
self._metadata = metadata
@classmethod
def _primitive_bind_call(cls, metadata):
return cls._primitive.bind(metadata=metadata)
def qfunc():
JustMetadataOp("Y")
qml.capture.enable()
print(jax.make_jaxpr(qfunc)())
{ lambda ; . let _:AbstractOperator() = JustMetadataOp[metadata=Y] in () }
As you can see, the input "Y"
, while being passed as a positional argument, is converted to
metadata within the custom _primitive_bind_call
method.
If needed, developers can also override the implementation method of the primitive like was done with Controlled
.
Controlled
needs to do so to handle packing and unpacking the control wires.
class MyCustomOp(qml.operation.Operator):
pass
@MyCustomOp._primitive.def_impl
def _(*args, **kwargs):
return type.__call__(MyCustomOp, *args, **kwargs)