Qiskit自宅実践ガイド

Qiskit Aerを用いた量子状態の精密な解析:状態ベクトルと密度行列の取得、可視化、そして物理的解釈

Tags: Qiskit Aer, 量子状態解析, 状態ベクトル, 密度行列, 量子シミュレーション

量子情報科学における研究や開発では、量子回路が最終的にどのような量子状態を生成するのかを正確に理解することが不可欠です。特にQiskitを用いたシミュレーション環境では、測定結果の統計だけではなく、回路途中の任意の時点、あるいは最終的な量子状態そのもの(状態ベクトルや密度行列)を直接取得し、解析する機能が非常に重要となります。

本記事では、Qiskit Aerシミュレータの強力な機能に焦点を当て、状態ベクトルおよび密度行列を効率的に取得し、その物理的な意味を深く解釈する方法について解説します。理論的な背景とQiskitコードの実装を明確に関連付けながら、具体的なコード例とともにその活用法と注意点を探ります。

量子状態の基礎:状態ベクトルと密度行列

量子系の状態は、純粋状態であれば状態ベクトル(Statevector)で記述され、混合状態や部分系であれば密度行列(Density Matrix)で記述されます。これらの表現は、量子力学の理論的な枠組みにおいて中心的な役割を果たし、Qiskit上でのシミュレーション結果を理解する上でも同様に重要です。

Qiskit Aerは、これら二つの形式での量子状態を直接シミュレーションし、結果として取得する機能を提供します。

Qiskit Aerでの状態ベクトルシミュレーション

statevector_simulatorは、理想的な(ノイズのない)量子回路が生成する純粋状態を状態ベクトルとして取得するために利用されます。これは、特定の量子アルゴリズムが意図した状態を正確に生成しているかを確認する際に非常に役立ちます。

状態ベクトルの取得と解釈

状態ベクトルを取得するには、まずAer.get_backend('statevector_simulator')でシミュレータを指定し、回路を実行します。結果オブジェクトからget_statevector()メソッドを用いて状態ベクトルを取り出します。

from qiskit import QuantumCircuit, Aer, transpile
from qiskit.visualization import plot_bloch_multivector, plot_state_qsphere

### 1. 回路の構築
qc_statevector = QuantumCircuit(2, 2)
qc_statevector.h(0)  # 0番目の量子ビットにアダマールゲートを適用
qc_statevector.cx(0, 1) # 0番目と1番目の量子ビットにCNOTゲートを適用 (エンタングル状態を生成)
qc_statevector.measure([0,1], [0,1]) # 測定は状態ベクトルシミュレータでは無視されます

print("--- 量子回路図 ---")
print(qc_statevector.draw(output='text'))

### 2. statevector_simulatorの指定と実行
simulator = Aer.get_backend('statevector_simulator')

# 測定ゲートは状態ベクトルシミュレーションには影響しないため、transpile時に削除可能
# ただし、今回は可視化のために元の回路をそのまま実行します
job = simulator.run(qc_statevector)
result = job.result()

### 3. 状態ベクトルの取得
statevector = result.get_statevector(qc_statevector)
print("\n--- 取得された状態ベクトル ---")
print(statevector)

### 4. 状態ベクトルの解釈
# この状態ベクトルは |00> と |11> の重ね合わせであるベル状態 (Entangled state) を示しています。
# 具体的には、1/√2 |00> + 1/√2 |11> に相当します。
# Qiskitでは、基底状態は |qn-1 ... q1 q0> の順で表されます。
# ここでは2量子ビットなので |q1 q0>。
# statevector[0] は |00> の振幅、statevector[3] は |11> の振幅に対応します。
# 他の要素 (statevector[1] = |01>, statevector[2] = |10>) はゼロに近い値になります。

# 各基底状態の確率計算 (振幅の絶対値の二乗)
probabilities = [abs(amp)**2 for amp in statevector]
print("\n--- 各基底状態の確率 ---")
print(f"|00> の確率: {probabilities[0]:.4f}")
print(f"|01> の確率: {probabilities[1]:.4f}")
print(f"|10> の確率: {probabilities[2]:.4f}")
print(f"|11> の確率: {probabilities[3]:.4f}")

### 5. 可視化の示唆
# 状態ベクトルの可視化は、特に複数の量子ビットを持つ系の状態を直感的に理解する上で非常に有効です。
# Qiskitはplot_bloch_multivectorやplot_state_qsphereといった強力な可視化ツールを提供しています。
# 例えば、`plot_bloch_multivector(statevector)` は各量子ビットのブロッホ球表現を生成し、
# `plot_state_qsphere(statevector)` は多量子ビットの重ね合わせ状態をQ-sphere上に視覚的に表示します。
# これらの図を用いることで、単なる数値の羅列では見えにくい量子もつれや重ね合わせの状態を直感的に把握できます。
# (ここでは図の生成は省略しますが、実際の研究では積極的に利用されることを推奨します。)

上記のコード例では、アダマールゲートとCNOTゲートを用いてベル状態(エンタングル状態)を生成し、その状態ベクトルを取得しています。出力された状態ベクトルから、|00>|11> の状態が$1/\sqrt{2}$の確率振幅で存在し、他の状態は存在しないことが読み取れます。これにより、理論と実装が一致していることを確認できます。

Qiskit Aerでの密度行列シミュレーション

density_matrix_simulatorは、ノイズモデルを考慮したシミュレーションや、量子回路の一部を測定・トレーシングアウトして部分系の状態を評価する際に不可欠です。純粋状態だけでなく混合状態も扱うことができます。

密度行列の取得と解釈

