量子フーリエ変換を開発する手順 

## はじめに

量子フーリエ変換の行列は、古典フーリエ変換と同じです。
面倒なのは、この行列を量子ゲートに直す作業です。
今回、２量子ビットの量子フーリエ変換の行列をゲートに変換するソフトを作りましたので紹介します。

２量子ビットの量子フーリエ変換を行列で表記すると下記のようになります
![qgmzu02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/7f0e9185-f153-cdde-fd29-385917e0c13b.jpeg)

この行列を列ごとに表記すると下記のようになります。
![qgmzu03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/4955e575-fe29-c6d3-b364-3019e60430d6.jpeg)

行列と余弦波との関係を図で表すと、下記のようになります。
この図は周期の異なる余弦波を並べたもので、古典フーリエ変換で使っているものと同じです。
![qgmzu01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/7311fe34-b8dc-a2f7-02e0-7445e286d42f.jpeg)

**量子フーリエ変換が古典フーリエ変換よりも速い理由**

下記の行列計算を従来の方法でやると下記のステップを順番に実行する必要があります。
下の図で、古典計算では**A**の計算、**B**の計算、**C**の計算、**D**の計算を順番に行います。
量子計算では複数の平行宇宙に置かれた計算機により、**A**の計算、**B**の計算、**C**の計算、**D**の計算を同時に行います。
つまり、量子計算が速いのは並列処理によるものです。
![qgmzu04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/c1ee22c5-3689-20f8-e691-7fcc5278090e.jpeg)

### 量子ゲートメーカー</b>を使った量子ゲートの作り方

