Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging utilities #51

Merged
merged 52 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
bdafc8d
Fix offset in wrong direction
lkdvos Jul 2, 2024
9b6b7df
Add contraction arbitrary local operator
lkdvos Jul 2, 2024
2f21958
Add contraction arbitrary local norm
lkdvos Jul 2, 2024
ce134c0
Add PEPSHamiltonian
lkdvos Jul 2, 2024
8700e78
Add nearest_neighbour hamiltonian
lkdvos Jul 2, 2024
692cefe
Further implement PEPSHamiltonian
lkdvos Jul 2, 2024
fc3f3e0
Update models to new interface
lkdvos Jul 2, 2024
2352f50
Implement warning in AD-compatible way
lkdvos Jul 2, 2024
bc96e06
Add cost model for contraction order
lkdvos Jul 2, 2024
9e26775
Cleanup
lkdvos Jul 2, 2024
fb4ea7d
Fixup contraction with N-body terms
lkdvos Jul 2, 2024
483d337
Revert accidental factor 1/4 in Heisenberg model
lkdvos Jul 3, 2024
a5bfde2
Add unitcell to models
lkdvos Jul 3, 2024
3a661da
Ensure lattice compatibility
lkdvos Jul 3, 2024
c6677d0
Print output gradient tests
lkdvos Jul 3, 2024
7fde9b4
Fix typo
lkdvos Jul 3, 2024
7a161da
Fix typo attempt II
lkdvos Jul 3, 2024
f59697a
Fix typo attempt III
lkdvos Jul 3, 2024
097fc8f
Fix spacecheck
lkdvos Jul 3, 2024
da51ce6
Adjust local operator code to new unit cell convention, add 2x2 Heise…
pbrehmer Jul 3, 2024
28d016e
Merge branch 'ld-expval' of github.com:quantumghent/PEPSKit.jl into l…
pbrehmer Jul 3, 2024
906bf38
Fix formatting
pbrehmer Jul 3, 2024
9cc218d
Fix Heisenberg 2x2 test
pbrehmer Jul 3, 2024
2156c66
Fix left_move for unit cells larger than (2, 2)
pbrehmer Jul 3, 2024
9ad0453
Add TF Ising Hamiltonian and test, add TensorKit compat
pbrehmer Jul 3, 2024
dbd9d21
Refactor tensor contraction indices
pbrehmer Jul 4, 2024
0db269d
Rename PEPSHamiltonian to LocalOperator
pbrehmer Jul 4, 2024
b4f2a46
Add @autoopt
lkdvos Jul 4, 2024
bef192b
Add unit cell convention docstring, add unit cell test
pbrehmer Jul 4, 2024
ba81552
Merge branch 'ld-expval' of github.com:quantumghent/PEPSKit.jl into l…
pbrehmer Jul 4, 2024
6bdca77
Add @autoopt to CTMRG contractions
pbrehmer Jul 4, 2024
7f4cecc
escape expression in @autoopt
lkdvos Jul 4, 2024
f0ce77c
Formatter
lkdvos Jul 8, 2024
a51ba5c
Remove debug prints
lkdvos Jul 9, 2024
5d2a8b3
Use non-hermitian eigensolvers for VUMPS
lkdvos Jul 9, 2024
fae7999
Add tf_ising tests
lkdvos Jul 9, 2024
e5e7738
fiddle with rng
lkdvos Jul 9, 2024
f983192
expectation_value is a number
lkdvos Jul 9, 2024
020de0b
update compats
lkdvos Jul 9, 2024
f9783dc
Fix expectation_values
lkdvos Jul 9, 2024
6ec560f
Fix magnetisation test
lkdvos Jul 9, 2024
2715875
Fix some more conventions
lkdvos Jul 9, 2024
e362de0
Update some logging facilities
lkdvos Jul 9, 2024
2944f06
Merge branch 'master' into logging
lkdvos Jul 9, 2024
e08c8c8
Dont destroy inputs
lkdvos Jul 9, 2024
aadb68a
Improve interaction with AD
lkdvos Jul 9, 2024
792a7a0
Fix more AD things
lkdvos Jul 9, 2024
f9fa606
Update defaults and docstrings
lkdvos Jul 14, 2024
0ba4d8a
More tests of logging
lkdvos Jul 14, 2024
c4d376d
Merge branch 'master' into logging
lkdvos Jul 14, 2024
2a84d58
Remove unused verbosity
lkdvos Jul 15, 2024
c9a0c17
Remove deprecated keyword arguments
lkdvos Jul 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36"
MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502"
OptimKit = "77e91f04-9b3b-57a6-a776-40b61faaebe0"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Expand Down
2 changes: 2 additions & 0 deletions src/PEPSKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ using Accessors
using VectorInterface
using TensorKit, KrylovKit, MPSKit, OptimKit, TensorOperations
using ChainRulesCore, Zygote
using LoggingExtras
using MPSKit: loginit!, logiter!, logfinish!, logcancel!

