Classiq exports the
QLayer object, which inherits from
torch.nn.Module (like most objects in the
torch.nn namespace), and it acts like one!
QLayer object is defined as:
class QLayer(nn.Module): def __init__( self, circuit: Circuit, execute: ExecuteFunciton, post_process: PostProcessFunction, ): ...
The first parameter,
circuit, is the result of
Note that the parameters are assumed to follow the API stated in qnn.
The second parameter is a callable, taking in a
Circuit, and a dictionary, mapping each parameter name to its value, and returning a
MultipleExecutionDetails, which is a wrapper to
The third parameter is a callble, taking in an
ExecutionDetails, parsing it, and returning a
An example of such callables is:
import torch from classiq.applications.qnn.types import ( MultipleArguments, Circuit, MultipleExecutionDetails, ) def execute(circuit: Circuit, arguments: MultipleArguments) -> MultipleExecutionDetails: return Executor(prefereces).execute_batch(circuit, arguments) def post_process(result: ExecutionDetails) -> Tensor: # for example, post process can take some value out of `result.counts`, which is a `dict` value = _post_process_result(result) return torch.tensor(value)
Behind the scenes¶
behind the scenes, the
QLayer does the following
- handles processing the PQC
- handles initializing and tracking parameters
- handles passing the inputs and weights (as multi dimensional tensors) to the execution function
- handles gradient calculation on the PQC