メインコンテンツへスキップ
このプロジェクトはベータ版です。バグを見つけましたか?GitHub Issueを開く。質問やアイデアがありますか?Discussionsで質問する — フィードバックをお待ちしています!
このページの翻訳品質はいかがですか?

Dynamics Simulator - Q-CTRL Fire Opal による Qiskit Function

API リファレンスを参照してください。

備考

Qiskit Functions は実験的な機能であり、IBM Quantum® Premium Plan、Flex Plan、On-Prem(IBM Quantum Platform API 経由)Plan のユーザーのみが利用できます。プレビューリリースの状態であり、変更される可能性があります。

概要​

Q-CTRL の Dynamics Simulator は、サポートされている量子多体モデルの時間発展を IBM Quantum ハードウェア上でシミュレートするための、Application functions の Qiskit Function です。量子回路を自分で構築する代わりに、物理モデル、初期状態、時間発展のパラメーター、測定するオブザーバブルを指定します。

この関数は、必要なダイナミック回路を構築して実行し、Fire Opal のハードウェアを考慮した最適化とエラー抑制のワークフローを適用します。結果は、要求したオブザーバブルの期待値の時間トレースです。この関数はエラー抑制を自動的に適用するため、記録的な深さの回路を実行しても意味のある信号が得られます。Dynamics Simulator は、既存の最先端の古典ツールに匹敵する解の精度を実現し、速度面での実証可能な優位性をもたらします。

実環境でのテストでは、最高解像度の古典テンソルネットワークシミュレーションと比較して、二乗平均平方根誤差(RMSE)1% 以内の一致が達成されました。研究コミュニティによる独立したテストでは、Q-CTRL の最初のデモンストレーションを超えても量子コンピューターが正確であり続けることが検証されています。

Two plots of classical tensor-network simulations at bond dimensions χ from 64 to 4096. The left plot shows the RMSE against time t, which stays near 0.01 until it rises sharply, later for larger bond dimensions. The right plot shows the simulation time in minutes against time t on a logarithmic scale, which increases with bond dimension.

ベンチマーク​

サイト数は必要なキュービット数を決定し、Trotter ステップ数は時間発展回路の深さを制御します。各格子サイトは、スピンアップとスピンダウンの占有を表すために 2 つのキュービットを使用します。

このワークフローは、30 Trotter ステップの 60 サイト(120 キュービット)のチェーン、および 90 Trotter ステップの 31 サイト(62 キュービット)のチェーンで実証されています。次の表は、報告された実験における回路リソースと QPU 実行時間を示しており、回路あたり 20,000 ショットで IBM® Heron r3(ibm_boston)デバイス上で実施されたものです。

システムサイズTrotter ステップ数2 キュービットの深さ2 キュービットゲート数QPU 時間REM + DR を含む QPU 時間
10 サイト(20 キュービット)301521,4572m 46s4m 25s
10 サイト(20 キュービット)603022,8975m 36s8m 42s
10 サイト(20 キュービット)904524,3378m 46s13m 26s
31 サイト(62 キュービット)301524,6492m 46s4m 25s
31 サイト(62 キュービット)603029,2395m 36s8m 42s
31 サイト(62 キュービット)9045213,8298m 46s13m 26s
60 サイト(120 キュービット)301529,0572m 46s4m 25s

Trotter ステップ数を固定した場合、報告された回路の深さと QPU 時間は、テストしたシステムサイズによらず同じですが、2 キュービットゲート数は増加します。ステップ数を増やすと、より深い回路が生成され、より多くの QPU 時間が必要になります。

ここで、QPU 時間は、主要なシミュレーション回路のハードウェア実行時間の累計です。最後の列には、読み出しエラー緩和(REM)と減衰回復(DR)で使用されるノイズ特性評価の QPU 時間も含まれます。 このガイドでは、小規模な 1 次元 Fermi-Hubbard の例を使用して、モデルの定義から測定されたダイナミクスのプロットまでの完全なワークフローを示します。

関数の説明​

量子ダイナミクスは、量子系が時間とともにどのように変化するかを記述します。この発展を調べることで、粒子がどのように動くか、相関がどのように発達するか、系が状態やハミルトニアンの変化にどのように応答するかを理解できます。

