Skip to content

Operators in classiq

classiq supports creating QMOD operator definitions, using the QCallable type-hint to specify an operand declaration. The QCallable type-hint accepts a list of parameters that specify the parameters of the operand: QParam or QVar. Following is an example:

from sympy import pi
from classiq import QFunc, QParam, QVar, QCallable, H, PHASE, allocate
from classiq import create_model, synthesize, show


@QFunc
def foo(
    n: QParam[int],
    my_operand: QCallable[QParam[float], QVar[1]],
    qv: QVar[1],
) -> None:
    H(target=qv)
    for i in range(4):
        my_operand((i / n) * pi, qv)


@QFunc
def bar(m: QParam[int], qv: QVar[1]) -> None:
    @QFunc
    def goo(arg0: QParam[float], arg1: QVar[1]) -> None:
        PHASE(theta=arg0, target=arg1)

    foo(n=m * 2, my_operand=goo, qv=qv)


@QFunc
def main() -> None:
    qv = QVar("qv")
    allocate(1, qv)
    bar(m=2, qv=qv)


model = create_model(main)
qprog = synthesize(model)
show(qprog)

This results in the following circuit: operators_qfunc.png

You can also specify an operand without the @QFunc decorator; instead, as a direct Python def or lambda:

from sympy import pi
from classiq import QFunc, QParam, QVar, QCallable, H, PHASE
from classiq import create_model, synthesize, show


@QFunc
def foo(
    n: QParam[int],
    my_operand: QCallable[QParam[float], QVar[1]],
    qv: QVar[1],
) -> None:
    H(target=qv)
    for i in range(4):
        my_operand((i / n) * pi, qv)


@QFunc
def bar(m: QParam[int], qv: QVar[1]) -> None:
    def goo(arg0, arg1):
        PHASE(theta=arg0, target=arg1)

    foo(n=m * 2, my_operand=goo, qv=qv)
    foo(
        n=m // 2,
        my_operand=lambda arg0, arg1: PHASE(theta=arg0, target=arg1),
        qv=qv,
    )


@QFunc
def main() -> None:
    qv = QVar("qv")
    allocate(1, qv)
    bar(m=2, qv=qv)