質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

436閲覧

量子状態の足し算について

Fallout_18

総合スコア124

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2018/03/08 08:51

編集2018/03/08 09:42

グローバーアルゴリズムをつかった、データベース探索のプログラムを行おうとしています。
問題設定】
左から番号1、2、3...nと名前がついた箱があり、このn個の箱のどれかに、値1があり、それ以外の箱は0を持っています。この1を持つ箱は何番目の箱なのかを探すプログラムをpythonで再現するようにしています。> http://testen.wp.xdomain.jp/2017/06/07/グローバーのアルゴリズム/

量子状態の足し算について困っています。
例として、
|Φ>=Σ|i>  (i=1~10)
なる、量子状態Φをどのように計算するのでしょうか?

python

1n=10 2def sigma(function, frm, to): 3 result = 0; 4 for i in range(frm, to+1): 5 result += func(i) 6 print(result) 7#Φの定義 8 phai = sigma(Qubit(i), 1, n)

Qubitは0か1状態でしか、計算できないので、Qubit(i)は間違っているのは自明なのですが、、、

私の考えとして、たとえば、5を2進数で展開すると、bin(5)='0b101'とbが入ってしまい、再びエラーになってしまいます。

それ以前に、Qubitと量子状態の意味を完全に理解していない気もしますが。。

ご鞭撻のほど、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2018/03/08 09:47

あ、ちんぷんかんぷんです^^; お役に立てずすみません。
Fallout_18

2018/03/08 09:49

いえ!ご協力ありがとうございます!
guest

回答3

0

ベストアンサー

ハミルトニアンに対する基底が決まれば、任意の状態はその完全系の線形結合で表現できます。
ですので、基底の数が有限nの場合、任意の状態は一本のn次元のベクトルで表現できます。
また、任意の作用素はnxn次元の行列になります。

そのうち今の選ばれた状態というのが以下のもので、

R

1f1 = rep(0,n) 2f1[sample(1:n,1)]=1

n次元のベクトルを0で初期化して、そのうちどれか一個の要素をランダムで選んで、1にしています。

psi = rep(1,n) / sqrt(n)|Φ>=Σ|i> (i=1~10)ですべての要素が1で初期化して、規格化してノルムを1にしています。

R

1Uf = diag(1,n) - 2 * f1 %*% bra(f1) 2Us = 2 * psi %*% bra(psi) - diag(1,n)

は「グローバー回転の動き」の後の式を、基底で展開して、連立方程式を考えると出てきます。

R

1for(i in 1:itr){ 2 psi = Us %*% Uf %*% psi 3}

この部分でUs,Ufをitr回作用させています。

ψにRを作用させることで、均等な重ね合わせ|ψ⟩から、|f1⟩の確率振幅が強められた状態に移ったことを意味します。

というのを実行しています。

最後に振幅が最大の要素を取り出せば終わりです。
which.max(psi^2)


pythonでnumpyを使って書くと以下になります。
(拡散行列は更新されてはいけないのですね。修正しました。)

python

1import numpy as np 2import matplotlib.pyplot as plt 3 4np.random.seed(1024) 5 6n = 2**3 7itr = 8 8f1 = np.zeros(n) 9r = np.random.randint(n) 10print(r) 11f1[r] = 1 12 13psi = np.ones(n) 14psi /= np.linalg.norm(psi) 15 16def Uf(v): 17 new = np.matmul(np.eye(n), v) - 2 * f1 * np.dot(f1, v) 18 return new / np.linalg.norm(new) 19 20def Us(v): 21 new = 2*np.matmul(np.ones((n,n))/n, v) - np.matmul(np.eye(n), v) 22 return new / np.linalg.norm(new) 23 24for i in range(itr): 25 psi = Us(Uf(psi)) 26 plt.plot(psi*psi, label=i) 27 28plt.yscale('log') 29plt.grid() 30plt.legend() 31plt.show() 32 33print(np.argmax(psi*psi))

sympyで自分で頑張る版。
実際はHadamardGateを使って初期状態を準備しますが、シンボリックで割り算をしてしまって大変なことになるので、無理やり一度実数で割っています。
IdentityGateなので使わなくてもいいのに、無駄に使って計算時間が少し増えています。

python

