Guard optimizers and linesearch against non-descent directions and zero steps - #48
Conversation
…ro steps A non-descent search direction (for example from a preconditioner that is indefinite in finite precision) made the linesearch return a zero step, which none of the optimizers handled: - ConjugateGradient: the next Hager-Zhang β is 0/0 = NaN; the resulting NaN direction passed the descent check of the linesearch, whose bracketing phase then loops forever. A zero initial guess (2 * 0) also loops forever there. - LBFGS and GradientDescent: the same zero step is retried until `maxiter`. The optimizers now check for descent before the linesearch. ConjugateGradient restarts from the preconditioned gradient when β is not finite or the conjugate direction is not a descent direction, and LBFGS resets its inverse Hessian approximation. If the preconditioned gradient itself is not a descent direction, or the linesearch makes no progress along it, they stop with a warning. The linesearch rejects invalid initial guesses, treats a NaN slope as non-descent, and bounds its bracket expansion by `maxfg`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #48 +/- ##
==========================================
+ Coverage 82.31% 83.29% +0.97%
==========================================
Files 8 8
Lines 752 802 +50
==========================================
+ Hits 619 668 +49
- Misses 133 134 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Closes #43. Partially addresses #44: adds warnings, a CG restart and an LBFGS memory reset. GD and CG no longer get stuck: with a wrong-sign gradient ( Related, not closed: #15 (only the zero-step case is covered), #11 ( Does not supersede #19. |
Co-authored-by: Jutho <Jutho@users.noreply.github.com>
Jutho
left a comment
There was a problem hiding this comment.
Nice; great to see some of these infinite loops and other instabilities gone.
|
I don't have any write access here so you'll have to merge/tag this one I fear :) |
A non-descent search direction (e.g. from a preconditioner that is indefinite in floating point, see QuantumKitHub/MPSKit.jl#532) makes the linesearch return a zero step, which no optimizer handled:
ConjugateGradienthangs: β becomes0/0 = NaN, the NaN direction passes the descent check, and the bracket expansion loops forever. A zero initial guess (2 * 0) loops there too.LBFGSandGradientDescentretry the zero step untilmaxiter.Changes
HagerZhangLineSearchrejects invalid initial guesses, treats a NaN slope as non-descent, and bounds the bracket expansion bymaxfg.Cost: one extra
innerper iteration.Tests
New tests for non-descent directions (all optimizers), CG with β = NaN or −1e3, and the linesearch guards. They fail or hang on master and pass here.
🤖 Generated with Claude Code