5、Tensor Decompositions(张量分解)(这一节很基础很重要)
许多常用的张量网络分解都是由矩阵分解建立起来的,如线性代数中已知的QR和奇异值分解(SVD)。
QR分解
T = randomITensor(i,j,k)
Q,R = qr(T,(i,k))
一个新的索引由qr函数生成,它将Q张量连接到R张量,如上所示。这使得只需使用*算子就可以直接恢复张量T:
Q*R ≈ T # true
但是,在希望检索此索引的情况下,一个方便的方法如下:
q = commonind(Q,R) # (dim=3|id=680|"Link,qr")
SVD在张量网络的计算中起着关键作用
W = randomITensor(i,j,m,k)
U,S,V = svd(W,(j,i))
U*S*V ≈ W # true

某些分解的一个重要特征,如SVD分解,是它们允许由因子分解产生的张量的控制截断。默认情况下,ITensor分解不会截断,尽管它们总是在可用时计算分解的“薄”版本。截断分解可以通过指定截断关键字参数来计算截断分解。在以下示例中
U,S,V = svd(W,(j,i);cutoff=1E-8,maxdim=10)
以下是一个小例子:
i=Index(3,"i")
j=Index(3,"j")
W=randomITensor(i,j)
U,S,V=svd(W,i;cutoff=1E-8,maxdim=10)
输出如下
ITensors.TruncSVD(ITensor ord=2
Dim 1: (dim=3|id=25|"i")
Dim 2: (dim=3|id=244|"Link,u")
NDTensors.Dense{Float64, Vector{Float64}}3×3-0.06074520753072965 0.3515955948952047 0.93417908208883380.36492821122555147 -0.8632923319783523 0.34864559397631610.9290518932835605 0.3620868503517718 -0.07586627965417801, ITensor ord=2
Dim 1: (dim=3|id=244|"Link,u")
Dim 2: (dim=3|id=711|"Link,v")
NDTensors.Diag{Float64, Vector{Float64}}3×31.3004500523343754 0.0 0.00.0 0.7714923084829652 0.00.0 0.0 0.15709690229548853, ITensor ord=2
Dim 1: (dim=3|id=278|"j")
Dim 2: (dim=3|id=711|"Link,v")
NDTensors.Dense{Float64, Vector{Float64}}3×30.4071617933196845 0.3024337543624265 -0.8618312469868716-0.6716870002226061 0.7385486473263854 -0.0581589998566261340.6189150570091626 0.602560967666023 0.503849612932997, Spectrum{Vector{Float64}, Float64}([1.6911703386164796, 0.5952003820483748, 0.02467943671083827], 0.0), (dim=3|id=244|"Link,u"), (dim=3|id=711|"Link,v"))
如果修改截断为
U,S,V=svd(W,i;cutoff=1E-8,maxdim=2)
结果可以将奇异值只保留前两个最大的
ITensors.TruncSVD(ITensor ord=2
Dim 1: (dim=3|id=25|"i")
Dim 2: (dim=2|id=459|"Link,u")
NDTensors.Dense{Float64, Vector{Float64}}3×2-0.06074520753072965 0.35159559489520470.36492821122555147 -0.86329233197835230.9290518932835605 0.3620868503517718, ITensor ord=2
Dim 1: (dim=2|id=459|"Link,u")
Dim 2: (dim=2|id=176|"Link,v")
NDTensors.Diag{Float64, Vector{Float64}}2×21.3004500523343754 0.00.0 0.7714923084829652, ITensor ord=2
Dim 1: (dim=3|id=278|"j")
Dim 2: (dim=2|id=176|"Link,v")
NDTensors.Dense{Float64, Vector{Float64}}3×20.4071617933196845 0.3024337543624265-0.6716870002226061 0.73854864732638540.6189150570091626 0.602560967666023, Spectrum{Vector{Float64}, Float64}([1.6911703386164796, 0.5952003820483748], 0.010678884070115963), (dim=2|id=459|"Link,u"), (dim=2|id=176|"Link,v"))
为了能看懂输出,我修改了以下输出格式
ITensors.TruncSVD(
------------------------------------------------------
ITensor ord=2
Dim 1: (dim=3|id=25|"i") <--------- 如下右图第一个圆的左索引名称为“i”,维度为3
Dim 2: (dim=2|id=459|"Link,u") <--------- 如下右图第一个圆的右索引名称为“u”,维度为2
NDTensors.Dense{Float64, Vector{Float64}}3×2-0.06074520753072965 0.35159559489520470.36492821122555147 -0.86329233197835230.9290518932835605 0.3620868503517718,
------------------------------------------------------
ITensor ord=2
Dim 1: (dim=2|id=459|"Link,u") <--------- 如下右图第二个圆的左索引名称为“u”,维度为2
Dim 2: (dim=2|id=176|"Link,v") <--------- 如下右图第二个圆的右索引名称为“v”,维度为2
NDTensors.Diag{Float64, Vector{Float64}}2×21.3004500523343754 0.0 <--------- 对应的奇异值由大到小排列,由于截断设为2,故只剩两个最大的奇异值0.0 0.7714923084829652,
------------------------------------------------------
ITensor ord=2
Dim 1: (dim=3|id=278|"j") <--------- 如下右图第三个圆的右索引名称为“j”,维度为3
Dim 2: (dim=2|id=176|"Link,v") <--------- 如下右图第三个圆的左索引名称为“v”,维度为2
NDTensors.Dense{Float64, Vector{Float64}}3×20.4071617933196845 0.3024337543624265-0.6716870002226061 0.73854864732638540.6189150570091626 0.602560967666023,
------------------------------------------------------
Spectrum{Vector{Float64}, Float64}([1.6911703386164796, 0.5952003820483748], 0.010678884070115963), (dim=2|id=459|"Link,u"), (dim=2|id=176|"Link,v"))
这样可以很清晰的看到分解过后的三个矩阵,虽然没什么实用价值,但是在初学阶段有助于理解程序。