include("utility/util.jl")
include("utility/svd.jl")
Expand Down
135 changes: 71 additions & 64 deletions src/algorithms/ctmrg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ Algorithm struct that represents the CTMRG algorithm for contracting infinite PE
Each CTMRG run is converged up to `tol` where the singular value convergence of the
corners as well as the norm is checked. The maximal and minimal number of CTMRG iterations
is set with `maxiter` and `miniter`. Different levels of output information are printed
depending on `verbosity` (0, 1 or 2). The projectors are computed from `svd_alg` SVDs
where the truncation scheme is set via `trscheme`.
depending on `verbosity`, where `0` suppresses all output, `1` only prints warnings, `2`
gives information at the start and end, and `3` prints information every iteration.
The projectors are computed from `svd_alg` SVDs where the truncation scheme is set via
`trscheme`.
"""
struct CTMRG
tol::Float64
Expand Down Expand Up @@ -67,70 +69,53 @@ function MPSKit.leading_boundary(state, alg::CTMRG)
return MPSKit.leading_boundary(CTMRGEnv(state, oneunit(spacetype(state))), state, alg)
end
function MPSKit.leading_boundary(envinit, state, alg::CTMRG)
normold = 1.0
CSold = map(x -> tsvd(x; alg=TensorKit.SVD())[2], envinit.corners)
TSold = map(x -> tsvd(x; alg=TensorKit.SVD())[2], envinit.edges)
ϵold = 1.0
CS = map(x -> tsvd(x; alg=TensorKit.SVD())[2], envinit.corners)
TS = map(x -> tsvd(x; alg=TensorKit.SVD())[2], envinit.edges)

η = one(real(scalartype(state)))
N = norm(state, envinit)
env = deepcopy(envinit)
log = ignore_derivatives(() -> MPSKit.IterLog("CTMRG"))

return LoggingExtras.withlevel(; alg.verbosity) do
ctmrg_loginit!(log, η, N)
local iter
for outer iter in 1:(alg.maxiter)
env, = ctmrg_iter(state, env, alg) # Grow and renormalize in all 4 directions
η, CS, TS = calc_convergence(env, CS, TS)
N = norm(state, env)
ctmrg_logiter!(log, iter, η, N)

(iter > alg.miniter && η <= alg.tol) && break
end

for i in 1:(alg.maxiter)
env, ϵ = ctmrg_iter(state, env, alg) # Grow and renormalize in all 4 directions

conv_condition, normold, CSold, TSold, ϵ = ignore_derivatives() do
# Compute convergence criteria and take max (TODO: How should we handle logging all of this?)
Δϵ = abs((ϵold - ϵ) / ϵold)
normnew = norm(state, env)
Δnorm = abs(normold - normnew) / abs(normold)
CSnew = map(c -> tsvd(c; alg=TensorKit.SVD())[2], env.corners)
ΔCS = maximum(zip(CSold, CSnew)) do (c_old, c_new)
# only compute the difference on the smallest part of the spaces
smallest = infimum(MPSKit._firstspace(c_old), MPSKit._firstspace(c_new))
e_old = isometry(MPSKit._firstspace(c_old), smallest)
e_new = isometry(MPSKit._firstspace(c_new), smallest)
return norm(e_new' * c_new * e_new - e_old' * c_old * e_old)
end
TSnew = map(t -> tsvd(t; alg=TensorKit.SVD())[2], env.edges)
# Do one final iteration that does not change the spaces
alg_fixed = @set alg.projector_alg.trscheme = FixedSpaceTruncation()
env′, = ctmrg_iter(state, env, alg_fixed)
envfix = gauge_fix(env, env′)

ΔTS = maximum(zip(TSold, TSnew)) do (t_old, t_new)
MPSKit._firstspace(t_old) == MPSKit._firstspace(t_new) ||
return scalartype(t_old)(Inf)
# TODO: implement when spaces aren't the same
return norm(t_new - t_old)
end
η = calc_elementwise_convergence(envfix, env; atol=alg.tol^(1 / 2))
N = norm(state, envfix)

conv_condition = max(Δnorm, ΔCS, ΔTS) < alg.tol && i > alg.miniter

if alg.verbosity > 1 || (alg.verbosity == 1 && (i == 1 || conv_condition))
@printf(
"CTMRG iter: %3d norm: %.2e Δnorm: %.2e ΔCS: %.2e ΔTS: %.2e ϵ: %.2e Δϵ: %.2e\n",
i,
abs(normnew),
Δnorm,
ΔCS,
ΔTS,
ϵ,
Δϵ
)
end
alg.verbosity > 0 &&
i == alg.maxiter &&
@warn(
"CTMRG reached maximal number of iterations at (Δnorm=$Δnorm, ΔCS=$ΔCS, ΔTS=$ΔTS)"
)
return conv_condition, normnew, CSnew, TSnew, ϵ
if η < alg.tol^(1 / 2)
ctmrg_logfinish!(log, iter, η, N)
else
ctmrg_logcancel!(log, iter, η, N)
end
conv_condition && break # Converge if maximal Δ falls below tolerance
return envfix
end

# Do one final iteration that does not change the spaces
alg_fixed = @set alg.projector_alg.trscheme = FixedSpaceTruncation()
env′, = ctmrg_iter(state, env, alg_fixed)
envfix = gauge_fix(env, env′)
check_elementwise_convergence(env, envfix; atol=alg.tol^(1 / 2)) ||
@warn "CTMRG did not converge elementwise."
return envfix
end

ctmrg_loginit!(log, η, N) = @infov 2 loginit!(log, η, N)
ctmrg_logiter!(log, iter, η, N) = @infov 3 logiter!(log, iter, η, N)
ctmrg_logfinish!(log, iter, η, N) = @infov 2 logfinish!(log, iter, η, N)
ctmrg_logcancel!(log, iter, η, N) = @warnv 1 logcancel!(log, iter, η, N)

@non_differentiable ctmrg_loginit!(args...)
@non_differentiable ctmrg_logiter!(args...)
@non_differentiable ctmrg_logfinish!(args...)
@non_differentiable ctmrg_logcancel!(args...)

"""
gauge_fix(envprev::CTMRGEnv{C,T}, envfinal::CTMRGEnv{C,T}) where {C,T}

