qml.adjoint¶
-
adjoint
(fn, lazy=True)[source]¶ Create the adjoint of an Operator or a function that applies the adjoint of the provided function.
- Parameters
fn (function or
Operator
) – A single operator or a quantum function that applies quantum operations.- Keyword Arguments
lazy=True (bool) – If the transform is behaving lazily, all operations are wrapped in a
Adjoint
class and handled later. Iflazy=False
, operation-specific adjoint decompositions are first attempted.- Returns
If an Operator is provided, returns an Operator that is the adjoint. If a function is provided, returns a function with the same call signature that returns the Adjoint of the provided function.
- Return type
(function or
Operator
)
Note
The adjoint and inverse are identical for unitary gates, but not in general. For example, quantum channels and observables may have different adjoint and inverse operators.
Note
This function supports a batched operator:
>>> op = qml.adjoint(qml.RX([1, 2, 3], wires=0)) >>> qml.matrix(op).shape (3, 2, 2)
But it doesn’t support batching of operators:
>>> op = qml.adjoint([qml.RX(1, wires=0), qml.RX(2, wires=0)]) ValueError: The object [RX(1, wires=[0]), RX(2, wires=[0])] of type <class 'list'> is not callable. This error might occur if you apply adjoint to a list of operations instead of a function or template.
See also
Example
The adjoint transform can accept a single operator.
>>> @qml.qnode(qml.device('default.qubit', wires=1)) ... def circuit2(y): ... qml.adjoint(qml.RY(y, wires=0)) ... return qml.expval(qml.PauliZ(0)) >>> print(qml.draw(circuit2)("y")) 0: ──RY(y)†─┤ <Z> >>> print(qml.draw(circuit2, expansion_strategy="device")(0.1)) 0: ──RY(-0.10)─┤ <Z>
The adjoint transforms can also be used to apply the adjoint of any quantum function. In this case,
adjoint
accepts a single function and returns a function with the same call signature.We can create a QNode that applies the
my_ops
function followed by its adjoint:def my_ops(a, wire): qml.RX(a, wires=wire) qml.SX(wire) dev = qml.device('default.qubit', wires=1) @qml.qnode(dev) def circuit(a): my_ops(a, wire=0) qml.adjoint(my_ops)(a, wire=0) return qml.expval(qml.PauliZ(0))
Printing this out, we can see that the inverse quantum function has indeed been applied:
>>> print(qml.draw(circuit)(0.2)) 0: ──RX(0.20)──SX──SX†──RX(0.20)†─┤ <Z>
Lazy Evaluation
When
lazy=False
, the function first attempts operation-specific decomposition of the adjoint via theOperator.adjoint()
method. Only if an Operator doesn’t have anOperator.adjoint()
method is the object wrapped with theAdjoint
wrapper class.>>> qml.adjoint(qml.PauliZ(0), lazy=False) PauliZ(wires=[0]) >>> qml.adjoint(qml.RX, lazy=False)(1.0, wires=0) RX(-1.0, wires=[0]) >>> qml.adjoint(qml.S, lazy=False)(0) Adjoint(S)(wires=[0])