トフォリゲートとコントロールユニタリーゲートの実機実装について


はじめに

量子ゲートモデルにはさまざまなゲートがありますが、そのうちの幾つかは理想的なゲート回路になっていて、実機編実装はされていません。しかし教科書や参考書では容赦無く登場しますので、それらを見直していきたいと思います。


トフォリゲート

トフォリゲートは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])

何も起きてないのが確認できました。以上です。