Skip to content

Commit

Permalink
Fix calc_elementwise_convergence in tests, add consistency test betwe…
Browse files Browse the repository at this point in the history
…en TensorKit.SVD and IterSVD, add safeguard
  • Loading branch information
pbrehmer committed Jul 15, 2024
1 parent fe17ed7 commit 9b00244
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 36 deletions.
1 change: 0 additions & 1 deletion src/algorithms/ctmrg_gauge_fix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ function fix_global_phases(envprev::CTMRGEnv, envfix::CTMRGEnv)
return CTMRGEnv(cornersgfix, edgesgfix)
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)
Expand Down
3 changes: 3 additions & 0 deletions src/algorithms/peps_opt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ struct PEPSOptimize{G}
if gradient_alg isa GradMode
if S == :sequential && G.parameters[1] == :fixed
throw(ArgumentError(":sequential and :fixed are not compatible"))
elseif boundary_alg.projector_alg.svd_alg.fwd_alg isa IterSVD &&
G.parameters[1] == :fixed
throw(ArgumentError("IterSVD and :fixed are currently not compatible"))
end
end
return new{G}(boundary_alg, optimizer, reuse_env, gradient_alg)
Expand Down
123 changes: 90 additions & 33 deletions test/ctmrg/fixed_iterscheme.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ using PEPSKit:
# initialize parameters
χbond = 2
χenv = 16
svd_algs = [SVDAdjoint(; fwd_alg=TensorKit.SVD()), SVDAdjoint(; fwd_alg=IterSVD())]
svd_algs = [SVDAdjoint(; fwd_alg=TensorKit.SVD())] #, SVDAdjoint(; fwd_alg=IterSVD())]
unitcells = [(1, 1), (3, 4)]

# test for element-wise convergence after application of fixed step
Expand All @@ -31,7 +31,7 @@ unitcells = [(1, 1), (3, 4)]
# do extra iteration to get SVD
env_conv2, info = ctmrg_iter(psi, env_conv1, ctm_alg)
env_fix, signs = gauge_fix(env_conv1, env_conv2)
@test calc_elementwise_convergence(env_conv1, env_fix) 0 atol=1e-6
@test calc_elementwise_convergence(env_conv1, env_fix) 0 atol = 1e-6

# fix gauge of SVD
U_fix, V_fix = fix_relative_phases(info.U, info.V, signs)
Expand All @@ -43,36 +43,93 @@ unitcells = [(1, 1), (3, 4)]
# do iteration with FixedSVD
env_fixedsvd, = ctmrg_iter(psi, env_conv1, ctm_alg_fix)
env_fixedsvd = fix_global_phases(env_conv1, env_fixedsvd)
@test calc_elementwise_convergence(env_conv1, env_fixedsvd) 0 atol=1e-6
@test calc_elementwise_convergence(env_conv1, env_fixedsvd) 0 atol = 1e-6
end

# TODO: Why doesn't fixed work with IterSVD?
##
# ctm_alg = CTMRG(;
# tol=1e-12,
# miniter=4,
# maxiter=100,
# verbosity=1,
# ctmrgscheme=:simultaneous,
# svd_alg=SVDAdjoint(; fwd_alg=IterSVD()),
# )

# # initialize states
# Random.seed!(91283219347)
# psi = InfinitePEPS(2, χbond)
# env_conv1 = leading_boundary(CTMRGEnv(psi, ComplexSpace(χenv)), psi, ctm_alg);

# # do extra iteration to get SVD
# env_conv2, info = ctmrg_iter(psi, env_conv1, ctm_alg);
# env_fix, signs = gauge_fix(env_conv1, env_conv2);
# @test calc_elementwise_convergence(env_conv1, env_fix) ≈ 0 atol=1e-6

# # fix gauge of SVD
# U_fix, V_fix = fix_relative_phases(info.U, info.V, signs);
# svd_alg_fix = SVDAdjoint(; fwd_alg=FixedSVD(U_fix, info.S, V_fix));
# ctm_alg_fix = CTMRG(; svd_alg=svd_alg_fix, trscheme=notrunc(), ctmrgscheme=:simultaneous);

# # do iteration with FixedSVD
# env_fixedsvd, = ctmrg_iter(psi, env_conv1, ctm_alg_fix);
# env_fixedsvd = fix_global_phases(env_conv1, env_fixedsvd);
# @test calc_elementwise_convergence(env_conv1, env_fixedsvd) ≈ 0 atol=1e-6
# TODO: Why doesn't FixedSVD work with previous U, S and V from IterSVD?
@testset "Element-wise consistency of TensorKit.SVD and IterSVD" begin
ctm_alg_iter = CTMRG(;
tol=1e-12,
verbosity=2,
ctmrgscheme=:simultaneous,
svd_alg=SVDAdjoint(; fwd_alg=IterSVD()),
)
ctm_alg_full = CTMRG(;
tol=1e-12,
verbosity=2,
ctmrgscheme=:simultaneous,
svd_alg=SVDAdjoint(; fwd_alg=TensorKit.SVD()),
)

