common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Overview
Terms of service

Privacy policy

Contact
Research

Sign in
Sign up
common.title

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

Yuichiro Minato

2022/07/20 06:57

特異値分解

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

!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]]

  [[0 0]
   [1 0]]]]

次にこれを分解します。特異値分解では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>

image

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

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>

image

画像を見る限りはきちんと戻ってますね。では、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>

image

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

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>

image

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

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>

image

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

© 2025, blueqat Inc. All rights reserved