D-Waveにサイコロをふらせてみる。

３回目に、　[n個のうちmだけを１にする問題をPyQUBOを使ってアニーリングマシンで解く](https://qiita.com/morimorijap/items/196e7fc86ecff927bf40)という記事を書きましたが、この考え方をもちいると、サイコロを降ることができます。 
サイコロは説明するまでもないですが、立方体で面に、１から６までの数字が書いてあり、それを降るとすべての面が同じ確率ででる（はず）のものすごいシンプルな構造です。

ちなみにnumpyの乱数を使ってPythonで擬似にサイコロを降らすのは、

```
import numpy as np

n = 1000
d = np.random.randint(1,7,n)

tmp = []
for i in range(1,7):
    tmp.append(list(d).count(i))

print(tmp)
```

このような感じで書くことが可能です。
```
[137, 154, 171, 178, 174, 186]
```
といった結果が出てきます。　

第３回目に、変数n個のうちmだけを１にするという問題はよく知られいて、QUBOにおいては、

$$H = \( \sum_{i}^n q_{i} -m \)^2 $$

とすることで表現することが可能だと書きましたが、これをそのまま使えば表現することが可能です。

サイコロなので、$n=6$で、１つだけの面がでるので、$m=1$となります。

<img width="366" alt="Screen Shot 2019-04-27 at 6.17.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260261/0bc847a7-e623-9b87-2920-35557f1c0092.png">

これをハミルトニアンの形式で表現すると、

$$ H = (q1+q2+q3+q4+q5+q6-1)^2 $$

となります。

PyQUBOとD-Wave Leapをもちいて、1000回アニーリングの計算をさせるとする場合は、

```
from pyqubo import Binary, solve_qubo
from dwave.system.samplers import DWaveSampler
from dwave.system.composites import EmbeddingComposite

# Define hamiltonian
q1, q2, q3, q4, q5, q6 = Binary("q1"), Binary("q2"), Binary("q3"), Binary("q4"), Binary("q5"), Binary("q6")

# Hamiltonian Eq.
H = (q1+q2+q3+q4+q5+q6-1)**2


# Create QUBO
model = H.compile()
qubo, offset = model.to_qubo()

# Solve QUBO model by D-Wave
# ---------------------------
endpoint = "https://cloud.dwavesys.com/sapi"
token = "xxxx" ##<--　ここは自分のKeyを入れる
solver_name = "DW_2000Q_VFYC_2_1"

sampler = EmbeddingComposite(DWaveSampler(endpoint=endpoint, token=token, solver=solver_name))
response = sampler.sample_qubo(qubo, num_reads = 1000)
print(response)
# ---------------------------
```

１回目の計算をしたら、
```
  q1 q2 q3 q4 q5 q6 energy num_oc. chain_b.
0  1  0  0  0  0  0   -1.0     317 0.166667
1  0  1  0  0  0  0   -1.0     674 0.166667
3  0  0  0  0  1  0   -1.0       2      0.0
4  0  0  1  0  0  0   -1.0       1      0.0
5  0  0  0  0  0  1   -1.0       2      0.0
6  1  0  0  0  0  0   -1.0       2      0.0
2  0  1  0  0  1  0    0.0       2 0.166667
['BINARY', 7 rows, 1000 samples, 6 variables]
```

このような感じで、q2の出現が674回、q1の出現が317回、それ以外は１回づつつかでませんした。サイコロにしてはすごく偏りがあります。
しかし、ハミルトニアンは−1.0と同じエネルギーが出ています。

もう一度やってみたら、今度は
```
 q1 q2 q3 q4 q5 q6 energy num_oc. chain_b.
0  0  0  0  0  0  1   -1.0      20 0.166667
1  0  1  0  0  0  0   -1.0     979 0.166667
2  0  0  0  0  0  1   -1.0       1      0.0
['BINARY', 3 rows, 1000 samples, 6 variables]
```
のようにでました。
q2の出現が979回、q1の出現が20回、q6が１回で、それ以外はでませんした。

また、 6個のうち1つを1にするのではなく、6個のうち5つを1にするようにしてみました。

```
H = (q1+q2+q3+q4+q5+q6-5)**2
```

そうすると、
```
  q1 q2 q3 q4 q5 q6 energy num_oc. chain_b.
0  1  0  1  1  1  1  -25.0     752 0.166667
1  0  1  1  1  1  1  -25.0     243 0.166667
2  1  1  1  1  0  1  -25.0       1 0.166667
3  1  1  1  0  1  1  -25.0       2      0.0
4  1  1  1  1  0  1  -25.0       1      0.0
5  1  1  1  1  1  0  -25.0       1      0.0
['BINARY', 6 rows, 1000 samples, 6 variables]
```

このような感じで、q1の出現が752回、q1の出現が243回、q3の出現が２回で、それ以外は１回づつつかでませんした。ハミルトニアンは−25.0と同じエネルギーが出ています。

なかなか、サイコロを再現するのは難しいみたいです。　

３回目に、　[n個のうちmだけを１にする問題をPyQUBOを使ってアニーリングマシンで解く](https://qiita.com/morimorijap/items/196e7fc86ecff927bf40)という記事を書きましたが、本当にこの数式が正しいかを4個のうち1つを1にする問題して検証してみると、

```
H = (q1+q2+q3+q4-1)**2
```

出現回数は
```
  q1 q2 q3 q4 energy num_oc. chain_.
0  0  1  0  0   -1.0     232     0.0
1  1  0  0  0   -1.0     262     0.0
2  0  0  0  1   -1.0     269     0.0
3  0  0  1  0   -1.0     237     0.0
['BINARY', 5 rows, 1000 samples, 4 variables]
```
このように一様になります。ただ、何回か計算をすると偏りがあります。

5個のうち1つを1にする問題して検証してみると、
```
H = (q1+q2+q3+q4+q5-1)**2
```
として、その出現回数は
```
  q1 q2 q3 q4 q5 energy num_oc. chain_.
0  1  0  0  0  0   -1.0     190     0.0
1  0  0  1  0  0   -1.0     173     0.0
2  0  0  0  0  1   -1.0     209     0.0
3  0  0  0  1  0   -1.0     228     0.0
4  0  1  0  0  0   -1.0     200     0.0
['BINARY', 5 rows, 1000 samples, 5 variables]
```
となり、だいたい一様になります。

次に、7個のうち1つを1にする問題して検証してみると、
```
H = (q1+q2+q3+q4+q5+q6+q7-1)**2
```
として、その出現回数は
```
   q1 q2 q3 q4 q5 q6 q7 energy num_oc. chain_b.
0   0  0  0  0  1  0  0   -1.0     616 0.285714
1   0  0  0  1  0  0  0   -1.0     250 0.285714
2   0  1  0  0  0  0  0   -1.0      26 0.142857
3   0  0  1  0  0  0  0   -1.0      17 0.142857
4   0  0  0  0  0  0  1   -1.0       5 0.142857
5   0  0  0  1  0  0  0   -1.0      11 0.142857
6   0  0  0  0  0  1  0   -1.0       4 0.142857
7   0  0  0  0  1  0  0   -1.0      20 0.142857
8   0  0  0  0  1  0  0   -1.0      29 0.142857
9   0  0  0  1  0  0  0   -1.0      15 0.142857
10  0  1  0  0  0  0  0   -1.0       1      0.0
11  0  0  0  0  1  0  0   -1.0       1      0.0
12  1  0  0  0  0  0  0   -1.0       1      0.0
13  0  0  0  0  0  1  0   -1.0       1      0.0
14  0  0  0  1  0  0  0   -1.0       1      0.0
15  0  0  0  0  0  0  0    0.0       1 0.285714
16  0  1  0  0  1  0  0    0.0       1 0.285714
['BINARY', 17 rows, 1000 samples, 7 variables]
```
となり、6個以降は、うまく一様な出現回数が現れないことがわかりました。

この原因は推測すると、詳細を検討したわけではないのですが、アニーリングは、一番エネルギーが低いところを探すというマシンですので、複数箇所エネルギーが低いところ出てくるようなこういう問題は不得意なのかもしれません。SAでも今後もう少し試してみようとおもいます。数が多くなるとD-Waveは全結合でなくなるので、その変換がうまくいってない可能性も考えられます。これは富士通のデジタルアニーラで試してみるとわかる可能性があります。

今日はこのくらいで。

2019.4.30追記：
7個の場合にミスがあったので修正しました。