1
Blueqat 0.4.1では(ようやく)任意の初期状態を指定して回路を動かせるようになりました。例えば次のように使うことができます。
Blueqatの旧バージョンがインストールされている場合は、次のようにアップデートします。
Copy !pip install -U blueqat
Collecting blueqat
Downloading blueqat-0.4.1-py3-none-any.whl (60 kB)
[K |████████████████████████████████| 60 kB 577 kB/s eta 0:00:011
[?25hRequirement already satisfied, skipping upgrade: scipy>=1.1.0 in /opt/conda/lib/python3.8/site-packages (from blueqat) (1.4.1)
Requirement already satisfied, skipping upgrade: numpy~=1.12 in /opt/conda/lib/python3.8/site-packages (from blueqat) (1.19.1)
[31mERROR: openfermionblueqat 0.2.2 has requirement blueqat~=0.3.3, but you'll have blueqat 0.4.1 which is incompatible.[0m
Installing collected packages: blueqat
Attempting uninstall: blueqat
Found existing installation: blueqat 0.3.18
Uninstalling blueqat-0.3.18:
Display all output >>>
runの引数にinitial=vec
のように初期ベクトルを指定することで、指定された初期ベクトルから計算を始めることができます。
Copy import numpy as np from blueqat import Circuit # まずは、普通に動かす c = Circuit().h[0].m[0] c.run(shots=100) # => 0と1が50%ずつ
Counter({'0': 49, '1': 51})
Copy # 状態ベクトルvec = (|0> - |1>)/√2 を用意 vec = np.array([1, -1]) / np.sqrt(2) # 回路cに状態ベクトルvecを指定→vecにアダマールゲートをかけると、1のみが測定される c.run(shots=100, initial=vec)
Counter({'1': 100})
状態ベクトルの大きさは、回路の2 ^ 量子ビット数
になっている必要があります。また、状態ベクトルが正規化されていることをblueqat側では確認していませんが、正規化されていない場合、測定などの動作が予期しない結果となることがあるので、正規化されたベクトルを利用することを推奨します。
Copy # 次元が合わないとエラーになります c.x[3].run(shots=100, initial=np.array([1, 0, 0, 0]))
Copy # 正規化はblueqat側では確認していません。正規化されていることを確認するには、以下のようにします。 # True: 正規化されている np.allclose(np.vdot(vec, vec), 1)
True
Copy # False: 正規化されていない vec2 = np.array([1, 1]) np.allclose(np.vdot(vec2, vec2), 1)
False
初期状態ベクトルはnumpyなどで作ることもできますが、blueqat回路の計算結果を流用することもできます。その際、量子ビット数を合わせて回路を実行する必要があります。
Copy # Circuit(2)のようにすることで、1量子ビットしかないc1も2量子ビットで計算を行います c1 = Circuit(2).x[0] c2 = Circuit(2).x[1] c2.run(initial=c1.run())
array([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j])
blueqatは、量子ビットのクロネッカー積を取る際、右から順にかけられていること(2番目1番目0番目となること)に注意して、以下の記事を読んでください。
Copy # AliceとBobは、ベル状態を共有しています bell = Circuit().h[0].cx[0, 1].run() bell
array([0.70710678+0.j, 0. +0.j, 0. +0.j, 0.70710678+0.j])
Copy # これをテレポーテーションします psi = np.array([np.cos(0.4), 1j*np.sin(0.4)]) psi
array([0.92106099+0.j , 0. +0.38941834j])
Copy # 系全体としては、bellとpsiのクロネッカー積を取った状態となります state = np.kron(bell, psi) state
array([0.65128847+0.j , 0. +0.27536035j,
0. +0.j , 0. +0.j ,
0. +0.j , 0. +0.j ,
0.65128847+0.j , 0. +0.27536035j])
Copy # Alice側: 量子テレポーテーションの回路 alice = Circuit(3).cx[0, 1].h[0].m[0, 1] # 状態ベクトルとショットの両方を取得します vec, shot = alice.run(returns="statevector_and_shots", shots=1, initial=state) vec, shot
(array([0. +0.j , 0. +0.j ,
0. +0.j , 0. -0.38941834j,
0. +0.j , 0. +0.j ,
0. +0.j , 0.92106099+0.j ]),
Counter({'110': 1}))
Copy # Alice→Bobに測定結果を伝えます measured = shot.most_common()[0][0] measured
'110'
Copy # Bob側: 量子テレポーテーションの回路 bob = Circuit(3) if measured[0] == '1': bob.x[2] if measured[1] == '1': bob.z[2] # Aliceが測定した続きから、Bobが測定をします result = bob.run(initial=vec) result
array([ 0. +0.j , 0. +0.j ,
0. +0.j , 0.92106099+0.j ,
-0. +0.j , -0. +0.j ,
-0. +0.j , 0. +0.38941834j])
Bobに状態ベクトルが転送されました。これを確認するには、この状態ベクトルが、テレポーテーションした状態psi
とaliceが手元に持っている状態のクロネッカー積であることを見ればよいです。
Copy alice_state = Circuit(2) if measured[0] == '1': alice_state.x[0] if measured[1] == '1': alice_state.x[1] expect = np.kron(psi, alice_state.run()) expect
array([0. +0.j , 0. +0.j ,
0. +0.j , 0.92106099+0.j ,
0. +0.j , 0. +0.j ,
0. +0.j , 0. +0.38941834j])
Copy # 一致していることが分かります np.allclose(result, expect)
True
Copy
© 2024, blueqat Inc. All rights reserved