QuantumKitHub / MPSKit.jl

A Julia package dedicated to simulating quantum many-body systems using Matrix Product States (MPS)
MIT License
127 stars 29 forks source link

GradientGrassmann stuck in a (quasi-) infinite loop #167

Open LHerviou opened 1 month ago

LHerviou commented 1 month ago

During groundstate simulations for MPS close to exact analytical state (e.g. SU(2)), the GradientGrassmann can hang in the linesearch function of OptimKit.jl

This is due to the maxiter taking its default value (typemax(Int) = 9223372036854775807) instead of the maxiter argument provided for at least some of the Optim methods.

Here is the result of println(alg) inside find_groundstate in gradient_grassmann.jl

`GradientGrassmann(ConjugateGradient{HagerZhang{Rational{Int64}}, Float64, HagerZhangLineSearch{Rational{Int64}}}(HagerZhang{Rational{Int64}}(2//5, 1//1), 44, 1.0e-12, HagerZhangLineSearch{Rational{Int64}}(1//10, 9//10, 1//1000000, 1//2, 2//3, 5//1, 9223372036854775807, 98), 9223372036854775807, 100), O ptimKit._finalize!)'

Note the two typemax that are still present. I do not know enough about the algorithm here to be sure of the fix.

lkdvos commented 1 month ago

The problem is actually even worse, the maxiter arguments in the linesearch are currently not really respected, and there are several steps where indeed the algorithm can get stuck. In principle, this is something that should be fixed by OptimKit.jl, and as far as I know there were some updates in the pipeline, but I am not sure what the status is on that @Jutho ?

LHerviou commented 1 month ago

As far as I can tell for my small problem, I forced linesearch to stop after 100 iterations and no longer see any significant slowdown. Though it might just be completely wrong to do that.

More precisely, see the change between (instead of k == ls.maxiter ) https://github.com/Jutho/OptimKit.jl/blob/8135d1c497318ef402e03574e80c777ecd3a1b6b/src/linesearches.jl#L248

function (ls::HagerZhangLineSearch)(fg, x₀, η₀, fg₀ = fg(x₀);
                    retract = _retract, inner = _inner,
                    initialguess = one(fg₀[1]), acceptfirst = false)
    (f₀, g₀) = fg₀
    df₀ = inner(x₀, g₀, η₀)
    if df₀ >= zero(df₀)
        error("linesearch was not given a descent direction!")
    end
    p₀ = LineSearchPoint(zero(f₀), f₀, df₀, x₀, f₀, g₀, η₀)
    iter = HagerZhangLineSearchIterator(fg, retract, inner, p₀, η₀, initialguess, acceptfirst, ls)
    next = iterate(iter)
    @assert next !== nothing
    k = 1
    while true
        (x, f, g, ξ, α, dϕ), state = next
        a, b, numfg, done = state
        if done**
            ls.verbosity >= 1 &&
                @info @sprintf("Linesearch converged after %2d iterations: α = %.2e, dϕ = %.2e, ϕ - ϕ₀ = %.2e", k, α, dϕ, f - f₀)
            return x, f, g, ξ, α, numfg
        elseif **k >= min(ls.maxiter, 100)**
            ls.verbosity >= 1 &&
                @info @sprintf("Linesearch not converged after %2d iterations: α = %.2e, dϕ = %.2e, ϕ - ϕ₀ = %.2e", k, α, dϕ, f - f₀)
            return x, f, g, ξ, α, numfg
        else
            ls.verbosity >= 2 &&
                @info @sprintf("Linesearch step %d: [a,b] = [%.2e, %.2e], dϕᵃ = %.2e, dϕᵇ = %.2e, ϕᵃ - ϕ₀ = %.2e, ϕᵇ - ϕ₀ = %.2e", k, a.α, b.α, a.dϕ, b.dϕ, a.ϕ - f₀, b.ϕ - f₀)
            next = iterate(iter, state)
            @assert next !== nothing
            k += 1
        end
    end
end
Jutho commented 1 month ago

The last commit in the OptimKit branch https://github.com/Jutho/OptimKit.jl/commits/jh/overhaul should already contain the corrected linesearch, with more sensible default and respecting the maxiter option. As the branch name suggest, I was also going to perform major changes to the rest of the routines, but this has been delayed in favor of work elsewhere. Maybe I can already merge and tag the linesearch changes ?

lkdvos commented 1 month ago

As far as I can tell for my small problem, I forced linesearch to stop after 100 iterations and no longer see any significant slowdown. Though it might just be completely wrong to do that.

I think I misunderstood your problem: Am I correct in assuming that you did not find how to impose the maxiter parameter of the linesearch in the GradientGrassmann method? If this is the case, then presumably we will want:

The first seems to be already fixed in the OptimKit branch, for which I would definitely vote merge. The second I can solve, I will look into it next week.


My confusion stems from some parts of the linesearch algorithm that might get stuck in an infinite loop, in some cases, which is not even resolved by the maxiter kwarg. Ie something like maxiter != max_f_eval, but it seems like this is not an issue you are hitting.

LHerviou commented 1 month ago

Sorry if I was unclear:

So if my understanding is good, @jutho 's fix should limit my issue (or solve it). And we need probably a better interface in MPSKit at some point if one wants to give the option to the user. Or at least a better doc explaining how to modify these parameters.

In any case, thanks a lot!


Something irrelevant: I get a lot of warnings on calcwr/calcwl failing such as [ Info: calclw failed to converge 2.3490148964077822e-14] Should I worry about that?

lkdvos commented 1 month ago

I did change these messages to be a little more informative at some point, but it was quite recently so probably not yet in the version you are using. This means that the (left) environment converged up to 2.3e-14, and you requested a stricter tolerance. For these numbers, you should definitely not worry, that sounds pretty converged to me, but it might hinder performance a little if it is really trying to converge but just stagnates. It might be worth it to try and set the environment tolerances to 1e-12 instead. (Depending on what version you are using, these are dynamically increased during the optimization, but still you can set some minimal tolerance to limit this).