量子ゲートモデルにはさまざまなゲートがありますが、そのうちの幾つかは理想的なゲート回路になっていて、実機編実装はされていません。しかし教科書や参考書では容赦無く登場しますので、それらを見直していきたいと思います。
トフォリゲートは3量子ビットゲートで、よく教科書ででます。CCNOTゲートとも呼ばれ、コントロールゲートとターゲットゲートからなります。コントロールゲートを*、ターゲットゲートを@とすると、こんな感じです。コントロールゲートが2つあり、両方が1のときだけ、ターゲットゲートにXゲートが適用されます。XゲートはNOTゲートとも呼ばれ、1のビットを0に、0のビットを1にします。
--*--
|
--*--
|
--@--
こちらのトフォリゲートは通常実装されていませんので、1量子ビットと2量子ビットの組み合わせで表現される必要があります。回路は下記のようになり、HとTとT†(回路上ではダガーを’にしています。)とCNOTで表現されます。
--------*--------*---*-T--*--
---*----|---*----|-T-@-T'-@--
-H-@-T'-@-T-@-T'-@-T-H---------
Blueqatコードでの表現は、
from blueqat import Circuit
import math
c = Circuit()
c.h[2].cx[1,2].rz(-math.pi/4)[2].cx[0,2].rz(math.pi/4)[2].cx[1,2].rz(-math.pi/4)[2].cx[0,2].rz(-math.pi/4)[1].rz(math.pi/4)[2].cx[0,1].h[2].rz(math.pi/4)[0].rz(-math.pi/4)[1].cx[0,1].m[0].m[1].m[2].run()
array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
となります。TゲートはRz回転、T†ゲートはRzの逆回転で表現できます。CNOT = CXです。
コントロールユニタリーゲートはコントロールゲートが1のときにターゲットビットを操作するというゲートの総称です。一番有名なのがCNOTゲート/CXゲートで、コントロールゲートが1のときにターゲットビットにXゲートを作用させます。
---*---
|
---X---
こちらに、Xゲートではなくて任意のゲート操作を適用したい(特に回転ゲート)というのをControlled Unitaryとしてよく教科書ででてきます。
---*---
|
---U---
こんな感じでしょうか。ただ、このようなゲートはありませんので、通常の1量子ビットゲートと2量子ビットゲートのCNOTを活用して作る必要があります。具体例としてコントロールCZゲートを作ってみます。
---*---
|
---Z---
CZゲートはZ軸回り回転ですが、よく考えるとCXから作れそうです。CXゲートはあるので、それをX/Zの間45度回転すれば軸を入れ替えられそうです。Hゲートを使って、
---*---
|
-H-X-H-
こちらで実現できそうです。確かめてみます。
from blueqat import Circuit
Circuit().h[1].h[1].cx[0,1].h[1].h[1].run()
array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
Circuit().x[0].h[1].h[1].cx[0,1].h[1].h[1].run()
array([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j])
きちんと0番目の量子ビットが1の時だけ、Z軸周りで反転しているのが確認できました。
次にCRzゲートを見てみたいと思います。CRzはコントロールゲートが1の時だけ、Z軸周りに任意回転をします。このゲートはABC=I , AXBXC=Uというルールを使いますが、答えから見てみると、
----------------*-----------------*--------
| |
--Rz(lambda/2)--X--Rz(-lambda/2)--X--------
こういうものを適用します。コントロールゲートが0の時はCXは何もせずにRz(lambda/2)回転からのRz(-lambda/2)で元に戻ります。一方、コントロールゲートが1の時にはRz(lambda/2)で回転した軸がX軸反転して、さらにRz(lambda/2)回転し、再度X軸反転して戻ります。実際に確かめてみます。
重ね合わせ状態から、普通にRz(lambda)した時の状態ベクトルは、
Circuit().x[0].h[1].rz(math.pi/2)[1].h[1].run()
array([0. +0.j , 0.70710678+0.j ,
0. +0.j , 0. -0.70710678j])
一方、CRzゲートを作って同じ状態を作ると、
Circuit().x[0].h[1].rz(math.pi/4)[1].cx[0,1].rz(-math.pi/4)[1].cx[0,1].h[1].run()
array([0. +0.j , 0.70710678+0.j ,
0. +0.j , 0. -0.70710678j])
同じ状態ベクトルになり、きちんと回転しているのが確認できました。コントロールゲートが0の場合には、
Circuit().h[1].rz(math.pi/4)[1].cx[0,1].rz(-math.pi/4)[1].cx[0,1].h[1].run()
array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
何も起きてないのが確認できました。以上です。
Tweetinfo@mdrft.com