IBM Quantum ExperienceとBlueqat で基本的な量子ゲートを触ってみる

$$
\def\bra#1{\mathinner{\left\langle{#1}\right|}}
\def\ket#1{\mathinner{\left|{#1}\right\rangle}}
\def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}
$$
量子コンピュータはド素人です。ひょんなことから関わることになり、本を読んだりしながら鋭意学習中です。まずは動かしてみたい！いうことで、よく名前を聞くIBM Quantum ExperienceとBlueqat で基本的な量子ゲートを試してみました。


#量子プログラミング環境の準備
量子コンピュータの本を開くと量子力学の話やら数学がわらわらと出てきます。最低限の知識は必要ですが、プログラミングである以上、まずはプログラムを書いて動かせる環境が必要です。なるべく手軽に始めたいのでクラウドで使えるものを選んでみました。
##IBM Quantum Experience
https://quantum-computing.ibm.com/
量子ゲート方式の雄であるIBMが用意しているサービス。作ったプログラム（回路）を実機で計算にかけることもできます。Circuit Composerというツールで、ビジュアルで確認しながら構築できるのが初心者にはうれしいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/f677d6e8-c8c8-4269-b8b5-f97e15268c54.png)
具体的な使い方はこちらをご覧ください。
[IBM Cloudで量子コンピューターを無償で触ってみよう！](https://qiita.com/testnin2/items/6dc777a2517d608b8d9f)
[IBM Q ExperienceのBeginners Guide日本語verつくってみた](https://qiita.com/nisuikiba/items/5026c5fba30c247d5f45)


##Blueqat
[Blueqat - Quantum Computer Library for Everyone](https://github.com/Blueqat/Blueqat)
Blueqatは日本のベンチャー企業MDR社が開発している量子コンピュータ向けSDKです。
こちらはGoogle Colaboratoryで`!pip install blueqat`とするだけで簡単に使えるようになり、とてもお手軽です。日本語のドキュメントが充実しているほか、コミュニティも活発なので、日本国内で量子コンピュータやるなら、まずはBlueqatを触るのが良さそうに思います。
詳しい利用方法は[Google ColaboratoryとBlueqatで始める量子コンピュータプログラミング01（1量子ビット）](https://qiita.com/YuichiroMinato/items/6908e00c98843cc64bf0)をご覧ください。

この記事では、基本的にIBM Quantum Experienceの方を触っていきますが、適宜Blueqatのコードも示していきます。

##Circuit Composerを開く
IBM Quantum Experienceにログインしたら、左上のメニューからCircuit Composerを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/a515b0ee-c488-6f49-c96a-beb3aa41d998.png)

デフォルトでは5量子ビットが用意されていますが、まずは単純な1量子ビットで試したいので'q' register qubitsを1にセットします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/c4f0a941-0b8c-b53f-5a82-9afad9d733d7.png)

続いて画面左側の縦棒グラフのアイコン（Visualization）をクリックします。この画面にプログラムの結果が表示されます。これは量子コンピュータの実機による計算結果ではなく、量子コンピュータを模擬したシミュレータの結果のようです。
計算結果にはMeasurement ProbabilityとDensity MatrixとStatevectorの3種類が用意されています。Measurement Probabilityで0と1の割合を出力します。通常はこれをチェックすれば良いと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/1cd08869-38a0-bfbb-bd7d-120aaa6def7b.png)

プログラムは楽譜のような線が引かれた場所にアイコン（量子ゲート）をドラッグ＆ドロップして記述します。現在は1量子ビットなのでq[0]のところに引かれている線のところにアイコンを置いてゲート操作します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/67789974-740c-7f5d-e60b-579baac80332.png)


##補助ツール：Try Bloch!
量子プログラミングするには上記のツールがあればよいのですが、ここから量子ゲートの操作をしだすとブロッホ球のイメージがあると理解しやすいです。幸いにもWeb上で三次元的にブロッホ球を表示・操作できるサイトが存在するので、こちらを開いておくといいと思います。
**[Try Bloch!](https://qease.herokuapp.com/bloch/try/)**

#量子プログラミングの実態
ここまでの話で気づかれたかと思いますが、量子プログラミングといってもPythonなどの高級言語とはまったく異なります。量子ゲートを操作する作業そのものがプログラミングにあたります。そのためか回路の作成と呼ぶことも多いようです。

#さっそく触ってみる
前置きが長くなりましたが、さっそく実際の量子プログラミングをやってみます。

##初期状態（ゲート操作なし）
まずはゲート操作なしの状態で結果を見てみます。Circuit Composerでは測定をしなくても結果が表示されていますが、本来は測定が必要なので黒いメーターの測定アイコンを置いておきます。すると0が100%という結果が表示されました。
量子コンピュータでは重ね合わせといって0と1の状態を併せ持つことができるのが大きな特徴ですが、初期状態では0が100%出る状態になっています。ブラケット記法での$\ket{0}$にあたります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/b85066ed-06c6-a8fa-acc0-44056220fed4.png)

Try Bloch!でブロッホ球を観察してみます。ブロッホ球を地球儀と見立てて+Z方向を北とすると、北に行けばいくほど0の割合が増え、南に行くほど1の割合が増えます。そして$\ket{0}$が北極（0が100%）、$\ket{1}$が南極（1が100%）になります。真ん中（赤道）は0と1が50%ずつとなります。
[Try Bloch!](https://qease.herokuapp.com/bloch/try/)の初期状態では矢印が北極を向いていますので、$\ket{0}$を示していることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/994acc9e-9fd0-65fa-42a7-a76d7e30acf3.png)


##Xゲート
$X$ゲートはブロッホ球のX軸回りに180度回転させる作用を持つゲートです。$\ket{0}$に適用すると、北極を向いていた矢印が南極を向きますので$\ket{1}$の状態を作ることができます。
Circuit ComposerでXのアイコンを追加すると、結果が1が100%になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/4cfa2ff5-50dd-2398-88a6-0313bebf8b5e.png)

