回答編集履歴
2
edit
answer
CHANGED
@@ -31,6 +31,8 @@
|
|
31
31
|
最後に振幅が最大の要素を取り出せば終わりです。
|
32
32
|
`which.max(psi^2)`
|
33
33
|
|
34
|
+
---
|
35
|
+
|
34
36
|
pythonでnumpyを使って書くと以下になります。
|
35
37
|
(拡散行列は更新されてはいけないのですね。修正しました。)
|
36
38
|
|
@@ -40,7 +42,7 @@
|
|
40
42
|
|
41
43
|
np.random.seed(1024)
|
42
44
|
|
43
|
-
n = 2**
|
45
|
+
n = 2**3
|
44
46
|
itr = 8
|
45
47
|
f1 = np.zeros(n)
|
46
48
|
r = np.random.randint(n)
|
@@ -68,4 +70,93 @@
|
|
68
70
|
plt.show()
|
69
71
|
|
70
72
|
print(np.argmax(psi*psi))
|
73
|
+
```
|
74
|
+
|
75
|
+
---
|
76
|
+
|
77
|
+
sympyで自分で頑張る版。
|
78
|
+
実際はHadamardGateを使って初期状態を準備しますが、シンボリックで割り算をしてしまって大変なことになるので、無理やり一度実数で割っています。
|
79
|
+
IdentityGateなので使わなくてもいいのに、無駄に使って計算時間が少し増えています。
|
80
|
+
```python
|
81
|
+
import itertools
|
82
|
+
from sympy.physics.quantum.qubit import Qubit, measure_all
|
83
|
+
from sympy.physics.quantum.dagger import Dagger
|
84
|
+
from sympy.physics.quantum.qapply import qapply
|
85
|
+
from sympy.physics.quantum.gate import HadamardGate, IdentityGate
|
86
|
+
from math import sqrt
|
87
|
+
import matplotlib.pyplot as plt
|
88
|
+
import functools
|
89
|
+
import operator
|
90
|
+
|
91
|
+
def prod(iterable):
|
92
|
+
return functools.reduce(operator.mul, iterable, 1)
|
93
|
+
|
94
|
+
n = 3
|
95
|
+
itr = 8
|
96
|
+
|
97
|
+
f_ = [0]*n
|
98
|
+
f_[1] = 1
|
99
|
+
fa = Qubit(*f_)
|
100
|
+
|
101
|
+
basis = []
|
102
|
+
for psi_ in itertools.product([0,1], repeat=n):
|
103
|
+
basis.append(Qubit(*psi_))
|
104
|
+
psi0 = sum(basis)/sqrt(2**n)
|
105
|
+
psi = sum(basis)/sqrt(2**n)
|
106
|
+
|
107
|
+
Hs = prod([HadamardGate(i) for i in range(n)])
|
108
|
+
Is = prod([IdentityGate(i) for i in range(n)])
|
109
|
+
|
110
|
+
'''
|
111
|
+
p_ = [0]*n
|
112
|
+
p = Qubit(*p_)
|
113
|
+
psi0 = qapply(Hs*p).doit()
|
114
|
+
psi = qapply(Hs*p)
|
115
|
+
'''
|
116
|
+
|
117
|
+
Uf = lambda q: qapply(Is*q - 2*fa*Dagger(fa)*q)
|
118
|
+
Us = lambda q: qapply(2*psi0*Dagger(psi0)*q - Is*q)
|
119
|
+
|
120
|
+
for i in range(itr):
|
121
|
+
psi = Us(Uf(psi))
|
122
|
+
y = [v[1] for v in measure_all(psi)]
|
123
|
+
x = [''.join(map(str, v[0].qubit_values)) for v in measure_all(psi)]
|
124
|
+
plt.plot(x, y, marker='.', label=i)
|
125
|
+
print(y)
|
126
|
+
|
127
|
+
plt.grid()
|
128
|
+
plt.yscale('log')
|
129
|
+
plt.legend()
|
130
|
+
plt.show()
|
131
|
+
```
|
132
|
+
|
133
|
+
---
|
134
|
+
|
135
|
+
grover見つけちゃったから答え合わせ版。
|
136
|
+
操作回数によって逆に振幅が下がるのが気持ち悪いのですが、ライブラリの実装と同じ結果になるので、ビット数が少なくて、操作回数が少ないことが原因だと思い込むことにします。
|
137
|
+
```python
|
138
|
+
from sympy.physics.quantum.qapply import qapply
|
139
|
+
from sympy.physics.quantum.qubit import IntQubit, Qubit, measure_all
|
140
|
+
from sympy.physics.quantum.grover import OracleGate
|
141
|
+
from sympy.physics.quantum.grover import superposition_basis
|
142
|
+
from sympy.physics.quantum.grover import grover_iteration, apply_grover
|
143
|
+
import matplotlib.pyplot as plt
|
144
|
+
|
145
|
+
numqubits = 3
|
146
|
+
f = lambda qubits: qubits == IntQubit(4)
|
147
|
+
v = OracleGate(numqubits, f)
|
148
|
+
q = superposition_basis(numqubits)
|
149
|
+
for i in range(8):
|
150
|
+
q = qapply(grover_iteration(q, v))
|
151
|
+
ans = qapply(apply_grover(f, numqubits, iterations=i+1))
|
152
|
+
y = [v[1] for v in measure_all(q)]
|
153
|
+
x = [''.join(map(str, v[0].qubit_values)) for v in measure_all(q)]
|
154
|
+
plt.plot(x, y, label=i)
|
155
|
+
print(q)
|
156
|
+
print(ans)
|
157
|
+
|
158
|
+
plt.legend()
|
159
|
+
plt.grid()
|
160
|
+
plt.yscale('log')
|
161
|
+
plt.show()
|
71
162
|
```
|
1
edit
answer
CHANGED
@@ -32,6 +32,7 @@
|
|
32
32
|
`which.max(psi^2)`
|
33
33
|
|
34
34
|
pythonでnumpyを使って書くと以下になります。
|
35
|
+
(拡散行列は更新されてはいけないのですね。修正しました。)
|
35
36
|
|
36
37
|
```python
|
37
38
|
import numpy as np
|
@@ -39,10 +40,12 @@
|
|
39
40
|
|
40
41
|
np.random.seed(1024)
|
41
42
|
|
42
|
-
n =
|
43
|
+
n = 2**4
|
43
44
|
itr = 8
|
44
45
|
f1 = np.zeros(n)
|
45
|
-
|
46
|
+
r = np.random.randint(n)
|
47
|
+
print(r)
|
48
|
+
f1[r] = 1
|
46
49
|
|
47
50
|
psi = np.ones(n)
|
48
51
|
psi /= np.linalg.norm(psi)
|
@@ -52,13 +55,16 @@
|
|
52
55
|
return new / np.linalg.norm(new)
|
53
56
|
|
54
57
|
def Us(v):
|
55
|
-
new = 2
|
58
|
+
new = 2*np.matmul(np.ones((n,n))/n, v) - np.matmul(np.eye(n), v)
|
56
59
|
return new / np.linalg.norm(new)
|
57
60
|
|
58
61
|
for i in range(itr):
|
59
62
|
psi = Us(Uf(psi))
|
60
|
-
plt.plot(psi*psi)
|
63
|
+
plt.plot(psi*psi, label=i)
|
61
64
|
|
65
|
+
plt.yscale('log')
|
66
|
+
plt.grid()
|
67
|
+
plt.legend()
|
62
68
|
plt.show()
|
63
69
|
|
64
70
|
print(np.argmax(psi*psi))
|