Skip to content

Commit 6e16161

Browse files
authored
Start adding infinite TDVP interface (#38)
* Start adding infinite TDVP interface by sharing code with VUMPS and swapping out the solver. VUMPS can be run with a TDVP time step of `-Inf`. Currently sequential TDVP gives incorrect results, and parallel TDVP is broken. * Add better formatting Github Action.
1 parent e126828 commit 6e16161

File tree

6 files changed

+132
-58
lines changed

6 files changed

+132
-58
lines changed

.github/workflows/format_check.yml

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,35 @@
1-
name: format-check
2-
1+
name: Format check
32
on:
43
push:
5-
branches:
6-
- 'main'
7-
- 'release-'
8-
tags: '*'
4+
branches: [master]
5+
tags: [v*]
96
pull_request:
107

118
jobs:
12-
build:
13-
runs-on: ${{ matrix.os }}
14-
strategy:
15-
matrix:
16-
julia-version: [1.7.1]
17-
julia-arch: [x86]
18-
os: [ubuntu-latest]
9+
format:
10+
name: "Format Check"
11+
runs-on: ubuntu-latest
1912
steps:
20-
- uses: julia-actions/setup-julia@latest
13+
- uses: actions/checkout@v2
14+
- uses: julia-actions/setup-julia@v1
2115
with:
22-
version: ${{ matrix.julia-version }}
23-
24-
- uses: actions/checkout@v1
16+
version: 1
2517
- name: Install JuliaFormatter and format
26-
# This will use the latest version by default but you can set the version like so:
27-
#
28-
# julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter", version="0.13.0"))'
2918
run: |
3019
julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter"))'
3120
julia -e 'using JuliaFormatter; format(".", verbose=true)'
32-
- name: Format check
21+
- name: Check format
3322
run: |
3423
julia -e '
3524
out = Cmd(`git diff --name-only`) |> read |> String
3625
if out == ""
3726
exit(0)
3827
else
39-
@error "Some files have not been formatted !!!"
28+
@error "The following files have not been formatted:"
4029
write(stdout, out)
30+
out_diff = Cmd(`git diff`) |> read |> String
31+
@error "Diff:"
32+
write(stdout, out_diff)
4133
exit(1)
34+
@error ""
4235
end'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Format suggestions
2+
3+
on:
4+
pull_request:
5+
6+
concurrency:
7+
# Skip intermediate builds: always.
8+
# Cancel intermediate builds: only if it is a pull request build.
9+
group: ${{ github.workflow }}-${{ github.ref }}
10+
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
11+
12+
jobs:
13+
format:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v2
17+
- uses: julia-actions/setup-julia@latest
18+
with:
19+
version: 1
20+
- run: |
21+
julia -e 'using Pkg; Pkg.add("JuliaFormatter")'
22+
julia -e 'using JuliaFormatter; format("."; verbose=true)'
23+
- uses: reviewdog/action-suggester@v1
24+
with:
25+
tool_name: JuliaFormatter
26+
fail_on_error: true
27+
filter_mode: added

examples/vumps/vumps_ising.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ maxdim = 5 # Maximum bond dimension
99
cutoff = 1e-12 # Singular value cutoff when increasing the bond dimension
1010
max_vumps_iters = 10 # Maximum number of iterations of the VUMPS algorithm at a fixed bond dimension
1111
outer_iters = 10 # Number of times to increase the bond dimension
12+
time_step = -Inf # -Inf corresponds to VUMPS
1213

1314
# Parameters of the transverse field Ising model
14-
model_params = (J=1.0, h=0.8)
15+
model_params = (J=1.0, h=0.9)
1516

1617
##############################################################################
1718
# CODE BELOW HERE DOES NOT NEED TO BE MODIFIED
@@ -38,14 +39,14 @@ H = InfiniteITensorSum(model, s; model_params...)
3839

3940
vumps_kwargs = (tol=1e-5, maxiter=max_vumps_iters)
4041
subspace_expansion_kwargs = (cutoff=cutoff, maxdim=maxdim)
41-
ψ = vumps(H, ψ; vumps_kwargs...)
42+
ψ = tdvp(H, ψ; time_step=time_step, vumps_kwargs...)
4243

4344
# Alternate steps of running VUMPS and increasing the bond dimension
4445
@time for _ in 1:outer_iters
4546
println("\nIncrease bond dimension")
4647
global ψ = subspace_expansion(ψ, H; subspace_expansion_kwargs...)
4748
println("Run VUMPS with new bond dimension")
48-
global ψ = vumps(H, ψ; vumps_kwargs...)
49+
global ψ = tdvp(H, ψ; time_step=time_step, vumps_kwargs...)
4950
end
5051

5152
# Check translational invariance

src/ITensorInfiniteMPS.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ using HDF5
1818
using QuadGK
1919

2020
using ITensors.NDTensors: eachdiagblock
21-
using KrylovKit: eigsolve, linsolve
21+
using KrylovKit: eigsolve, linsolve, exponentiate
2222

2323
import Base: getindex, length, setindex!, +, -, *
2424

@@ -67,6 +67,7 @@ export Cell,
6767
reference,
6868
subspace_expansion,
6969
translatecell,
70+
tdvp,
7071
vumps,
7172
,
7273
,

src/vumps_mpo.jl renamed to src/broken/vumps_mpo.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
#################################################################
2+
# XXX: This version of VUMPS using MPOs is not working. It was
3+
# the initial implementation of VUMPS I (@mtfishman) tried to make, but
4+
# there was a bug and it was temporarily abandoned in favor
5+
# of the simpler local Hamiltonian implementation found in
6+
# `src/vumps_localham.jl`. Help getting this working would be highly
7+
# appreciated so we can support more generic Hamiltonians.
8+
# Ideally, the implementation would only overload the minimal amount
9+
# of code needed to be modified (like computing quasi-left and
10+
# right environments and updates to `AC` and `C`), and share the high
11+
# level code with the existing VUMPS code in `src/vumps_localham.jl`.
12+
#
13+
# Please reach out on this issue: https://github.com/ITensor/ITensorInfiniteMPS.jl/issues/39
14+
# if you are interested in implementing this feature.
15+
#################################################################
116

217
# Make an ITensorMap representing the transfer matrix T|v> = |Tv>
318
function transfer_matrix::InfiniteMPS)

