Nobisuke
Dekisugi
RAG
Privacy policy
2021/07/05 15:47
1
1
今回はQAOAについて確認します。量子ゲートで組合せ最適化問題を解きます。まずはblueqat cloudでの計算を確かめます。
https://blueqat.com/gyu-don/87fcb9ce-f5c2-4f9e-8697-191c8781d70b
Copy from bqcloud import load_api from bqcloud import Device from blueqat import Circuit import math #apiキーを読み込みます api = load_api()
Copy #回路を書いてみます。rxxゲートを使ってpi/2の角度をしてすることでもつれを作ることができます。 qc = Circuit().rxx(math.pi/2)[0,1]
Copy #まずはシミュレータで実行 qc.m[:].run(shots=100)
Counter({'00': 46, '11': 54})
Copy #次にIonQの実機で実行します。 qc = Circuit().rxx(math.pi/2)[0,1] task = api.execute(qc, Device.IonQDevice, 10)
Copy #タスクが処理されました print(task.status())
Status.QUEUED
Copy #結果を表示してみます result = task.wait(timeout=3600) if result: print(result.shots()) else: print("timeout")
Counter({'00': 5, '11': 5})
無事計算結果が出ました。では、IonQでQAOAをやってみます。
まずは簡単な式から、3つの頂点のmaxcut問題を考えてみます。
3つの頂点を考え、辺の重みをすべて1としてみます。
定式化はイジングモデルを考えます。ハミルトニアンという式を作ります。頂点に量子ビットを割り当て、それぞれの値が1もしくは-1を取るとします。
定式化は、
と置くことができます。Zの前の係数はそれぞれ辺の重みに対応しています。
次にもう一つ定式化を準備する必要があります。それが、解を探索するためのミキサーです。これは通常では一番簡単なXを利用します。
上記定式化においてもう一つ準備する必要があるのが、に対応した固有状態である重ね合わせ状態です。こちらは、アダマールゲートを適用することで作ることができます。
そして、量子状態を時間発展させます。時間発展させる式は、時間tに対して、ハミルトニアンを少しずつ入れ替える操作を行います。時間発展は、
かけるハミルトニアンは、上記の二つのハミルトニアンを入れ替える過程の、
で時間発展演算子を利用します。
トロッタ展開やらほにゃほにゃすると、QAOAを利用した回路は、p=1という1ステップで解く回路は、
|0> --H--RZZ(beta)-------------RZZ(beta)--RX(gamma)--
| |
|0> --H--RZZ(beta)--RZZ(beta)--|----------RX(gamma)--
| |
|0> --H-------------RZZ(beta)--RZZ(beta)--RX(gamma)--
こちらのbetaとgammaを最適化することで回転角を求めて実行することができます。 もともとblueqatにはQAOAを実行する機能があります。この回路のことをAnsatzと呼びます。
Copy from blueqat.pauli import Z from blueqat import vqe hamiltonian = Z[0]*Z[1] + Z[1]*Z[2] + Z[2]*Z[0] result = vqe.Vqe(vqe.QaoaAnsatz(hamiltonian, 1)).run() print(result.most_common(12))
(((1, 0, 0), 0.162033015432909), ((1, 1, 0), 0.162033015432909), ((0, 0, 1), 0.162033015432909), ((0, 1, 1), 0.162033015432909), ((0, 1, 0), 0.16203301543290893), ((1, 0, 1), 0.16203301543290893), ((0, 0, 0), 0.013900953701272978), ((1, 1, 1), 0.013900953701272978))
回路を確認する機能があります。
Copy result.circuit
Circuit(3).h[:].cx[0, 1].rz(-25.930489083659825)[1].cx[0, 1].cx[0, 2].rz(-25.930489083659825)[2].cx[0, 2].cx[1, 2].rz(-25.930489083659825)[2].cx[1, 2].rx(0.4578213663591716)[:]
rzzは以前はcx,rz,cxの組合せで書かれていました。こちらの回路の状態ベクトルを確認してみると、
Copy beta = -25.930489083659825 gamma = 0.4578213663591716 Circuit(3).h[:].cx[0, 1].rz(beta)[1].cx[0, 1].cx[0, 2].rz(beta)[2].cx[0, 2].cx[1, 2].rz(beta)[2].cx[1, 2].rx(gamma)[:].run()
array([-0.02214869+0.11580323j, 0.27513225-0.29382863j,
0.27513225-0.29382863j, 0.27513225-0.29382863j,
0.27513225-0.29382863j, 0.27513225-0.29382863j,
0.27513225-0.29382863j, -0.02214869+0.11580323j])
rzzで書き直したものと比較してみると、
Copy Circuit(3).h[:].rzz(beta)[0,1].rzz(beta)[0,2].rzz(beta)[1,2].rx(gamma)[:].run()
array([-0.02214869+0.11580323j, 0.27513225-0.29382863j,
0.27513225-0.29382863j, 0.27513225-0.29382863j,
0.27513225-0.29382863j, 0.27513225-0.29382863j,
0.27513225-0.29382863j, -0.02214869+0.11580323j])
同じですね。IonQは基本のゲートにrzzやrxxを利用するので、こちらのほうがqaoaが簡単にきれいに書けました。では、さっそく実機にかけてみます。
Copy task = api.execute(Circuit(3).h[:].rzz(beta)[0,1].rzz(beta)[0,2].rzz(beta)[1,2].rx(gamma)[:], Device.IonQDevice, 100)
Copy #タスクが処理されました print(task.status())
Status.QUEUED
Copy #結果を表示してみます result = task.wait(timeout=3600) if result: print(result.shots()) else: print("timeout")
Counter({'110': 19, '101': 19, '100': 18, '001': 16, '011': 13, '010': 12, '111': 2, '000': 1})
以上、IonQの実機でqaoaが実行できました。思ったよりも精度が高いです。
© 2024, blueqat Inc. All rights reserved