ブログ
18
June
,
2025

Generative and Symbolic Descriptions in Qmod

記事をシェア
ライブラリ

Qmod is Classiq's quantum programming language. It is possible to write Qmod programs in Python using Qmod's Python embedding available through the Classiq SDK. This post covers the powerful integration of Qmod and the Python language and ecosystem realized by Qmod's generative descriptions.

Let's start with a simple example of Qmod's Python embedding. The following program sets two qubits in a Bell state.

@qfunc
def bell_state(a: QBit, b: QBit):
    H(a)
    CX(a, b)
@qfunc
def main():
    a = QBit()
    b = QBit()
    allocate(a)
    allocate(b)
    bell_state(a, b)

This Qmod program contains a main entry point and a bell_state function. After compiling the program, we get the following QASM code:

gate main__bell_state q0,q1 {
  h q0;
  cx q0,q1;
}

qreg q[2];
main__bell_state q[0],q[1];

Observe that the bell_state function was compiled directly into a QASM gate.

It is also possible to create parametric QASMs by adding classical parameters to the main entry point:

@qfunc
def bell_entangler(angle: CReal, a: QBit, b: QArray):
    H(a)
    for i in range(b.len):
        CRX(angle, a, b[i])
@qfunc
def main(angle: CReal):
    a = QBit()
    b = QArray(length=4)
    allocate(a)
    allocate(b)
    bell_entangler(angle, a, b)

This program implements a modified version of the Bell state called bell_entangler, in which the CX gate was replaced by an CRX operation controlled by an angle parameter and applied to every qubit of the quantum array b. Notice how a regular Python for-loop is used to describe the quantum function in this case. This could have been written with a native Qmod 'repeat' statement, but it's often more convenient to just use Python. Here's the resulting QASM:

input float[64] angle_param;
gate main__bell_entangler(angle_param) _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3, _gate_q_4 {
  h _gate_q_0;
  crx(angle_param) _gate_q_0, _gate_q_1;
  crx(angle_param) _gate_q_0, _gate_q_2;
  crx(angle_param) _gate_q_0, _gate_q_3;
  crx(angle_param) _gate_q_0, _gate_q_4;
}
qubit[5] q;
main__bell_entangler(angle_param) q[0], q[1], q[2], q[3], q[4];

Qmod's generative descriptions make it possible to integrate Python objects and control flow into quantum functions. For example, we can add a Python list parameter to our bell_entanglerfunction:

@qfunc
def bell_entangler(multipliers: list[float], angle: CReal, a: QBit, b: QArray):
    H(a)
    for i in range(b.len):
        CRX(angle * numpy.arctan(multipliers[i]), a, b[i])


@qfunc
def main(angle: CReal):
    a = QBit()
    b = QArray(length=4)
    allocate(a)
    allocate(b)
    bell_entangler([1, 2, 3, 4], angle, a, b)
    bell_entangler(numpy.arange(0, 1, 0.3), angle, a, b)

Function bell_entangler now accepts a Pythonic parameter multipliers comprising a list of float values. Since multipliers is a Python object, we can send its elements to a third-party library, Numpy. Unlike the previous example, here the Python loop and iteration variable are mandatory, because Numpy cannot handle a Qmod symbolic expression. We call bell_entangler a generative description because it generates a different gate for each value of multipliers. As bell_entangler is called twice in the program above, the Qmod compiler generates two instances of the function, one for multipliers=[1, 2, 3, 4] and one for multipliers=numpy.arange(0, 1, 0.3).

input float[64] angle_param;
gate main__bell_entangler_0(angle_param) _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3, _gate_q_4 {
  h _gate_q_0;
  crx(pi/4*angle_param) _gate_q_0, _gate_q_1;
  crx(1.1071*angle_param) _gate_q_0, _gate_q_2;
  crx(1.2490*angle_param) _gate_q_0, _gate_q_3;
  crx(1.3258*angle_param) _gate_q_0, _gate_q_4;
}
gate main__bell_entangler_1(angle_param) _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3, _gate_q_4 {
  h _gate_q_0;
  crx(0) _gate_q_0, _gate_q_1;
  crx(0.2914*angle_param) _gate_q_0, _gate_q_2;
  crx(0.5404*angle_param) _gate_q_0, _gate_q_3;
  crx(0.7328*angle_param) _gate_q_0, _gate_q_4;
}
qubit[5] q;
main__bell_entangler_0(angle_param) q[0], q[1], q[2], q[3], q[4];
main__bell_entangler_1(angle_param) q[0], q[1], q[2], q[3], q[4];

Because the multipliers parameter is Pythonic, it was interpreted and erased by the Qmod compiler. On the other hand, the symbolic angle parameter is preserved in the final QASM.

The Classiq library includes several models that employ generative descriptions, such as our Decoded Quantum Interferometry implementation. This and other Qmod models use generative descriptions to enrich quantum functions with the awsome features of the Python ecosystem.

Qmod is Classiq's quantum programming language. It is possible to write Qmod programs in Python using Qmod's Python embedding available through the Classiq SDK. This post covers the powerful integration of Qmod and the Python language and ecosystem realized by Qmod's generative descriptions.

Let's start with a simple example of Qmod's Python embedding. The following program sets two qubits in a Bell state.

