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

テンソルネットワークを用いた近似量子コンパイル (AQC-Tensor) を使ってみる

Package versions

このページのコードは、以下の要件を使って開発されました。 これらのバージョン以降を使用することをお勧めします。

qiskit[all]~=2.3.0
qiskit-aer~=0.17
qiskit-addon-utils~=0.3.0
qiskit-addon-aqc-tensor[aer,quimb-jax]~=0.2.0; sys.platform != 'darwin'
scipy~=1.16.3

このガイドでは、AQC-Tensor を使い始めるための簡単な動作例を示します。この例では、横磁場イジングモデルの時間発展をシミュレートする Trotter 回路を取り上げ、AQC-Tensor 手法を用いて得られる回路の深さを削減します。また、この例では問題生成器として qiskit-addon-utils パッケージ、テンソルネットワークシミュレーションとして qiskit-aer、パラメータ最適化として scipy が必要です。

まず、横磁場イジングモデルのハミルトニアンは次の形を持つことを思い出してください。

HIsing=i=1NJi,(i+1)ZiZi+1+hiXi\mathcal{H}_{Ising} = \sum_{i=1}^N J_{i,(i+1)}Z_iZ_{i+1} + h_i X_i

ここで周期境界条件を仮定します。つまり i=10i=10 のとき i+1=111i+1=11\rightarrow 1 となり、JJ は2サイト間の結合強度、hh は外部磁場の強さです。

以下のコードスニペットは、周期境界条件を持つ10サイトのイジング鎖のハミルトニアンを生成します。

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-addon-aqc-tensor qiskit-addon-utils qiskit-aer scipy
from qiskit.transpiler import CouplingMap
from qiskit_addon_utils.problem_generators import generate_xyz_hamiltonian
from qiskit.synthesis import SuzukiTrotter
from qiskit_addon_utils.problem_generators import (
generate_time_evolution_circuit,
)
from qiskit_addon_aqc_tensor import generate_ansatz_from_circuit
from qiskit_addon_aqc_tensor.simulation import tensornetwork_from_circuit
from qiskit_addon_aqc_tensor.simulation import compute_overlap
from qiskit_addon_aqc_tensor.objective import MaximizeStateFidelity
from qiskit_aer import AerSimulator
from scipy.optimize import OptimizeResult, minimize

# Generate some coupling map to use for this example
coupling_map = CouplingMap.from_heavy_hex(3, bidirectional=False)

# Choose a 10-qubit circle on this coupling map
reduced_coupling_map = coupling_map.reduce(
[0, 13, 1, 14, 10, 16, 4, 15, 3, 9]
)

# Get a qubit operator describing the Ising field model
hamiltonian = generate_xyz_hamiltonian(
reduced_coupling_map,
coupling_constants=(0.0, 0.0, 1.0),
ext_magnetic_field=(0.4, 0.0, 0.0),
)

時間発展を古典実行と量子実行の2つに分割する

この例の全体的な目標は、モデルハミルトニアンの時間発展をシミュレートすることです。ここでは Trotter 発展を用い、それを2つの部分に分割します。

  1. 行列積状態 (MPS) を使ってシミュレート可能な初期部分。これが AQC-Tensor を用いて「コンパイル」される部分です。
  2. 量子ハードウェア上で実行される後続部分。

システムを時刻 tf=5t_f=5 まで発展させ、AQC-Tensor を使って時刻 t=4t=4 までの時間発展を圧縮してから、通常の Trotter ステップで tft_f まで発展させます。

次に、2つの回路を生成します。1つ目は AQC-Tensor で圧縮される回路、2つ目は QPU 上で実行される回路です。1つ目の回路は行列積状態を使って古典的にシミュレートされるため、Trotter 誤差を最小化するために多数のレイヤーを使用します。一方、ti=4t_i=4 から tf=5t_f=5 までの時間発展をシミュレートする2つ目の回路は、深さを最小化するためにはるかに少ないレイヤーを使用します。

# Generate circuit to be compressed
aqc_evolution_time = 4.0
aqc_target_num_trotter_steps = 45

aqc_target_circuit = generate_time_evolution_circuit(
hamiltonian,
synthesis=SuzukiTrotter(reps=aqc_target_num_trotter_steps),
time=aqc_evolution_time,
)

# Generate circuit to execute on hardware
subsequent_evolution_time = 1.0
subsequent_num_trotter_steps = 5

subsequent_circuit = generate_time_evolution_circuit(
hamiltonian,
synthesis=SuzukiTrotter(reps=subsequent_num_trotter_steps),
time=subsequent_evolution_time,
)

比較のために、3つ目の回路も生成します。これは t=4t=4 まで発展しますが、ti=4t_i=4 から tf=5t_f=5 まで発展する2つ目の回路と同じ数のレイヤーを持ちます。これは AQC-Tensor 手法を使用しなかった場合に実行していたであろう回路です。これを比較回路と呼ぶことにします。

aqc_comparison_num_trotter_steps = int(
subsequent_num_trotter_steps
/ subsequent_evolution_time
* aqc_evolution_time
)
aqc_comparison_num_trotter_steps

