複数トランスパイラを統合的に扱えるフレームワークTranquを開発しました
大阪大学QIQBの束野(@snuffkin)です。
先日、大阪大学とTIS株式会社との共同研究で、Tranqu(トランク)というOSSを開発しました。この記事ではそのTranquについてご紹介します。
背景
量子コンピュータを利用する際、Qiskit, Qulacs等の量子回路ライブラリを使って実装しますが、実装した量子回路がそのまま実機で動くわけではありません。量子デバイスに関する情報を元に実機で動くゲートに変換したり、プログラムをなるべく短くなるように最適化したものを、実機で動かします。この変換・最適化処理をトランスパイルと呼び、トランスパイルするプログラムをトランスパイラと呼びます。
NISQと呼ばれる現在の量子コンピュータはノイズの影響が大きく、トランスパイラが実行精度に大きな影響を与えます。実際、QV(Quantum Volume)等の量子コンピュータのベンチマーク指標には、トランスパイラの能力も影響しています。
最適なトランスパイルを行うことはNP完全問題であるため、現実的には難しく、基本的にトランスパイラにはヒューリスティックなアルゴリズムが採用されています。多くのトランスパイラが存在しますが、「どのトランスパイラがベストか?」というのは量子回路やデバイス情報によって異なります(問題のインスタンスに依存)。「あらゆる量子回路に対してベストの結果を返す、トランスパイラの決定版」というのは(少なくとも現時点では)存在しません。
そこで、様々なトランスパイラを使って量子回路を実行してみて、もっともよい結果を採用するのがよさそうです。
ですが、実際に様々なトランスパイラを使うには敷居が高いのが現状です。量子回路ライブラリは量子クラウドのベンダーがサポートするものに限定されます。また、量子回路ライブラリを決めると、それをサポートするトランスパイラも限定されます。
そのため、トランスパイラを使い分けるのが難しいのが現状です。
そこで開発したが、Tranqu(トランク)です。
Tranquの概要
Tranquは複数の量子回路ライブラリ・形式に対応した、トランスパイラのワンストップ・フレームワークです。
量子回路や量子デバイス情報(量子チップ情報)を、ユーザが指定したトランスパイラが対応している形式に変換し、トランスパイルを行います。
Tranquの主な機能は次の通りです。
- プログラム変換: 量子回路を別のライブラリの形式に変換します。
- デバイス情報変換: デバイス情報を別のライブラリの形式に変換します。
- トランスパイル: 量子回路とデバイス情報の両方を変換し、ユーザが指定したトランスパイラを実行します。トランスパイラのオプションは、そのトランスパイラを使っているユーザに自然な形式で指定できます。
- 統計情報: トランスパイル前後の統計データを出力します。
- カスタム・コンポーネントの利用: Tranquは、ユーザがトランスパイラ、プログラム変換、デバイス情報変換の機能を作成して、Tranquで使えるようにできます。
多くの量子回路ライブラリがPythonで開発されているため、TranquもPythonで開発しています。
Tranquのドキュメント、GitHubリポジトリは次のURLです。
- ドキュメント: https://tranqu.readthedocs.io/
- GitHubリポジトリ: https://github.com/oqtopus-team/tranqu
使い方
ここでは、Tranquの使い方を紹介します。まずは、Tranquをインストールしましょう。
pip install tranqu
ひとまず、Qiskitで書いた量子回路を、Qiskitでトランスパイルしてみましょう。
from qiskit import QuantumCircuit
from tranqu import Tranqu
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
tranqu = Tranqu()
result = tranqu.transpile(
program=circuit,
program_lib="qiskit",
transpiler_lib="qiskit",
)
トランスパイル結果の量子回路は次のように確認できます。(この例は単純な回路のため、トランスパイル前後で変化はありませんが)
print(result.transpiled_program)
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■───░─┤M├───
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├─░──╫─┤M├
└───┘ ░ ║ └╥┘
meas: 2/══════════════╩══╩═
0 1
トランスパイル前後のゲート数など、統計情報も確認できます。
print(result.stats)
{'before': {'n_qubits': 2, 'n_gates': 5, 'n_gates_1q': 3, 'n_gates_2q': 2, 'depth': 3}, 'after': {'n_qubits': 2, 'n_gates': 5, 'n_gates_1q': 3, 'n_gates_2q': 2, 'depth': 3}}
Qiskitトランスパイラのオプションbasis_gates
を指定してみましょう。
Pythonの辞書形式でオプションを指定し、Tranquの引数transpiler_options
に渡します。
options = {
"basis_gates": ["id", "sx", "x", "rz", "cx"]
}
result = tranqu.transpile(
program=circuit,
program_lib="qiskit",
transpiler_lib="qiskit",
transpiler_options=options,
)
print(result.transpiled_program)
global phase: π/4
┌─────────┐┌────┐┌─────────┐ ░ ┌─┐
q_0: ┤ Rz(π/2) ├┤ √X ├┤ Rz(π/2) ├──■───░─┤M├───
└─────────┘└────┘└─────────┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ────────────────────────────┤ X ├─░──╫─┤M├
└───┘ ░ ║ └╥┘
meas: 2/═════════════════════════════════════╩══╩═
0 1
Qiskitトランスパイラを使う場合、transpiler_options
に何を指定できるかはQiskitのtranspile関数の引数にしたがいます。そのため、Qiskitトランスパイラを使い慣れた人であれば、TranquからQiskitトランスパイラを使うのは簡単です。
ここまでは、Qiskitしか使っていない自明な例でした。
次の例では、入力をOpenQASM3に変えてみましょう。
program = """OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
h q[0];
cx q[0], q[1];
"""
result = tranqu.transpile(
program=program,
program_lib="openqasm3",
transpiler_lib="qiskit",
transpiler_options=options,
)
print(result.transpiled_program)
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
rz(pi/2) q[0];
sx q[0];
rz(pi/2) q[0];
cx q[0], q[1];
このように、量子回路の形式(この例ではOpenQASM3)とトランスパイラ(この例ではQiskit)が異なっていても、Tranquが適切に変換して実行します。
TranquのGetting startedには他にも様々な例が載っていますので、ぜひご覧ください。
また、Tranquは「動くドキュメント」を提供しています。
Usageの各ページの上部には次のようなリンクがあり、クリックするとJupyterLabで動かすことができます。
自分の環境にインストールしなくても試用できますので、ぜひ触ってみてください。
今後
この記事の執筆時点(2024/12/14)では、まだβ版の状態です。
Tranquが対応しているライブラリはBuilt-in Componentsに記載していますが、まだまだ少ないです。
今後、多くのライブラリに対応し、手軽にいろんなトランスパイラを利用できるようにしていきます。
興味を持たれた方は、ぜひご利用ください。
(PRも大歓迎です!)
Discussion