qml.templates.core.subroutine_resource_rep

subroutine_resource_rep(subroutine, *args, **kwargs)[source]

Generate a CompressedResourceOp similar to resource_rep() that is more specifically targeted for use with Subroutine instances.

Parameters:

subroutine (Subroutine) – the subroutine we are going to use in a decomposition.

Returns:

a condensed representation of the subroutine that can be used in specifying the resources of another function.

Return type:

pennylane.decomposition.CompressedResourceOp

Warning

Note that the following features only work with tape-based PennyLane, and do not work with Catalyst.

Suppose we have a Subroutine we want to use in the decomposition of another Operator.

from functools import partial

def S_resources(params, wires, rotation):
    return {qml.resource_rep(rotation): params.shape[0]}

@partial(qml.templates.Subroutine, static_argnames="rotation", compute_resources=S_resources)
def S(params, wires, rotation):
    for x in params:
        rotation(x, wires)

We can add S to the resources of another Operator by using this function together with an abstract form of the arguments it will be called with, using AbstractArray.

from pennylane.templates import AbstractArray, subroutine_resource_rep

class MyOp(qml.operation.Operation):
    pass

abstract_params = AbstractArray((4, ), float)
abstract_wires = AbstractArray(()) # a single wire
S_rep = subroutine_resource_rep(S, abstract_params, abstract_wires, qml.RX)

@qml.decomposition.register_resources({S_rep: 1})
def my_op_decomposition(wires):
    # data of shape (4, ) and dtype float
    params = np.array([1.0, 2.0, 3.0, 4.0])
    S(params, wires, qml.RX)

qml.add_decomps(MyOp, my_op_decomposition)

We can now see MyOp decompose into the relevant subroutine:

qml.decomposition.enable_graph()

@qml.qnode(qml.device('reference.qubit', wires=1))
def c():
    MyOp(wires=0)
    return qml.state()
>>> print(qml.draw(qml.decompose(c, max_expansion=1))())
0: ──S(M0)─┤  State

M0 =
[1. 2. 3. 4.]