ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

Qiskit Global Summer School 2023 Lab2 参加記録

各Labの記録

まえがき

Qiskit Global Summer School 2023 Lab2の記録です。

Lab2

ex1

CHSH不等式の説明(問題文から引用)

ex2の問題文の引用。Estimatorに渡すobservableを作る問題

IX = SparsePauliOp("IX")
XI = SparsePauliOp("XI")
IZ = SparsePauliOp("IZ")
ZI = SparsePauliOp("ZI")

# 「Aはq0にIX演算をする」、「Bはq1にXI演算をする」とすると、ABはXX演算になる。
AB = SparsePauliOp("XX")
Ab = SparsePauliOp("ZX")
aB = SparsePauliOp("XZ")
ab = SparsePauliOp("ZZ")

提出コードは以下。

obsv = AB - Ab + aB + ab# create operator for chsh witness
obsv
# SparsePauliOp(['XX', 'ZX', 'XZ', 'ZZ'],
#               coeffs=[ 1.+0.j, -1.+0.j,  1.+0.j,  1.+0.j])

ex2

Ex2の問題文

|<CHSH>| > 2 となるθを4つ探せという問題。マンデルブロ集合かな?

Demonstrate the violation of the CHSH inequality with the Estimator primitiveを参考にしつつ答えを探した。

まず[-2π, 2π]の区間で角度を100分割したものを作る。

angles = []
diff = np.pi*4/100
for i in range(0, 100):
    angles.append([-2*np.pi+diff*i])

すると以下のようなグラフが得られた。

estimator = Estimator()
job = estimator.run([qc]*len(angles), observables=[obsv]*len(angles), parameter_values=angles)
exps = job.result().values

plt.plot(angles, exps, marker='x', ls='-', color='green')
plt.plot(angles, [2]*len(angles), ls='--', color='red', label='Classical Bound')
plt.plot(angles, [-2]*len(angles), ls='--', color='red')
plt.xlabel('angle (rad)')
plt.ylabel('CHSH Witness')
plt.legend(loc=4)

|<CHSH>| > 2 となるθを見つけたい

このグラフを眺めて答えを提出した。例えば i=13, 14, 15, 16 のときにCHSHの破れが起きているので、以下のコードを提出すればよい。

# i=[13, 16] が破れているので、以下を答えとして提出する
angles = []
diff = np.pi*4/100
for i in range(13, 17):
    angles.append([-2*np.pi+diff*i])

ex3

Ex3 の問題文(引用)

このエクササイズでやることは、

  • bell[0]が1を出力した場合は、アリスはボブに彼の量子ビットにXゲートを適用するように伝える
  • qが1を出力した場合は、アリスはボブに彼の量子ビットにZゲートを適用するように伝える

ということをすればいい。

条件付きゲート: c_if メソッド を使って実装できる。

graded_qc = tele_qc.copy()

##############################
# add gates to graded_qc here

graded_qc.x(bell[1]).c_if(alice[1], 1)
graded_qc.z(bell[1]).c_if(alice[0], 1)

##############################

graded_qc.draw('mpl')

graded_qc回路

ex4

θ=5π/7として量子テレポーテーション回路を実行してみるらしい(問題文から引用)

Statevector は動的回路では使えないので、 Samplerを使って量子テレポーテーション回路を実行する。

θ=5π/7として実行すると、1が80%、0が20%の確率で測定される。

from qiskit_aer.primitives import Sampler

angle = 5*np.pi/7

sampler = Sampler()
qc.measure_all()
job_static = sampler.run(qc.bind_parameters({theta: angle}))
job_dynamic = sampler.run(graded_qc.bind_parameters({theta: angle}))

print(f"Original Dists: {job_static.result().quasi_dists[0].binary_probabilities()}")
print(f"Teleported Dists: {job_dynamic.result().quasi_dists[0].binary_probabilities()}")
# Original Dists: {'0': 0.2109375, '1': 0.7890625}
# Teleported Dists: {'001': 0.0439453125, '000': 0.052734375, '010': 0.048828125, '110': 0.1787109375, '101': 0.2041015625, '100': 0.216796875, '011': 0.0478515625, '111': 0.20703125}

今回のエクササイズは、「得られた Teleported Dists の結果を、Original Dists と同じ確率分布になるように周辺化せよ」という問題。

ここで周辺化(Marginalize)とは、6. 確率・統計の基礎 — ディープラーニング入門によると、

同時確率が与えられたとき、着目していない方の確率変数がとり得る全ての値について同時確率を計算しその和をとることを周辺化 (marginalization) と呼び、結果として得られる確率を周辺確率 (marginal probability) と呼びます

とある。

今回の場合では、Bobの量子ビット(2番目のビット)だけに着目したいのであって、それ以外の量子ビットは興味ない。ので、

  • 100, 101, 110, 111 を1に周辺化する
  • 000, 001, 010, 011 を0に周辺化する

とすればよい。

得られた周辺確率分布は Original State の確率分布とほぼ等しくなるはずである。

まず、周辺化前の分布を比較すると以下になった。

legend = ['Original State', 'Teleported State']
plot_histogram([job_static.result().quasi_dists[0].binary_probabilities(), job_dynamic.result().quasi_dists[0].binary_probabilities()], legend=legend)

周辺化前の確率分布(赤色)

この確率分布を周辺化する。周辺化には qiskit.result.marginal_counts ライブラリを使えば良い。

from qiskit.result import marginal_counts

tele_counts = marginal_counts(job_dynamic.result().quasi_dists[0].binary_probabilities(), indices=[2]) # indices引数で2ビット目を周辺化することを指定する

周辺化後の確率分布は以下になった。

legend = ['Original State', 'Teleported State']
plot_histogram([job_static.result().quasi_dists[0].binary_probabilities(), tele_counts], legend=legend)

周辺化後の確率分布(赤色)