Qiskit で遊んでみる (6) — QGSS2022 より
目的
前回 に引き続き Qiskit Global Summer School 2022: Quantum Simulations で興味を持ったテーマを復習する。
今回はハードウェアノイズのシミュレーションを題材にする。
準備
以下を import しているとする。
import numpy as np
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.providers.aer import AerSimulator
from qiskit.providers.aer.noise import NoiseModel, coherent_unitary_error, depolarizing_error
from qiskit.circuit.library import RXGate
import matplotlib.pylab as plt
実機での計測
1 量子ビットの回路で
実際に試してみると:
def measure_0(n_xgates, backend):
qr = QuantumRegister(1)
cr = ClassicalRegister(1)
qc = QuantumCircuit(qr, cr)
# 指定の回数だけ X ゲートを適用する
for _ in range(n_xgates):
qc.x(0)
qc.measure(qr, cr)
shots = 1024
counts = backend.run(qc, shots=shots).result().get_counts()
count0 = 0
if '0' in counts:
count0 = counts['0']
return count0/shots
IBMQ.load_account()
provider = IBMQ.get_provider()
backend = provider.get_backend('ibmq_belem')
prob0 = measure_0(20, backend)
print(prob0)
[0.9599609375]
どうやら 4% くらい
もし理想的な FTQC 上で実験ができたとすれば、以下のシミュレータの結果のようになるはずである(横は
実機のフェイクでの測定
流石に実機で沢山の回数の試行を試すのは厳しいので、実機のノイズモデルを使ったシミュレータで測定してみよう。Fake Provider を参考に ibmq_belem
のフェイクを作成する。
provider = IBMQ.load_account()
backend = provider.get_backend('ibmq_belem')
backend_sim = AerSimulator.from_backend(backend)
probs = []
for i in range(100):
prob0 = measure_0(i, backend_sim)
probs.append(prob0)
plt.plot(list(range(len(probs))), probs)
plt.show()
すると、FTQC とは異なり以下のように少しずつ確率が下がっていっている。
前回のおさらい
前回、
次回の記事の伏線の形で、ハミルトニアン
の時間発展について考えてみる。これは H = X であるが、 U(t) = \exp(-itH) を思い出すと、 R_X(\theta) = \exp(-i \frac{\theta}{2} X) であることが分かる。 U(t) = R_X(2t)
といったことを書いたが、時間
ノイズモデルの適用
measure_0
を少し書き直す:
def measure_0_with_noise(n_xgates, backend, noise_model=None):
qr = QuantumRegister(1)
cr = ClassicalRegister(1)
qc = QuantumCircuit(qr, cr)
# 指定の回数だけ X ゲートを適用する
# 但し、ノイズが乗っているので少しずつ理想からはずれた形になっていく
for _ in range(n_xgates):
# qc.x(np.pi, 0)
qc.rx(np.pi, 0)
qc.measure(qr, cr)
shots = 1024
counts = backend.run(qc, shots=shots).result().get_counts()
count0 = 0
if '0' in counts:
count0 = counts['0']
return count0/shots
次に、以下のような第 1 量子ビットの
def add_coherent_noise(noise_model):
epsilon = 3*np.pi/180
epsilon_rotation = RXGate(epsilon).to_matrix()
over_rotation = coherent_unitary_error(epsilon_rotation)
noise_model.add_quantum_error(over_rotation, ['rx'],
qubits=[0], warnings=False)
def add_depolarizing_noise(noise_model):
error = depolarizing_error(.02, 1)
noise_model.add_quantum_error(error, ['rx'], qubits=[0], warnings=False)
これを使って、実験をしてみよう。
コヒーレントノイズだけの時
noise_model = NoiseModel()
add_coherent_noise(noise_model)
sim = AerSimulator(noise_model=noise_model)
probs = []
for i in range(100):
prob0 = measure_0_with_noise(i, sim, noise_model)
probs.append(prob0)
plt.plot(list(range(len(probs))), probs)
plt.show()
これは大分極端な結果になっているが、上に掲載した ibmq_belem
のフェイクの時と同様に徐々に測定結果として
脱分極ノイズも追加する
noise_model = NoiseModel()
add_coherent_noise(noise_model)
add_depolarizing_noise(noise_model)
sim = AerSimulator(noise_model=noise_model)
probs = []
for i in range(100):
prob0 = measure_0_with_noise(i, sim, noise_model)
probs.append(prob0)
plt.plot(list(range(len(probs))), probs)
plt.show()
これも大袈裟になってしまっているが、大分酷い結果になってしまった。
まとめ
大分粗い設定かもしれないが、ある種のノイズモデルを定義して単純な回路のシミュレーションを行ってみた。これにより完璧ではないにせよ、どういったことが起こり得るかの知見が少し得られたように思う。また Qiskit で遊んでみる (4) の時に試したグローバーのアルゴリズムでは実際にかなり酷い結果になってしまった。
NISQ の抱える現実的な問題を踏まえつつ、測定エラーの軽減 (error mitigation) といったことも学んで最適なアプローチを模索したい。
-
もっと色んな回数で試したかったが実機の待ち行列が厳しいので 1 回だけにした。 ↩︎
Discussion