@qfunc
def bell_state(a: QBit, b: QBit):
    H(a)
    CX(a, b)
@qfunc
def main():
    a = QBit()
    b = QBit()
    allocate(a)
    allocate(b)
    bell_state(a, b)

This Qmod program contains a main entry point and a bell_state function. After compiling the program, we get the following QASM code:

gate main__bell_state q0,q1 {
  h q0;
  cx q0,q1;
}

qreg q[2];
main__bell_state q[0],q[1];

Observe that the bell_state function was compiled directly into a QASM gate.

It is also possible to create parametric QASMs by adding classical parameters to the main entry point:

@qfunc
def bell_entangler(angle: CReal, a: QBit, b: QArray):
    H(a)
    for i in range(b.len):
        CRX(angle, a, b[i])
@qfunc
def main(angle: CReal):
    a = QBit()
    b = QArray(length=4)
    allocate(a)
    allocate(b)
    bell_entangler(angle, a, b)

This program implements a modified version of the Bell state called bell_entangler, in which the CX gate was replaced by an CRX operation controlled by an angle parameter and applied to every qubit of the quantum array b. Notice how a regular Python for-loop is used to describe the quantum function in this case. This could have been written with a native Qmod 'repeat' statement, but it's often more convenient to just use Python. Here's the resulting QASM:

input float[64] angle_param;
gate main__bell_entangler(angle_param) _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3, _gate_q_4 {
  h _gate_q_0;
  crx(angle_param) _gate_q_0, _gate_q_1;
  crx(angle_param) _gate_q_0, _gate_q_2;
  crx(angle_param) _gate_q_0, _gate_q_3;
  crx(angle_param) _gate_q_0, _gate_q_4;
}
qubit[5] q;
main__bell_entangler(angle_param) q[0], q[1], q[2], q[3], q[4];

Qmod's generative descriptions make it possible to integrate Python objects and control flow into quantum functions. For example, we can add a Python list parameter to our bell_entanglerfunction:

@qfunc
def bell_entangler(multipliers: list[float], angle: CReal, a: QBit, b: QArray):
    H(a)
    for i in range(b.len):
        CRX(angle * numpy.arctan(multipliers[i]), a, b[i])


@qfunc
def main(angle: CReal):
    a = QBit()
    b = QArray(length=4)
    allocate(a)
    allocate(b)
    bell_entangler([1, 2, 3, 4], angle, a, b)
    bell_entangler(numpy.arange(0, 1, 0.3), angle, a, b)

Function bell_entangler now accepts a Pythonic parameter multipliers comprising a list of float values. Since multipliers is a Python object, we can send its elements to a third-party library, Numpy. Unlike the previous example, here the Python loop and iteration variable are mandatory, because Numpy cannot handle a Qmod symbolic expression. We call bell_entangler a generative description because it generates a different gate for each value of multipliers. As bell_entangler is called twice in the program above, the Qmod compiler generates two instances of the function, one for multipliers=[1, 2, 3, 4] and one for multipliers=numpy.arange(0, 1, 0.3).

input float[64] angle_param;
gate main__bell_entangler_0(angle_param) _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3, _gate_q_4 {
  h _gate_q_0;
  crx(pi/4*angle_param) _gate_q_0, _gate_q_1;
  crx(1.1071*angle_param) _gate_q_0, _gate_q_2;
  crx(1.2490*angle_param) _gate_q_0, _gate_q_3;
  crx(1.3258*angle_param) _gate_q_0, _gate_q_4;
}
gate main__bell_entangler_1(angle_param) _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3, _gate_q_4 {
  h _gate_q_0;
  crx(0) _gate_q_0, _gate_q_1;
  crx(0.2914*angle_param) _gate_q_0, _gate_q_2;
  crx(0.5404*angle_param) _gate_q_0, _gate_q_3;
  crx(0.7328*angle_param) _gate_q_0, _gate_q_4;
}
qubit[5] q;
main__bell_entangler_0(angle_param) q[0], q[1], q[2], q[3], q[4];
main__bell_entangler_1(angle_param) q[0], q[1], q[2], q[3], q[4];

Because the multipliers parameter is Pythonic, it was interpreted and erased by the Qmod compiler. On the other hand, the symbolic angle parameter is preserved in the final QASM.

The Classiq library includes several models that employ generative descriptions, such as our Decoded Quantum Interferometry implementation. This and other Qmod models use generative descriptions to enrich quantum functions with the awsome features of the Python ecosystem.

"Qubit Guyのポッドキャスト "について

The Qubit Guy(弊社最高マーケティング責任者ユヴァル・ボーガー)がホストを務めるこのポッドキャストは、量子コンピューティングのオピニオンリーダーをゲストに迎え、量子コンピューティングのエコシステムに影響を与えるビジネスや技術的な疑問について議論します。ゲストは、量子コンピュータのソフトウェアやアルゴリズム、量子コンピュータのハードウェア、量子コンピューティングの主要なアプリケーション、量子産業の市場調査などについて興味深いインサイトを提供します。

ポッドキャストへのゲスト推薦をご希望の方は、こちらまでご連絡ください

さらに見る

見つかりませんでした。

量子ソフトウェア開発を開始

お問い合わせ