OpenQASM 2 と Qiskit SDK
このページのコードは、以下の要件に基づいて開発された。 これらのバージョンまたは新しいバージョンの使用をお勧めします。
qiskit[all]~=2.5.1
Qiskit SDKは、量子プログラムの OpenQASM 表現の間で変換するためのいくつかのツールを提供します。 QuantumCircuit クラスを提供します。
OpenQASM 2プログラムをQiskitにインポートする
OpenQASM 2のプログラムをQiskitにインポートする2つの関数。
これらは qasm2.load()ファイル名を取る qasm2.loads()は、 OpenQASM 2 プログラムを文字列として受け取ります。
import qiskit.qasm2
qiskit.qasm2.load(filename, include_path=('.',), include_input_directory='append', custom_instructions=(), custom_classical=(), strict=False)
qiskit.qasm2.loads(program, include_path=('.',), custom_instructions=(), custom_classical=(), strict=False)詳しくは OpenQASM 2 Qiskit APIをご覧ください。
簡単なプログラムをインポートする
ほとんどの OpenQASM 2プログラムでは、単純に qasm2.load と qasm2.loads を1つの引数で使うことができる。
例: OpenQASM 2 プログラムを文字列としてインポートする
qasm2.loads() を使って、 OpenQASM 2 プログラムを文字列としてインポートする。 QuantumCircuit:
import qiskit.qasm2
program = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0], q[1];
measure q -> c;
"""
circuit = qiskit.qasm2.loads(program)
circuit.draw()Output:
┌───┐ ┌─┐
q_0: ┤ H ├──■──┤M├───
└───┘┌─┴─┐└╥┘┌─┐
q_1: ─────┤ X ├─╫─┤M├
└───┘ ║ └╥┘
c: 2/═══════════╩══╩═
0 1
例: ファイルから OpenQASM 2プログラムをインポートする
load() を使って、 OpenQASM 2 プログラムをファイルからインポートする。 QuantumCircuit:
import qiskit.qasm2
circuit = qiskit.qasm2.load("myfile.qasm")OpenQASM 2つのゲートをQiskitゲートで接続
デフォルトでは、Qiskitの OpenQASM 2インポータはインクルードファイル "qelib1.inc" を事実上の標準ライブラリとして扱います。
インポーターはこのファイルを、 OpenQASM 2を定義した元の論文に記述されているゲートを正確に含むものとして扱う。
Qiskitは回路ライブラリの組み込みゲートを使用して、 "qelib1.inc" のゲートを表現します。
マニュアル OpenQASM 2 gate ステートメントによってプログラム内で定義されたゲートは、デフォルトでは、カスタム Qiskit Gate サブクラスとして構築されます。
インポーターに特定の Gategate を使うように指示できます。
このメカニズムを使って、追加のゲート名を「ビルトイン」、つまり明示的な定義を必要としないものとして扱うこともできる。
"qelib1.inc" の外部で、 gate ステートメントに使用するゲート・クラスを指定すると、通常、結果の回路はより効率的に動作します。
Qiskit SDK v1.0 の時点で、Qiskitの OpenQASM* 2エクスポーター* ( OpenQASM 2へのQiskit回路のエクスポートを参照)は、依然として実際のゲート数よりも多いゲート数 "qelib1.inc" があるかのように動作します。
これは、インポーターのデフォルト設定では、当社のインポーターでエクスポートされたプログラムをインポートできない可能性があることを意味します。
この問題を解決するためのレガシーエクスポーターの使用方法については、具体的な例を参照してください。
この矛盾はQiskitのレガシーな動作であり、 Qiskitの後のリリースで解決される予定です。
カスタム命令に関する情報を OpenQASM 2 インポータに渡すには、 qasm2.CustomInstruction クラスを使用します。
これには4つの必須情報があり、順に説明する:
- OpenQASM 2 プログラムで使用されるゲートの名前
- ゲートが取る角度パラメータの数
- ゲートが作用する量子ビットの数
- Python ゲートのコンストラクタクラスまたは関数。個々の引数としてゲートパラメータ(量子ビットは含まない)を取る
インポーターは、指定されたカスタム命令と一致する gate 定義に遭遇した場合、そのカスタム情報を使用してゲート・オブジェクトを再構築する。
カスタム命令の name と一致する gate ステートメントに遭遇したが、パラメータの数と量子ビットの数の両方と一致しない場合、インポーターは、提供された情報とプログラムとの不一致を示すために QASM2ParseErrorを発生させ、提供された情報とプログラムの不一致を示します。
さらに、5番目の引数 builtin をオプションで True に設定すると、ゲートが明示的に定義されていなくても、 OpenQASM 2 プログラム内で自動的に利用できるようになる。
インポーターが組み込みカスタム命令の明示的な gate 定義に遭遇した場合、それを黙って受け入れる。
以前と同様、同じ名前の明示的な定義が、提供されたカスタム命令と互換性がない場合は QASM2ParseError が発生します。
これは、古い OpenQASM 2 エクスポーターや、ハードウェアの「ベーシス・ゲート」を内蔵命令として扱う他の量子プラットフォームとの互換性を保つのに役立つ。
Qiskit は、 Qiskit の OpenQASM 2 エクスポート機能のレガシーバージョンで作成された OpenQASM 2 プログラムを操作するためのデータ属性を提供します。
これは qasm2.LEGACY_CUSTOM_INSTRUCTIONSの custom_instructions 引数として与えられる。 qasm2.load() そして qasm2.loads().
例: Qiskitのレガシーエクスポーターで作成されたプログラムをインポートする
この OpenQASM 2プログラムでは、 "qelib1.inc" のオリジナル・バージョンにはないゲートを宣言せずに使用しているが、Qiskitのライブラリには標準的なゲートである。
を使用することができます。 qasm2.LEGACY_CUSTOM_INSTRUCTIONS を使うと、Qiskitの OpenQASM 2 エクスポーターが以前使っていたのと同じゲートのセットを使うように、インポーターに簡単に指示できます。
from qiskit import qasm2
program = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[4];
creg c[4];
h q[0];
cx q[0], q[1];
// 'rxx' is not actually in `qelib1.inc`,
// but Qiskit used to behave as if it were.
rxx(0.75) q[2], q[3];
measure q -> c;
"""
circuit = qasm2.loads(
program,
custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS,
)例: OpenQASM 2プログラムをインポートする際に特定のゲートクラスを使用する
Qiskitは一般的に、 OpenQASM 2 gate ステートメント内の定義がQiskit標準ライブラリゲートに正確に対応しているかどうかを検証することはできません。
代わりにQiskitは、提供された正確な定義を使ってカスタムゲートを選択します。
これは、内蔵の標準ゲートやユーザー定義のカスタムゲートを使うよりも効率が悪くなる可能性がある。
gate ステートメントを特定のクラスで手動で定義することができます。
from qiskit import qasm2
from qiskit.circuit import Gate
from qiskit.circuit.library import RZXGate
# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])
custom_instructions = [
# Link the OpenQASM 2 name 'my' with our custom gate.
qasm2.CustomInstruction("my", 2, 1, MyGate),
# Link the OpenQASM 2 name 'rzx' with Qiskit's
# built-in RZXGate.
qasm2.CustomInstruction("rzx", 1, 2, RZXGate),
]
program = """
OPENQASM 2.0;
gate my(theta, phi) q {
U(theta / 2, phi, -theta / 2) q;
}
gate rzx(theta) a, b {
// It doesn't matter what definition is
// supplied, if the parameters match;
// Qiskit will still use `RZXGate`.
}
qreg q[2];
my(0.25, 0.125) q[0];
rzx(pi) q[0], q[1];
"""
circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)例: OpenQASM 2プログラムで新しい組み込みゲートを定義する
引数 builtin=True が設定されている場合、カスタム・ゲートは関連する定義を持つ必要はない。
from qiskit import qasm2
from qiskit.circuit import Gate
# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])
custom_instructions = [
qasm2.CustomInstruction("my", 2, 1, MyGate, builtin=True),
]
program = """
OPENQASM 2.0;
qreg q[1];
my(0.25, 0.125) q[0];
"""
circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)カスタムの古典関数を定義する
OpenQASM 2には、ゲート引数で使用する古典的な関数がいくつか組み込まれている。
の引数 custom_classical を使用することで、より多くの関数で言語を拡張することができる。 qasm2.load() と qasm2.loads()引数を qasm2.CustomClassical クラスの引数で指定します。
カスタム・クラシック関数を定義するには、以下のように指定する必要がある:
- OpenQASM 2 プログラムに表示される関数名
- 浮動小数点の引数の数
- 関数を評価する、呼び出し可能な Python オブジェクト
定義されたすべてのカスタム古典関数は、インポーターによって OpenQASM 2言語の組み込みとして扱われます。 OpenQASM 2言語には、新しい関数を定義する公式な方法はありません。これはQiskitの拡張機能です。
例:カスタムの古典的命令を使用する
ここでは、2つのカスタム・クラシック関数を提供する。
最初は単純で、入力に1を加えるだけだ。
2つ目は、四分円を意識した方法で数学演算 を表す関数 math.atan2。
import math
from qiskit import qasm2
program = """
include "qelib1.inc";
qreg q[2];
rx(arctan(pi, 3 + add_one(0.2))) q[0];
cx q[0], q[1];
"""
def add_one(x):
return x + 1
customs = [
# Our `add_one` takes only one parameter.
qasm2.CustomClassical("add_one", 1, add_one),
# `arctan` takes two parameters, and `math.atan2` implements it.
qasm2.CustomClassical("arctan", 2, math.atan2),
]
circuit = qasm2.loads(program, custom_classical=customs)厳密モード
デフォルトでは、このパーサーは公式仕様よりも緩和されている。
パラメータリストの末尾のカンマ、不要な(空の)ステートメントのセミコロン、 OPENQASM 2.0; バージョンステートメントの省略、その他いくつかの品質向上が、エラーを出さずにできるようになった。
しかし、 strict=True で「letter-of-spec」モードを使うことができる。
Qiskit回路を OpenQASM にエクスポートする 2
Qiskitは QuantumCircuit を OpenQASM 2。
関数 qasm2.dump() を使ってファイルに書き込み qasm2.dumps() 文字列への書き込みには
これらの関数は現在、非常にシンプルなインターフェースを持っている。 qasm2.dump()の場合のみ、出力を書き込む場所を指定する。
Qiskit の OpenQASM 2 エクスポーターは、レガシーな非標準バージョンの "qelib1.inc" インクルードファイルをまだ想定しています。
これはQiskitの後のリリースで解決される予定ですが、それまでの間、Qiskitで作成された OpenQASM 2プログラムを再インポートする必要がある場合は、 インポーターにレガシーゲートについて伝える方法について上記の例を使用してください。
例: 回路を OpenQASM 2にエクスポートする
from qiskit import QuantumCircuit, qasm2
# Define any circuit.
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure([0, 1], [0, 1])
# Export to a string.
program = qasm2.dumps(circuit)
# Export to a file.
qasm2.dump(circuit, "my_file.qasm")次のステップ
- IBM Quantum Composer ガイドで、 OpenQASM コードを生成する方法を学んでください。
- OpenQASM 2 Qiskit API リファレンスを参照。
- 「プログラムの確認 」のトピックを確認してください。
- OpenQASM ライブ仕様をご覧ください。