回答編集履歴
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))
         | 