1import itertools 2from sympy.physics.quantum.qubit import Qubit, measure_all 3from sympy.physics.quantum.dagger import Dagger 4from sympy.physics.quantum.qapply import qapply 5from sympy.physics.quantum.gate import HadamardGate, IdentityGate 6from math import sqrt 7import matplotlib.pyplot as plt 8import functools 9import operator 10 11def prod(iterable): 12 return functools.reduce(operator.mul, iterable, 1) 13 14n = 3 15itr = 8 16 17f_ = [0]*n 18f_[1] = 1 19fa = Qubit(*f_) 20 21basis = [] 22for psi_ in itertools.product([0,1], repeat=n): 23 basis.append(Qubit(*psi_)) 24psi0 = sum(basis)/sqrt(2**n) 25psi = sum(basis)/sqrt(2**n) 26 27Hs = prod([HadamardGate(i) for i in range(n)]) 28Is = prod([IdentityGate(i) for i in range(n)]) 29 30''' 31p_ = [0]*n 32p = Qubit(*p_) 33psi0 = qapply(Hs*p).doit() 34psi = qapply(Hs*p) 35''' 36 37Uf = lambda q: qapply(Is*q - 2*fa*Dagger(fa)*q) 38Us = lambda q: qapply(2*psi0*Dagger(psi0)*q - Is*q) 39 40for i in range(itr): 41 psi = Us(Uf(psi)) 42 y = [v[1] for v in measure_all(psi)] 43 x = [''.join(map(str, v[0].qubit_values)) for v in measure_all(psi)] 44 plt.plot(x, y, marker='.', label=i) 45 print(y) 46 47plt.grid() 48plt.yscale('log') 49plt.legend() 50plt.show()

grover見つけちゃったから答え合わせ版。
操作回数によって逆に振幅が下がるのが気持ち悪いのですが、ライブラリの実装と同じ結果になるので、ビット数が少なくて、操作回数が少ないことが原因だと思い込むことにします。

python

1from sympy.physics.quantum.qapply import qapply 2from sympy.physics.quantum.qubit import IntQubit, Qubit, measure_all 3from sympy.physics.quantum.grover import OracleGate 4from sympy.physics.quantum.grover import superposition_basis 5from sympy.physics.quantum.grover import grover_iteration, apply_grover 6import matplotlib.pyplot as plt 7 8numqubits = 3 9f = lambda qubits: qubits == IntQubit(4) 10v = OracleGate(numqubits, f) 11q = superposition_basis(numqubits) 12for i in range(8): 13 q = qapply(grover_iteration(q, v)) 14 ans = qapply(apply_grover(f, numqubits, iterations=i+1)) 15 y = [v[1] for v in measure_all(q)] 16 x = [''.join(map(str, v[0].qubit_values)) for v in measure_all(q)] 17 plt.plot(x, y, label=i) 18 print(q) 19 print(ans) 20 21plt.legend() 22plt.grid() 23plt.yscale('log') 24plt.show()

投稿2018/03/08 14:39

編集2018/03/08 19:59
mkgrei

総合スコア8560

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Fallout_18

2018/03/08 16:40

お答えありがとうございます!! こちらも、ひとつの参考にしたいと思います。 ブラケット表記で計算していくと、グラフができないということですよね。。? 以下に、与えられた式をそのまま直訳して、私なりにコードを書いてみました。
Fallout_18

2018/03/08 16:57

力足らずですいません。 以下のエラーがでました。 plt.plot(psi*psi) AttributeError: module 'matplotlib' has no attribute 'plot'
mkgrei

2018/03/08 17:00

import matplotlib.pyplot as plt ではなく import matplotlib as plt をしていませんか。
Fallout_18

2018/03/09 10:29

すごいです。。。
guest

0

皆さま、お答えありがとうございます!!
私なりに、チャレンジしてみました。まだ完成ではないのですが、4割~6割ほどの出来だと思います。よろしければ、添削の程をお願い致します。

python

1from sympy.physics.quantum import* 2from sympy.physics.quantum.gate import IdentityGate as I 3from sympy.physics.quantum.qubit import Qubit 4from sympy.physics.quantum.dagger import Dagger 5import math 6import numpy as np 7import random 8from sympy import* 9import sympy 10#準備 11n = 10 12itr = 8     #Grover回転の回数 13f = np.zeros(n)  #0が10個の箱を作る 14a = random.randint(0, n-1)  #1からnのいずれかの一つを選ぶ 15f[a] = 1       #選んだ箱に1を入れる 16A = '{:04b}'.format(a) #Qubitを使うために、2進数表記 17fa = Qubit(A) #|f1> 18fb = Dagger(fa) 19 20def s(t): 21 p = Qubit('{:04b}'.format(t)) 22 return(1/sympy.sqrt(n))*p 23def w(t): 24 r = Dagger(p) 25 return(1/sympy.sqrt(n))*r 26 27def sigma(function, start, end): 28 result = 0; 29 for i in range(start, end+1): 30 result += function(i) 31 print(result) 32 33Uf = I - 2*fa * fb 34Us = 2*sigma(s,1,n)*sigma(w,1,n) - I 35for i in range(itr): 36 z = Us*Uf*sigma(s,1,n) 37 38#plt.plot(n, z^2) 39#plt.show() 40print(z)