Expand Down Expand Up @@ -275,15 +260,37 @@ function fix_relative_phases(envfinal::CTMRGEnv, signs)
return stack([C1, C2, C3, C4]; dims=1), stack([T1, T2, T3, T4]; dims=1)
end

function calc_convergence(envs, CSold, TSold)
CSnew = map(x -> tsvd(x; alg=TensorKit.SVD())[2], envs.corners)
ΔCS = maximum(zip(CSold, CSnew)) do (c_old, c_new)
# only compute the difference on the smallest part of the spaces
smallest = infimum(MPSKit._firstspace(c_old), MPSKit._firstspace(c_new))
e_old = isometry(MPSKit._firstspace(c_old), smallest)
e_new = isometry(MPSKit._firstspace(c_new), smallest)
return norm(e_new' * c_new * e_new - e_old' * c_old * e_old)
end

TSnew = map(x -> tsvd(x; alg=TensorKit.SVD())[2], envs.edges)
ΔTS = maximum(zip(TSold, TSnew)) do (t_old, t_new)
MPSKit._firstspace(t_old) == MPSKit._firstspace(t_new) ||
return scalartype(t_old)(Inf)
return norm(t_new - t_old)
end

@debug "maxᵢ|Cⁿ⁺¹ - Cⁿ|ᵢ = $ΔCS maxᵢ|Tⁿ⁺¹ - Tⁿ|ᵢ = $ΔTS"

return max(ΔCS, ΔTS), CSnew, TSnew
end

@non_differentiable calc_convergence(args...)

"""
check_elementwise_convergence(envfinal, envfix; atol=1e-6)
calc_elementwise_convergence(envfinal, envfix; atol=1e-6)

Check if the element-wise difference of the corner and edge tensors of the final and fixed
CTMRG environments are below some tolerance.
"""
function check_elementwise_convergence(
envfinal::CTMRGEnv, envfix::CTMRGEnv; atol::Real=1e-6
)
function calc_elementwise_convergence(envfinal::CTMRGEnv, envfix::CTMRGEnv; atol::Real=1e-6)
ΔC = envfinal.corners .- envfix.corners
ΔCmax = norm(ΔC, Inf)
ΔCmean = norm(ΔC)
Expand All @@ -306,10 +313,10 @@ function check_elementwise_convergence(
)
end

return isapprox(ΔCmax, 0; atol) && isapprox(ΔTmax, 0; atol)
return max(ΔCmax, ΔTmax)
end

