テンソルネットワークの計算をするための
ITensor—Intelligent Tensor—
http://itensor.org/
についての忘備録。
http://itensor.org/docs.cgi?vers=cppv3&page=book
をざっくり日本語でまとめたものである。
ITensorとは、テンソルを扱うc++のライブラリである。これを使って密度行列繰り込み群(DMRG)などができ、量子多体系の計算できる。
ITensorはc++17以降で動く。
ITensorでは、インデックス(index)を定義することができる。
auto i = Index(3);
これは要素が3個あるインデックスiを意味している。
なので、足が三つあるテンソルは
auto i = Index(2,"index i");
auto j = Index(3,"index j");
auto k = Index(4,"index k");
auto T = ITensor(i,j,k);
println("The order of T is ",order(T));
とかける。このテンソルTは、iが2要素、jが3要素、kが4要素あり、全部で24成分ある。そしてゼロに初期化されている。
テンソルの足の数はorder(T)
で調べられる。テンソルの中身に値をセットしたいときは、
T.set(i=2,j=1,k=3, 4.56);
とすればよい。また、要素を取り出したい場合には、
auto x = elt(T,k=3,i=2,j=1);
println("x = ",x);
//prints: x = 4.56
とすればよい。複素数の値をセットできるし、取り出すこともできる。
T.set(i=2,k=3,j=1, 7+8_i);
auto z = eltC(T,i=2,k=3,j=1);
println("z = ",z);
//prints: z = (7,8)
同じindexを持つ場合には、足し算や引き算ができる。テンソルの足の順番が違っていても、indexが同じなら、よしなに和を取ってくれる。
auto Q = 2*T;
auto R = Q/3 + T*4_i;
auto S = R - T;
S *= 5;
//etc.
テンソルの積は、同じindexの足を潰すように計算される
auto i = Index(2,"index i");
auto j = Index(3,"index j");
auto k = Index(4,"index k");
auto A = ITensor(i,j);
auto B = ITensor(k,j);
auto C = A * B;
足が同じところを足すので、A*B
もB*A
も同じ結果になる。
同じテンソル同士の積をする場合には、
auto W = ITensor(i,s,j);
auto D = W * prime(W,s);
のようにする。ここでは、右側のWのindex sだけをs'にしていることを意味しており、それ以外のindexであるiとjは共通なので和が取られる。
テンソルの特異値分解は、
auto T = ITensor(i,j,k);
auto [U,S,V] = svd(T,{i,k});
でできる。ここで、{i,k}
はindexのi,kを行とみなす、ということを意味している。
つまり、行列A_{ij}での特異値分解A = USV^+
を$A_{ij} = U_{il} S_l V_{jl}$と書いたときのiである。
特異値分解を使うと情報を減らすことができる。
特異値のうち小さいものを除去することで、行列のサイズを小さくすることができる。これは、
auto T = randomITensor(i,j,k);
auto [U,S,V] = svd(T,{i,k},{"Cutoff=",1E-2,"MaxDim=",50});
とすればよい。ここで、特異値がCutoff以下のものを切り捨て、特異値の数は最大でもMaxDimとする、としている。
ある値以下の特異値を捨て去るということは、元のテンソルと差のノルムが
auto truncerr = sqr(norm(U*S*V - T)/norm(T));
Print(truncerr);
//typical output: truncerr = 9.24E-03
となることを意味している。