-
Notifications
You must be signed in to change notification settings - Fork 27
Description
I ran into an issue when running leading_boundary on a InfinitePartitionFunction using SimultaneousCTMRG (originally pointed out by @dartsushi).
Usually, when running leading_boundary at a fixed environment bond dimension trscheme = FixedSpaceTruncation() or trscheme = truncdim(χ), I would initialize a CTMRG environment with a total bond dimension leading_boundary call. However, it turns out that the default randomly initialized environments can give very bad convergence if you directly intialize them with a nontrivial virtual space. Initializing with a trivial virtual space and growing it solves this, but in this case you can't use FixedSpaceTruncation.
For example, for the 2D classical Ising model with a
using TensorKit
using PEPSKit
using Random
using MPSKitModels: classical_ising
Random.seed!(1234) # same problem for many seeds...
# toggle symmetry, but same issue for both
S = Z2Irrep
# S = Trivial
χ = 20
tol = 1.0e-4
maxiter = 1000
verbosity = 2
# initialize
T = classical_ising(S)
O = T[1]
n = InfinitePartitionFunction([O O; O O])
Venv = S == Z2Irrep ? Z2Space(0 => χ / 2, 1 => χ / 2) : ℂ^χ
P = space(O, 2)
trscheme = FixedSpaceTruncation()
# simultaneous CTMRG: very sensitive to initial guess
simultaneous_alg = (;
alg = :simultaneous,
tol,
verbosity,
trscheme,
maxiter,
)
env0 = CTMRGEnv(n, Venv)
env_sim, = leading_boundary(env0, n; simultaneous_alg...)gives
[ Info: CTMRG init: obj = -2.222242140629e+01 +1.949978774954e+01im err = 1.0000e+00
┌ Warning: CTMRG cancel 1000: obj = +3.739239477627e+01 -5.522835410994e-01im err = 2.5066866523e-01 time = 11.77 sec
└ @ PEPSKit ~/ctmbench/lib/PEPSKit.jl/src/algorithms/ctmrg/ctmrg.jl:152
Initializing with a trivial virtual space and growing until truncdim(χ) to grow the environment first seems to avoid this,
env0 = CTMRGEnv(n, oneunit(P))
env_sim, = leading_boundary(env0, n; trscheme = truncdim(χ), simultaneous_alg...)[ Info: CTMRG init: obj = +3.397056274848e+01 err = 1.0000e+00
[ Info: CTMRG conv 534: obj = +4.121413131732e+01 err = 9.9855540314e-05 time = 6.24 sec
but this can give a space that is slightly different from the one we want,
space(env_sim.corners[1])Rep[ℤ₂](0=>11, 1=>9) ← Rep[ℤ₂](0=>11, 1=>9)
For some reason, SequentialCTMRG seems to suffer much less from this problem:
sequential_alg = (;
alg = :sequential,
tol,
verbosity,
trscheme = FixedSpaceTruncation(),
maxiter,
)
env0 = CTMRGEnv(n, Venv)
env_seq, = leading_boundary(env0, n; sequential_alg...)[ Info: CTMRG conv 318: obj = +4.121402200669e+01 -7.312051507224e-05im err = 9.9978661272e-05 time = 4.70 sec
[ Info: CTMRG init: obj = +3.397056274848e+01 err = 1.0000e+00
To circumvent the problem for SimultaneousCTMRG, sometimes initializing with ones instead of randn stabilizes things, but seems a bit too black magic to actually change the default.
A better solution that seems to really solve things is to initialize an environment with the proper virtualspace Venv by growing it from a trivial virtual space using a few dummy CTMRG iteration with trscheme = truncspace(Venv), and then starting from there,
dummy_alg = (;
alg = :simultaneous,
trscheme = truncspace(Venv),
maxiter = 5,
)
env0 = CTMRGEnv(n, oneunit(P))
env1, = leading_boundary(env0, n; dummy_alg...)
env_sim_better, = leading_boundary(env1, n; simultaneous_alg...)[ Info: CTMRG init: obj = +3.397056274848e+01 err = 1.0000e+00
┌ Warning: CTMRG cancel 5: obj = +4.095118941961e+01 err = 9.9825766951e-02 time = 0.02 sec
└ @ PEPSKit ~/ctmbench/lib/PEPSKit.jl/src/algorithms/ctmrg/ctmrg.jl:152
[ Info: CTMRG init: obj = +4.095118941961e+01 err = 1.0000e+00
[ Info: CTMRG conv 190: obj = +4.121361334018e+01 err = 9.8857674692e-05 time = 0.82 sec
So long story short, I was wondering if it's sensible to just not use random initializations, but always initialize an environment of with a requested virtual space by growing it from a smaller one?