@non_differentiable check_elementwise_convergence(args...)
@non_differentiable calc_elementwise_convergence(args...)

"""
ctmrg_iter(state, env::CTMRGEnv{C,T}, alg::CTMRG) where {C,T}
Expand Down
2 changes: 0 additions & 2 deletions src/algorithms/peps_opt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ based on the CTMRG gradient and updates the PEPS parameters. In this optimizatio
the CTMRG runs can be started on the converged environments of the previous optimizer
step by setting `reuse_env` to true. Otherwise a random environment is used at each
step. The CTMRG gradient itself is computed using the `gradient_alg` algorithm.
Different levels of output verbosity can be activated using `verbosity` (0, 1 or 2).
"""
@kwdef struct PEPSOptimize{G}
boundary_alg::CTMRG = CTMRG() # Algorithm to find boundary environment
Expand All @@ -49,7 +48,6 @@ Different levels of output verbosity can be activated using `verbosity` (0, 1 or
)
reuse_env::Bool = true # Reuse environment of previous optimization as initial guess for next
gradient_alg::G = GeomSum() # Algorithm to solve gradient linear problem
verbosity::Int = 0
end

"""
Expand Down
9 changes: 4 additions & 5 deletions test/ctmrg/gaugefix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ using PEPSKit
using TensorKit
using Accessors

using PEPSKit: ctmrg_iter, gauge_fix, check_elementwise_convergence
using PEPSKit: ctmrg_iter, gauge_fix, calc_elementwise_convergence

scalartypes = [Float64, ComplexF64]
unitcells = [(1, 1), (2, 2), (3, 2)]
χ = 6
verbosity = 3

function _make_symmetric(psi)
if ==(size(psi)...)
Expand Down Expand Up @@ -45,7 +46,6 @@ end
Random.seed!(987654321) # Seed RNG to make random environment consistent
ctm = CTMRGEnv(psi, ctm_space)

verbosity = 1
alg = CTMRG(;
tol=1e-10, miniter=4, maxiter=400, verbosity, trscheme=truncdim(dim(ctm_space))
)
Expand All @@ -54,7 +54,7 @@ end
ctm = leading_boundary(ctm, psi, alg)
ctm2, = ctmrg_iter(psi, ctm, alg_fixed)
ctm_fixed = gauge_fix(ctm, ctm2)
@test PEPSKit.check_elementwise_convergence(ctm, ctm_fixed; atol=1e-4)
@test PEPSKit.calc_elementwise_convergence(ctm, ctm_fixed) ≈ 0 atol = 1e-4
end

@testset "Z2 symmetry ($T) - ($unitcell)" for (T, unitcell) in
Expand All @@ -70,7 +70,6 @@ end
Random.seed!(123456789) # Seed RNG to make random environment consistent
ctm = CTMRGEnv(psi, ctm_space)

verbosity = 1
alg = CTMRG(;
tol=1e-10, miniter=4, maxiter=400, verbosity, trscheme=truncdim(dim(ctm_space))
)
Expand All @@ -79,5 +78,5 @@ end
ctm = leading_boundary(ctm, psi, alg)
ctm2, = ctmrg_iter(psi, ctm, alg_fixed)
ctm_fixed = gauge_fix(ctm, ctm2)
@test PEPSKit.check_elementwise_convergence(ctm, ctm_fixed; atol=1e-4)
@test PEPSKit.calc_elementwise_convergence(ctm, ctm_fixed) ≈ 0 atol = 1e-4
end
1 change: 0 additions & 1 deletion test/heisenberg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ opt_alg = PEPSOptimize(;
optimizer=LBFGS(4; maxiter=100, gradtol=1e-3, verbosity=2),
gradient_alg=GMRES(; tol=1e-6, maxiter=100),
reuse_env=true,
verbosity=2,
)

# initialize states
Expand Down
1 change: 0 additions & 1 deletion test/pwave.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ opt_alg = PEPSOptimize(;
optimizer=LBFGS(4; maxiter=10, gradtol=1e-3, verbosity=2),
gradient_alg=GMRES(; tol=1e-3, maxiter=2, krylovdim=50),
reuse_env=true,
verbosity=2,
)

# initialize states
Expand Down
1 change: 0 additions & 1 deletion test/tf_ising.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ opt_alg = PEPSOptimize(;
optimizer=LBFGS(4; maxiter=100, gradtol=1e-3, verbosity=2),
gradient_alg=GMRES(; tol=1e-6, maxiter=100),
reuse_env=true,
verbosity=2,
)

# initialize states
Expand Down
Loading