**量子ゲートメーカー**(フリーソフト)は**Vector**からダウンロードしてください。
 [量子ゲートメーカーの説明ページ](https://www.vector.co.jp/soft/winnt/edu/se526677.html)

初は分かりにくいと思いますが、とりあえず説明通りに実行してみてください。

**初めに、制御ゲートだけ使い量子フーリエ変換ゲートを作ります**

「**ターゲット行列をセット**」ボタンを押します。
![qgmzu05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/8375da5f-34a4-f283-d721-0ca62b54de98.jpeg)

「**QFTセット**」ボタンを押し、「**決定して閉じる**」ボタンを押します。
![qgmzu06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/02536d01-38c0-9723-d62a-ac51fdcc8d50.jpeg)

行列の**３**行**１**列をクリックます。
![qgmzu07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/c2fc4904-bde3-60d3-c8b2-603b2d9a3279.jpeg)

「**ゲート選択(L)**」ボタンを押します。
![qgmzu08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/7637b0b0-5a87-d67c-7817-d9f53b9b3962.jpeg)

下記のような表示になります。
図の(**1**)は現時点のターゲット行列を表します。
赤色のセルの数値は**0**以外。
青色のセルは**0**を表します。
図(**1**)の実際の行列は図(**4**)です。
図(**2**)は選択された量子ゲートを表します。
図(**5**)には、この量子ゲートの逆行列が表示されます。
図(**3**)には、現時点で行った処理の一つ前のターゲット行列が表示されます。
行列の関係は、図(**5**)×図(**4**)＝図(**3**)になります。
![qgmzu10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/cc0712af-c3f7-4d44-a0d4-489febb18554.jpeg)
![qgmzu09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/8d195958-5dbc-ac0f-ee28-1942f13bc712.jpeg)

上記の操作に続けて、下記の図を見て番号順にクリックします。
![qgmzu11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/ca9a0473-78d1-1961-ffd7-6575052a5761.jpeg)

「**最終ゲート**」ボタンを押します。
![qgmzu12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/c0e7c128-098a-b40a-1b8b-cb81996e1e4d.jpeg)

「**実行**」ボタンを押します。
![qgmzu13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/0580f306-7214-9131-dcca-c859cc5de129.jpeg)

ターゲット行列を分解した全ゲートが表示されます。
![qgmzu14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/e7e7c28f-1461-b7cc-6c3a-eef07912e1a8.jpeg)

下記に全ゲートを表示しました。
右側は具体的なゲートです。
![qgmzu16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/54c6c0e5-3b8d-eb54-4183-d9a0009f5296.jpeg)

ゲートを逆方向から連結していきます。
![qgmzu17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/0b00f58d-5ebd-27ff-46e7-2a538957b1da.jpeg)

**qiskit**で記述すると下記のようになります。

qc = QuantumCircuit(3,3)

qc.ccx(0,1,2)
----------------------- 7
qc.cu1(1/2＊np.pi,0,1)
----------------------- 6
qc.cx(0,1)
qc.ch(0,1)
qc.cx(0,1)
qc.cu1(-1/2＊np.pi,0,1)
qc.cz(2,1)
qc.cx(2,1)
----------------------- 5
qc.ch(1,0)
qc.cry(0.35,1,0)
----------------------- 4
qc.cx(0,1)
qc.cz(0,1)
----------------------- 3
qc.x(0)
qc.ch(0,1)
qc.cry(-0.52,0,1)
qc.x(0)
----------------------- 2
qc.x(1)
qc.ch(1,0)
qc.cry(-0.35,1,0)
qc.x(1)
----------------------- 1
qc.cx(0,1)
----------------------- 0
qc.x(1)
qc.ch(1,0)
qc.x(1)

結果
![qgmzu18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/40990806-3dfd-a9cd-db99-2dc44de4bb55.jpeg)

計算結果は、行列の計算と一致します。
![qgmzu19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/1a9bb953-3552-020b-cfe3-bd4df594a9ca.jpeg)

以上のように、制御ゲート**だけ**使って量子フーリエ変換ゲートを作ると、回路が複雑になります。

**次に、単一ゲートと制御ゲートを組み合わせて量子フーリエ変換ゲートを作ります**

「**ターゲット行列をセット**」ボタンを押します。
![qgmzu05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/226f64d9-eedb-202c-440c-efb19541462b.jpeg)

「**QFTセット**」ボタンを押し、「**決定して閉じる**」ボタンを押します。
![qgmzu06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/98b8f5d6-da26-438c-8fc2-669de9cb23ce.jpeg)

行列の**３**行**１**列をクリックます。
![qgmzu07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/0e97576d-160d-0a05-103a-e57aeabe7eb0.jpeg)

「**ゲート選択(L)**」ボタンを押します。
![qgmzu08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/90e47c92-25ae-531c-7689-5108c0c0dd95.jpeg)

「**単一ゲートにする**」ボタンを押します。
![qgmzu20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/d7291847-9061-ce67-fe42-cd69e07b4fc8.jpeg)

ゲート行列を見ると、**q0**の単一アダマールゲートだと分かります。
ターゲット行列を見ると、**q1**の単一アダマールゲートに回転ゲートを組み合わせたものだと分かります。
![qgmzu21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/bcb3fffa-6f5e-9a26-a859-791cbbd8a8af.jpeg)

「**最終ゲート**」ボタンを押します。
「**最終ゲート**」では、制御回転ゲートを作ります。
エディット出来るのは**４**行**４**列セルだけです。
デフォルトで「**-i**」と書かれているので、そのまま「**実行**」ボタンを押します。
これで、アダマールゲートと回転ゲートを分離することができます。
![qgmzu22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/ff1f971c-54c2-5a92-b596-8d28a5535947.jpeg)

完成画面
![qgmzu23.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/99f4555f-d13a-4c10-d7f1-c3dd3f41ae02.jpeg)

下記に全ゲートを表示しました。
右側は具体的なゲートです。
![qgmzu24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/51a7c4aa-dc17-ec45-1cfb-6404e376ba62.jpeg)

ゲートを逆方向から連結していきます。
![qgmzu25.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/439839ba-1a46-41ef-9592-ffd4f0f08f64.jpeg)

**qiskit**で記述すると下記のようになります。

qc = QuantumCircuit(2,2)

qc.h(1)
qc.cu1(1/2＊np.pi,0,1)
qc.h(0)

結果
![qgmzu26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/7fc19590-e729-19ef-5ad6-b69d2e06bb59.jpeg)

計算結果は、行列の計算と一致します。
![qgmzu19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/19e5ede1-9455-2c0f-d22e-02a862e29cba.jpeg)

**次に、逆量子フーリエ変換のゲートを作ります**

量子フーリエ変換の逆行列が逆量子フーリエ変換になります。
下記のように、**QFT**の出力値を**IQFT**に入力すると、**IQFT**の出力値は**QFT**の入力値になります。
![qgmzu27.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/36bafd11-b25a-1541-36ba-003fc2f7ca27.jpeg)

この時点で、逆量子フーリエ変換のゲートは分かりますが、量子ゲートメーカーを使って逆量子フーリエ変換のゲートを作ってみます。

「**ターゲット行列をセット**」ボタンを押します。
![qgmzu05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/0dcde4a9-ede9-c5a7-4e05-d4689a716468.jpeg)

「**IQFTセット**」ボタンを押し、「**決定して閉じる**」ボタンを押します。
![qgmzu28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/0deb127a-5c23-970a-e725-4624418dff28.jpeg)

行列の**２**行**１**列をクリックます。
![qgmzu29.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/d472f9f9-44b3-e475-fb14-713dc01d038c.jpeg)

「**ゲート選択(L)**」ボタンを押します。
![qgmzu30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/712f9b04-9e6c-776b-17eb-d2b8a4ad8ac6.jpeg)

「**単一ゲートにする**」ボタンを押します。
![qgmzu31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/ba6fec09-2d98-2637-fcf7-ed3b5a5718be.jpeg)

ゲート行列を見ると、**q1**の単一アダマールゲートだと分かります。
ターゲット行列を見ると、**q0**の単一アダマールゲートに回転ゲートを組み合わせたものだと分かります。
![qgmzu32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/ed67662a-93c1-ec5e-68e8-edf01b9bf7ac.jpeg)

「**最終ゲート**」ボタンを押します。
「**最終ゲート**」では、制御回転ゲートを作ります。
エディット出来るのは４行４列セルだけです。
「**-i**」を「**i**」に書き換えて「**実行**」ボタンを押します。
これで、アダマールゲートと回転ゲートを分離することができます。
![qgmzu33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/82ffd78c-32bd-e461-ed67-47a67595064c.jpeg)

完成画面
![qgmzu34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/9142028d-57e4-806e-31d4-25a325b1f645.jpeg)

下記に全ゲートを表示しました。
右側は具体的なゲートです。
![qgmzu35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/ff1c73ca-accd-59eb-cac4-bfa3f8d1175f.jpeg)

ゲートを逆方向から連結していきます。
![qgmzu36.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/6cd7d795-7a58-215c-cc8e-a0467d406a18.jpeg)

**QFT**と**IQFT**を連結すると、入力値と出力値が一致します。

**QFT**と**IQFT**を連結した回路図。
![qgmzu38.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/7c1e1bad-5378-a696-6367-2a6a8d83ac44.jpeg)

**qiskit**で記述すると下記のようになります。

qc = QuantumCircuit(2,2)

**QFT**
qc.h(1)
qc.cu1(1/2＊np.pi,0,1)
qc.h(0)

**IQFT**
qc.h(0)
qc.cu1(-1/2＊np.pi,0,1)
qc.h(1)

結果
![qgmzu37.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556981/bf8aa0b6-cea2-e05e-0af8-a5b4819f2928.jpeg)