メインコンテンツへスキップ

ハミルトニアンシミュレーション回路のコンパイル手法

推定QPU使用量:このチュートリアルはトランスパイルプロセスに焦点を当てているため、実行は行っていません。

背景

量子回路コンパイルは、量子コンピューティングワークフローにおける重要なステップです。高レベルの量子アルゴリズムを、ターゲットとなる量子ハードウェアの制約に準拠した物理量子回路に変換する処理を含みます。効果的なコンパイルは、回路の深さ、ゲート数、実行時間を削減することで、量子アルゴリズムの性能に大きな影響を与えることができます。このチュートリアルでは、Qiskit における3つの異なる量子回路コンパイルアプローチを探索し、実践的な例を通じてそれぞれの強みと応用を紹介します。

このチュートリアルの目的は、Qiskit における3つのコンパイル手法(SABREトランスパイラ、AI搭載トランスパイラ、Rustiqプラグイン)の適用方法と評価方法をユーザーに教えることです。各手法の効果的な使用方法と、さまざまな量子回路にわたるパフォーマンスのベンチマーク方法を学びます。このチュートリアルの終了時には、回路の深さの削減、ゲート数の最小化、ランタイムの改善といった特定の最適化目標に基づいて、コンパイル戦略を選択・調整できるようになります。

学習内容

  • レイアウトおよびルーティング最適化のためのSABREを用いたQiskitトランスパイラの使用方法。
  • 高度な自動回路最適化のためのAIトランスパイラの活用方法。
  • 特にハミルトニアンシミュレーションタスクにおいて、演算の精密な合成を必要とする回路向けのRustiqプラグインの活用方法。

このチュートリアルでは、Qiskit パターンワークフローに従った3つのサンプル回路を使用して、各コンパイル手法の性能を説明します。このチュートリアルの終了時には、特定の要件と制約に基づいて適切なコンパイル戦略を選択できるようになります。

コンパイル手法の概要

1. SABREを用いたQiskitトランスパイラ

Qiskitトランスパイラは、SABRE(SWAP-based BidiREctional heuristic search)アルゴリズムを使用して回路のレイアウトとルーティングを最適化します。SABREは、ハードウェアの接続性制約に準拠しながら、SWAPゲートの数とそれらが回路の深さに与える影響を最小化することに焦点を当てています。この手法は非常に汎用性が高く、汎用的な回路最適化に適しており、性能と計算時間のバランスを提供します。[1] で詳述されているSABREの最新の改善を活用するには、試行回数を増やすことができます(例:layout_trials=400, swap_trials=400)。このチュートリアルでは、Qiskitのデフォルトトランスパイラとの比較のために、試行回数のデフォルト値を使用します。SABREの利点とパラメータ探索については、別の詳細チュートリアルで扱っています。

2. AIトランスパイラ

QiskitのAI搭載トランスパイラは、機械学習を使用して、回路構造とハードウェア制約のパターンを分析し、与えられた入力に対して最適な最適化シーケンスを選択することで、最適なトランスパイル戦略を予測します。この手法は、大規模な量子回路に対して特に効果的であり、多様な問題タイプへの高度な自動化と適応性を提供します。一般的な回路最適化に加えて、AIトランスパイラは AIPauliNetworkSynthesis パスと組み合わせて使用できます。このパスは、H、S、SX、CX、RX、RY、RZゲートで構成されるブロックであるPauliネットワーク回路を対象とし、強化学習ベースの合成アプローチを適用します。AIトランスパイラとその合成戦略の詳細については、[2] および [3] を参照してください。

3. Rustiqプラグイン

Rustiqプラグインは、トロッター化ダイナミクスで一般的に使用されるパウリ回転を表す PauliEvolutionGate 演算に特化した高度な合成手法を導入します。このプラグインは、量子化学や物理学の問題で使用されるようなハミルトニアンシミュレーションを実装する回路に有用であり、問題ハミルトニアンを効果的にシミュレーションするために正確なパウリ回転が不可欠です。Rustiqは、これらの特殊な演算に対して精密で低深度の回路合成を提供します。Rustiqの実装と性能の詳細については、[4] を参照してください。

これらのコンパイル手法を詳細に探索することで、このチュートリアルはユーザーに量子回路の性能を向上させるためのツールを提供し、より効率的で実用的な量子計算への道を開きます。

要件

