IQPEの実機実行
これまでQPE,IQPEを色々勉強してきました。
Qiskitで量子位相推定を勉強する
Qiskitで反復量子位相推定を勉強する
Qiskitで反復量子位相推定(回路整理version)
Qiskitで反復量子位相推定(回路整理version)では、IQPEを実装したものの、reset,c_ifなどIBMQ実機ではサポートされていない処理があり実機実行できませんでした。
今回、この点を修正して実機実行まで持っていきました。
ただ、どうしても回路単体では出来ず、古典的なif文も使って回路を作っていくことにしました。
また、Qiskit 機能色々(TIPS)の内容も使っています。
スクリプト
# initialization
import matplotlib.pyplot as plt
import numpy as np
import math
# importing Qiskit
from qiskit import IBMQ, Aer
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, execute
from qiskit.tools.monitor import job_monitor
# import basic plot tools
from qiskit.visualization import plot_histogram
counts_list = []
psi = [0,1]
# psi = np.multiply([1,1],1/np.sqrt(2))
flag_sim = 0
# U = [1 0 ; 0 exp(pi/4)]
# eigen value is 2pi(0) for |0> , 2pi(0.001) for |1>
t = 3 # num of iteration
k = 3 # iteration
qpe = QuantumCircuit(2,1) # 1 bit for eigen state and 1 ancilla bit for phase kick back
qpe.initialize(psi,1)
qpe.h(0) # Hadamard for 1st ancilla bit
for i in range(2**(t-1)):
qpe.cu1(math.pi/4, 0, 1); # This is Controlled-U , controll-qubit is 0 (ancilla) , target-qubit is 1 (eigen)
qpe.h(0) # Hadamard for 1st ancilla bit
qpe.measure(0,0)
if flag_sim==1:
backend = Aer.get_backend('qasm_simulator')
shots = 1024
results = execute(qpe, backend=backend, shots=shots).result()
else:
backend = provider.get_backend('ibmqx2')
job = execute(qpe, backend, shots=1024)
job_monitor(job, interval = 2)
results = job.result()
counts = results.get_counts()
counts_list.append(counts)
print(counts)
j3 = int(counts.most_frequent(),2)
print('j3='+str(j3)+'\n')
k = 2 # iteration
qpe = QuantumCircuit(2,1) # 1 bit for eigen state and 1 ancilla bit for phase kick back
qpe.initialize(psi,1)
qpe.h(0) # Hadamard for 1st ancilla bit
if j3==1:
qpe.rz(-1*math.pi/2,0)
for i in range(2**(k-1)):
qpe.cu1(math.pi/4, 0, 1); # This is Controlled-U , controll-qubit is 0 (ancilla) , target-qubit is 1 (eigen)
qpe.h(0) # Hadamard for 1st ancilla bit
qpe.measure(0,0)
if flag_sim==1:
backend = Aer.get_backend('qasm_simulator')
shots = 1024
results = execute(qpe, backend=backend, shots=shots).result()
else:
backend = provider.get_backend('ibmqx2')
job = execute(qpe, backend, shots=1024)
job_monitor(job, interval = 2)
results = job.result()
counts = results.get_counts()
counts_list.append(counts)
print(counts)
j2 = int(counts.most_frequent(),2)
print('j2='+str(j2)+'\n')
k = 1 # iteration
qpe = QuantumCircuit(2,1) # 1 bit for eigen state and 1 ancilla bit for phase kick back
qpe.initialize(psi,1)
qpe.h(0) # Hadamard for 1st ancilla bit
if j3==1:
qpe.rz(-1*math.pi/4,0)
if j2==1:
qpe.rz(-1*math.pi/2,0)
for i in range(2**(k-1)):
qpe.cu1(math.pi/4, 0, 1); # This is Controlled-U , controll-qubit is 0 (ancilla) , target-qubit is 1 (eigen)
qpe.h(0) # Hadamard for 1st ancilla bit
qpe.measure(0,0)
if flag_sim==1:
backend = Aer.get_backend('qasm_simulator')
shots = 1024
results = execute(qpe, backend=backend, shots=shots).result()
else:
backend = provider.get_backend('ibmqx2')
job = execute(qpe, backend, shots=1024)
job_monitor(job, interval = 2)
results = job.result()
counts = results.get_counts()
counts_list.append(counts)
print(counts)
j1 = int(counts.most_frequent(),2)
print('j1='+str(j1)+'\n')
print('Phase = 2π*('+'0.'+str(j1)+str(j2)+str(j3)+')')
# 新規ウインドウ作成
fig = plt.figure(figsize=(20,4))
plt.subplots_adjust(wspace=0.4, hspace=0.6)
# flg全体をX*Yに分割し、plot位置に画像を配置する。
X = 1
Y = 3
ax1 = fig.add_subplot(X, Y, 3)
plot_histogram(counts_list[0], legend=['j 3'],ax=ax1)
ax2 = fig.add_subplot(X, Y, 2)
plot_histogram(counts_list[1], legend=['j 2'],ax=ax2)
ax3 = fig.add_subplot(X, Y, 1)
plot_histogram(counts_list[2], legend=['j 1'],ax=ax3)
解説
counts.most_frequent() で、最大頻度のビットを取り出しています。
ビットの値に応じて if でrzゲートを与えるかどうかを決めています。
出力結果(シミュレーター)
正しい解は $j_{1}j_{2}j_{3} = 001$ です。
出来ています。
出力(実機, ibmqx2)
雑音によるエラーはありますが、出来ています。
更に、QPEでの結果Qiskitで量子位相推定を勉強する と比べてみます。
明らかにIQPEのほうが良いですね。
QPEでは3桁を1つの回路で一気に読み出しますので、
- 回路が長い
- 補助量子ビットが3個必要 (IQPEは1個)
という点が劣位であったと考えられます。
結論
フルスクラッチでIQPEを実機実行できるものが書けた。
qiskit.aquaにはライブラリとしてIQPEがあるが、おそらく同じような手順ではないだろうか。