密度行列を取得するには、Aer.get_backend('density_matrix_simulator')を使用します。結果オブジェクトからget_density_matrix()メソッドを用いて密度行列を取り出します。

from qiskit import QuantumCircuit, Aer
from qiskit.providers.aer.noise import NoiseModel
from qiskit.providers.aer.noise.errors import depolarizing_error
import numpy as np

### 1. 回路の構築 (先ほどと同じベル状態生成回路)
qc_density_matrix = QuantumCircuit(2)
qc_density_matrix.h(0)
qc_density_matrix.cx(0, 1)

print("--- 量子回路図 ---")
print(qc_density_matrix.draw(output='text'))

### 2. density_matrix_simulatorの指定と実行
# まず、ノイズモデルなしで純粋状態の密度行列を取得
simulator_ideal = Aer.get_backend('density_matrix_simulator')
job_ideal = simulator_ideal.run(qc_density_matrix)
result_ideal = job_ideal.result()
density_matrix_ideal = result_ideal.get_density_matrix(qc_density_matrix)

print("\n--- 理想的な(ノイズなし)状態の密度行列 ---")
print(np.round(density_matrix_ideal, 4))

### 3. ノイズモデルの導入
# 例として、単一量子ビットにdepolarizing errorを適用するノイズモデルを作成
noise_model = NoiseModel()
# 0番目の量子ビットに0.1の確率でdepolarizing errorを適用
depolarizing_err = depolarizing_error(0.1, 1)
noise_model.add_all_qubit_quantum_error(depolarizing_err, ['h', 'cx']) # HとCXゲートに適用

# ノイズモデルを適用してシミュレーションを実行
simulator_noisy = Aer.get_backend('density_matrix_simulator')
job_noisy = simulator_noisy.run(qc_density_matrix, noise_model=noise_model)
result_noisy = job_noisy.result()
density_matrix_noisy = result_noisy.get_density_matrix(qc_density_matrix)

print("\n--- ノイズあり状態の密度行列 ---")
print(np.round(density_matrix_noisy, 4))

### 4. 密度行列の解釈
# 理想的な状態の密度行列は純粋状態 (|00> + |11>)/sqrt(2) の期待値演算子になります。
# |ψ⟩⟨ψ| = (1/√2 |00⟩ + 1/√2 |11⟩)(1/√2 ⟨00| + 1/√2 ⟨11|)
#       = 1/2 (|00⟩⟨00| + |00⟩⟨11| + |11⟩⟨00| + |11⟩⟨11|)
# ノイズありの状態では、対角成分 (例: |00⟩⟨00|, |11⟩⟨11|) が理想状態から変化し、
# 非対角成分 (例: |00⟩⟨11|, |11⟩⟨00|) が減少する傾向が見られます。
# これは、デコヒーレンスによって量子もつれや重ね合わせが失われ、混合状態に近づいていることを示唆します。

# 密度行列からエントロピーを計算することで、純粋度を定量的に評価することも可能です。
# 例えば、von Neumannエントロピー S(ρ) = -Tr(ρ log2 ρ) は、混合度合いを示す指標となります。
# (Qiskitには密度行列の様々な性質を計算するツールも用意されています。)

上記の例では、理想的なシミュレーションと、デポラライジングノイズを導入したシミュレーションの2パターンで密度行列を取得しています。ノイズがない場合は理想的なベル状態の密度行列が得られますが、ノイズが導入されると非対角成分が減少し、系が混合状態に近づく様子が確認できます。これは、ノイズが量子系のコヒーレンスを破壊する効果を直接的に示しており、実機での量子計算における誤差の影響を理解する上で非常に重要です。

状態解析の応用と注意点

測定結果との関連付け

状態ベクトルや密度行列は、測定前の量子系の完全な情報を含んでいます。したがって、これらの情報から任意の基底での測定結果の確率分布を予測できます。例えば、状態ベクトル$|\psi\rangle$が与えられたとき、特定の基底状態$|k\rangle$での測定確率は$|\langle k|\psi\rangle|^2$で計算されます。密度行列$\rho$の場合は、測定確率$P(k) = \mathrm{Tr}(\rho |k\rangle\langle k|)$となります。これにより、理論的な予測とQiskitのqasm_simulatorなどによる測定シミュレーション結果との整合性を確認できます。

デバッグツールとしての活用

量子回路が期待通りに動作しない場合、中間状態の状態ベクトルや密度行列を追跡することで、どのゲート操作で問題が生じているかを特定する強力なデバッグツールとなります。例えば、特定のゲート適用前後の状態変化を比較することで、ゲートの実装誤りや意図しない副作用を発見できる可能性があります。

大規模系における課題

状態ベクトルシミュレータや密度行列シミュレータは、量子ビット数が$N$の場合、$2^N$次元の情報を扱います。これは量子ビット数が線形に増えるのに対し、必要なメモリや計算時間が指数関数的に増加することを意味します。したがって、量子ビット数が20〜30を超えると、これらのシミュレータを一般的な計算機で実行することは非常に困難になります。このため、大規模な回路の解析には、別の手法(例: 測定シミュレータで部分的な情報にアクセスする、量子状態の近似手法を用いる)を検討する必要があります。

まとめ

本記事では、Qiskit Aerを用いた量子状態の精密な解析に焦点を当て、状態ベクトルおよび密度行列の取得と、その物理的な解釈について詳しく解説しました。

Qiskitが提供するこれらの高度なシミュレーション機能を活用することで、量子情報科学における理論と実践のギャップを埋め、より深い洞察と効率的な研究開発が可能になるでしょう。大規模な量子系への挑戦や、ノイズ環境下での挙動解析など、今後の研究においてもこれらの解析手法が大いに役立つことを期待します。