まずは簡単な量子ビットを準備して、Xゲートをかけてみます。
import numpy as np
psi = np.array([1,0])
X = np.array([[0,1],[1,0]])
#これらのテンソルを縮約して量子状態を作ります。
psi2 = np.einsum('i,ij->j', psi, X)
#プリント
print ('psi2:', psi2)
psi2: [0 1]
次に重ね合わせを作ってみます。
psi = np.array([1,0])
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
#これらのテンソルを縮約して量子状態を作ります。
psi2 = np.einsum('i,ij->j', psi, H)
#プリント
print ('psi2:', psi2)
psi2: [0.70710678 0.70710678]
次にGHZを
psi1 = np.array([1,0])
psi2 = np.array([1,0])
psi3 = np.array([1,0])
H = np.array([[1,1],[1,-1]])/np.sqrt(2)
CX = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]).reshape(2,2,2,2)
#これらのテンソルを縮約して量子状態を作ります。
psi4 = np.einsum('i,j,k,il,ljon,nkpr', psi1,psi2,psi3,H,CX,CX)
path_info = np.einsum_path('i,j,k,il,ljon,nkpr', psi1,psi2,psi3,H,CX,CX, optimize='greedy')
#プリント
print(path_info[0])
print(path_info[1])
print ('psi4:', psi4.reshape(8))
['einsum_path', (1, 4), (1, 3), (0, 1), (0, 2), (0, 1)]
Complete contraction: i,j,k,il,ljon,nkpr->opr
Naive scaling: 8
Optimized scaling: 4
Naive FLOP count: 1.536e+03
Optimized FLOP count: 1.210e+02
Theoretical speedup: 12.694
Largest intermediate: 8.000e+00 elements
--------------------------------------------------------------------------
scaling current remaining
--------------------------------------------------------------------------
4 ljon,j->lno i,k,il,nkpr,lno->opr
4 nkpr,k->npr i,il,lno,npr->opr
2 il,i->l lno,npr,l->opr
3 l,lno->no npr,no->opr
4 no,npr->opr opr->opr
psi4: [0.70710678 0. 0. 0. 0. 0.
0. 0.70710678]
合ってる自信はなかったのですが、なんか状態ベクトルで000と111が半々で出てますのであってる気がします。optimized scalingも4で収まっています。楽しいですね。以上です。