Skip to content

Commit 830df92

Browse files
authored
VUMPS with Infinite MPO (#50)
1 parent 05c2044 commit 830df92

File tree

13 files changed

+892
-100
lines changed

13 files changed

+892
-100
lines changed

examples/vumps/development/vumps_mpo.jl

Lines changed: 35 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,43 @@ using ITensors
22
using ITensorInfiniteMPS
33
using Random
44

5-
# Helper function to make an MPO
6-
import ITensors: op
7-
op(::OpName"Zero", ::SiteType"S=1/2", s::Index) = ITensor(s', dag(s))
8-
9-
function tfi_mpo(s, l, r; J=1.0, h)
10-
dₗ = 3 # The link dimension of the TFI
11-
Hmat = fill(op("Zero", s), dₗ, dₗ)
12-
Hmat[1, 1] = op("Id", s)
13-
Hmat[2, 2] = op("Id", s)
14-
Hmat[3, 3] = op("Id", s)
15-
Hmat[2, 1] = -J * op("X", s)
16-
Hmat[3, 2] = -J * op("X", s)
17-
Hmat[3, 1] = -h * op("Z", s)
18-
H = ITensor()
19-
for i in 1:dₗ, j in 1:dₗ
20-
H += Hmat[i, j] * setelt(l => i) * setelt(r => j)
21-
end
22-
return H
5+
# Parameters
6+
cutoff = 1e-8
7+
maxdim = 100
8+
tol = 1e-8
9+
maxiter = 20
10+
outer_iters = 3
11+
12+
N = 2
13+
model = Model"ising"()
14+
15+
function space_shifted(::Model"ising", q̃sz)
16+
return [QN("SzParity", 1 - q̃sz, 2) => 1, QN("SzParity", 0 - q̃sz, 2) => 1]
2317
end
2418

25-
Random.seed!(1234)
26-
27-
N = 1
28-
s = siteinds("S=1/2", N)
29-
χ = 6
30-
@assert iseven(χ)
31-
if any(hasqns, s)
32-
space = (("SzParity", 1, 2) => χ ÷ 2) (("SzParity", 0, 2) => χ ÷ 2)
33-
else
34-
space = χ
35-
end
36-
#ψ = InfiniteMPS(ComplexF64, s; space = space)
37-
ψ = InfiniteMPS(s; space=space)
38-
randn!.(ψ)
39-
40-
# Use a finite MPO to create the infinite MPO
41-
H = InfiniteMPO(N)
42-
43-
# H = -J Σⱼ XⱼXⱼ₊₁ - h Σⱼ Zⱼ
44-
J = 1.0
45-
h = 2.0
46-
47-
# For the finite unit cell
48-
= addtags.(s, "c=1")
49-
= [Index(3, "Link,l=$n,c=1") for n in 1:N]
50-
for n in 1:N
51-
# TODO: use a CelledVector here to make the code logic simpler
52-
l¹ₙ = n == 1 ? replacetags(dag(l¹[N]), "c=1" => "c=0") : l¹[n - 1]
53-
r¹ₙ = l¹[n]
54-
H[n] = tfi_mpo(s¹[n], l¹ₙ, r¹ₙ; J=J, h=h)
19+
space_ = fill(space_shifted(model, 1), N)
20+
s = infsiteinds("S=1/2", N; space=space_)
21+
initstate(n) = ""
22+
ψ = InfMPS(s, initstate)
23+
24+
model_params = (J=-1.0, h=0.9)
25+
vumps_kwargs = (multisite_update_alg="sequential", tol=tol, maxiter=maxiter)
26+
subspace_expansion_kwargs = (cutoff=cutoff, maxdim=maxdim)
27+
28+
H = InfiniteITensorSum(model, s; model_params...)
29+
# Alternate steps of running VUMPS and increasing the bond dimension
30+
ψ1 = vumps(H, ψ; vumps_kwargs...)
31+
for _ in 1:outer_iters
32+
ψ1 = subspace_expansion(ψ1, H; subspace_expansion_kwargs...)
33+
ψ1 = vumps(H, ψ1; vumps_kwargs...)
5534
end
5635

57-
ψf = vumps(H, ψ; nsweeps=10)
36+
Hmpo = InfiniteMPOMatrix(model, s; model_params...)
37+
# Alternate steps of running VUMPS and increasing the bond dimension
38+
ψ2 = vumps(Hmpo, ψ; vumps_kwargs...)
39+
for _ in 1:outer_iters
40+
ψ2 = subspace_expansion(ψ2, Hmpo; subspace_expansion_kwargs...)
41+
ψ2 = vumps(Hmpo, ψ2; vumps_kwargs...)
42+
end
5843

59-
s⃗ = [uniqueind(ψ[n], ψ[n - 1], ψ[n + 1]) for n in 1:2]
60-
h = -J * op("X", s⃗, 1) * op("X", s⃗, 2) - h * op("Z", s⃗, 1) * op("Id", s⃗, 2)
61-
#ψ2 = ψf.AL[1] * ψf.C[1] * ψf.AR[2]
62-
ψ2 = ψf.AL[1] * ψf.AL[2] * ψf.C[2]
63-
@show ψ2 * h * prime(dag(ψ2), "Site")
44+
SzSz = prod(op("Sz", s[1]) * op("Sz", s[2]))

src/ITensorInfiniteMPS.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ include("abstractinfinitemps.jl")
3232
include("infinitemps.jl")
3333
include("infinitempo.jl")
3434
include("infinitecanonicalmps.jl")
35+
include("infinitempomatrix.jl")
3536
include("transfermatrix.jl")
3637
include("models/models.jl")
3738
include("models/ising.jl")
@@ -44,6 +45,7 @@ include("infinitemps_approx.jl")
4445
include("nullspace.jl")
4546
include("subspace_expansion.jl")
4647
include("vumps_localham.jl")
48+
include("vumps_mpo.jl")
4749

4850
export Cell,
4951
CelledVector,
@@ -52,6 +54,7 @@ export Cell,
5254
InfMPS,
5355
InfiniteSum,
5456
InfiniteMPO,
57+
InfiniteMPOMatrix,
5558
InfiniteSumLocalOps,
5659
ITensorMap,
5760
ITensorNetwork,

src/celledvectors.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ end
5656

5757
translatecell(T::ITensor, n::Integer) = ITensors.setinds(T, translatecell(inds(T), n))
5858
translatecell(T::MPO, n::Integer) = translatecell.(T, n)
59+
translatecell(T::Matrix{ITensor}, n::Integer) = translatecell.(T, n)
5960

6061
struct CelledVector{T} <: AbstractVector{T}
6162
data::Vector{T}

src/infinitempo.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55

66
mutable struct InfiniteMPO <: AbstractInfiniteMPS
7-
data::Vector{ITensor}
7+
data::CelledVector{ITensor}
88
llim::Int #RealInfinity
99
rlim::Int #RealInfinity
1010
reverse::Bool
@@ -16,3 +16,5 @@ end
1616
## InfiniteSumLocalOps(N::Int) = InfiniteSumLocalOps(Vector{ITensor}(undef, N))
1717
## InfiniteSumLocalOps(data::Vector{ITensor}) = InfiniteSumLocalOps(CelledVector(data))
1818
## getindex(l::InfiniteSumLocalOps, n::Integer) = ITensors.data(l)[n]
19+
20+
# TODO? Instead of having a big quasi empty ITensor, store only the non zero blocks

src/infinitempomatrix.jl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
mutable struct InfiniteMPOMatrix <: AbstractInfiniteMPS
3+
data::CelledVector{Matrix{ITensor}}
4+
llim::Int #RealInfinity
5+
rlim::Int #RealInfinity
6+
reverse::Bool
7+
end
8+
9+
# TODO better printing?
10+
function Base.show(io::IO, M::InfiniteMPOMatrix)
11+
print(io, "$(typeof(M))")
12+
(length(M) > 0) && print(io, "\n")
13+
for i in eachindex(M)
14+
if !isassigned(M, i)
15+
println(io, "#undef")
16+
else
17+
A = M[i]
18+
println(io, "Matrix tensor of size $(size(A))")
19+
for k in 1:size(A)[1], l in 1:size(A)[2]
20+
if !isassigned(A, k + (size(A)[1] - 1) * l)
21+
println(io, "[($k, $l)] #undef")
22+
elseif isempty(A[k, l])
23+
println(io, "[($k, $l)] empty")
24+
else
25+
println(io, "[($k, $l)] $(inds(A[k, l]))")
26+
end
27+
end
28+
end
29+
end
30+
end
31+
32+
function getindex::InfiniteMPOMatrix, n::Integer)
33+
return ψ.data[n]
34+
end
35+
36+
function InfiniteMPOMatrix(arrMat::Vector{Matrix{ITensor}})
37+
return InfiniteMPOMatrix(arrMat, 0, size(arrMat)[1], false)
38+
end
39+
40+
#nrange(H::InfiniteMPOMatrix) = [size(H[j])[1] - 1 for j in 1:nsites(H)]

src/infinitemps.jl

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,31 @@ struct InfiniteSum{T}
8888
end
8989
InfiniteSum{T}(N::Int) where {T} = InfiniteSum{T}(Vector{T}(undef, N))
9090
InfiniteSum{T}(data::Vector{T}) where {T} = InfiniteSum{T}(CelledVector(data))
91-
9291
# Automatically converts from ITensor to MPO.
9392
# XXX: check this conversion is correct.
94-
InfiniteSum{T}(data::Vector{ITensor}) where {T} = InfiniteSum{T}(CelledVector(T.(data)))
93+
#InfiniteSum{T}(data::Vector{ITensor}) where {T} = InfiniteSum{T}(CelledVector(T.(data)))
94+
#This crashed for me when T is ITensor
95+
function InfiniteSum{MPO}(data::Vector{ITensor})
96+
N = length(data)
97+
temp_inds = [filterinds(data[n]; plev=0) for n in 1:N]
98+
return InfiniteSum{MPO}([
99+
MPO(
100+
data[n],
101+
[(temp_inds[n][j], dag(prime(temp_inds[n][j]))) for j in 1:length(temp_inds[n])],
102+
) for n in 1:N
103+
])
104+
end
105+
106+
function InfiniteSum{MPO}(infsum::InfiniteSum{ITensor})
107+
N = nsites(infsum)
108+
temp_inds = [filterinds(infsum[n]; plev=0) for n in 1:N]
109+
return InfiniteSum{MPO}([
110+
MPO(
111+
infsum[n],
112+
[(temp_inds[n][j], dag(prime(temp_inds[n][j]))) for j in 1:length(temp_inds[n])],
113+
) for n in 1:N
114+
])
115+
end
95116

96117
function Base.getindex(l::InfiniteSum, n1n2::Tuple{Int,Int})
97118
n1, n2 = n1n2

src/models/models.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ function InfiniteSum{MPO}(model::Model, s::CelledVector; kwargs...)
2828
return InfiniteSum{MPO}(mpos)
2929
end
3030

31+
function InfiniteSum{ITensor}(model::Model, s::CelledVector; kwargs...)
32+
N = length(s)
33+
itensors = [ITensor(model, s, n; kwargs...) for n in 1:N] #slightly improved version. Note: the current implementation does not really allow for staggered potentials for example
34+
return InfiniteSum{ITensor}(itensors)
35+
end
36+
3137
# MPO building version
3238
function ITensors.MPO(model::Model, s::CelledVector, n::Int64; kwargs...)
3339
n1, n2 = 1, 2
@@ -39,3 +45,33 @@ end
3945
function ITensors.ITensor(model::Model, s::CelledVector, n::Int64; kwargs...)
4046
return prod(MPO(model, s, n; kwargs...)) #modification to allow for more than two sites per term in the Hamiltonians
4147
end
48+
49+
# Helper function to make an MPO
50+
import ITensors: op
51+
op(::OpName"Zero", ::SiteType, s::Index) = ITensor(s', dag(s))
52+
53+
function InfiniteMPOMatrix(model::Model, s::CelledVector; kwargs...)
54+
N = length(s)
55+
temp_H = InfiniteSum{MPO}(model, s; kwargs...)
56+
range_H = nrange(temp_H)[1]
57+
ls = CelledVector([Index(1, "Link,c=1,n=$n") for n in 1:N])
58+
mpos = [Matrix{ITensor}(undef, 1, 1) for i in 1:N]
59+
for j in 1:N
60+
Hmat = fill(op("Zero", s[j]), range_H + 1, range_H + 1)
61+
identity = op("Id", s[j])
62+
Hmat[1, 1] = identity
63+
Hmat[end, end] = identity
64+
for n in 0:(range_H - 1)
65+
idx = findfirst(x -> x == j, findsites(temp_H[j - n]; ncell=N))
66+
if isnothing(idx)
67+
Hmat[range_H + 1 - n, range_H - n] = identity
68+
else
69+
Hmat[range_H + 1 - n, range_H - n] = temp_H[j - n][idx]#replacetags(linkinds, temp_H[j - n][idx], "Link, l=$n", tags(ls[j-1]))
70+
end
71+
end
72+
mpos[j] = Hmat
73+
#mpos[j] += dense(Hmat) * setelt(ls[j-1] => total_dim) * setelt(ls[j] => total_dim)
74+
end
75+
#return mpos
76+
return InfiniteMPOMatrix(mpos)
77+
end

src/orthogonalize.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,15 @@ function mixed_canonical(
145145
end
146146

147147
ITensors.orthogonalize::InfiniteMPS, ::Colon; kwargs...) = mixed_canonical(ψ; kwargs...)
148+
149+
#TODO put these functions somewhere else
150+
function ortho_overlap(AC, C)
151+
AL, _ = polar(AC * dag(C), uniqueinds(AC, C))
152+
return noprime(AL)
153+
end
154+
155+
function ortho_polar(AC, C)
156+
UAC, _ = polar(AC, uniqueinds(AC, C))
157+
UC, _ = polar(C, commoninds(C, AC))
158+
return noprime(UAC) * noprime(dag(UC))
159+
end

0 commit comments

Comments
 (0)