common.title

SVDで量子ゲートの分解と近似

Yuichiro Minato 21 days ago

特異値分解

今回は量子ゲートの分解でも利用される特異値分解を見てみます。 まずはツールを読み込みます。

!pip install tensornetwork
Collecting tensornetwork

  Using cached tensornetwork-0.4.6-py3-none-any.whl (364 kB)

Requirement already satisfied: scipy>=1.1 in /opt/conda/lib/python3.10/site-packages (from tensornetwork) (1.8.1)

Requirement already satisfied: h5py>=2.9.0 in /opt/conda/lib/python3.10/site-packages (from tensornetwork) (3.7.0)

Requirement already satisfied: opt-einsum>=2.3.0 in /opt/conda/lib/python3.10/site-packages (from tensornetwork) (3.3.0)

Collecting graphviz>=0.11.1

  Using cached graphviz-0.20-py3-none-any.whl (46 kB)

Requirement already satisfied: numpy>=1.17 in /opt/conda/lib/python3.10/site-packages (from tensornetwork) (1.21.0)

Installing collected packages: graphviz, tensornetwork

Successfully installed graphviz-0.20 tensornetwork-0.4.6

量子コンピュータのゲートでのCNOTをみてみましょう。CXともいわれます。

import tensornetwork as tn import numpy as np #行列 cx = tn.Node(np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]).reshape(2,2,2,2))
print(cx.tensor)
[[[[1 0]

   [0 0]]



  [[0 1]

   [0 0]]]





 [[[0 0]

   [0 1]]


次にこれを分解します。特異値分解では3つのパートに分解されます。左右の腕を残したまま分解します。

U, s, V, trun_error = tn.split_node_full_svd(cx, [cx[0],cx[1]], [cx[2],cx[3]])

無事分解できたので三つのテンソルを確認します。まずはU。

U.tensor
array([[[ 1.,  0.,  0.,  0.],

        [ 0.,  1.,  0.,  0.]],



       [[ 0.,  0.,  0., -1.],

        [ 0.,  0., -1.,  0.]]])

そしてV

V.tensor
array([[[ 1.,  0.],

        [ 0.,  0.]],



       [[ 0.,  1.],

        [ 0.,  0.]],



       [[-0., -0.],

        [-1., -0.]],



       [[-0., -0.],

        [-0., -1.]]])

最後にs

s.tensor
array([[1, 0, 0, 0],

       [0, 1, 0, 0],

       [0, 0, 1, 0],

       [0, 0, 0, 1]])

sは対角行列となっています。前回のトライアルとでは真ん中のsは自動的に平方根をつけて左右に割り振られていました。分解されたテンソルが元に戻るか確認してみます。

final = U@s@V print(final.tensor.reshape(4,4))
[[1. 0. 0. 0.]

 [0. 1. 0. 0.]

 [0. 0. 0. 1.]

 [0. 0. 1. 0.]]

元に戻りましたね。真ん中のsを4x4から3x3にしてみます。

s_dash = s.tensor[:3,:3] print(s_dash)
[[1 0 0]

 [0 1 0]

 [0 0 1]]

いつも通り行列に戻してみると、

U.tensor.reshape(4,4)@s.tensor@V.tensor.reshape(4,4)
array([[1., 0., 0., 0.],

       [0., 1., 0., 0.],

       [0., 0., 0., 1.],

       [0., 0., 1., 0.]])

sの次元を削ったものでやってみると、

U.tensor.reshape(4,4)[:,:3]@s.tensor[:3,:3]@V.tensor.reshape(4,4)[:3,:]
array([[1., 0., 0., 0.],

       [0., 1., 0., 0.],

       [0., 0., 0., 0.],

       [0., 0., 1., 0.]])

もとの行列とちょっと変わってしまいました。さらに削ってみると、

U.tensor.reshape(4,4)[:,:2]@s.tensor[:2,:2]@V.tensor.reshape(4,4)[:2,:]
array([[1., 0., 0., 0.],

       [0., 1., 0., 0.],

       [0., 0., 0., 0.],

       [0., 0., 0., 0.]])

だいぶ削れました。CXで近似は無理がありました。きちんとsを保存する必要があります。より大きな行列ではどうなるかを見てみます。 もはや量子ゲートではないですが、適当な行列を作ってみます。

a = np.array([np.random.randint(100) for _ in range(100)]) from matplotlib import pyplot as plt plt.imshow(a.reshape(10,10), interpolation='nearest') plt.show()
<Figure size 432x288 with 1 Axes>output

なんか画像となりました。これを分解してみます。

b = tn.Node(a.reshape(10,10)) print(b.tensor) U, s, V, trun_error = tn.split_node_full_svd(b, [b[0]], [b[1]])
[[72 32 73 77 63 43 86 51 54 77]

 [81 92 67 16 39 21 75 71 32 46]

 [32 41 62 37 68 47  2 69 41 55]

 [32 59 80 86 65 55 61 22 49 53]

 [59 36 94 34  1 62 76  4 37 10]

 [75  1 59 21 98 51  8 65 11 76]

 [33 68 45 55 78  1 61 65 58 57]

 [15 74 60 78 17  5 11  2 14 52]

 [11 96 53 56 39 25 53 44 90 41]

 [35 80 51 10 66 63 54  3 23 60]]

できたsを見てみます。

s.tensor
array([[498,   0,   0,   0,   0,   0,   0,   0,   0,   0],

       [  0, 136,   0,   0,   0,   0,   0,   0,   0,   0],

       [  0,   0, 111,   0,   0,   0,   0,   0,   0,   0],

       [  0,   0,   0,  92,   0,   0,   0,   0,   0,   0],

       [  0,   0,   0,   0,  77,   0,   0,   0,   0,   0],

       [  0,   0,   0,   0,   0,  63,   0,   0,   0,   0],

       [  0,   0,   0,   0,   0,   0,  56,   0,   0,   0],

       [  0,   0,   0,   0,   0,   0,   0,  21,   0,   0],

       [  0,   0,   0,   0,   0,   0,   0,   0,  12,   0],

       [  0,   0,   0,   0,   0,   0,   0,   0,   0,   6]])

戻してみます。

c = U@s@V plt.imshow(c.tensor.reshape(10,10), interpolation='nearest') plt.show()
<Figure size 432x288 with 1 Axes>output

画像を見る限りはきちんと戻ってますね。では、sを削って近似してみます。

N = 9 d = U.tensor.reshape(10,10)[:,:N]@s.tensor[:N,:N]@V.tensor.reshape(10,10)[:N,:] plt.imshow(d, interpolation='nearest') plt.show()
<Figure size 432x288 with 1 Axes>output

あまり違いは見えません。

N = 3 d = U.tensor.reshape(10,10)[:,:N]@s.tensor[:N,:N]@V.tensor.reshape(10,10)[:N,:] plt.imshow(d, interpolation='nearest') plt.show()
<Figure size 432x288 with 1 Axes>output

かなり変わってしまいましたが、真ん中あたりは面影が見えます。

N = 5 d = U.tensor.reshape(10,10)[:,:N]@s.tensor[:N,:N]@V.tensor.reshape(10,10)[:N,:] plt.imshow(d, interpolation='nearest') plt.show()
<Figure size 432x288 with 1 Axes>output

多少の面影はありますね。このように、画像を圧縮することができます。今後はより大きな量子ゲート計算にこのSVDを適用しますが、コツがありますので今後はそれも見ていきます。

Yuichiro Minato

@yuichiro_minato2

blueqat CEO/CTO

About us ©2022 Copyright © 2022 blueqat Inc. All rights reserved