src/vumps_localham.jl

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -184,28 +184,30 @@ function right_environment(hᴿ, ψ; tol=1e-15)
184184
return Hᴿ
185185
end
186186

187-
function vumps_iteration(args...; multisite_update_alg="sequential", kwargs...)
187+
function tdvp_iteration(args...; multisite_update_alg="sequential", kwargs...)
188188
if multisite_update_alg == "sequential"
189-
return vumps_iteration_sequential(args...; kwargs...)
189+
return tdvp_iteration_sequential(args...; kwargs...)
190190
elseif multisite_update_alg == "parallel"
191-
return vumps_iteration_parallel(args...; kwargs...)
191+
return tdvp_iteration_parallel(args...; kwargs...)
192192
else
193193
error(
194194
"Multisite update algorithm multisite_update_alg = $multisite_update_alg not supported, use \"parallel\" or \"sequential\"",
195195
)
196196
end
197197
end
198198

199-
function vumps_iteration_sequential(
199+
function tdvp_iteration_sequential(
200+
solver::Function,
200201
∑h::InfiniteITensorSum,
201202
ψ::InfiniteCanonicalMPS;
202203
(ϵᴸ!)=fill(1e-15, nsites(ψ)),
203204
(ϵᴿ!)=fill(1e-15, nsites(ψ)),
204-
eigsolve_tol=(x -> x / 100),
205+
time_step,
206+
solver_tol=(x -> x / 100),
205207
)
206208
Nsites = nsites(ψ)
207209
ϵᵖʳᵉˢ = max(maximum(ϵᴸ!), maximum(ϵᴿ!))
208-
krylov_tol = eigsolve_tol(ϵᵖʳᵉˢ)
210+
_solver_tol = solver_tol(ϵᵖʳᵉˢ)
209211
ψᴴ = dag(ψ)
210212
ψ′ = ψᴴ'
211213
# XXX: make this prime the center sites
@@ -267,24 +269,23 @@ function vumps_iteration_sequential(
267269
for k in 1:Nsites
268270
𝕙ᴸ[k] = left_environment_cell(ψ, ψ̃, hᴸ, k)
269271
end
270-
Hᴸ = left_environment(hᴸ, 𝕙ᴸ, ψ; tol=krylov_tol)
272+
Hᴸ = left_environment(hᴸ, 𝕙ᴸ, ψ; tol=_solver_tol)
271273
for k in 2:Nsites
272274
hᴿ[k] = hᴿ[k + 1] * ψ.AR[k + 1] * ψ̃.AR[k + 1] + hᴿ[k]
273275
end
274-
Hᴿ = right_environment(hᴿ, ψ; tol=krylov_tol)
276+
Hᴿ = right_environment(hᴿ, ψ; tol=_solver_tol)
275277

276-
Cvalsₙ₋₁, Cvecsₙ₋₁, Cinfoₙ₋₁ = eigsolve(
277-
Hᶜ(∑h, Hᴸ, Hᴿ, ψ, n - 1), ψ.C[n - 1], 1, :SR; ishermitian=true, tol=krylov_tol
278+
Cvalsₙ₋₁, Cvecsₙ₋₁, Cinfoₙ₋₁ = solver(
279+
Hᶜ(∑h, Hᴸ, Hᴿ, ψ, n - 1), time_step, ψ.C[n - 1], _solver_tol
278280
)
279-
Cvalsₙ, Cvecsₙ, Cinfoₙ = eigsolve(
280-
Hᶜ(∑h, Hᴸ, Hᴿ, ψ, n), ψ.C[n], 1, :SR; ishermitian=true, tol=krylov_tol
281+
Cvalsₙ, Cvecsₙ, Cinfoₙ = solver(Hᶜ(∑h, Hᴸ, Hᴿ, ψ, n), time_step, ψ.C[n], _solver_tol)
282+
Avalsₙ, Avecsₙ, Ainfoₙ = solver(
283+
Hᴬᶜ(∑h, Hᴸ, Hᴿ, ψ, n), time_step, ψ.AL[n] * ψ.C[n], _solver_tol
281284
)
282-
Avalsₙ, Avecsₙ, Ainfoₙ = eigsolve(
283-
Hᴬᶜ(∑h, Hᴸ, Hᴿ, ψ, n), ψ.AL[n] * ψ.C[n], 1, :SR; ishermitian=true, tol=krylov_tol
284-
)
285-
C̃[n - 1] = Cvecsₙ₋₁[1]
286-
C̃[n] = Cvecsₙ[1]
287-
Ãᶜ[n] = Avecsₙ[1]
285+
286+
C̃[n - 1] = Cvecsₙ₋₁
287+
C̃[n] = Cvecsₙ
288+
Ãᶜ[n] = Avecsₙ
288289

289290
function ortho_overlap(AC, C)
290291
AL, _ = polar(AC * dag(C), uniqueinds(AC, C))
@@ -324,16 +325,17 @@ function vumps_iteration_sequential(
324325
return ψ, (eᴸ, eᴿ)
325326
end
326327

327-
function vumps_iteration_parallel(
328+
function tdvp_iteration_parallel(
329+
solver::Function,
328330
∑h::InfiniteITensorSum,
329331
ψ::InfiniteCanonicalMPS;
330332
(ϵᴸ!)=fill(1e-15, nsites(ψ)),
331333
(ϵᴿ!)=fill(1e-15, nsites(ψ)),
332-
eigsolve_tol=(x -> x / 100),
334+
solver_tol=(x -> x / 100),
333335
)
334336
Nsites = nsites(ψ)
335337
ϵᵖʳᵉˢ = max(maximum(ϵᴸ!), maximum(ϵᴿ!))
336-
krylov_tol = ϵᵖʳᵉˢ / 100
338+
_solver_tol = solver_tol(ϵᵖʳᵉˢ)
337339
ψᴴ = dag(ψ)
338340
ψ′ = ψᴴ'
339341
# XXX: make this prime the center sites
@@ -381,22 +383,21 @@ function vumps_iteration_parallel(
381383
for n in 2:Nsites
382384
hᴸ[n] = hᴸ[n - 1] * ψ.AL[n] * ψ̃.AL[n] + hᴸ[n]
383385
end
384-
Hᴸ = left_environment(hᴸ, ψ; tol=krylov_tol)
386+
Hᴸ = left_environment(hᴸ, ψ; tol=_solver_tol)
385387

386388
for n in 2:Nsites
387389
hᴿ[n] = hᴿ[n + 1] * ψ.AR[n + 1] * ψ̃.AR[n + 1] + hᴿ[n]
388390
end
389-
Hᴿ = right_environment(hᴿ, ψ; tol=krylov_tol)
391+
Hᴿ = right_environment(hᴿ, ψ; tol=_solver_tol)
390392

391393
= InfiniteMPS(Vector{ITensor}(undef, Nsites))
392394
Ãᶜ = InfiniteMPS(Vector{ITensor}(undef, Nsites))
393395
for n in 1:Nsites
394-
Cvalsₙ, Cvecsₙ, Cinfoₙ = eigsolve(
395-
Hᶜ(∑h, Hᴸ, Hᴿ, ψ, n), ψ.C[n], 1, :SR; ishermitian=true, tol=krylov_tol
396-
)
397-
Avalsₙ, Avecsₙ, Ainfoₙ = eigsolve(
398-
Hᴬᶜ(∑h, Hᴸ, Hᴿ, ψ, n), ψ.AL[n] * ψ.C[n], 1, :SR; ishermitian=true, tol=krylov_tol
396+
Cvalsₙ, Cvecsₙ, Cinfoₙ = solver(Hᶜ(∑h, Hᴸ, Hᴿ, ψ, n), time_step, ψ.C[n], _solver_tol)
397+
Avalsₙ, Avecsₙ, Ainfoₙ = solver(
398+
Hᴬᶜ(∑h, Hᴸ, Hᴿ, ψ, n), time_step, ψ.AL[n] * ψ.C[n], _solver_tol
399399
)
400+
400401
C̃[n] = Cvecsₙ[1]
401402
Ãᶜ[n] = Avecsₙ[1]
402403
end
@@ -421,28 +422,32 @@ function vumps_iteration_parallel(
421422
return InfiniteCanonicalMPS(Ãᴸ, C̃, Ãᴿ), (eᴸ, eᴿ)
422423
end
423424

424-
function vumps(
425+
function tdvp(
426+
solver::Function,
425427
∑h,
426428
ψ;
427429
maxiter=10,
428430
tol=1e-8,
429431
outputlevel=1,
430432
multisite_update_alg="sequential",
431-
eigsolve_tol=(x -> x / 100),
433+
solver_tol=(x -> x / 100),
434+
time_step,
432435
)
433436
N = nsites(ψ)
434437
(ϵᴸ!) = fill(tol, nsites(ψ))
435438
(ϵᴿ!) = fill(tol, nsites(ψ))
436439
outputlevel > 0 &&
437440
println("Running VUMPS with multisite_update_alg = $multisite_update_alg")
438441
for iter in 1:maxiter
439-
ψ, (eᴸ, eᴿ) = vumps_iteration(
442+
ψ, (eᴸ, eᴿ) = tdvp_iteration(
443+
solver,
440444
∑h,
441445
ψ;
442446
(ϵᴸ!)=(ϵᴸ!),
443447
(ϵᴿ!)=(ϵᴿ!),
444448
multisite_update_alg=multisite_update_alg,
445-
eigsolve_tol=eigsolve_tol,
449+
solver_tol=solver_tol,
450+
time_step=time_step,
446451
)
447452
ϵᵖʳᵉˢ = max(maximum(ϵᴸ!), maximum(ϵᴿ!))
448453
maxdimψ = maxlinkdim(ψ[0:(N + 1)])
@@ -459,6 +464,38 @@ function vumps(
459464
return ψ
460465
end
461466

467+
function vumps_solver(M, time_step, v₀, solver_tol)
468+
λ⃗, v⃗, info = eigsolve(M, v₀, 1, :SR; ishermitian=true, tol=solver_tol)
469+
return λ⃗[1], v⃗[1], info
470+
end
471+
472+
return function tdvp_solver(M, time_step, v₀, solver_tol)
473+
v, info = exponentiate(M, time_step, v₀; ishermitian=true, tol=solver_tol)
474+
return nothing, v, info
475+
end
476+
477+
function vumps(
478+
args...; time_step=-Inf, eigsolve_tol=(x -> x / 100), solver_tol=eigsolve_tol, kwargs...
479+
)
480+
@assert isinf(time_step) && time_step < 0
481+
println("Using VUMPS solver with time step $time_step")
482+
return tdvp(vumps_solver, args...; time_step=time_step, solver_tol=solver_tol, kwargs...)
483+
end
484+
485+
function tdvp(args...; time_step, solver_tol=(x -> x / 100), kwargs...)
486+
solver = if !isinf(time_step)
487+
println("Using TDVP solver with time step $time_step")
488+
tdvp_solver
489+
elseif time_step < 0
490+
# Call VUMPS instead
491+
println("Using VUMPS solver with time step $time_step")
492+
vumps_solver
493+
else
494+
error("Time step $time_step not supported.")
495+
end
496+
return tdvp(solver, args...; time_step=time_step, solver_tol=solver_tol, kwargs...)
497+
end
498+
462499
##################################################################
463500
# Old functionality, only used for testing
464501

0 commit comments

Comments
 (0)