Fermi-Hubbard モデルは、格子サイト間を移動し、同じサイトを占有したときに相互作用するフェルミオンを記述します。ホッピングと相互作用の競合により、このモデルは強相関電子の研究に有用です。その時間発展により、スピンと電荷がどのように伝播するか、また、最初に秩序を持っていた系がどのように緩和するかが明らかになります。

モデル​

Dynamics Simulator は、開放境界を持つ 1 次元の Fermi-Hubbard チェーンをサポートします。LL 個のサイトからなるチェーンに対して、ハミルトニアンは次のように定義されます。

H=−∑i=0L−2∑σ∈{↑,↓}th,i(ciσ†ci+1,σ+ci+1,σ†ciσ)+∑i=0L−1Uini↑ni↓−∑i=0L−1∑σ∈{↑,↓}μiniσ.H = -\sum_{i=0}^{L-2}\sum_{\sigma\in\{\uparrow,\downarrow\}} t_{h,i} \left( c^\dagger_{i\sigma}c_{i+1,\sigma} + c^\dagger_{i+1,\sigma}c_{i\sigma} \right) +\sum_{i=0}^{L-1}U_i n_{i\uparrow}n_{i\downarrow} -\sum_{i=0}^{L-1}\sum_{\sigma\in\{\uparrow,\downarrow\}} \mu_i n_{i\sigma}.

ここで、ciσ†c^\dagger_{i\sigma} と ciσc_{i\sigma} は、サイト ii におけるスピン σ\sigma のフェルミオンを生成および消滅させます。個数演算子 niσ=ciσ†ciσn_{i\sigma}=c^\dagger_{i\sigma}c_{i\sigma} は、そのスピン軌道の占有を測定します。

モデルの入力では、次の係数を指定します。

  • hopping_amplitude: th,it_{h,i}。隣接するサイト ii と i+1i+1 の間のホッピングを制御します。

  • on_site_interaction: UiU_i。同じサイトを占有するスピンアップとスピンダウンのフェルミオン間の相互作用です。

  • chemical_potential: μi\mu_i。局所的な化学ポテンシャルで、ハミルトニアンにはマイナス符号付きで入ります。

チェーン全体で同じ係数を使用する場合はスカラーを、個々の結合やサイトに係数を指定する場合はリストを指定します。

ℏ=1\hbar=1 とする単位系では、初期状態は次のように発展します。

∣ψ(t)⟩=e−iHt∣ψ(0)⟩.|\psi(t)\rangle=e^{-iHt}|\psi(0)\rangle.

この関数は、連続するシミュレーション時刻において、指定したオブザーバブルの期待値を推定します。

ワークフロー​

この関数のワークフローは、次のステップで構成されます。

  1. アルゴリズム合成: この関数は、ハミルトニアンとシミュレーション時間の設定を使用して最適化された Trotter-Suzuki シーケンスを構築し、シミュレーションの精度を考慮しながら回路の深さを削減します。

  2. ハードウェアを考慮したマッピング: この関数は、選択した IBM Quantum バックエンドのキュービット接続性とエラー特性を使用して、回路のマッピングとルーティングを行います。

  3. 物理層のエラー抑制: Fire Opal は、動的デカップリングとパルスレベルの補正を取り入れ、ハードウェア実行中の環境ノイズとクロストークを抑制します。

この関数はこれらのステージを自動的に管理し、要求されたオブザーバブルの期待値を時間経過とともに返します。

関数の入力を通じて、物理的な問題とシミュレーション設定を定義します。現在のインターフェースは Trotter 時間発展をサポートしており、time_step は各ステップの長さを、step_count はステップ数を設定します。

詳細については、Fire Opal dynamics simulator の概要と simulate_dynamics API リファレンスを参照してください。

はじめに​

この Qiskit Function へのアクセス情報は、Qiskit Functions Catalog で確認できます。

このガイドでは、Dynamics Simulator を読み込み、4 サイトの Fermi-Hubbard チェーンをシミュレートする方法を示します。次のコードは、IBM Quantum Platform の API キーとインスタンス CRN をすでにローカル環境に保存していることを前提としています。

