qat.lang.qfunc

qat.lang.qfunc(*func, **kwargs)

Decorator that turns a python function into a job based function.

It allows to quickly and simply write an energy sampling job by:

  • specifying the circuit to sample in the body of the function (similarily to what qrout allows)

  • specifying the observable(s) or qbits to sample in the return statement

The argument can either be scalar (that will be replaced by variables when the function is decorated) or arrays whose shape needs to be specified in the decorator (see qrout() for more details).

Example

Let us say that we want to apply a RX gate and measure the expected value of the operator \(\sigma_z\).

Such a “procedure” can be understood as a function that takes the angle \(theta\) of the RX gate as argument and returns the expected value of \(\sigma_z\) over state \(RX(theta)|0\rangle\). As such one would love to declare this procedure as a python function. This is what qfunc allows:

import numpy as np
from qat.lang import qfunc, RX
from qat.core import Observable as Obs

@qfunc
def my_function(theta):
    RX(theta)(0)
    return Obs.sigma_z(0)

# The function can be evaluated as a python function:
some_random_point = np.random.random() * 2 * np.pi
print(f"The energy for theta = {some_random_point} is {my_function(some_random_point)}")

# Since there is a job and a circuit underneath this function, one can also plot it:
my_function.display(batchmode=True)

# The proper variational job that was built at decoration can be found here:
print(type(my_function.qlm_obj))
The energy for theta = 1.6141193715166473 is -0.043309532884245605
 ┌─────────┐
─┤RX[theta]├
 └─────────┘
            

<class 'qat.core.wrappers.job.Job'>
No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)