Nobisuke
Dekisugi
RAG
Privacy policy
1
量子回路とテンソルネットワークについて、頭をできるだけ使わない形 (難しいことは苦手・・・) でぼんやり眺めてみたいと思います。ということで、今回、任意の 2 量子ビットゲートはテンソルの縮約として記述されうるのか?を見てみたいと思います。
今までテンソルネットワークをふわっと眺めていたのですが、よく考えると量子回路がテンソルネットワークとして書けることはそれほど自明でないような気もしました。
などの記事を見ると、なるほどと思う部分もあるのですが、私は何か腹落ちしません。ここはやはり鉛筆と紙で手計算ですね・・・としたいのですが、実際はかなりややこしい計算になるので、sympy
と numpy
で手計算したつもりを狙います (難しい手計算をさぼる)。
それでは早速 2 量子ビットゲートを見てみましょう。2 量子ビットゲートというと CX ゲートが有名と思います。以下のようなやつですね。
Copy from blueqat import Circuit c = Circuit().cx[0, 1] print(c.run(backend='numpy'))
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
Copy c.run(backend='draw')
<Figure size 1800x180 with 1 Axes>
上記の回路を計算基底で測定していると考えて数式で書くと、
となり、 が確率 1 で測定されることを表しています。ここでは簡単のため を と書きました。
ここまでで簡単な量子回路をみました。これが以下のようなテンソルネットワークで記述できるであろうというのが今回のテーマになります。(詳細は例えば テンソルネットワークを用いた量子回路シミュレーション.pdf が参考になりそうです)
量子回路は横方向は普通に行列の積を掛けていく計算ですが、縦方向はテンソル積 (クロネッカー積) を “掛けていく” 計算なので、併せると全部テンソル計算になるというのは、個人的にはイマイチ即座には分かりません。
つまり数式で書くと、
みたいに 4 階のテンソル計算で書けるのだろうか?ということになります。・・・うんうん考えるのはやめましょう。実際に計算してしまえばいいです。
ここで
とします。これを (1) 式の左辺の方式で計算した結果と同じになるような右辺のテンソル計算が見つかれば、少なくとも 2 量子ゲートはテンソル計算に落とし込める と言えるのではないでしょうか?
ここから sympy
の出番です。
Copy import numpy as np import sympy as sp a = np.array(sp.symbols('a0:2')) b = np.array(sp.symbols('b0:2')) S = np.array(sp.symbols('S0:16')) c = np.array(sp.symbols('c0:2')) d = np.array(sp.symbols('d0:2'))
Copy display(S.reshape(4, 4))
array([[S0, S1, S2, S3],
[S4, S5, S6, S7],
[S8, S9, S10, S11],
[S12, S13, S14, S15]], dtype=object)
とりあえず、これで左辺の計算の準備はできました。早速計算します:
Copy ans = np.kron(c, d)@S.reshape(4, 4)@np.kron(a, b).T display(sp.simplify(ans))
a0*b0*(S0*c0*d0 + S12*c1*d1 + S4*c0*d1 + S8*c1*d0) + a0*b1*(S1*c0*d0 + S13*c1*d1 + S5*c0*d1 + S9*c1*d0) + a1*b0*(S10*c1*d0 + S14*c1*d1 + S2*c0*d0 + S6*c0*d1) + a1*b1*(S11*c1*d0 + S15*c1*d1 + S3*c0*d0 + S7*c0*d1)
とてつもない式が出てきました・・・。手計算でこれをしたくないので、sympy
を使ったのです。とにかくこれが、普通のテンソル積と行列計算で求めた の式になります。
この値はメモリ上に残りますので、続けて右辺を計算します。
から対応する 4 階のテンソルを作りたいです。ここは天下り的ですが S.reshape(2, 2, 2, 2)
をしてみましょう。
Copy S1 = S.reshape(2, 2, 2, 2) display(S1)
array([[[[S0, S1],
[S2, S3]],
[[S4, S5],
[S6, S7]]],
[[[S8, S9],
[S10, S11]],
[[S12, S13],
[S14, S15]]]], dtype=object)
とりあえずそれっぽくなりました。これに対して を計算すると、なんと左辺と一致することを以下でみます。np.einsum
を使って一気に
np.einsum('i,j,ijkl,k,l->', c, d, S, a, b, optimize='optimal')
みたいな計算したいのですが、sympy
の文字式だとうまく動いてくれないようなので、とりあえず動いてくれる方法でちょっとずつ計算していきます・・・。
Copy T = np.einsum('i,ijkl->jkl', c, S1, optimize='optimal') U = np.einsum('j,jkl->kl', d, T, optimize='optimal') V = np.einsum('kl,k->l', U, a, optimize='optimal') W = np.einsum('l,l->', V, b, optimize='optimal') - 0 # unboxing
最後の行でちょっとしたハックまがいのことをやっていますが、- 0
などをしないと、文字式が 0 次元の numpy.ndarray
に包まれた形になってしまうので、強引にアンボクシングします。とりあえず W
を見てみましょう。
Copy display(sp.simplify(W))
b0*(a0*(d0*(S0*c0 + S8*c1) + d1*(S12*c1 + S4*c0)) + a1*(d0*(S10*c1 + S2*c0) + d1*(S14*c1 + S6*c0))) + b1*(a0*(d0*(S1*c0 + S9*c1) + d1*(S13*c1 + S5*c0)) + a1*(d0*(S11*c1 + S3*c0) + d1*(S15*c1 + S7*c0)))
これまた酷い式が出てきました。こんなことで、果たして計算結果の W
は左辺の ans
と一致するのでしょうか?
Copy sp.simplify(W-ans) == 0
True
やりました!一致しているそうです。つまり我々は以下を得ました。
命題
2 量子ビットの量子回路に対して
が成立する。ここで、 は左辺では 2 量子ゲートに対応する 2x2 行列を表し、右辺ではそれを 2x2x2x2 の 4 階のテンソルと解釈したものとする。
本当に頭を使わなかったか?と問われると何とも言えませんが、手計算で唸ることは避けられたように思います。
「でも、これって 2 量子ビットの回路だけですよね?一般の 量子ビットの回路について何も証明してませんよね?」と言われると耳が痛いですが、そこは誰か根気強いかたにお任せしたいです。このくらいの計算で「なんとなく量子回路はテンソルネットで書けそうだ!」という気持ちになられた方は、雰囲気でテンソルネットワークに落として、ガリガリとライブラリで計算したら良いかなと思います。私はそうしたいです。
© 2024, blueqat Inc. All rights reserved