近似量子コンパイラ
qiskit.synthesis.unitary.aqc
論文 [1で述べられて]いる近似量子コンパイラの実装。
インターフェース
このモジュールの主なパブリック・インターフェースには、 unitary_synthesis_method='aqc' を渡して到達します。 transpile(). これにより、合成方法が AQCSynthesisPlugin に切り替わる。 個々のクラスは以下の通り:
AQC[(オプティマイザ、シード)] | 近似量子コンパイラの汎用実装。 |
ApproximateCircuit(num_qubits[, name] ) | 近似回路を表す基本クラス。 |
ApproximatingObjective() | 最適化問題定義の基本クラス。 |
CNOTUnitCircuit(num_qubits, cnots[, tol, name] ) | CNOTユニットブロックに基づく近似回路を表すクラス。 |
CNOTUnitObjective(num_qubits, cnots) | CNOTユニットに基づく問題定義のための基本クラス。 |
DefaultCNOTUnitObjective(num_qubits, cnots) | CNOTユニットに基づく目的関数の素朴な実装。 |
FastCNOTUnitObjective(num_qubits, cnots) | 目的関数と勾配計算機の実装。 DefaultCNOTUnitObjective に似ているが、数倍速い。 |
数学的詳細
我々は量子回路のコンパイルに興味がある。このコンパイルは、いくつかのハードウェア制約を追加した上で、対象となるユニタリー行列 の順序ゲート列の観点から最適な回路表現を見つけることとして定式化する。 特に、ゲートの深さだけでなく、ハードウェアの接続性の点でも制約を受けうる表現に注目し、CNOTゲートと回転ゲートの観点からゲートの基礎を選択する。 CNOTと回転ゲートの組み合わせは、 、普遍的なものであるため、コンパイルが制限されることはない。
「最適な回路表現」という概念を適切に定義するため、我々は、コンパイルされた回路のユニタリ行列 と目標ユニタリ行列 との間のフロベニウスノルム、すなわち を指標として定義する。この選択は、数理計画法上の考察に基づくものであり、文献に見られる他の定式化とも関連している。 この問題について、もう少し詳しく見てみましょう。
を量子ビット数、 を量子ビット数とする。CNOT構造 と回転角度のベクトル が与えられると、パラメトリック回路は行列 を形成する。行列を形成するターゲット回路 が与えられたとすると、次のように計算したい
ここで内積はフロベニウス内積である。 と のすべてのユニタリーに対して があるので、目的は に範囲を持つことに注意。
我々の戦略は最大化することである
その勾配を利用する。 では、具体的な例を挙げて説明しよう。
の範囲は構造上 の部分集合であるが、ターゲット回路は一般的なユニタリー行列を形成することができる。 しかし、 、
したがって、対象回路をグローバル位相で正規化し、正規化された回路を近似的にコンパイルする必要がある。 グローバル・フェーズは、その後に追加すればいい。
このアルゴリズムでは、 を正規化されていないターゲット行列、 を正規化されたターゲット行列とする。 が得られたので、勾配関数をネステロフ法のオプティマイザーに与え、 を計算する。
グローバル・フェーズを戻すには、制御回路を次のように構成すればよい
論文ではネステロフ法を用いて最適化を行ったが、これは収束の保証のためであり、実際のスピードのためではないことに注意されたい。 この実装ではデフォルトのオプティマイザとして使用されているL-BFGSを使用する方がはるかに高速である。
AQCアルゴリズムの基本的な使い方は、以下のステップで構成される:
# Define a target circuit as a unitary matrix
unitary = ...
# Define a number of qubits for the algorithm, at least 3 qubits
num_qubits = round(math.log2(unitary.shape[0]))
# Choose a layout of the CNOT structure for the approximate circuit, e.g. ``spin`` for
# a linear layout.
layout = options.get("layout") or "spin"
# Choose a connectivity type, e.g. ``full`` for full connectivity between qubits.
connectivity = options.get("connectivity") or "full"
# Define a targeted depth of the approximate circuit in the number of CNOT units.
depth = int(options.get("depth") or 0)
# Generate a network made of CNOT units
cnots = make_cnot_network(
num_qubits=num_qubits,
network_layout=layout,
connectivity_type=connectivity,
depth=depth
)
# Create an optimizer to be used by AQC
optimizer = partial(scipy.optimize.minimize, method="L-BFGS-B")
# Create an instance
aqc = AQC(optimizer)
# Create a template circuit that will approximate our target circuit
approximate_circuit = CNOTUnitCircuit(num_qubits=num_qubits, cnots=cnots)
# Create an objective that defines our optimization problem
approximating_objective = DefaultCNOTUnitObjective(num_qubits=num_qubits, cnots=cnots)
# Run optimization process to compile the unitary
aqc.compile_unitary(
target_matrix=unitary,
approximate_circuit=approximate_circuit,
approximating_objective=approximating_objective
)さて、 approximate_circuit は、対象となるユニタリーをある程度近似した回路であり、元の行列の代わりに使うことができる。
これはヘルパー関数を使用している、 make_cnot_network.
make_cnot_network
qiskit.synthesis.unitary.aqc.make_cnot_network(num_qubits, network_layout='spin', connectivity_type='full', depth=0)
それぞれがCNOTゲートと、場合によっては1量子ビットのゲートを含むビルディングブロックからなるネットワークを生成する。 このネットワークは、量子演算子をモデル化している。 各構成ブロックは、2つの量子ビットに対応する2つの入力と出力を持つ。 ここで実際に返されるのは、列のすべてのビルディング・ブロックが共有する量子ビット対のインデックスの連鎖である。
パラメーター
- num_qubits (int) – 量子ビットの数。
- network_layout (str) – ネットワーク形状の種類、
{"sequ", "spin", "cart", "cyclic_spin", "cyclic_line"}。 - connectivity_type (str) – 量子ビット間接続のタイプ、
{"full", "line", "star"}。 - depth (int) – CNOTネットワークの深さ、すなわちレイヤーの数。各レイヤーは単一のCNOTブロックで構成される。
L <= 0の場合、デフォルト値が選択される。
戻り値
cnot-network のレイヤーを定義する、サイズ (2, N) の行列。 N
は、 L に等しいか、ネットワークの具体的な型によって定義される。
レイズ
ValueError - サポートされていないタイプのCNOTネットワークレイアウト、量子ビットの数、またはパラメータの組み合わせが渡された場合。
戻りの型
目的関数の加速バージョンを利用することもできる。 デフォルトのもの DefaultCNOTUnitObjective と同じ数学的アルゴリズムを実装しているが、実行速度は数倍速い。 加速目的関数クラスのインスタンス化は、デフォルトの場合と同様である:
# 最適化問題を定義する目的語を作成 approximating_objective = FastCNOTUnitObjective(num_qubits=num_qubits, cnots=cnots)
上記の例の残りのコードは変更しない。
参考文献
[1] : Liam Madden, Andrea Simonetto, Best Approximate Quantum Compiling Problems.