common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Overview
Contact
Event
Project
Research

Terms of service (Web service)

Terms of service (Quantum and ML Cloud service)

Privacy policy


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