IBM Quantum ExperienceとBlueqatでCXゲートと量子もつれを体験する

$$
\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}}
$$

量子コンピュータ初心者です。[前回](https://qiita.com/Zensa55/items/7291c1d6a356a3d5a79c)は1量子ビットで様々な量子ゲートを適用して変化を観察しました。引き続きIBM Quantum ExperienceとBlueqatで量子ゲートの基礎を勉強していきます。今回は2量子ビットです。

#量子ビットを2つに増やす
ではさっそく2量子ビットにチャレンジしてみます。IBM Quantum ExperienceのCircuit Composerを開き、Settingsで'q' register qubitsを2に設定して2量子ビットにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/5514b093-4b02-74d0-eca7-f345f90c351a.png)

結果はMeasurement Probabilityを観察します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/5694ec0f-19bc-b856-ab47-190b02999f7a.png)

##2量子ビットの結果の見方
量子ビットが2つに増えたので、結果は00とか01などの値で出てきます。いくつか試して感触をつかんでみます。

###00
Circuit Composerでは測定しなくても結果が出てきますが、本来は測定が必要なのでメーターのアイコンを置いておきます。この状態で結果を見ると00になっています。まだ何も操作するゲートを入れていないので当然ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/2c935a22-c39b-c167-f8ba-605e36f38439.png)

###01
1番目の量子ビットq[0]に$X$ゲートを適用して$\ket{0}$を$\ket{1}$に変えてみると、結果は01となりました。先頭の量子ビットの結果が一番後ろにくるようですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/8bdd9412-604c-1a4d-3f4c-0712df316d32.png)

Blueqatのコード。`Circuit(2)`で量子ビットが2つあることを宣言しています。

```python
from blueqat import Circuit
Circuit(2).x[0].m[:].run(shots=1)
```

結果を見るときは少し注意が必要で、Blueqatは量子ビットの順番に結果を出すのでCircuit Composerとは順番が逆になります。

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

同様にして2番目の量子ビットに$X$ゲートを適用すれば01の結果になります。

###00と10の重ね合わせ
1番目の量子ビットに$H$ゲートを適用すると0と1が半々になりますので、結果は00と01が50%ずつとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/2990c18e-25a6-7241-a108-0e12c906d2ef.png)

Blueqatのコード。`from blueqat import Circuit`は2回目以降不要です。

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

結果

```python
Counter({'00': 55, '10': 45})
```


#2つの量子ビットをつなげる
ここまでは2つの量子ビットは独立した存在でしたが、ここからいよいよ本題の量子もつれです。2つの量子ビットをつなげて影響を及ぼさせることができます。
Circuit Composerで量子ビットを繋げられそうなアイコンを見るとこの3つでしょうかね。実は3つ繋げられるやつもあるのですが難しいので今はパスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/f2601e96-b611-bea8-36f1-bf628403fb9c.png)

##CXゲート（CNOTゲート）![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/ee541040-8636-9bf2-c365-0c136af2215c.png)
$CX$ゲート（controlled-X gate）または$CNOT$ゲート（controlled-NOT）とも呼ばれます。Circuit Composerで置いてみると片方が●でもう片方が＋になっています。●のほうを制御ビット（control bit）といい、＋のほうをターゲットビット（target bit）といいます。制御ビットが1のときにだけ＋のほうを反転します。

###CNOT（入力q[0]=0,q[1]=0）
この例ではq[0]が制御ビット、q[1]がターゲットビットになります。制御ビットが0なので何も起こりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/c570b9cb-f4e3-aa23-24a9-1cce87021390.png)

###CNOT（入力q[0]=1,q[1]=0）
制御ビットが1なのでターゲットビットが反転されて1になり結果は11になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/04ca1988-ea6c-5b79-8005-c1f77578f6b7.png)

###CNOT（入力q[0]=0,q[1]=1）
制御ビットが0なので入力がそのまま出力されて結果は10になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/24b8a5ab-4221-957c-a29d-847f38961e0b.png)

