common.title

Overview
Service overview
Terms of service

Privacy policy

Contact

Sign in
Sign up
common.title

何番煎じだ?量子回路とテンソルネットワークについて計算をしてみる

derwind

2023/04/16 12:24

1

目標

量子回路とテンソルネットワークについて、頭をできるだけ使わない形 (難しいことは苦手・・・) でぼんやり眺めてみたいと思います。ということで、今回、任意の 2 量子ビットゲートはテンソルの縮約として記述されうるのか?を見てみたいと思います。

背景

今までテンソルネットワークをふわっと眺めていたのですが、よく考えると量子回路がテンソルネットワークとして書けることはそれほど自明でないような気もしました。

などの記事を見ると、なるほどと思う部分もあるのですが、私は何か腹落ちしません。ここはやはり鉛筆と紙で手計算ですね・・・としたいのですが、実際はかなりややこしい計算になるので、sympynumpy で手計算したつもりを狙います (難しい手計算をさぼる)。

量子回路の簡単なサンプル

それでは早速 2 量子ビットゲートを見てみましょう。2 量子ビットゲートというと CX ゲートが有名と思います。以下のようなやつですね。

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]
c.run(backend='draw')
<Figure size 1800x180 with 1 Axes>output

上記の回路を計算基底で測定していると考えて数式で書くと、

00CX00=00CX00=[1  0  0  0][1000010000010010][1000]=1\begin{align*} \langle 00| CX | 00 \rangle &= \langle 0| \langle 0| CX | 0 \rangle |0 \rangle \\ & = \begin{bmatrix} 1 \ \ 0 \ \ 0 \ \ 0 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = 1 \end{align*}

となり、00| 0 \rangle |0 \rangle が確率 1 で測定されることを表しています。ここでは簡単のため 00| 0 \rangle \otimes |0 \rangle00| 0 \rangle |0 \rangle と書きました。

ここまでで簡単な量子回路をみました。これが以下のようなテンソルネットワークで記述できるであろうというのが今回のテーマになります。(詳細は例えば テンソルネットワークを用いた量子回路シミュレーション.pdf が参考になりそうです)

量子回路は横方向は普通に行列の積を掛けていく計算ですが、縦方向はテンソル積 (クロネッカー積) を “掛けていく” 計算なので、併せると全部テンソル計算になるというのは、個人的にはイマイチ即座には分かりません。

つまり数式で書くと、

00CX00=ijklcidjSijklakbl\begin{align*} \langle 0| \langle 0| CX | 0 \rangle |0 \rangle = \sum_{ijkl} c_i d_j S_{ijkl} a_k b_l \tag{1} \end{align*}

みたいに 4 階のテンソル計算で書けるのだろうか?ということになります。・・・うんうん考えるのはやめましょう。実際に計算してしまえばいいです。

実際に cdSab\langle c| \langle d| S | a \rangle |b \rangle を計算する

ここで

    • a| a \rangle, b| b \rangle, c| c \rangle, d| d \rangle は 2x1 の縦ベクトル
    • SS は 2x2 の行列

とします。これを (1) 式の左辺の方式で計算した結果と同じになるような右辺のテンソル計算が見つかれば、少なくとも 2 量子ゲートはテンソル計算に落とし込める と言えるのではないでしょうか?

左辺を計算する

ここから sympy の出番です。

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'))
display(S.reshape(4, 4))
array([[S0, S1, S2, S3],

       [S4, S5, S6, S7],

       [S8, S9, S10, S11],

       [S12, S13, S14, S15]], dtype=object)

とりあえず、これで左辺の計算の準備はできました。早速計算します:

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 を使ったのです。とにかくこれが、普通のテンソル積と行列計算で求めた cdSab\langle c| \langle d| S | a \rangle |b \rangle の式になります。

この値はメモリ上に残りますので、続けて右辺を計算します。

右辺を計算する

SS から対応する 4 階のテンソルを作りたいです。ここは天下り的ですが S.reshape(2, 2, 2, 2) をしてみましょう。

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)

とりあえずそれっぽくなりました。これに対して ijklcidjSijklakbl\sum_{ijkl} c_i d_j S_{ijkl} a_k b_l を計算すると、なんと左辺と一致することを以下でみます。np.einsum を使って一気に

np.einsum('i,j,ijkl,k,l->', c, d, S, a, b, optimize='optimal')

みたいな計算したいのですが、sympy の文字式だとうまく動いてくれないようなので、とりあえず動いてくれる方法でちょっとずつ計算していきます・・・。

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 を見てみましょう。

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 と一致するのでしょうか?

sp.simplify(W-ans) == 0
True

やりました!一致しているそうです。つまり我々は以下を得ました。

命題

2 量子ビットの量子回路に対して

cdSab=ijklcidjSijklakbl\begin{align*} \langle c| \langle d| S | a \rangle |b \rangle = \sum_{ijkl} c_i d_j S_{ijkl} a_k b_l \end{align*}

が成立する。ここで、SS は左辺では 2 量子ゲートに対応する 2x2 行列を表し、右辺ではそれを 2x2x2x2 の 4 階のテンソルと解釈したものとする。

まとめ

本当に頭を使わなかったか?と問われると何とも言えませんが、手計算で唸ることは避けられたように思います。

「でも、これって 2 量子ビットの回路だけですよね?一般の NN 量子ビットの回路について何も証明してませんよね?」と言われると耳が痛いですが、そこは誰か根気強いかたにお任せしたいです。このくらいの計算で「なんとなく量子回路はテンソルネットで書けそうだ!」という気持ちになられた方は、雰囲気でテンソルネットワークに落として、ガリガリとライブラリで計算したら良いかなと思います。私はそうしたいです。

© 2024, blueqat Inc. All rights reserved