グローバーアルゴリズムとは、|0>,|1>,|2>,....|N>
の線形重ね合わせから、任意の状態 |a>
の確率振幅を増幅して、できるだけ 1に近づけるアルゴリズムである。
sympy でお手軽グローバー
sympy ではライブラリ化されているので使うのはめっちゃ簡単。3-qubitの系で、|7>
を取り出したいな。|7> = |111>
の観測確率は、その他の状態の 121 倍に増幅されている。
>>> from sympy.physics.quantum.qubit import IntQubit, measure_all
>>> from sympy.physics.quantum.qapply import qapply
>>> from sympy.physics.quantum.grover import apply_grover
>>> isKet7 = lambda state: state == IntQubit(7)
>>> measure_all(qapply(apply_grover(isKet7, 3)))
[(|000>, 1/128), (|001>, 1/128), (|010>, 1/128), (|011>, 1/128), (|100>, 1/128), (|101>, 1/128), (|110>, 1/128), (|111>, 121/128)]
sympy でもう少し踏み込んでグローバー
以上で終わりなのだが、これだけだとあまりにもつまらないので、もう少し手作り感をだそう。|7> = |111>
に対応するオラクルは、OracleGate
が対応する。行列表示をすれば一目瞭然に |7>
だけがフェーズシフトされる様子がわかる。
>>> from sympy.physics.quantum.grover import OracleGate
>>> from sympy.physics.quantum.represent import represent
>>> ora = OracleGate(3, isKet7)
>>> represent(ora)
Matrix([
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, -1]])
オラクルの後は、Inversion about mean という操作をする。これは sympy では WGate
と呼ばれている。よってグローバーオペレータGを定義できる。G を 1回、2回かけた際にどのように確率振幅がどのようになるかを見よう。
from sympy.physics.quantum.qapply import qapply
from sympy.physics.quantum.dagger import Dagger
from sympy.physics.quantum.grover import apply_grover, OracleGate, WGate, superposition_basis
from sympy.physics.quantum.qubit import Qubit, IntQubit, measure_all
from sympy.physics.quantum.gate import I, X, Z, H, CNOT, CGate
G = WGate(3) * OracleGate(3, lambda state: state == IntQubit(7))
print(measure_all(qapply(G*superposition_basis(3))))
print(measure_all(qapply(G*G*superposition_basis(3))))
結果は以下の通り、2回 Gをかけた結果が、前述のapply_grover
の結果と一致している。
[(|000>, 1/32), (|001>, 1/32), (|010>, 1/32), (|011>, 1/32), (|100>, 1/32), (|101>, 1/32), (|110>, 1/32), (|111>, 25/32)]
[(|000>, 1/128), (|001>, 1/128), (|010>, 1/128), (|011>, 1/128), (|100>, 1/128), (|101>, 1/128), (|110>, 1/128), (|111>, 121/128)]
sympy で完全手作りグローバー
さて、私たちは具体的にこのオラクルの具体的な実現方式を知っている(CGate((0,1,2),X(3))
末尾の参考文献参照)。それと比べてみよう。インプットとして 3-qubit, オラクルビットとして 1bit の計 4-qubit の系が必要。
from sympy.physics.quantum.qapply import qapply
from sympy.physics.quantum.dagger import Dagger
from sympy.physics.quantum.grover import apply_grover, OracleGate
from sympy.physics.quantum.qubit import Qubit, IntQubit
from sympy.physics.quantum.gate import I, X, Z, H, CNOT, CGate
myora = CGate((0,1,2),X(3))
for state in range(8):
inputState = qapply(H(3) * IntQubit(8+state))
applied = qapply(myora * inputState)
print (qapply(Dagger(inputState) * applied))
出力。確かに、 |7>
の時だけフェーズシフトされていることがわかる。よってこのように構成した量子ゲートは上述のオラクルと対応付けることができる。つまり、我々の構成した 4-qubit の量子ゲートは、以降の全ての処理では、オラクルキュービットを無視するので、3-qubit の前述のオラクルで代替可能である。以降 3-qubit系で議論を進める。
1
1
1
1
1
1
1
-1
Wゲートに関してもその具体的な構成方法がわかっているので、グローバーオペレータを定義できる。
from sympy.physics.quantum.qapply import qapply
from sympy.physics.quantum.dagger import Dagger
from sympy.physics.quantum.grover import OracleGate, superposition_basis
from sympy.physics.quantum.qubit import Qubit, IntQubit, measure_all
from sympy.physics.quantum.gate import I, X, Z, H, CNOT, CGate
ora = OracleGate(3, lambda state: state == IntQubit(7))
W = X(0) * X(1) * X(2) * CGate((0,1),Z(2)) * X(0) * X(1) * X(2)
myG = H(0) * H(1) * H(2) * W * H(0) * H(1) * H(2) * ora
state1 = qapply(myG*superposition_basis(3))
print(measure_all(state1))
state2 = qapply(myG*state1)
print(measure_all(state2))
結果は以下のようになる。ばっちりOK。
[(|000>, 1/32), (|001>, 1/32), (|010>, 1/32), (|011>, 1/32), (|100>, 1/32), (|101>, 1/32), (|110>, 1/32), (|111>, 25/32)]
[(|000>, 1/128), (|001>, 1/128), (|010>, 1/128), (|011>, 1/128), (|100>, 1/128), (|101>, 1/128), (|110>, 1/128), (|111>, 121/128)]
だれか sympy で次元の圧縮のやり方を知っている人がいればおしえてほすい