🔰 Blueqat で学ぶ量子ゲート操作 🔰 


量子ゲートの操作を直感的に理解しながら進めたかったので、基本的な操作を行うコードと、それに付随する量子回路図を並べてみました。


コードの内容は [Blueqat日本語チュートリアル](https://github.com/mdrft/Blueqat_tutorials_ja/tree/master/docs) を参考に、回路図は [Quirk](https://algassert.com/quirk#circuit) からスクショを撮りました。


## 前提知識
個人的には、「量子ビットは[ブロッホ球](https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%AD%E3%83%83%E3%83%9B%E7%90%83)で表現できる」ことが分かっていればコーディングを始められると思っています。

[Try Bloch!](https://qease.herokuapp.com/bloch/try/) で X, Y, Z, H あたりを押して見ると、イメージが早いと思います。

イメージ図:
![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/3ee2ef9b-07e4-a7a0-db01-116973101834.png)


量子ビット内を指す点を操作して、北極に近づけるほど0の確率が高くなり、南極に近づけるほど1の確率が高くなります。


## 初期ゲート

便宜上、2量子ビットを初期値とします。

```python
from blueqat import Circuit

Circuit(2).m[:].run(shots=100) # Counter({'00': 100})
```

`Circuit(2)` で2個の量子ビットを宣言、 `m[:]` で現在の状態を計測、 `run(shots=100)` で実行回数を指定し実行します。

これを実行すると、 `00` が 100 となりました。

1つ目の量子ビット -> 0
2つ目の量子ビット -> 0

上記の状態が100回計測されたということになります。

量子ビットは、何も操作をしないと北極地点(0)を指すということがわかりました。


量子回路図は以下のようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/b0f7858a-356f-c649-cbc5-91977ba4bb4a.png)
 [Quirk / Circuit Link](https://algassert.com/quirk#circuit={"cols":[["…","…"]],"gates":[{"id":"~jh77","matrix":"{{0.9238795-0.2705981i,-0.2705981i},{-0.2705981i,0.9238795+0.2705981i}}"},{"id":"~e9oj","matrix":"{{√½,√½i},{√½i,√½}}"},{"id":"~3cb7","matrix":"{{√½-½i,-½i},{-½i,√½+½i}}"},{"id":"~c682","matrix":"{{0.9999619-0.0061706i,-0.0061706i},{-0.0061706i,0.9999619+0.0061706i}}"},{"id":"~a8e5","matrix":"{{0.9238795-0.2705981i,-0.2705981i},{-0.2705981i,0.9238795+0.2705981i}}"}]})

( 上記のツールでは `...` は何もしないゲートという意味だそうです。 ~~これを入れないとヒントが出てきて邪魔だったのと、１つだけの量子回路の作り方がわからなかったので２つにした。~~ )
　


## Xゲートの操作

ブロッホ球のx軸の周りを 180°回転をさせるものを「Pauli-X ゲート」または「ビット反転演算子」[^1]と呼びます。

```shell
Circuit(2).x[0].m[:].run(shots=100) # Counter({'10': 100})
```

`x[0]` で、配列0番目の量子ビットにXゲートを適用させました。

それにより、以下の状態が100回観測されました。

1つ目の量子ビット -> 1
2つ目の量子ビット -> 0

量子回路は以下になります。 

![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/841dc2ed-23a3-3514-b104-d558cbcdfe6c.png)
[Quirk / Circuit Link](https://algassert.com/quirk#circuit={%22cols%22:[[%22X%22,%22%E2%80%A6%22]]})

:warning: :warning: :warning: :warning:
※Blueqatでは量子ビットを左から順に `10` と並べて表しますが、Quirkの数式（[ケットベクトル](https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%A9-%E3%82%B1%E3%83%83%E3%83%88%E8%A8%98%E6%B3%95)）では右から順に `|01⟩` と表現されるので注意。右端の水色の円にカーソルを乗せると表示されます。

## Yゲートの操作
同様にy軸の周りに 180°回転をさせるものを「Pauli-Y ゲート」または「位相・ビット反転演算子」[^2]と呼びます。

```python
Circuit(2).y[0].m[:].run(shots=100) # Counter({'10': 100})
```

xゲートと同様に、 `y[0]` がそれです。 


量子回路図は以下になります。 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/d78a6e89-8db9-f9df-a801-5858ad3fc5ce.png)
[Quirk / Circuit Link](https://algassert.com/quirk#circuit={%22cols%22:[[%22Y%22,%22%E2%80%A6%22]]})


## Zゲートの操作
同様にz軸の周りに 180°回転をさせるものを「Pauli-Z ゲート」または「位相反転演算子」[^3]と呼びます。
0の時は何も変化させず、1の時に位相を反転させます。

```python
Circuit(2).z[0].m[:].run(shots=100) # Counter({'00': 100})
```

量子回路図は以下になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/e01047bd-b9b8-f004-2547-3c5ca989d561.png)
[Quirk / Circuit Link](https://algassert.com/quirk#circuit={%22cols%22:[[%22Z%22,%22%E2%80%A6%22]]})

上記の北極地点では、結果に何も影響を与えないので、後続のアダマールゲートで加えて説明します。


## アダマールゲートの操作

これはちょっと特殊で、z軸からx軸へと向かう中間の 45°を軸として 180°の回転をさせるもので、「アダマール変換」[^4]とも呼びます。
（ [Try Block](https://qease.herokuapp.com/bloch/try/) で H を押して見たほうがイメージしやすいかと思います )

```python
Circuit(2).h[0].m[:].run(shots=100) # Counter({'00': 47, '10': 53})
```

`h[0]` がそれです。

1つ目の量子ビットが赤道に位置することで重ね合わせ状態となり、0である確率が50%, 1である確率が50% となりました。
100回実行時の確認で、 `00` が 47回, `10` が 53回と、大体50%前後に収まってることが確認できるかと思います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/626c3f96-b165-a525-e41e-1001f6f22968.png)
[Quirk / Circuit Link](https://algassert.com/quirk#circuit={%22cols%22:[[%22H%22,%22%E2%80%A6%22]]})


---


また、赤道はぐるりと回っているので、どの地点にいるかを判別する方法があります。

```python
Circuit(2).h[0].run() # array([0.70710678+0.j, 0.70710678+0.j, 0.        +0.j, 0.        +0.j])
```

`m[:]` を外して状態を確定させる測定を止め、 `shots=100` の実行回数指定を外すと、状態を取得できます。
（この実行はシミュレーターでのみ使える機能[^5]のようです)

実行すると、状態を以下の複素ベクトル[^6]で取得できました。

結果の1つ目は `00` -> 0.70710678+0.j
結果の2つ目は `10` -> 0.70710678+0.j
結果の3つ目は `01` -> 0.        +0.j
結果の4つ目は `11` -> 0.        +0.j

結果の配列は、上記の量子ビットに対応していることを確認しました。

アダマールゲートを適用した直後の赤道では、複素ベクトルは `0.70710678+0.j` となるようです。
（この複素ベクトルは絶対値を2乗することで確率を取得できます[^6]）

---


赤道上を移動するにはZゲートが使えます。


```python
Circuit(2).h[0].z[0].run() # array([ 0.70710678+0.j, -0.70710678+0.j,  0.        +0.j, -0.        +0.j])
```

結果の1つ目は `00` -> 0.70710678+0.j
結果の2つ目は `10` -> -0.70710678+0.j
結果の3つ目は `01` -> 0.        +0.j
結果の4つ目は `11` -> 0.        +0.j

Zゲートは `1` の時に作用するので、1つ目の量子ビットが 1 である `10` の結果が、負になっていることを確認できたかと思います。
アダマールゲート適用直後の手前の赤道が + の最大値となり、そこから半周(180°)回した地点では - の最大値になります。
その性質により、位置（位相）を計算できるようです。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/b80a6398-6798-8ec8-07da-d9488df0d5d9.png)
[Quirk / Circuit Link](https://algassert.com/quirk#circuit={%22cols%22:[[%22H%22,%22%E2%80%A6%22],[%22Z%22]]})



## 位相シフトゲートの操作

z軸の周りに角度θ 回転させるもので、「位相シフト演算子」とも呼ばれます。回転方向は手前の球面から右方向になります。

```python
Circuit(2).h[0].rz(math.pi/4)[0].run() # array([0.70710678+0.j , 0.5       +0.5j, 0.        +0.j , 0.        +0.j ])
```

`rz(math.pi/4)[0]` がそれです。
Zゲートは180度回転なので、 `math.pi/4` でその4分の1、45度の回転を行います。

結果の1つ目は `00` -> 0.70710678+0.j
結果の2つ目は `10` -> 0.5       +0.5j
結果の3つ目は `01` -> 0.        +0.j
結果の4つ目は `11` -> 0.        +0.j

1つ目の量子ビットが1である`10`の時に、結果が変わっていることを確認できたかと思います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/0d0dd8d0-4710-fa69-2b6a-0edc176da07d.png)
[Quirk Circuit Link](https://algassert.com/quirk#circuit={%22cols%22:[[%22H%22,%22%E2%80%A6%22],[%22Z^%C2%BC%22]]})



#### メモ帳 📝

* `rz(math.pi/4)` は手前の球面から右方向に回転します。
* `rz(-math.pi/4)` だと左方向に回転します。
* `rz(math.pi/2)` は Sゲートと呼ばれることもあります。
* `rz(-math.pi/4)` は T†ゲートと呼ばれることもあります。


## CNOTゲートの操作

2つの量子をもつれさせるゲートです。「制御NOTゲート」[^7]とも呼ばれます。
片方の量子ビット（制御量子ビット）が1の時だけ、もう片方の量子ビット（標的量子ビット）にXゲートを適用させます。


```python
Circuit(2).x[0].cx[0,1].m[:].run(shots=100) # Counter({'11': 100})
```

`cx[0,1]` で指定します。
左側の0が制御量子ビットを指定していて、右側の1が標的量子ビットを指定しています。

1つ目の量子ビットが `x[0]` で1になっているため、2つ目の量子ビットがCNOTゲートにより1になり、結果は `11` が100%となります。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/85111/0e04eec9-9f15-a46a-2015-7298a24ba102.png)

[Quirk Circuit Link](https://algassert.com/quirk#circuit={%22cols%22:[[%22X%22],[%22%E2%80%A2%22,%22X%22]]})

~~やっと2個の量子ビットを使う例を出せました。~~

---

基本的なゲート操作は以上になります。

## 最後に

量子力学やその関連数式も学んではいますが、大抵は「なるほどわからん」という感じです。
ただ、わからなくても辛くはなく、逆にどうしてその謎の数式が出てくるんだろうといった興味が沸いてくるので、そのうちわかっていくだろうと楽観的に思っています。内容はとても面白いので、参考URLを乗せておきます。

* [予備校のノリで学ぶ - 【大学物理】量子力学入門シリーズ / 1-7](https://www.youtube.com/channel/UCqmWJJolqAgjIdLqK3zD1QQ/search?query=allintitle%3A%22%E3%80%90%E5%A4%A7%E5%AD%A6%E7%89%A9%E7%90%86%E3%80%91%E9%87%8F%E5%AD%90%E5%8A%9B%E5%AD%A6%E5%85%A5%E9%96%80%22)
* [量子計算（量子回路）の考え方を理解するために最低限必要な量子力学の知識を（それなりに納得感のある形で）うまいこと導入する方法について考えてみた（目次） / 全7記事](http://enakai00.hatenablog.com/entry/2018/05/28/151207)


#### 自分への戒め
* 強化学習のコード等を量子コンピューターにうつせる力が無ければ実利を出せない。触って楽しいで終わるのではなく、生活をより豊かにすることを前提に行動を選択していく。


[^1]: http://lyncs.hateblo.jp/entry/2017/12/16/000103#%E3%83%91%E3%82%A6%E3%83%AAX
[^2]: http://lyncs.hateblo.jp/entry/2017/12/16/000103#%E3%83%91%E3%82%A6%E3%83%AAY
[^3]: http://lyncs.hateblo.jp/entry/2017/12/16/000103#%E3%83%91%E3%82%A6%E3%83%AAZ
[^4]: http://eman-physics.net/quantum/computer3.html > 回転ゲート
[^5]: https://github.com/mdrft/Blueqat_tutorials_ja/blob/master/docs/003_basic_superposition.ipynb > （応用）マイナス状態で重ね合わせを作ってみる
[^6]: http://enakai00.hatenablog.com/entry/2018/05/20/170047 > 純粋状態と混合状態の違いについて
[^7]: http://lyncs.hateblo.jp/entry/2017/12/16/000103#CNOT%E3%82%B2%E3%83%BC%E3%83%88