アカウントのセットアップとクライアントのインストール手順については、Qiskit Functions を始めるを参照してください。

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "qctrlvisualizer": "qctrlvisualizer", "qiskit_ibm_catalog": "qiskit-ibm-catalog"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Access the Q-CTRL Dynamics Simulator Qiskit Function.
sim_qf = catalog.load("q-ctrl/dynamics-simulator")
# Check the list of backends you have access to
catalog.backends()
[<IBMBackend('ibm_boston')>,
<IBMBackend('ibm_fez')>,
<IBMBackend('ibm_kingston')>,
<IBMBackend('ibm_marrakesh')>,
<IBMBackend('ibm_miami')>,
<IBMBackend('ibm_phoenix')>,
<IBMBackend('ibm_pittsburgh')>]
# Select the backend you want to use
backend = catalog.backend("ibm_phoenix")

例: 4 サイトの Fermi-Hubbard チェーンのシミュレーション​

ホッピング振幅 th=1t_h=1、サイト内相互作用なし、化学ポテンシャルゼロの 4 サイトの 1 次元 Fermi-Hubbard チェーンを考えます。1 つのスピンアップのフェルミオンがサイト 0 から始まり、チェーン全体に広がって発展します。

この小さな問題により、Dynamics Simulator のワークフローに焦点を絞れます。

  1. モデルとシミュレーションを定義します。

  2. 初期状態とオブザーバブルを定義します。

  3. Qiskit Function のジョブを送信します。

  4. 期待値を取得します。

  5. ダイナミクスをプロットします。

1. 問題を定義する​

site_count = 4

model = {
"hopping_amplitude": 1.0,
"on_site_interaction": 0.0,
"chemical_potential": 0.0,
}

simulation = {
"time_step": 0.2,
"step_count": 8,
}

initial_state = "eeeu"

observables = [
{
"operators": [[["Nup", site]]],
"coefficients": [1.0],
}
for site in range(site_count)
]

shot_count = 2048

オブザーバブルのリストは、各サイトにおけるスピンアップの占有を測定します。

⟨ni↑⟩\langle n_{i\uparrow} \rangle

オブザーバブルは、指定した順序と同じ順序で返されます。

2. ダイナミクスシミュレーションを実行する​

Qiskit Function を通じて問題を送信します。Qiskit Functions Catalog が IBM Quantum の認証を処理するため、sim_qf.run() に Fire Opal やハードウェアプロバイダーの認証情報を別途渡す必要はありません。

job = sim_qf.run(
model=model,
simulation=simulation,
observables=observables,
initial_state=initial_state,
shots=shot_count,
backend_name=backend.name,
)
print(job.job_id, job.status())
68202fad-6919-425d-8fd2-c1c649cd15b1 DONE

返されるオブジェクトは Qiskit Function のジョブです。ジョブ ID を保持しておくと、後でワークロードを取得または確認できます。

3. 結果を取得する​

result = job.result()

print("Result keys:", sorted(result.keys()))
print("Warnings:", result.get("warnings", []))
Result keys: ['metadata', 'observable_expectation_values', 'observables', 'warnings']
Warnings: []

オブザーバブルの期待値を NumPy 配列に変換します。各行は 1 つのオブザーバブルに、各列は t=0t=0 から始まる記録されたシミュレーション時刻に対応します。この例では、4 つの行にサイト 0 から 3 のスピンアップの占有が含まれます。

import numpy as np

expectation_values = np.asarray(
result["observable_expectation_values"],
dtype=float,
)

print("Expectation-value array shape:", expectation_values.shape)
Expectation-value array shape: (4, 9)

4. ダイナミクスを可視化する​

初期状態には、スピンアップのフェルミオンが 1 つ含まれ、スピンダウンのフェルミオンは含まれません。したがって、その発展は 1 粒子部分空間内にとどまり、その 4 つの基底状態は、フェルミオンがサイト 0、1、2、3 を占有する状態に対応します。

この部分空間では、ハミルトニアンは隣接するサイトをホッピング振幅 −th-t_h で結びます。ここで使用しているパラメーターでは、

H1p=−th(0100101001010010).H_{\mathrm{1p}} = -t_h \begin{pmatrix} 0 & 1 & 0 & 0 \\ 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{pmatrix}.

この行列を NumPy で対角化し、Dynamics Simulator が返したものと同じ時刻で初期状態を発展させます。各状態振幅の絶対値の二乗が、対応するサイトのスピンアップの占有を与えます。

