@yuichirominato 2018.11.14更新 46views

Blueqatで汎用型量子ゲートの多量子ビットの一般的な加算器と減算器を実装する

Blueqat 加算 量子ゲート 量子コンピュータ

はじめに

汎用型のSDKのBlueqatで汎用型量子ゲートマシンの多量子ビットの加算器と減算器をしてみたいと思います。

2進数での桁上がり

量子ビットはそれぞれ0と1をとるバイナリ値と呼ばれるものです。こちらを利用して加算(足し算)を行うには主に論理ゲートを使って、桁上がりなどの実現が主になります。

量子ビットを使った数字の表現

10進数は2進数で表現する必要があります。量子ビットを利用して、たとえば、15は
$q_0*2^0+q_1*2^1+q_2*2^2+q_3*2^3$
のとき、$q_0=q_1=q_2=q_3=1$とすれば平気です。

参考

こちらを参考にします。とても良い記事です。
「量子コンピュータ(シミュレータ)でモジュール化可能な加算器を作る」
https://qiita.com/converghub/items/c61b2b91b311cf730e18

まず2量子ビット同士の加算

まずは余分な量子ビットを使った2量子ビットの加算をみていきます。
$\mid a,b,0 \rangle = \mid a,b,a+b \rangle$を実現します。
$a=a_0*2^0+a_1*2^1$と$b=b_0*2^0+b_1*2^1$と$c=c_0*2^0+c_1*2^1+c_2*2^2$を用意します。
a+bをする際に答えのcは1量子ビット増やしておく必要があります。


a0 ----------------
a1 ----------------
b0 ----------------
b1 ----------------
c0 ----------------
c1 ----------------
c2 ----------------

こんな感じで回路をスタートさせます。まずは桁上がりを全て実装してみます。まずはa0,b0の桁上がりをc1に反映します。次にa1,b1,c1の桁上がりを3つのCCNOTを使って反映します。


a0 -*--------------
a1 -|-*-*----------
b0 -*-|-|----------
b1 -|-*-|-*--------
c0 -|-|-|-|--------
c1 -+-|-*-*--------
c2 ---+-+-+--------

そして最後に各くらいの数字を揃えます。


a0 -*-----------*------
a1 -|-*-*---*---|------
b0 -*-|-|---|---|-*----
b1 -|-*-|-*-|-*-|-|----
c0 -|-|-|-|-|-|-+-+----
c1 -+-|-*-*-+-+--------
c2 ---+-+-+------------

これでできました。あとはa0,a1,b0,b1に数字を入れていけば任意の加算ができます。任意の数字はXゲートで入れていきます。
0+0,0+1,1+0,1+1,0+2,2+0,1+2,2+1,2+2,2+3,3+2,3+3あたりまでできます。


from blueqat import Circuit 
import math  

tof1 = Circuit().h[5].cx[2,5].rz(-math.pi/4)[5].cx[0,5].rz(math.pi/4)[5].cx[2,5].rz(-math.pi/4)[5].cx[0,5].rz(-math.pi/4)[2].rz(math.pi/4)[5].cx[0,2].h[5].rz(math.pi/4)[0].rz(-math.pi/4)[2].cx[0,2]

tof2 = Circuit().h[6].cx[3,6].rz(-math.pi/4)[6].cx[1,6].rz(math.pi/4)[6].cx[3,6].rz(-math.pi/4)[6].cx[1,6].rz(-math.pi/4)[3].rz(math.pi/4)[6].cx[1,3].h[6].rz(math.pi/4)[1].rz(-math.pi/4)[3].cx[1,3]

tof3 = Circuit().h[6].cx[5,6].rz(-math.pi/4)[6].cx[1,6].rz(math.pi/4)[6].cx[5,6].rz(-math.pi/4)[6].cx[1,6].rz(-math.pi/4)[5].rz(math.pi/4)[6].cx[1,5].h[6].rz(math.pi/4)[1].rz(-math.pi/4)[5].cx[1,5]

tof4 = Circuit().h[6].cx[5,6].rz(-math.pi/4)[6].cx[3,6].rz(math.pi/4)[6].cx[5,6].rz(-math.pi/4)[6].cx[3,6].rz(-math.pi/4)[5].rz(math.pi/4)[6].cx[3,5].h[6].rz(math.pi/4)[3].rz(-math.pi/4)[5].cx[3,5]

after = Circuit().cx[1,5].cx[3,5].cx[0,4].cx[2,4]
measure = Circuit().m[:]

