進捗のようなもの

やったこと書きます

Qiskitで量子フーリエ変換(QFT)やってみた

はじめに

IBM Quantum Challenge 2019に参加してからもっと量子コンピュータを学びたいと思い、最近はQuantum Native Dojoで勉強しています!!

dojo.qulacs.org

量子状態の理論を復習しつつ、量子アルゴリズムを理解できるので自分にとても合っているページです。
今回は第2章に出てくる量子フーリエ変換(Quantum Fourier Transform, QFT)をQiskitで実装してきます。


\def\bra#1{\mathinner{\left\langle{#1}\right|}}
\def\ket#1{\mathinner{\left|{#1}\right\rangle}}
\def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}

量子フーリエ変換とは

簡単に言うと、信号処理で用いられてる離散フーリエ変換量子ビットに適用したものです。
数式を用いた理論の説明は、下記を参考にしてみてください。ここでは、説明しません。

Quantum Native Dojo 2-3
dojo.qulacs.org

慶応の量子コンピュータの講義も参考になりました。
www.youtube.com

Qiskitでの実装

3qubitで実装してきます。
 \ket{0} \ket{0}+\ket{2}+\ket{4}+\ket{6}を入力した場合、QFTの出力はそれぞれ次のようになります。

 \ket{0} \xrightarrow{QFT} \ket{0}+\ket{1}+\ket{2}+\ket{3}+\ket{4}+\ket{5}+\ket{6}+\ket{7}
 \ket{0}+\ket{2}+\ket{4}+\ket{6} \xrightarrow{QFT} \ket{0}+\ket{4}
※係数は無視

これを量子ビットに適用するため、2進数に書き直すと下記のようになります。

 \ket{000} \xrightarrow{QFT} \ket{000}+\ket{001}+\ket{010}+\ket{011}+\ket{100}+\ket{101}+\ket{110}+\ket{111}
 \ket{000}+\ket{010}+\ket{100}+\ket{110} \xrightarrow{QFT} \ket{000}+\ket{100}

入力 \ket{000} の場合
#パッケージのインポート
import numpy as np

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit import execute,Aer
from qiskit.tools.monitor import job_monitor
from qiskit import IBMQ
from qiskit.providers.ibmq import least_busy
from qiskit.visualization import plot_histogram

# IBMQを使用する
IBMQ.load_account()

#QFT回路の実装
q = QuantumRegister(3)
c = ClassicalRegister(3)
qc = QuantumCircuit(q,c)

qc.h(q[0])
qc.cu1(1/2*np.pi,q[1],q[0])
qc.cu1(1/4*np.pi,q[2],q[0])

qc.h(q[1])
qc.cu1(1/2*np.pi,q[2],q[1])

qc.h(q[2])

qc.barrier()

qc.measure(q,c)

qc.draw(output='mpl')

f:id:SJSY:20191202225218p:plain

# IBMQのシミュレータで実行
provider = IBMQ.get_provider(group='open')
backend = provider.get_backend('ibmq_qasm_simulator')
job = execute(qc, backend=backend, shots=8000, seed_simulator=0, backend_options={"fusion_enable":True})
result = job.result()
count = result.get_counts()

plot_histogram(count)

f:id:SJSY:20191202225306p:plain
 \ket{000}+\ket{001}+\ket{010}+\ket{011}+\ket{100}+\ket{101}+\ket{110}+\ket{111}
が出力されて、QFTが実装できました!!!

# 量子コンピュータ実機でも実行
provider = IBMQ.get_provider(group='open')
backend_lb = least_busy(provider.backends(simulator=False, operational=True))
print("Least busy backend: ", backend_lb)

backend = backend_lb
shots = 8000
job_exp = execute(qc, backend=backend, shots=shots)

job_monitor(job_exp, interval = 2)
results = job_exp.result()
plot_histogram(results.get_counts(qc))

f:id:SJSY:20191202225652p:plain
エラーやノイズによって?確率にばらつきはありますが、しっかり実行できてます!

入力 \ket{000}+\ket{010}+\ket{100}+\ket{110} の場合
q = QuantumRegister(3)
c = ClassicalRegister(3)
qc = QuantumCircuit(q,c)

# 入力の用意
qc.h(q[0])
qc.h(q[1])

qc.barrier()

# QFT
qc.h(q[0])

qc.cu1(1/2*np.pi,q[1],q[0])
qc.cu1(1/4*np.pi,q[2],q[0])

qc.h(q[1])
qc.cu1(1/2*np.pi,q[2],q[1])

qc.h(q[2])

qc.barrier()

qc.measure(q,c)

qc.draw(output='mpl')

f:id:SJSY:20191202224926p:plain

# IBMQシミュレータで実行
provider = IBMQ.get_provider(group='open')
backend = provider.get_backend('ibmq_qasm_simulator')
job = execute(qc, backend=backend, shots=8000, seed_simulator=0, backend_options={"fusion_enable":True})
result = job.result()
count = result.get_counts()

plot_histogram(count)

f:id:SJSY:20191202225032p:plain
 \ket{000}+\ket{100}が出力されました!

# 量子コンピュータ実機でも実行
provider = IBMQ.get_provider(group='open')
backend_lb = least_busy(provider.backends(simulator=False, operational=True))
print("Least busy backend: ", backend_lb)

backend = backend_lb
shots = 8000
job_exp = execute(qc, backend=backend, shots=shots)

job_monitor(job_exp, interval = 2)
results = job_exp.result()
plot_histogram(results.get_counts(qc))

f:id:SJSY:20191202225117p:plain
3qubitのQFTは実装できましたー!