量子コンピューティング

量子コンピュータでの計算をシミュレータ(qiskit)を使って説明しています。言語は Python です。

Python で qiskit を使うには、とりあえずは Anaconda を入れて pip install qiskit すれば O.K. 

とはいえ一からプログラムを書き下すのは大変だと思うので、簡単な例(ダウンロードダウンロード)を用意しておきました。

応用(量子アニーリング)については サブページ で説明しています。何個かのコードを サブページ で公開しています。

基礎的な話は 講義テキスト にまとめてあるので、そちらを参照してみてください。

さて qiskit は IBM が用意しているユニバーサルな(ゲート)形式の量子コンピュータのシミュレータです。

他の形式には量子アニーリング(これは機構の根幹にイジング模型が使われています)を用いたものがあります。

もちろん、実機を web 経由で Job を投げて動かすこともできます(アカウントを作る必要がありますが)。

実機というと驚く人もいますが、まだ商用として販売されていないだけで研究用の実機が実際にあります。

右の画像をクリックすると IBM のページに飛びますのでいろいろ読んでみてください。


量子コンピュータでの計算では、量子回路を組んで計算していきます。

ここではイジング模型の計算を例にして具体的な計算過程を見ていきましょう。


まず古典コンピュータでは計算の最小の単位として bit があります。

コンピュータはスイッチ(on/off)の集合とも言え、情報は 0 と 1 の集合として記述されます。

一方の量子コンピュータでは、量子重ね合わせ状態を利用して情報を記述します。

そして、最後に”測定”を行い確率的に計算結果を見出します。つまり、


が qubit と呼ばれる計算の最小の単位となります。

ちなみにαとβ は複素数で、αα*+ββ*=1 (絶対の2乗の和が 1)を満たします。


さてイジング模型を量子コンピューターに載せてみましょう。

特にイジング模型のスピンは2方向しかとらないため、量子計算とはとても相性が良く計算しやすいです。

以下の内容は Quantum Native Dojo の内容を参考にしています。

ちなみに考えるイジング模型は横磁場イジング模型と呼ばれるものです(量子イジング模型とも)。

(横磁場の無い場合で基底状態を時間発展で求めるは意外と難しいため。ここ 参照)


以下では適当な状態を時間発展させるコードを書いてみましょう。

まず、回路を設定するため、

q  = QuantumRegister(n, "q")    ← 量子レジスター

c  = ClassicalRegister(n, "c")  ← 古典レジスター

qc = QuantumCircuit(q, c)       ← 量子と古典レジスターで計算のための回路を用意

とします。講義で習った(と思いますが)論理演算と似ていますね。

実際、計算の根幹に量子力学を使っている事が違うくらいです。

q が qubit を意味しているので、試しに0番目のものを重ね合わせ状態にしてみましょう。

具体的には、

qc.h(q[0])

で、h は Hadamard gateを意味します(Hadamard  gate は基本ゲートの一つ)。


さて単純に時間発展させる事は難しいので、時間発展演算子を鈴木-トロッター分解しましょう。

つまり、

unit_ZZ(qc, q[k], q[(k+1)%(n)], delta)

unit_X (qc, q[k], h*delta)

を繰り返し演算させ、時間発展(ユニタリー発展)させます。

これは、単純に時間発展させようとすると 2^n の行列が必要となることに起因します(n は qubit の数)。

つまりこの分解をしないと計算がとても難しくなるということです。

delta は時間の刻み幅で、量子回路はそれぞれ、

def unit_ZZ(qc, q0, q1, k):

    qc.cx( q0, q1)

    qc.rz(2*k, q1)

    qc.cx( q0, q1)


def unit_X(qc, q0, h):

    qc.rx(2*h, q0)

と定義されています。これを input の状態に作用させて分配関数を計算していくわけですね。

cx や rz、rx がどのようなゲートかは qiskit のページを確認して下さい(翻訳ページだと例えば ここ)。


さて、状態をユニタリー発展させていき最後に "観測" を行って終状態を確定(古典的に)させます。

具体的には下のコードの qc.measure(q[j], c[j]) の部分です。

もちろん量子計算なので全く同じ様に計算しても、最後結果は一意ではなく分布をなします。

そのため、shot数に対する統計和を取る必要があります。


以上の事をプログラムしてみましょう。

単純な一次元イジング模型は面白くないので、横磁場まで入れたイジング模型を考えます。

実際のコードでは、まず必要なライブラリをインポートしましょう:

import math

import numpy as np

import matplotlib.pyplot as plt

import matplotlib as mpl

import time

from tqdm import tqdm

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit

from qiskit import BasicAer, execute

from qiskit.tools.visualization import plot_histogram

次に状態を勘定する際に必要なルーチンを書いておきます。

以下は(digit_sum 部分)は少しわかりにくいので、測定のところまで理解した後に読んでください):

def digit_sum(n):

    digit_str = str(n)

    sum = 0

    for i in range(len(digit_str)):

        sum += int(digit_str[i])

    return sum

イジング模型を計算する際に必要なイジングゲートを定義します:

def unit_ZZ(qc, q0, q1, k):

    qc.cx( q0, q1)

    qc.rz(2*k, q1)

    qc.cx( q0, q1)


def unit_X(qc, q0, h):

    qc.rx(2*h, q0)

計算で必要な格子のサイト数や時間の刻み幅などを定義します:

n  = 6

nt = 100

x_time = 3.0

delta = x_time/nt

h = 3.0

試しにサイト数を6、時間発展の刻みを 100 にしています。

実際に計算する部分です:

shots = 200000

backend = BasicAer.get_backend("qasm_simulator")


x = []; y = []


for i in tqdm(range(1,nt+1)):

    x.append(delta*i)

    

    q  = QuantumRegister(n, "q")

    c  = ClassicalRegister(n, "c")

    qc = QuantumCircuit(q, c)


    for j in range(1,i+1):

        for k in range(n):

            unit_ZZ(qc, q[k], q[(k+1)%(n)], delta)

            unit_X (qc, q[k], h*delta)

        

    for j in range(n):

        qc.measure(q[j], c[j])        

    job = execute(qc, backend=backend, shots=shots)

    result = job.result()

    counts = result.get_counts()


    M = 0

    for digit, count in counts.items():

        M += (1-2*digit_sum(digit)/n)*count/shots

    y.append(M)

    time.sleep(0.1)

    

plt.plot(x,y, "-")

plt.show()

となります。(注意:n 個の qubit を用意したいので、(n, "q") という書き方を上ではしています)

意外と短いですね。

実際に動かしながら各部分がどの様な意味を持っているのか考えてみてください。


ちなみに上記コードは最初 |000000> の状態から始め、どの様に時間発展していくかを計算してプロットします。

実行すると、

という結果がえられます。横軸が時間、縦軸がスピンの空間平均値です。

具体的には1という値から出発してそれがある値へ収束していっている事が見て取れます。

(空間上のすべてのイジングスピンが上向きにそろった状態からランダムな状態へ収束している)


上記の内容に加えて非ユニタリー発展まで考えると、イジング模型の分配関数を計算できます。

ただこれは色々と難しいので 論文へのリンク を張って終わりにしましょう。

興味があればプログラムしてみてください。

古典イジング模型の基底状態(エネルギー最低状態)の計算は少し工夫が必要です(ここ 参照)


量子回路は古典回路とは色々作法が違うので混乱すると思いますが、とりあえずはサンプルコードで遊んでみましょう。

IBM Q のページ



Quasntum Native Dojo のページ


qisikit ではなく Qulacs が使われています