###CNOT（入力11）
制御ビットが1なのでターゲットビットが反転されて0になり結果は01になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/b046a78a-de14-df76-b02f-a5c1cf447de2.png)

ここまでの操作のBlueqatのコード。面倒なのでまとめて書いてしまいました。

```python
res00 = Circuit(2).cx[0,1].m[:].run(shots=1)            #入力q[0]=0,q[1]=0
res01 = Circuit(2).x[0].cx[0,1].m[:].run(shots=1)       #入力q[0]=1,q[1]=0
res10 = Circuit(2).x[1].cx[0,1].m[:].run(shots=1)       #入力q[0]=0,q[1]=1
res11 = Circuit(2).x[0,1].cx[0,1].m[:].run(shots=1)     #入力q[0]=1,q[1]=1

print('Result\n{}\n{}\n{}\n{}'.format(res00,res01,res10,res11))
```

実行結果。前述の通りCircuit Composerとは逆で、量子ビットの順番で結果を出すので注意が必要です。

```python
Result
Counter({'00': 1})
Counter({'11': 1})
Counter({'01': 1})
Counter({'10': 1})
```

###CXゲートの結果まとめ
q[0]が制御ビット、q[1]がターゲットビットの場合は以下のようになります。

|q[0]入力  |q[1]入力  |q[0]出力  |q[1]出力  |Circuit Composerの結果  |Blueqatの結果|
|---|---|---|---|---|---|
|0| 0| 0| 0| 00| 00|
|1| 0| 0| 0| 11| 11|
|0| 1| 0| 0| 10| 01|
|1| 1| 0| 0| 01| 10|

##Hゲートを適用したあとにCXゲートを適用する
$H$ゲートで重ね合わせの状態を作ったあとで$CX$ゲートを適用してみます。すると結果は00と11が半々となりました。上記の表の1行目と2行目の状態が出ています。これで量子もつれを実装できました。
Blueqatのチュートリアルによると、重ね合わせただけでは組み合わせが多すぎて計算結果をうまく選べないので、もつれを使って解を絞り込むことで速度を生かしたアルゴリズムを作り出すことができるそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/87bfc176-a55c-1e24-0b2d-949c5751039d.png)

Blueqatのコード

```python
Circuit().h[0].cx[0,1].m[:].run(shots=100)
```

出力

```python
Counter({'00': 58, '11': 42})
```

##SWAPゲート![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/d000e204-fa84-9513-95dd-d280d30fd864.png)
こちらは2つの量子ビットをスワップ（入れ替える）ゲートです。たぶん何かの役に立つのでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/9e4911ec-a13a-bd53-1a48-b57458d9288e.png)

Blueqatのコード

```python
Circuit().x[0].swap[0,1].m[:].run(shots=1)
```

出力

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

##CZゲート![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/4866cd66-9b3e-c9f2-383e-c2f1fe4113d6.png)
これは制御ビットが1のときに、ターゲットビットに$Z$ゲートを適用するというものだそうです。これは位相を変える働きがありますが、何の役に立つのかはよくわかりません。

Circuit Composerでは位相が変わるだけだとMeasurement Probabilityでの結果に変化が出ないので、Statevector（状態ベクトル）に変更します。まずは$CZ$ゲート適用前の結果。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/db072275-831b-f229-ffe5-9cd8f608f377.png)

$CZ$ゲート適用後。色が変わって位相が変化したことを知らせてくれます。親切！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346401/f0ba5f48-789d-f686-0a14-8f6ae6f8108a.png)

Blueqatで状態ベクトルを出すにはこのようにします。

```python
Circuit().x[0].h[1].cz[0,1].run()
```

出力するとこんな感じ。うーん、難しい。

```python
array([ 0.        +0.j,  0.70710678+0.j,  0.        +0.j, -0.70710678+0.j])
```


#参考資料
[量子コンピュータSDKのBlueqatで使える全量子ゲート早見表](https://qiita.com/YuichiroMinato/items/4624ecee213dcc176961)

[IBM Quantum ExperienceのGates Glossary](https://quantum-computing.ibm.com/support/guides/gate-overview)