c01 = Circuit().x[2]                                                                                                                 
c10 = Circuit().x[0]                                                                                                                 
c11 = Circuit().x[2].x[0]                                                                                                            
c02 = Circuit().x[3]                                                                                                                 
c20 = Circuit().x[1]                                                                                                                 
c12 = Circuit().x[0].x[3]                                                                                                  
c21 = Circuit().x[1].x[2]                                                                                                  
c22 = Circuit().x[1].x[3]                                                                                                  
c23 = Circuit().x[1].x[2].x[3]                                                                                             
c32 = Circuit().x[0].x[1].x[3]                                                                                             
c33 = Circuit().x[0].x[1].x[2].x[3] 


e = c01 + tof1 + tof2 + tof3 + tof4 + after + measure
e.run()
e.last_result()
(0, 0, 1, 0, 1, 0, 0)


e = c10 + tof1 + tof2 + tof3 + after + measure
e.run()
e.last_result()
(1, 0, 0, 0, 1, 0, 0)


e = c11 + tof1 + tof2 + tof3 + after + measure
e.run()
e.last_result()
(1, 0, 1, 0, 0, 1, 0)


e = c12 + tof1 + tof2 + tof3 + after + measure
e.run()
e.last_result()
(1, 0, 0, 1, 1, 1, 0)


e = c21 + tof1 + tof2 + tof3 + after + measure
e.run()
e.last_result()
(0, 1, 1, 0, 1, 1, 0)


e = c22 + tof1 + tof2 + tof3 + after + measure
e.run()
e.last_result()
(0, 1, 0, 1, 0, 0, 1)


e = c23 + tof1 + tof2 + tof3 + after + measure 
e.run()
e.last_result()
(0, 1, 1, 1, 1, 0, 1)


e = c32 + tof1 + tof2 + tof3 + after + measure
e.run()
e.last_result()
(1, 1, 0, 1, 1, 0, 1)


e = c33 + tof1 + tof2 + tof3 + after + measure
e.run()
e.last_result()
(1, 1, 1, 1, 0, 1, 1)

減算器について

減算器は加算器を逆にすればいいようです。ただ、実際にどのように動作するのかわからないといけないので、確認してみます。
先ほどの回路を全く逆にしてみます。


a0 ---*-----------*----
a1 ---|---*---*-*-|----
b0 -*-|---|---|-|-*----
b1 -|-|-*-|-*-|-*-|----
c0 -+-+-|-|-|-|-|-|----
c1 -----+-+-*-*-|-+----
c2 ---------+-+-+------

コードで書くと、CNOTが先に来て、CCNOT群が後に来ます。測定して結果を見てみると、ここで具体例で3-3をしてみます。


after2 = Circuit().cx[2,4].cx[0,4].cx[3,5].cx[1,5]
cc303 = Circuit().x[0].x[1].x[4].x[5]                                                                                                             
e = cc303 + after2 + tof4 + tof3 + tof2 + tof1 + measure  
e.run()
e.last_result()
(1, 1, 0, 0, 0, 0, 0)

c-aをしていますが、c-aの値がcに上書きされて出てきています。同様にa+b=cでc-bをしてみます。


cc013 = Circuit().x[2].x[4].x[5]
e = cc013 + after2 + tof4 + tof3 + tof2 + tof1 + measure
e.run()
e.last_result()
(0, 0, 1, 0, 0, 1, 0)

これもcが上書きされて答えの2がでました。最後にcに3をaとbに1をセットしてみます。


cc113 = Circuit().x[0].x[2].x[4].x[5]                                                                                                             
e = cc113 + after2 + tof4 + tof3 + tof2 + tof1 + measure
e.last_result()                                                                                                                                   
(1, 0, 1, 0, 1, 0, 0) 

cに3-1-1がセットされました。

ということで、回路の工夫がまだできますが、まずは基本的な加算と減算をみました。基本的には上記もしくは上記の改造をすることで、任意の桁数の二進数の数字の加算ができます。トフォリゲートを駆使して0の位から大きな位に計算を進め、再度大きな位から0の位に戻ってCNOTを活用することでできるようです。

あわせて読みたい

SERVICE

汎用量子コンピュータ向けアプリケーション開発SDK

詳しく見る Githubで入手する(無料)

汎用量子コンピュータ向け高速シミュレータ

詳しく見る

量子コンピュータ向けクラウドサービス(準備中)

詳しく見る

イジングマシン向けアプリケーション開発SDK

詳しく見る Githubで入手する(無料)

COMMUNITY

量子コンピュータのことを学びたい、仕事としたいなどの情報交換の場を設け、コミュニティの形成を進めています。オフラインの勉強会と、オンラインのチャットコミュニティの2種類あります。オフラインのConnpassは1400名、オンラインのSlackは880名を超える参加があります。どちらも無料ですのでお気軽にご参加ください。

CONNPASS SLACK

CONTACT

弊社あての連絡はinfo@mdrft.comより用件を明記の上、メールで連絡を頂けますと幸いです。

ブログトップに戻る

Recent Posts