このチュートリアルを開始する前に、以下がインストールされていることを確認してください:

  • Qiskit SDK v1.3以降、可視化サポート付き
  • Qiskit Runtime v0.28以降(pip install qiskit-ibm-runtime
  • Qiskit IBM Transpiler(pip install qiskit-ibm-transpiler
  • Qiskit AI Transpiler ローカルモード(pip install qiskit_ibm_ai_local_transpiler
  • Networkx グラフライブラリ(pip install networkx

セットアップ

# Added by doQumentation — installs packages not in the Binder environment
%pip install -q qiskit-ibm-transpiler
from qiskit.circuit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.circuit.library import (
efficient_su2,
PauliEvolutionGate,
)
from qiskit_ibm_transpiler import generate_ai_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig
from collections import Counter
from IPython.display import display
import time
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import json
import requests
import logging

# Suppress noisy loggers
logging.getLogger(
"qiskit_ibm_transpiler.wrappers.ai_local_synthesis"
).setLevel(logging.ERROR)

seed = 42 # Seed for reproducibility

パート1:Efficient SU2回路

ステップ1:古典的な入力を量子問題にマッピングする

このセクションでは、変分量子アルゴリズム(VQEなど)や量子機械学習タスクで一般的に使用されるハードウェア効率の良いアンザッツである efficient_su2 回路を探索します。この回路は、量子状態空間を効果的に探索しながら管理可能な深さを維持するように設計された、単一量子ビット回転とエンタングリングゲートが円形パターンで交互に配置された層で構成されています。

まず、異なるコンパイル手法を比較する方法を示すために、1つの efficient_su2 回路を構築します。パート1の後、より大規模な回路セットに分析を拡張し、さまざまなコンパイル手法の性能を評価するための包括的なベンチマークを行います。

qubit_size = list(range(10, 101, 10))
qc_su2_list = [
efficient_su2(n, entanglement="circular", reps=1)
.decompose()
.copy(name=f"SU2_{n}")
for n in qubit_size
]

# Draw the first circuit
qc_su2_list[0].draw(output="mpl")

Output of the previous code cell

ステップ2:量子ハードウェア実行のための問題の最適化

このステップはチュートリアルの主要な焦点です。ここでは、実際の量子ハードウェアでの効率的な実行のために量子回路を最適化することを目指します。主な目的は、実行忠実度の向上とハードウェアノイズの軽減における重要な要素である回路の深さとゲート数を削減することです。

  • SABREトランスパイラ:SABREレイアウトおよびルーティングアルゴリズムを使用するQiskitのデフォルトトランスパイラを使用します。
  • AIトランスパイラ(ローカルモード):ローカル推論とデフォルト合成戦略を使用する標準のAI搭載トランスパイラです。
  • Rustiqプラグイン:ハミルトニアンシミュレーションタスクに特化した低深度コンパイル用に設計されたトランスパイラプラグインです。

このステップの目標は、トランスパイルされた回路の深さとゲート数の観点から、これらの手法の結果を比較することです。もう1つの重要な指標として、トランスパイルのランタイムも考慮します。これらの指標を分析することで、各手法の相対的な強みを評価し、選択したハードウェアでの実行に最も効率的な回路を生成する手法を判断できます。

注:最初のSU2回路の例では、SABREトランスパイラとデフォルトのAIトランスパイラのみを比較します。ただし、後続のHamlib回路を使用したベンチマークでは、3つのトランスパイル手法すべてを比較します。

# QiskitRuntimeService.save_account(channel="ibm_quantum_platform", token="<YOUR-API-KEY>", overwrite=True, set_as_default=True)
service = QiskitRuntimeService(channel="ibm_quantum_platform")
backend = service.backend("ibm_torino")
print(f"Using backend: {backend}")
qiskit_runtime_service._get_crn_from_instance_name:WARNING:2025-07-30 21:46:30,843: Multiple instances found. Using all matching instances.
Using backend: <IBMBackend('ibm_torino')>

SABREを用いたQiskitトランスパイラ:

pm_sabre = generate_preset_pass_manager(
optimization_level=3, backend=backend, seed_transpiler=seed
)

AIトランスパイラ:

# Standard AI transpiler pass manager, using the local mode
pm_ai = generate_ai_pass_manager(
backend=backend, optimization_level=3, ai_optimization_level=3
)

Rustiqプラグイン:

hls_config = HLSConfig(
PauliEvolution=[
(
"rustiq",
{
"nshuffles": 400,
"upto_phase": True,
"fix_clifford": True,
"preserve_order": False,
"metric": "depth",
},
)
]
)
pm_rustiq = generate_preset_pass_manager(
optimization_level=3,
backend=backend,
hls_config=hls_config,
seed_transpiler=seed,
)

トランスパイルとメトリクスの取得

コンパイル手法の性能を比較するために、入力回路をトランスパイルし、関連するメトリクスを一貫した方法で取得する関数を定義します。これには、回路全体の深さ、全体のゲート数、トランスパイル時間が含まれます。

これらの標準的なメトリクスに加えて、2量子ビットゲートの深さも記録します。これは量子ハードウェアでの実行を評価するうえで特に重要なメトリクスです。すべてのゲートを含む全体の深さとは異なり、2量子ビットの深さはハードウェア上での回路の実際の実行時間をより正確に反映します。これは、ほとんどの量子デバイスにおいて2量子ビットゲートが時間およびエラーバジェットの大部分を占めるためです。そのため、2量子ビットの深さを最小化することは、忠実度の向上と実行中のデコヒーレンス効果の軽減にとって重要です。

この関数を使用して、複数の回路にわたるさまざまなコンパイル手法の性能を分析します。

def capture_transpilation_metrics(
results, pass_manager, circuits, method_name
):
"""
Capture transpilation metrics for a list of circuits and stores the results in a DataFrame.

Args:
results (pd.DataFrame): DataFrame to store the results.
pass_manager: Pass manager used for transpilation.
circuits (list): List of quantum circuits to transpile.
method_name (str): Name of the transpilation method.

Returns:
list: List of transpiled circuits.
"""
transpiled_circuits = []

for i, qc in enumerate(circuits):
# Transpile the circuit
start_time = time.time()
transpiled_qc = pass_manager.run(qc)
end_time = time.time()

# Needed for AI transpiler to be consistent with other methods
transpiled_qc = transpiled_qc.decompose(gates_to_decompose=["swap"])

# Collect metrics
transpilation_time = end_time - start_time
circuit_depth = transpiled_qc.depth(
lambda x: x.operation.num_qubits == 2
)
circuit_size = transpiled_qc.size()

# Append results to DataFrame
results.loc[len(results)] = {
"method": method_name,
"qc_name": qc.name,
"qc_index": i,
"num_qubits": qc.num_qubits,
"ops": transpiled_qc.count_ops(),
"depth": circuit_depth,
"size": circuit_size,
"runtime": transpilation_time,
}
transpiled_circuits.append(transpiled_qc)
print(
f"Transpiled circuit index {i} ({qc.name}) in {transpilation_time:.2f} seconds with method {method_name}, "
f"depth {circuit_depth}, and size {circuit_size}."
)

return transpiled_circuits
results_su2 = pd.DataFrame(
columns=[
"method",
"qc_name",
"qc_index",
"num_qubits",
"ops",
"depth",
"size",
"runtime",
]
)

tqc_sabre = capture_transpilation_metrics(
results_su2, pm_sabre, qc_su2_list, "sabre"
)
tqc_ai = capture_transpilation_metrics(results_su2, pm_ai, qc_su2_list, "ai")
Transpiled circuit index 0 (SU2_10) in 0.06 seconds with method sabre, depth 13, and size 167.
Transpiled circuit index 1 (SU2_20) in 0.24 seconds with method sabre, depth 20, and size 299.
Transpiled circuit index 2 (SU2_30) in 10.72 seconds with method sabre, depth 72, and size 627.
Transpiled circuit index 3 (SU2_40) in 16.16 seconds with method sabre, depth 40, and size 599.
Transpiled circuit index 4 (SU2_50) in 76.89 seconds with method sabre, depth 77, and size 855.
Transpiled circuit index 5 (SU2_60) in 86.12 seconds with method sabre, depth 60, and size 899.
Transpiled circuit index 6 (SU2_70) in 94.46 seconds with method sabre, depth 79, and size 1085.
Transpiled circuit index 7 (SU2_80) in 69.05 seconds with method sabre, depth 80, and size 1199.
Transpiled circuit index 8 (SU2_90) in 88.25 seconds with method sabre, depth 105, and size 1420.
Transpiled circuit index 9 (SU2_100) in 83.80 seconds with method sabre, depth 100, and size 1499.
Transpiled circuit index 0 (SU2_10) in 0.17 seconds with method ai, depth 10, and size 168.
Transpiled circuit index 1 (SU2_20) in 0.29 seconds with method ai, depth 20, and size 299.
Transpiled circuit index 2 (SU2_30) in 13.56 seconds with method ai, depth 36, and size 548.
Transpiled circuit index 3 (SU2_40) in 15.95 seconds with method ai, depth 40, and size 599.
Transpiled circuit index 4 (SU2_50) in 80.70 seconds with method ai, depth 54, and size 823.
Transpiled circuit index 5 (SU2_60) in 75.99 seconds with method ai, depth 60, and size 899.
Transpiled circuit index 6 (SU2_70) in 64.96 seconds with method ai, depth 74, and size 1087.
Transpiled circuit index 7 (SU2_80) in 68.25 seconds with method ai, depth 80, and size 1199.
Transpiled circuit index 8 (SU2_90) in 75.07 seconds with method ai, depth 90, and size 1404.
Transpiled circuit index 9 (SU2_100) in 63.97 seconds with method ai, depth 100, and size 1499.

回路の1つのトランスパイル結果を表示します。

print("Sabre transpilation")
display(tqc_sabre[0].draw("mpl", fold=-1, idle_wires=False))
print("AI transpilation")
display(tqc_ai[0].draw("mpl", fold=-1, idle_wires=False))
Sabre transpilation

Output of the previous code cell

AI transpilation

Output of the previous code cell

結果テーブル:

summary_su2 = (
results_su2.groupby("method")[["depth", "size", "runtime"]]
.mean()
.round(2)
)
print(summary_su2)

results_su2
depth   size  runtime
method
ai 56.4 852.5 45.89
sabre 64.6 864.9 52.57
method  qc_name  qc_index  num_qubits                                ops  \
0 sabre SU2_10 0 10 {'rz': 81, 'sx': 70, 'cz': 16}
1 sabre SU2_20 1 20 {'rz': 160, 'sx': 119, 'cz': 20}
2 sabre SU2_30 2 30 {'sx': 295, 'rz': 242, 'cz': 90}
3 sabre SU2_40 3 40 {'rz': 320, 'sx': 239, 'cz': 40}
4 sabre SU2_50 4 50 {'rz': 402, 'sx': 367, 'cz': 86}
5 sabre SU2_60 5 60 {'rz': 480, 'sx': 359, 'cz': 60}
6 sabre SU2_70 6 70 {'rz': 562, 'sx': 441, 'cz': 82}
7 sabre SU2_80 7 80 {'rz': 640, 'sx': 479, 'cz': 80}
8 sabre SU2_90 8 90 {'rz': 721, 'sx': 585, 'cz': 114}
9 sabre SU2_100 9 100 {'rz': 800, 'sx': 599, 'cz': 100}
10 ai SU2_10 0 10 {'rz': 81, 'sx': 71, 'cz': 16}
11 ai SU2_20 1 20 {'rz': 160, 'sx': 119, 'cz': 20}
12 ai SU2_30 2 30 {'sx': 243, 'rz': 242, 'cz': 63}
13 ai SU2_40 3 40 {'rz': 320, 'sx': 239, 'cz': 40}
14 ai SU2_50 4 50 {'rz': 403, 'sx': 346, 'cz': 74}
15 ai SU2_60 5 60 {'rz': 480, 'sx': 359, 'cz': 60}
16 ai SU2_70 6 70 {'rz': 563, 'sx': 442, 'cz': 82}
17 ai SU2_80 7 80 {'rz': 640, 'sx': 479, 'cz': 80}
18 ai SU2_90 8 90 {'rz': 721, 'sx': 575, 'cz': 108}
19 ai SU2_100 9 100 {'rz': 800, 'sx': 599, 'cz': 100}

depth size runtime
0 13 167 0.058845
1 20 299 0.238217
2 72 627 10.723922
3 40 599 16.159262
4 77 855 76.886604
5 60 899 86.118255
6 79 1085 94.458287
7 80 1199 69.048184
8 105 1420 88.254809
9 100 1499 83.795482
10 10 168 0.171532
11 20 299 0.291691
12 36 548 13.555931
13 40 599 15.952733
14 54 823 80.702141
15 60 899 75.993404
16 74 1087 64.960162
17 80 1199 68.253280
18 90 1404 75.072412
19 100 1499 63.967446

結果グラフ

メトリクスを一貫して取得する関数を定義したのと同様に、メトリクスをグラフ化する関数も定義します。ここでは、各コンパイル手法の2量子ビットの深さ、ゲート数、ランタイムを回路ごとにプロットします。

def plot_transpilation_metrics(results, overall_title, x_axis="qc_index"):
"""
Plots transpilation metrics (depth, size, runtime) for different transpilation methods.

Parameters:
results (DataFrame): Data containing columns ['num_qubits', 'method', 'depth', 'size', 'runtime']
overall_title (str): The title of the overall figure.
x_axis (str): The x-axis label, either 'num_qubits' or 'qc_index'.
"""

fig, axs = plt.subplots(1, 3, figsize=(24, 6))
metrics = ["depth", "size", "runtime"]
titles = ["Circuit Depth", "Circuit Size", "Transpilation Runtime"]
y_labels = ["Depth", "Size (Gate Count)", "Runtime (s)"]

methods = results["method"].unique()
colors = plt.colormaps["tab10"]
markers = ["o", "^", "s", "D", "P", "*", "X", "v"]
color_list = [colors(i % colors.N) for i in range(len(methods))]
color_map = {method: color_list[i] for i, method in enumerate(methods)}
marker_map = {
method: markers[i % len(markers)] for i, method in enumerate(methods)
}
jitter_factor = 0.1 # Small x-axis jitter for visibility
handles, labels = [], [] # Unique handles for legend

# Plot each metric
for i, metric in enumerate(metrics):
for method in methods:
method_data = results[results["method"] == method]

# Introduce slight jitter to avoid exact overlap
jitter = np.random.uniform(
-jitter_factor, jitter_factor, len(method_data)
)

scatter = axs[i].scatter(
method_data[x_axis] + jitter,
method_data[metric],
color=color_map[method],
label=method,
marker=marker_map[method],
alpha=0.7,
edgecolors="black",
s=80,
)

if method not in labels:
handles.append(scatter)
labels.append(method)

axs[i].set_title(titles[i])
axs[i].set_xlabel(x_axis)
axs[i].set_ylabel(y_labels[i])
axs[i].grid(axis="y", linestyle="--", alpha=0.7)
axs[i].tick_params(axis="x", rotation=45)
axs[i].set_xticks(sorted(results[x_axis].unique()))

fig.suptitle(overall_title, fontsize=16)
fig.legend(
handles=handles,
labels=labels,
loc="upper right",
bbox_to_anchor=(1.05, 1),
)

plt.tight_layout()
plt.show()
plot_transpilation_metrics(
results_su2, "Transpilation Metrics for SU2 Circuits", x_axis="num_qubits"
)

Output of the previous code cell

SU2回路コンパイル結果の分析

この実験では、efficient_su2 回路のセットに対して、QiskitのSABREトランスパイラとAI搭載トランスパイラの2つのトランスパイル手法を比較します。これらの回路には PauliEvolutionGate 演算が含まれていないため、Rustiqプラグインはこの比較には含まれていません。

平均すると、AIトランスパイラは回路の深さの面でより優れた性能を発揮し、SU2回路の全範囲にわたって10%以上の改善を示しています。ゲート数(回路サイズ)とトランスパイルのランタイムについては、両手法とも全体的に同様の結果を示しています。

ただし、個々のデータポイントを詳しく調べると、より深い洞察が得られます:

  • ほとんどの量子ビットサイズでは、SABREとAIはほぼ同一の結果を生成しており、多くの場合、両手法が同様に効率的な解に収束することを示唆しています。
  • 特定の回路サイズ、具体的には30、50、70、90量子ビットでは、AIトランスパイラがSABREよりも大幅に浅い回路を見つけています。これは、SABREヒューリスティックでは見つけられないケースにおいて、AIの学習ベースのアプローチがより最適なレイアウトやルーティングパスを発見できることを示しています。

この挙動は重要な知見を示しています:

SABREとAIは多くの場合同等の結果を生成しますが、AIトランスパイラは特に深さの面でより優れた解を発見できることがあり、これによりハードウェア上での性能が大幅に改善される可能性があります。

パート2:ハミルトニアンシミュレーション回路

ステップ1:PauliEvolutionGate を用いた回路の調査

このセクションでは、ハミルトニアンの効率的なシミュレーションを可能にする PauliEvolutionGate を使用して構築された量子回路を調査します。さまざまなハミルトニアンに対して、異なるコンパイル手法がこれらの回路をどのように最適化するかを分析します。

ベンチマークで使用されるハミルトニアン

このベンチマークで使用されるハミルトニアンは、ZZZZXXXXYYYY などの項を含む、量子ビット間のペアワイズ相互作用を記述します。これらのハミルトニアンは、相互作用する粒子系をモデル化する量子化学、凝縮系物理学、材料科学において広く使用されています。

参考として、より広範なハミルトニアンのセットについては、こちらの論文をご参照ください:Efficient Hamiltonian Simulation on Noisy Quantum Devices

ベンチマークの出典:Hamlib と Benchpress

このベンチマークで使用される回路は、現実的なハミルトニアンシミュレーションのワークロードを含む Hamlib ベンチマークリポジトリ から取得されています。

これらの同じ回路は、量子トランスパイレーション性能を評価するためのオープンソースフレームワークである Benchpress を使用して以前にベンチマークされました。この標準化された回路セットを使用することで、代表的なシミュレーション問題に対するさまざまなコンパイル戦略の有効性を直接比較できます。

ハミルトニアンシミュレーションは、分子シミュレーション、最適化問題、量子多体物理学に応用される量子コンピューティングの基礎的なタスクです。異なるコンパイル手法がこれらの回路をどのように最適化するかを理解することで、近い将来の量子デバイスにおけるこのような回路の実用的な実行を改善するのに役立ちます。

# Obtain the Hamiltonian JSON from the benchpress repository
url = "https://raw.githubusercontent.com/Qiskit/benchpress/e7b29ef7be4cc0d70237b8fdc03edbd698908eff/benchpress/hamiltonian/hamlib/100_representative.json"
response = requests.get(url)
response.raise_for_status() # Raise an error if download failed
ham_records = json.loads(response.text)
# Remove circuits that are too large for the backend
ham_records = [
h for h in ham_records if h["ham_qubits"] <= backend.num_qubits
]
# Remove the circuits that are large to save transpilation time
ham_records = sorted(ham_records, key=lambda x: x["ham_terms"])[:35]

qc_ham_list = []
for h in ham_records:
terms = h["ham_hamlib_hamiltonian_terms"]
coeff = h["ham_hamlib_hamiltonian_coefficients"]
num_qubits = h["ham_qubits"]
name = h["ham_problem"]

evo_gate = PauliEvolutionGate(SparsePauliOp(terms, coeff))

qc_ham = QuantumCircuit(num_qubits)
qc_ham.name = name

qc_ham.append(evo_gate, range(num_qubits))
qc_ham_list.append(qc_ham)
print(f"Number of Hamiltonian circuits: {len(qc_ham_list)}")

# Draw the first Hamiltonian circuit
qc_ham_list[0].draw("mpl", fold=-1)
Number of Hamiltonian circuits: 35

Output of the previous code cell

ステップ2:量子ハードウェア実行のための問題の最適化

前の例と同様に、比較の一貫性を確保するために同じバックエンドを使用します。パスマネージャー(pm_sabrepm_aipm_rustiq)は既に初期化されているため、各手法を使用してハミルトニアン回路のトランスパイルを直接実行できます。

このステップでは、トランスパイルの実行と、深さ、ゲート数、トランスパイル実行時間などの結果の回路メトリクスの記録にのみ焦点を当てます。これらの結果を分析することで、このタイプの回路に対する各トランスパイル手法の効率性を判断することを目指します。 トランスパイルの実行とメトリクスの取得:

results_ham = pd.DataFrame(
columns=[
"method",
"qc_name",
"qc_index",
"num_qubits",
"ops",
"depth",
"size",
"runtime",
]
)

tqc_sabre = capture_transpilation_metrics(
results_ham, pm_sabre, qc_ham_list, "sabre"
)
tqc_ai = capture_transpilation_metrics(results_ham, pm_ai, qc_ham_list, "ai")
tqc_rustiq = capture_transpilation_metrics(
results_ham, pm_rustiq, qc_ham_list, "rustiq"
)
Transpiled circuit index 0 (all-vib-o3) in 0.02 seconds with method sabre, depth 6, and size 58.
Transpiled circuit index 1 (all-vib-c2h) in 1.10 seconds with method sabre, depth 2, and size 39.
Transpiled circuit index 2 (all-vib-bh) in 0.01 seconds with method sabre, depth 3, and size 30.
Transpiled circuit index 3 (all-vib-c2h) in 0.03 seconds with method sabre, depth 18, and size 115.
Transpiled circuit index 4 (graph-gnp_k-2) in 0.02 seconds with method sabre, depth 24, and size 129.
Transpiled circuit index 5 (all-vib-fccf) in 0.05 seconds with method sabre, depth 14, and size 134.
Transpiled circuit index 6 (all-vib-hno) in 8.39 seconds with method sabre, depth 6, and size 174.
Transpiled circuit index 7 (all-vib-bhf2) in 3.92 seconds with method sabre, depth 22, and size 220.
Transpiled circuit index 8 (LiH) in 0.03 seconds with method sabre, depth 67, and size 290.
Transpiled circuit index 9 (uf20-ham) in 0.04 seconds with method sabre, depth 50, and size 340.
Transpiled circuit index 10 (all-vib-fccf) in 0.62 seconds with method sabre, depth 30, and size 286.
Transpiled circuit index 11 (all-vib-fccf) in 0.04 seconds with method sabre, depth 67, and size 339.
Transpiled circuit index 12 (all-vib-ch2) in 0.04 seconds with method sabre, depth 87, and size 421.
Transpiled circuit index 13 (tfim) in 0.05 seconds with method sabre, depth 36, and size 222.
Transpiled circuit index 14 (all-vib-cyclo_propene) in 9.51 seconds with method sabre, depth 22, and size 345.
Transpiled circuit index 15 (graph-gnp_k-4) in 0.05 seconds with method sabre, depth 128, and size 704.
Transpiled circuit index 16 (all-vib-hc3h2cn) in 13.83 seconds with method sabre, depth 2, and size 242.
Transpiled circuit index 17 (TSP_Ncity-4) in 0.05 seconds with method sabre, depth 106, and size 609.
Transpiled circuit index 18 (tfim) in 0.29 seconds with method sabre, depth 73, and size 399.
Transpiled circuit index 19 (all-vib-h2co) in 21.97 seconds with method sabre, depth 30, and size 572.
Transpiled circuit index 20 (Be2) in 0.09 seconds with method sabre, depth 324, and size 1555.
Transpiled circuit index 21 (graph-complete_bipart) in 0.12 seconds with method sabre, depth 250, and size 1394.
Transpiled circuit index 22 (all-vib-f2) in 0.07 seconds with method sabre, depth 215, and size 1027.
Transpiled circuit index 23 (all-vib-cyclo_propene) in 41.22 seconds with method sabre, depth 30, and size 1144.
Transpiled circuit index 24 (TSP_Ncity-5) in 1.89 seconds with method sabre, depth 175, and size 1933.
Transpiled circuit index 25 (H2) in 0.32 seconds with method sabre, depth 1237, and size 5502.
Transpiled circuit index 26 (uuf100-ham) in 0.20 seconds with method sabre, depth 385, and size 4303.
Transpiled circuit index 27 (ham-graph-gnp_k-5) in 0.20 seconds with method sabre, depth 311, and size 3654.
Transpiled circuit index 28 (tfim) in 0.15 seconds with method sabre, depth 276, and size 3213.
Transpiled circuit index 29 (uuf100-ham) in 0.21 seconds with method sabre, depth 520, and size 5250.
Transpiled circuit index 30 (flat100-ham) in 0.15 seconds with method sabre, depth 131, and size 3157.
Transpiled circuit index 31 (uf100-ham) in 0.24 seconds with method sabre, depth 624, and size 7378.
Transpiled circuit index 32 (OH) in 0.88 seconds with method sabre, depth 2175, and size 9808.
Transpiled circuit index 33 (HF) in 0.66 seconds with method sabre, depth 2206, and size 9417.
Transpiled circuit index 34 (BH) in 0.89 seconds with method sabre, depth 2177, and size 9802.
Transpiled circuit index 0 (all-vib-o3) in 0.02 seconds with method ai, depth 6, and size 58.
Transpiled circuit index 1 (all-vib-c2h) in 1.11 seconds with method ai, depth 2, and size 39.
Transpiled circuit index 2 (all-vib-bh) in 0.01 seconds with method ai, depth 3, and size 30.
Transpiled circuit index 3 (all-vib-c2h) in 0.11 seconds with method ai, depth 18, and size 94.
Transpiled circuit index 4 (graph-gnp_k-2) in 0.11 seconds with method ai, depth 22, and size 129.
Transpiled circuit index 5 (all-vib-fccf) in 0.06 seconds with method ai, depth 22, and size 177.
Transpiled circuit index 6 (all-vib-hno) in 8.62 seconds with method ai, depth 10, and size 198.
Transpiled circuit index 7 (all-vib-bhf2) in 3.71 seconds with method ai, depth 18, and size 195.
Transpiled circuit index 8 (LiH) in 0.19 seconds with method ai, depth 62, and size 267.
Transpiled circuit index 9 (uf20-ham) in 0.22 seconds with method ai, depth 47, and size 321.
Transpiled circuit index 10 (all-vib-fccf) in 0.71 seconds with method ai, depth 38, and size 369.
Transpiled circuit index 11 (all-vib-fccf) in 0.24 seconds with method ai, depth 65, and size 315.
Transpiled circuit index 12 (all-vib-ch2) in 0.24 seconds with method ai, depth 91, and size 430.
Transpiled circuit index 13 (tfim) in 0.15 seconds with method ai, depth 12, and size 251.
Transpiled circuit index 14 (all-vib-cyclo_propene) in 8.50 seconds with method ai, depth 18, and size 311.
Transpiled circuit index 15 (graph-gnp_k-4) in 0.25 seconds with method ai, depth 117, and size 659.
Transpiled circuit index 16 (all-vib-hc3h2cn) in 16.11 seconds with method ai, depth 2, and size 242.
Transpiled circuit index 17 (TSP_Ncity-4) in 0.39 seconds with method ai, depth 98, and size 564.
Transpiled circuit index 18 (tfim) in 0.38 seconds with method ai, depth 23, and size 437.
Transpiled circuit index 19 (all-vib-h2co) in 24.97 seconds with method ai, depth 38, and size 707.
Transpiled circuit index 20 (Be2) in 1.07 seconds with method ai, depth 293, and size 1392.
Transpiled circuit index 21 (graph-complete_bipart) in 0.61 seconds with method ai, depth 229, and size 1437.
Transpiled circuit index 22 (all-vib-f2) in 0.57 seconds with method ai, depth 178, and size 964.
Transpiled circuit index 23 (all-vib-cyclo_propene) in 50.89 seconds with method ai, depth 34, and size 1425.
Transpiled circuit index 24 (TSP_Ncity-5) in 1.61 seconds with method ai, depth 171, and size 2020.
Transpiled circuit index 25 (H2) in 6.39 seconds with method ai, depth 1148, and size 5208.
Transpiled circuit index 26 (uuf100-ham) in 3.97 seconds with method ai, depth 376, and size 5048.
Transpiled circuit index 27 (ham-graph-gnp_k-5) in 3.54 seconds with method ai, depth 357, and size 4451.
Transpiled circuit index 28 (tfim) in 1.72 seconds with method ai, depth 216, and size 3026.
Transpiled circuit index 29 (uuf100-ham) in 4.45 seconds with method ai, depth 426, and size 5399.
Transpiled circuit index 30 (flat100-ham) in 7.02 seconds with method ai, depth 86, and size 3108.
Transpiled circuit index 31 (uf100-ham) in 12.85 seconds with method ai, depth 623, and size 8354.
Transpiled circuit index 32 (OH) in 15.19 seconds with method ai, depth 2084, and size 9543.
Transpiled circuit index 33 (HF) in 17.51 seconds with method ai, depth 2063, and size 9446.
Transpiled circuit index 34 (BH) in 15.33 seconds with method ai, depth 2094, and size 9730.
Transpiled circuit index 0 (all-vib-o3) in 0.02 seconds with method rustiq, depth 13, and size 83.
Transpiled circuit index 1 (all-vib-c2h) in 1.11 seconds with method rustiq, depth 2, and size 39.
Transpiled circuit index 2 (all-vib-bh) in 0.01 seconds with method rustiq, depth 3, and size 30.
Transpiled circuit index 3 (all-vib-c2h) in 0.01 seconds with method rustiq, depth 13, and size 79.
Transpiled circuit index 4 (graph-gnp_k-2) in 0.02 seconds with method rustiq, depth 31, and size 131.
Transpiled circuit index 5 (all-vib-fccf) in 0.04 seconds with method rustiq, depth 50, and size 306.
Transpiled circuit index 6 (all-vib-hno) in 14.03 seconds with method rustiq, depth 22, and size 276.
Transpiled circuit index 7 (all-vib-bhf2) in 3.15 seconds with method rustiq, depth 13, and size 155.
Transpiled circuit index 8 (LiH) in 0.03 seconds with method rustiq, depth 54, and size 270.
Transpiled circuit index 9 (uf20-ham) in 0.04 seconds with method rustiq, depth 65, and size 398.
Transpiled circuit index 10 (all-vib-fccf) in 0.16 seconds with method rustiq, depth 41, and size 516.
Transpiled circuit index 11 (all-vib-fccf) in 0.02 seconds with method rustiq, depth 34, and size 189.
Transpiled circuit index 12 (all-vib-ch2) in 0.03 seconds with method rustiq, depth 49, and size 240.
Transpiled circuit index 13 (tfim) in 0.05 seconds with method rustiq, depth 20, and size 366.
Transpiled circuit index 14 (all-vib-cyclo_propene) in 9.08 seconds with method rustiq, depth 16, and size 277.
Transpiled circuit index 15 (graph-gnp_k-4) in 0.04 seconds with method rustiq, depth 116, and size 612.
Transpiled circuit index 16 (all-vib-hc3h2cn) in 13.89 seconds with method rustiq, depth 2, and size 257.
Transpiled circuit index 17 (TSP_Ncity-4) in 0.05 seconds with method rustiq, depth 133, and size 737.
Transpiled circuit index 18 (tfim) in 0.11 seconds with method rustiq, depth 25, and size 680.
Transpiled circuit index 19 (all-vib-h2co) in 27.19 seconds with method rustiq, depth 66, and size 983.
Transpiled circuit index 20 (Be2) in 0.07 seconds with method rustiq, depth 215, and size 1030.
Transpiled circuit index 21 (graph-complete_bipart) in 0.14 seconds with method rustiq, depth 328, and size 1918.
Transpiled circuit index 22 (all-vib-f2) in 0.05 seconds with method rustiq, depth 114, and size 692.
Transpiled circuit index 23 (all-vib-cyclo_propene) in 62.25 seconds with method rustiq, depth 74, and size 2348.
Transpiled circuit index 24 (TSP_Ncity-5) in 0.20 seconds with method rustiq, depth 436, and size 3605.
Transpiled circuit index 25 (H2) in 0.21 seconds with method rustiq, depth 643, and size 3476.
Transpiled circuit index 26 (uuf100-ham) in 0.24 seconds with method rustiq, depth 678, and size 6120.
Transpiled circuit index 27 (ham-graph-gnp_k-5) in 0.22 seconds with method rustiq, depth 588, and size 5241.
Transpiled circuit index 28 (tfim) in 0.34 seconds with method rustiq, depth 340, and size 5901.
Transpiled circuit index 29 (uuf100-ham) in 0.33 seconds with method rustiq, depth 881, and size 7667.
Transpiled circuit index 30 (flat100-ham) in 0.31 seconds with method rustiq, depth 279, and size 4910.
Transpiled circuit index 31 (uf100-ham) in 0.38 seconds with method rustiq, depth 1138, and size 10607.
Transpiled circuit index 32 (OH) in 0.38 seconds with method rustiq, depth 1148, and size 6512.
Transpiled circuit index 33 (HF) in 0.37 seconds with method rustiq, depth 1090, and size 6256.
Transpiled circuit index 34 (BH) in 0.37 seconds with method rustiq, depth 1148, and size 6501.

結果テーブル(出力回路が非常に大きいため、可視化は省略します):

summary_ham = (
results_ham.groupby("method")[["depth", "size", "runtime"]]
.mean()
.round(2)
)
print(summary_ham)

results_ham
depth     size  runtime
method
ai 316.86 2181.26 5.97
rustiq 281.94 2268.80 3.86
sabre 337.97 2120.14 3.07
method        qc_name  qc_index  num_qubits  \
0 sabre all-vib-o3 0 4
1 sabre all-vib-c2h 1 4
2 sabre all-vib-bh 2 2
3 sabre all-vib-c2h 3 3
4 sabre graph-gnp_k-2 4 4
.. ... ... ... ...
100 rustiq flat100-ham 30 90
101 rustiq uf100-ham 31 46
102 rustiq OH 32 10
103 rustiq HF 33 10
104 rustiq BH 34 10

ops depth size runtime
0 {'rz': 28, 'sx': 24, 'cz': 6} 6 58 0.016597
1 {'rz': 17, 'sx': 16, 'cz': 4, 'x': 2} 2 39 1.102089
2 {'sx': 14, 'rz': 13, 'cz': 3} 3 30 0.011042
3 {'sx': 46, 'rz': 45, 'cz': 18, 'x': 6} 18 115 0.025816
4 {'sx': 49, 'rz': 47, 'cz': 24, 'x': 9} 24 129 0.023077
.. ... ... ... ...
100 {'sx': 2709, 'cz': 1379, 'rz': 817, 'x': 5} 279 4910 0.309448
101 {'sx': 6180, 'cz': 3120, 'rz': 1303, 'x': 4} 1138 10607 0.380977
102 {'sx': 3330, 'cz': 1704, 'rz': 1455, 'x': 23} 1148 6512 0.383564
103 {'sx': 3213, 'cz': 1620, 'rz': 1406, 'x': 17} 1090 6256 0.368578
104 {'sx': 3331, 'cz': 1704, 'rz': 1447, 'x': 19} 1148 6501 0.374822

[105 rows x 8 columns]

回路インデックスに基づくパフォーマンスの可視化:

plot_transpilation_metrics(
results_ham, "Transpilation Metrics for Hamiltonian Circuits"
)

Output of the previous code cell

各手法が最良のパフォーマンスを示した回路の割合を可視化します。

def analyze_and_plot_best_methods(results, metric):
"""
Analyze the best-performing methods for a given metric and plot a pie chart.

Parameters:
results (DataFrame): The input DataFrame containing method performance data.
metric (str): The metric to evaluate ("depth" or "size").
"""
method_counts = Counter()
for qc_idx, group in results.groupby("qc_index"):
min_value = group[metric].min()

# Find all methods that achieved this minimum value
best_methods = group[group[metric] == min_value]["method"]
# Update counts for all best methods (handling ties)
method_counts.update(best_methods)
best_method_counts = dict(
sorted(method_counts.items(), key=lambda x: x[1], reverse=True)
)

# Print summary
print(f"Best-performing methods based on {metric}:")
for method, count in best_method_counts.items():
print(f" {method}: {count} circuit(s)")

# Plot pie chart
num_methods = len(best_method_counts)
colors = plt.cm.viridis_r(range(0, 256, 256 // num_methods))
plt.figure(figsize=(5, 5))
plt.pie(
best_method_counts.values(),
labels=best_method_counts.keys(),
autopct="%1.1f%%",
startangle=140,
wedgeprops={"edgecolor": "black"},
textprops={"fontsize": 10},
colors=colors,
)
plt.title(
f"Percentage of Circuits Method Performed Best for {metric.capitalize()}",
fontsize=12,
fontweight="bold",
)
plt.show()

analyze_and_plot_best_methods(results_ham, "depth")
analyze_and_plot_best_methods(results_ham, "size")
Best-performing methods based on depth:
ai: 16 circuit(s)
rustiq: 16 circuit(s)
sabre: 10 circuit(s)

Output of the previous code cell

Best-performing methods based on size:
sabre: 18 circuit(s)
rustiq: 14 circuit(s)
ai: 10 circuit(s)

Output of the previous code cell

ハミルトニアン回路コンパイル結果の分析

このセクションでは、ハミルトニアンシミュレーションタスクで一般的に使用される PauliEvolutionGate を用いて構築された量子回路に対する、3つのトランスパイル手法(SABRE、AIトランスパイラ、Rustiq)の性能を評価します。

Rustiq は回路深さの観点で平均的に最も優れた性能を示し、SABRE と比較して約20%低い深さを達成しました。これは、Rustiq が PauliEvolutionGate 演算を最適化された低深さの分解戦略で合成するために特別に設計されているため、期待通りの結果です。さらに、深さのプロットは、回路の規模と複雑さが増大するにつれて、Rustiq が最も効果的にスケールし、より大きな回路において AI と SABRE の両方よりも大幅に低い深さを維持していることを示しています。

AI トランスパイラは回路深さに関して強力で一貫した性能を示し、ほとんどの回路で SABRE を一貫して上回りました。しかし、特に大規模な回路において最も高い実行時間を要し、時間に制約のあるワークロードでは実用性が制限される可能性があります。深さにおいて確実な改善を提供するものの、実行時間のスケーラビリティは依然として主要な課題です。

SABRE は最も高い平均深さを生成しましたが、最も低い平均ゲート数を達成し、AI トランスパイラがそれに僅差で続きました。これは、ゲート数の直接的な最小化を優先する SABRE のヒューリスティックの設計と一致しています。Rustiq は深さの削減に優れているにもかかわらず、最も高い平均ゲート数を示しており、回路の持続時間よりも回路サイズが重要なアプリケーションにおいて考慮すべき重要なトレードオフです。

まとめ

AI トランスパイラは一般的に SABRE よりも優れた結果を提供しますが、特に回路深さにおいて、「常に AI トランスパイラを使用すべき」という単純な結論にはなりません。考慮すべき重要なニュアンスがあります:

  • AI トランスパイラは通常信頼性が高く、深さが最適化された回路を提供しますが、実行時間にトレードオフがあり、サポートされるカップリングマップや合成機能などの制限もあります。これらの詳細は Qiskit Transpiler Service ドキュメント に記載されています。

  • 特に非常に大規模な回路やハードウェア固有の回路では、AI トランスパイラが効果的でない場合があります。そのような場合、デフォルトの SABRE トランスパイラは非常に信頼性が高く、パラメータを調整することでさらに最適化できます(SABRE 最適化チュートリアル を参照)。

  • 手法を選択する際には、回路の構造を考慮することも重要です。例えば、rustiqPauliEvolutionGate を含む回路のために特別に構築されており、ハミルトニアンシミュレーション問題に対して最良の性能を発揮することが多いです。

推奨事項:

万能なトランスパイル戦略は存在しません。ユーザーの皆様には、回路の構造を理解し、AI、SABRE、Rustiq などの専門ツールを含む複数のトランスパイル手法をテストして、特定の問題とハードウェア制約に対して最も効率的なソリューションを見つけることをお勧めします。

ステップ3:Qiskit プリミティブを使用した実行

このチュートリアルはトランスパイルに焦点を当てているため、量子デバイス上での実験は実行しません。目標は、ステップ2の最適化を活用して、深さとゲート数が削減されたトランスパイル済み回路を取得することです。

ステップ4:後処理と希望する古典形式での結果の返却

このノートブックでは実行を行わないため、後処理する結果はありません。

参考文献

[1] "LightSABRE: A Lightweight and Enhanced SABRE Algorithm". H. Zou, M. Treinish, K. Hartman, A. Ivrii, J. Lishman et al. https://arxiv.org/abs/2409.08368

[2] "Practical and efficient quantum circuit synthesis and transpiling with Reinforcement Learning". D. Kremer, V. Villar, H. Paik, I. Duran, I. Faro, J. Cruz-Benito et al. https://arxiv.org/abs/2405.13196

[3] "Pauli Network Circuit Synthesis with Reinforcement Learning". A. Dubal, D. Kremer, S. Martiel, V. Villar, D. Wang, J. Cruz-Benito et al. https://arxiv.org/abs/2503.14448