teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

edit

2018/03/08 19:59

投稿

mkgrei
mkgrei

スコア8562

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**4
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

2018/03/08 19:59

投稿

mkgrei
mkgrei

スコア8562

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 = 100
43
+ n = 2**4
43
44
  itr = 8
44
45
  f1 = np.zeros(n)
45
- f1[np.random.randint(n)] = 1
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 * psi * np.dot(psi, v) - np.matmul(np.eye(n), v)
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))