Try Bloch!で確認するとこんな感じになります。（球を適宜回転させてます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/7fef8bb8-6519-84f3-a29f-3ba7c67ff339.png)

Blueqatではこのように記述します。（importは2回目以降省略可能）
x[0]が$X$ゲート操作にあたります。m[:]は測定を表します。shotsは実行回数です。ここではあまり意味がありませんが、重ね合わせを使うときに必要になります。

```python
from blueqat import Circuit
Circuit().x[0].m[:].run(shots=10)
```
これを実行すると以下のようになります。10回実行して全部1になります。$\ket{1}$は1が100%なので当たり前ですね。

```python
Counter({'1': 10})
```


##Hゲート（アダマールゲート）
量子コンピュータの醍醐味である0と1の重ね合わせを作るゲートです。Circuit Composerで先ほど置いた$X$ゲートを消して（アイコンを選択して右上のXマークをクリック）、$H$ゲートを挿入します。
すると結果は0と1が50%ずつになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/7719fb37-7ff9-d0b5-fd8f-8949d9436f32.png)

Try Bloch!で確認するとこんな感じになります。北極を向いていた矢印が赤道方向に向きました。Try Bloch!では矢印が動く様子がアニメーションで表示されますので、$X$軸と$Z$軸の中間の軸を中心に回転していることが直感的に理解できると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/4d10e479-a3ba-1200-5380-0912603be49d.png)

Blueqatではこのように記述します。
h[0]がHゲート操作にあたります。

```python
Circuit().h[0].m[:].run(shots=100)
```
これを実行すると以下のようになります。多少誤差はありますが0と1が50%ずつ出るはずです。

```python
Counter({'0': 48, '1': 52})
```

##XゲートとHゲートを組み合わせる
矢印を赤道に向けるだけなら、初期状態の$\ket{0}$ではなく、$\ket{1}$にHゲートを適用してもいいはずです。
ということでCircuit Composerでやってみると、先程と同じく0と1が50%ずつの結果になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/058f0b60-0450-0b64-ce68-3d06af940c0c.png)

ところが同じ操作をTry Bloch!でやってみると矢印の向きが反対になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/463eba73-ea94-ace6-63d4-b5ed54f2d40e.png)

このような違いを区別するために、先程の$\ket{0}$に$H$ゲートを適用したものを$\ket{+}$状態、今回のを$\ket{-}$状態と呼びます。地球儀のたとえでいうと、北極や南極は地球上に1つしかありませんが、赤道上の国はインドネシアもケニアもコロンビアなどいろいろありますので、これらを区別して取り扱いたいときに使うのだと思います。

このような違いを結果として確認するには、もう一度Hゲートを適用します。するとそれぞれ0と1しか結果が得られないことがわかります。

###Hゲート→Hゲート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/5a97eab7-6cb8-6131-524d-a40ceb8acca2.png)

Blueqatのコード

```python
Circuit().h[0].h[0].m[:].run(shots=100)
```
結果

```python
Counter({'0': 100})
```

###Xゲート→Hゲート→Hゲート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/3b3dc8b3-fbef-3d0c-88c1-cb3f6a37ae3d.png)

Blueqatのコード

```python
Circuit().x[0].h[0].h[0].m[:].run(shots=100)
```
結果

```python
Counter({'1': 100})
```

##Sゲート
$S$ゲートは$Z$軸回りに90度回転させます。$S^†$ゲートは反対方向に90度回転させます。
$\ket{0}$に$H$ゲートを適用して重ね合わせた状態に$S$ゲートを適用しても赤道上をぐるぐる周るだけですので、結果は0と1が50%のままです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/fb5c8545-e230-ede3-7a6c-3b693bfe9b8c.png)

Try Bloch!で確認すると、このようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/f1aada2f-4465-be05-5f75-dccbd3525323.png)

これは位相を変えたことにあたりますが、どういう使いみちがあるのかはよくわかってません。



##Tゲート
$T$ゲートは$Z$軸回りに45度回転させます。$T^†$ゲートは反対方向に45度回転させます。
$\ket{0}$に$H$ゲートを適用して重ね合わせた状態に$T$ゲートを適用しても、$S$ゲートと同じ理屈で結果は0と1が50%のままです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/eab3bcec-6c94-ec8c-0cae-eb4e0036cb03.png)

$T$ゲートは$S$ゲートと違って、もう一度$H$ゲートを適用すると0が約85%、1が約15%という結果を返してきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/a5d234e2-0dbb-f84a-b866-34453714b75d.png)
Try Bloch!で確認すると、このようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/9e2fb97a-d615-f454-42b8-b84acd0ed08d.png)

これもどういう使いみちがあるのかはよくわかってません。

#参考資料
[いちばんやさしい量子コンピューターの教本](https://www.amazon.co.jp/dp/4295006076/)
量子ゲートの入門書

[IBM Q ExperienceのBeginners Guide日本語verつくってみた](https://qiita.com/nisuikiba/items/5026c5fba30c247d5f45)
とても参考になります。

[古典プログラマ向け量子プログラミング入門](https://www.slideshare.net/OsSAL-org/ss-198802364)
ここまで力の入った資料が一般公開されているのは素晴らしいです。　

[【2020年永久保存版】量子コンピュータ未経験から独学で量子プログラマーになる５つの方法](https://qiita.com/YuichiroMinato/items/50e7b606023c9e94e812)
触発されました。



今後、Blueqatなどの各種チュートリアルを順次試していきたいと思います。