# initialize states
Random.seed!(91283219347)
psi = InfinitePEPS(2, χbond)
env_init = CTMRGEnv(psi, ComplexSpace(χenv))
env_conv1 = leading_boundary(env_init, psi, ctm_alg_full)

# do extra iteration to get SVD
env_conv2_iter, info_iter = ctmrg_iter(psi, env_conv1, ctm_alg_iter)
env_fix_iter, signs_iter = gauge_fix(env_conv1, env_conv2_iter)
@test calc_elementwise_convergence(env_conv1, env_fix_iter) 0 atol = 1e-6

env_conv2_full, info_full = ctmrg_iter(psi, env_conv1, ctm_alg_full)
env_fix_full, signs_full = gauge_fix(env_conv1, env_conv2_full)
@test calc_elementwise_convergence(env_conv1, env_fix_full) 0 atol = 1e-6

# fix gauge of SVD
U_fix_iter, V_fix_iter = fix_relative_phases(info_iter.U, info_iter.V, signs_iter)
svd_alg_fix_iter = SVDAdjoint(; fwd_alg=FixedSVD(U_fix_iter, info_iter.S, V_fix_iter))
ctm_alg_fix_iter = CTMRG(;
svd_alg=svd_alg_fix_iter, trscheme=notrunc(), ctmrgscheme=:simultaneous
)

U_fix_full, V_fix_full = fix_relative_phases(info_full.U, info_full.V, signs_full)
svd_alg_fix_full = SVDAdjoint(; fwd_alg=FixedSVD(U_fix_full, info_full.S, V_fix_full))
ctm_alg_fix_full = CTMRG(;
svd_alg=svd_alg_fix_full, trscheme=notrunc(), ctmrgscheme=:simultaneous
)

# do iteration with FixedSVD
env_fixedsvd_iter, = ctmrg_iter(psi, env_conv1, ctm_alg_fix_iter)
env_fixedsvd_iter = fix_global_phases(env_conv1, env_fixedsvd_iter)
# @test calc_elementwise_convergence(env_conv1, env_fixedsvd_iter) ≈ 0 atol = 1e-6 # This should work, but doesn't!

env_fixedsvd_full, = ctmrg_iter(psi, env_conv1, ctm_alg_fix_full)
env_fixedsvd_full = fix_global_phases(env_conv1, env_fixedsvd_full)
@test calc_elementwise_convergence(env_conv1, env_fixedsvd_full) 0 atol = 1e-6

# check matching decompositions
atol = 1e-12
decomposition_check = all(
zip(info_iter.U, info_iter.S, info_iter.V, info_full.U, info_full.S, info_full.V),
) do (U_iter, S_iter, V_iter, U_full, S_full, V_full)
diff = U_iter * S_iter * V_iter - U_full * S_full * V_full
all(x -> isapprox(abs(x), 0; atol), diff.data)
end
@test decomposition_check

# check matching singular values
svalues_check = all(zip(info_iter.S, info_full.S)) do (S_iter, S_full)
diff = S_iter - S_full
all(x -> isapprox(abs(x), 0; atol), diff.data)
end
@test svalues_check

# check normalization of U's and V's
Us = [info_iter.U, U_fix_iter, info_full.U, U_fix_full]
Vs = [info_iter.V, V_fix_iter, info_full.V, V_fix_full]
for (U, V) in zip(Us, Vs)
U_check = all(U) do u
uu = u' * u
diff = uu - id(space(uu, 1))
all(x -> isapprox(abs(x), 0; atol), diff.data)
end
@test U_check
V_check = all(V) do v
vv = v * v'
diff = vv - id(space(vv, 1))
all(x -> isapprox(abs(x), 0; atol), diff.data)
end
@test V_check
end
end
4 changes: 2 additions & 2 deletions test/ctmrg/gaugefix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ schemes = [:simultaneous, :sequential]
ctm = leading_boundary(ctm, psi, alg)
ctm2, = ctmrg_iter(psi, ctm, alg)
ctm_fixed, = gauge_fix(ctm, ctm2)
@test calc_elementwise_convergence(ctm, ctm_fixed) 0 atol=1e-6
@test calc_elementwise_convergence(ctm, ctm_fixed) 0 atol = 1e-6
end

@testset "Z2 symmetry ($T) - ($unitcell) - ($ctmrgscheme)" for (T, unitcell, ctmrgscheme) in
Expand All @@ -52,5 +52,5 @@ end
ctm = leading_boundary(ctm, psi, alg)
ctm2, = ctmrg_iter(psi, ctm, alg)
ctm_fixed, = gauge_fix(ctm, ctm2)
@test calc_elementwise_convergence(ctm, ctm_fixed) 0 atol=1e-6
@test calc_elementwise_convergence(ctm, ctm_fixed) 0 atol = 1e-6
end

0 comments on commit 9b00244

Please sign in to comment.