comparison_circuit = generate_time_evolution_circuit(
hamiltonian,
synthesis=SuzukiTrotter(reps=aqc_comparison_num_trotter_steps),
time=aqc_evolution_time,
)

アンサッツの生成と MPS シミュレーションの構築

次に、最適化するアンサッツを生成します。これは最初の回路と同じ発展時刻(ti=0t_i=0 から tf=4t_f=4)まで発展しますが、Trotter ステップ数は少なくなります。

回路が生成されたら、AQC-Tensor の generate_ansatz_from_circuit() 関数に渡します。この関数は2量子ビット接続性を解析し、2つのものを返します。1つ目は同じ2量子ビット接続性を持つ生成されたアンサッツ回路で、2つ目はアンサッツに代入すると入力回路を再現するパラメータの集合です。

aqc_ansatz_num_trotter_steps = 5

aqc_good_circuit = generate_time_evolution_circuit(
hamiltonian,
synthesis=SuzukiTrotter(reps=aqc_ansatz_num_trotter_steps),
time=aqc_evolution_time,
)

aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(
aqc_good_circuit, qubits_initially_zero=True
)
aqc_ansatz.draw("mpl", fold=-1)

Output of the previous code cell

次に、AQC で近似されるべき状態の MPS 表現を構築します。また、より多くの Trotter ステップを使用したターゲット状態を生成する回路と、比較回路が準備する状態との間の忠実度 ψ1ψ22|\langle\psi_1 | \psi_2 \rangle |^2 を計算します。

# Generate MPS simulator settings and obtain the MPS representation of the target state
simulator_settings = AerSimulator(
method="matrix_product_state",
matrix_product_state_max_bond_dimension=100,
)
aqc_target_mps = tensornetwork_from_circuit(
aqc_target_circuit, simulator_settings
)

# Compute the fidelity between the MPS representation of the target state and the state produced by the comparison circuit
comparison_mps = tensornetwork_from_circuit(
comparison_circuit, simulator_settings
)
comparison_fidelity = (
abs(compute_overlap(comparison_mps, aqc_target_mps)) ** 2
)
print(f"Comparison fidelity: {comparison_fidelity}")
Comparison fidelity: 0.9997111919739693

MPS を使ってアンサッツのパラメータを最適化する

最後に、アンサッツ回路を最適化して、comparison_fidelity よりも高い忠実度でターゲット状態を生成できるようにします。最小化するコスト関数は MaximizeStateFidelity で、scipy の L-BFGS オプティマイザーを使って最適化されます。

objective = MaximizeStateFidelity(
aqc_target_mps, aqc_ansatz, simulator_settings
)

stopping_point = 1 - comparison_fidelity

def callback(intermediate_result: OptimizeResult):
print(f"Intermediate result: Fidelity {1 - intermediate_result.fun:.8}")
if intermediate_result.fun < stopping_point:
# Good enough for now
raise StopIteration

result = minimize(
objective,
aqc_initial_parameters,
method="L-BFGS-B",
jac=True,
options={"maxiter": 100},
callback=callback,
)
if (
result.status
not in (
0,
1,
99,
)
): # 0 => success; 1 => max iterations reached; 99 => early termination via StopIteration
raise RuntimeError(
f"Optimization failed: {result.message} (status={result.status})"
)

print(f"Done after {result.nit} iterations.")
aqc_final_parameters = result.x
Intermediate result: Fidelity 0.95084365
Intermediate result: Fidelity 0.98409893
Intermediate result: Fidelity 0.99142033
Intermediate result: Fidelity 0.99521405
Intermediate result: Fidelity 0.99566673
Intermediate result: Fidelity 0.99650054
Intermediate result: Fidelity 0.99683487
Intermediate result: Fidelity 0.99720426
Intermediate result: Fidelity 0.99761726
Intermediate result: Fidelity 0.99809073
Intermediate result: Fidelity 0.99838244
Intermediate result: Fidelity 0.99861841
Intermediate result: Fidelity 0.99874617
Intermediate result: Fidelity 0.99892696
Intermediate result: Fidelity 0.99908129
Intermediate result: Fidelity 0.99917737
Intermediate result: Fidelity 0.99925456
Intermediate result: Fidelity 0.99933134
Intermediate result: Fidelity 0.99947173
Intermediate result: Fidelity 0.99956469
Intermediate result: Fidelity 0.99964488
Intermediate result: Fidelity 0.99967419
Intermediate result: Fidelity 0.99968821
Intermediate result: Fidelity 0.9997448
Done after 24 iterations.

この時点で、AQC を使用せずに比較回路が生成したであろう状態よりも高い忠実度でターゲット状態を生成するパラメータの集合が得られました。これらの最適パラメータにより、圧縮された回路は元の回路よりも Trotter 誤差が小さく、かつ深さも浅くなります。

最後のステップとして、以下のコードスニペットは、トランスパイラパイプラインに渡して量子ハードウェア上で実行できる完全な時間発展回路を構築します。

final_circuit = aqc_ansatz.assign_parameters(aqc_final_parameters)
final_circuit.compose(subsequent_circuit, inplace=True)
final_circuit.draw("mpl", fold=-1)

Output of the previous code cell

次のステップ

推奨事項