投稿2018/03/08 16:43

Fallout_18

総合スコア124

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mkgrei

2018/03/08 17:01

z = sigma(s,1,n) for i in range(itr): ....z = Us*Uf*z ....はインデントです。 再代入を忘れていませんか。
Fallout_18

2018/03/09 10:18 編集

申し訳ないです、チンプンカンプンです。 ただ、for分のよく間違える典型例だということしか理解できません。。 for i in range(itr): z = sigma(s,1,n) y = Us*Uf*si z +=y
mkgrei

2018/03/09 10:46

得たいものはR=UsUfとして RRRRRRRRz なので、作用する回数をべた書きしなくてもいいようにわけます。 R(R(R(R(R(R((R(Rz)))))))) これを得るために z = Rz でRを一度作用させることができて、 それをfor文で8回繰り返すことで達成できます。 pythonの構文とsympy独自の書き方が混ざっているので紛らわしいです。
Fallout_18

2018/03/09 15:12 編集

fa = Qubit(A) fb = Dagger(fa) ・・・ Uf = I - 2*Qubit(A)(Dagger(fa)) Us = 2*sigma(s,1,n)(sigma(w,1,n)) - I for i in range(itr): z = sigma(s,1,n) R = UsUf z = Rz print(z) で実行すると、 Uf = I - 2*Qubit(A)(Dagger(fa)) TypeError: 'Qubit' object is not callable と出力されました。上記のおっしゃる、python構文とsympy構文がごっちゃになっていることが原因なのでしょうか?
mkgrei

2018/03/09 15:34

2*Qubit(A)(Dagger(fa)) これですが Qubit(...)(...) になっています。 a = Qubit() a() となってしまうので、エラーになっています。クラスを関数としてコールしたので。 2*Qubit(A)*(Dagger(fa)) 掛け算が必要です。
guest

0

質問の内容も理解できない全くの門外漢ですがQuantum Mechanicsを使うとなんとなくそれっぽい結果が得られました。
結果の意味も分かっていませんが。
参考:SymPy で量子プログラミングを体験してみましょう

Python

1from sympy.physics.quantum.qubit import Qubit 2ret = None 3for i in range(10): # 1(0000)から10(1010) 4 s = '{:04b}'.format(i+1) # '0101'など 5 q = Qubit(s) 6 print(q) 7 if ret is None: 8 ret = q 9 else: 10 ret += q 11print(ret) 12# |0001> + |0010> + |0011> + |0100> + |0101> + |0110> + |0111> + |1000> + |1001> + |1010>

投稿2018/03/08 09:25

can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2018/03/08 09:51

内容全く理解できませんが^^; Rでできることの大半はPythonでもできるようなので、まずは代替ライブラリがないか探してみてはいかがでしょうか? お役に立てずすみません。
Fallout_18

2018/03/08 09:51

すいません、以下のプログラム s = '{:04b}'.format(i+1) # '0101'など について、解説をいただけませんでしょうか? これが、もしかしたら私が求めている答えかもしれません。
can110

2018/03/08 09:55

それは単に1~10までの数値を2進数表現の文字列にしているだけです。 たとえば5は`0101`という文字列になります。 Qubitはこのような2進表現文字列から生成できるので。
Fallout_18

2018/03/08 09:59

すいません、私の勉強不足です。 5は2進数に表すと、 bin(5)='0b101' で0101ではないと思うのですが。
can110

2018/03/08 10:05

bin(5)の表示結果「0b101」のうち「0b」は「2進表記ですよ」という目印です。 値として意味のあるのは「101」の部分です。 hex(5)の表示結果「0x5」のうち「0x」部分が「16進表記ですよ」と同じ意味です。 そのような目印は不要で、4桁0詰の文字列を得たいので s= ~のようなコードを書いています。
Fallout_18

2018/03/08 10:08

理解しました! 一度、コードを書き直してみます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問