この計算は厳密なハミルトニアン時間発展を与えます。ハードウェアによる推定値とこの基準との差には、有限のトロッターステップ、測定の統計、およびハードウェアに残る誤差が含まれる可能性があります。

times = np.arange(expectation_values.shape[1]) * simulation["time_step"]

# This reference is specific to a single spin-up fermion.
if (
len(initial_state) != site_count
or initial_state.count("u") != 1
or initial_state.count("e") != site_count - 1
):
raise ValueError(
"This reference requires one spin-up fermion and otherwise empty sites."
)

# Build the Hamiltonian in the single-particle subspace.
hamiltonian = -model["hopping_amplitude"] * (
np.eye(site_count, k=1) + np.eye(site_count, k=-1)
)
hamiltonian -= model["chemical_potential"] * np.eye(site_count)

# The rightmost character of initial_state corresponds to site 0.
initial_amplitudes = np.zeros(site_count, dtype=complex)
initial_site = initial_state[::-1].index("u")
initial_amplitudes[initial_site] = 1.0

# Evolve the initial state in the Hamiltonian eigenbasis.
energies, eigenvectors = np.linalg.eigh(hamiltonian)
initial_coefficients = eigenvectors.conj().T @ initial_amplitudes

phases = np.exp(-1j * np.outer(energies, times))
states = eigenvectors @ (initial_coefficients[:, None] * phases)

ideal_expectation_values = np.abs(states) ** 2

各サイトごとに1つのパネルをプロットします。実線は記録された時刻における厳密な基準値を、マーカーは Dynamics Simulator が返したハードウェアによる推定値を示します。

import matplotlib.pyplot as plt
import qctrlvisualizer as qv
from qctrlvisualizer import QCTRL_STYLE_COLORS as colors

plt.style.use(qv.get_qctrl_style())

fig, ax = plt.subplots(figsize=(10, 6))

for site in range(len(expectation_values)):
site_color = colors[site % len(colors)]

ax.plot(
times,
ideal_expectation_values[site],
color=site_color,
linewidth=2,
label=f"Site {site}: exact reference",
)

ax.plot(
times,
expectation_values[site],
color=site_color,
linestyle="--",
linewidth=1.5,
marker="o",
markersize=5,
label=f"Site {site}: hardware estimate",
)

ax.set_xlim(times[0], times[-1])
ax.set_ylim(-0.05, 1.05)

ax.set_xlabel(r"Time (units of $\hbar/t_h$)")
ax.set_ylabel(r"$\langle n_{i\uparrow} \rangle$")
ax.set_title("Spin-up occupation dynamics")

ax.legend(
ncol=2,
fontsize=10,
loc="best",
)

fig.tight_layout()
plt.show()

Output of the previous code cell

t=0t=0 では、厳密なスピンアップの占有数はサイト0で1、その他のサイトで0です。系が時間発展するにつれて、ホッピングによって粒子の確率が鎖全体に広がります。最初にサイト1の占有数が増加し、続いてサイト2と3の占有数が増加します。この例のパラメータでは、最後に記録される時刻は t=1.6t=1.6 です。サイト0から3までの厳密な占有数は、それぞれおよそ0.026、0.370、0.392、0.211です。

厳密な占有数は、粒子数の保存を反映して、あらゆる時刻で次の式を満たします。

∑i=03⟨ni↑(t)⟩=1\sum_{i=0}^{3}\langle n_{i\uparrow}(t)\rangle=1

粒子が有限の鎖の中を時間発展するにつれて、個々のサイトの占有数は増減することがあります。

エラーメッセージを取得する​

ワークロードが ERROR 状態になった場合は、job.result() を呼び出してエラーメッセージを取得します。利用可能であれば、関数のログを確認することもできます。

print(job.status())

if job.status() == "ERROR":
print(job.result())
print(job.logs())
DONE

入力検証でよくある問題には、サポートされていないモデルやシミュレーション方法、長すぎる初期状態の文字列、observable の項と係数の不一致、初期状態の文字列の範囲外のサイトを参照している observable などがあります。

サポートを受ける​

Dynamics Simulator や Fire Opal の動作に関する質問は、Q-CTRL のドキュメントを参照するか、Q-CTRL に問い合わせてください。

Qiskit Functions の認証、ジョブ管理、または IBM Quantum Platform へのアクセスについては、Qiskit Functions のドキュメントを参照してください。

次のステップ​

推奨事項