Skip to content

Fix LBFGS iteration counter always showing 0 #948

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

Merged
merged 2 commits into from
Jul 23, 2025

Conversation

ChrisRackauckas
Copy link
Member

Summary

Fixes #907 - This PR fixes the LBFGS solver's iteration counter which was always showing 0 in callbacks.

Problem

When using callbacks with Optimization.LBFGS(), the opt_state.iter value was always 0, making it impossible to track optimization progress. This was inconsistent with other solvers like Adam which properly increment the iteration counter.

Example from the issue:

callback = (opt_state, loss_val) -> (println(opt_state.iter); false;)
sol = solve(prob, Optimization.LBFGS(); callback, maxiters = 10)
# Prints: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...

Solution

Added iteration tracking using a Ref counter that increments with each loss function evaluation:

  • Added iter_count = Ref(0) before the _loss function definition
  • Increment iter_count[] inside the loss function
  • Pass iter_count[] to the OptimizationState constructor
  • Applied the fix to both constrained and unconstrained optimization cases

Testing

Tested with the example from the issue:

callback = (opt_state, loss_val) -> (println(opt_state.iter); false;)
sol = solve(prob, Optimization.LBFGS(); callback, maxiters = 10)
# Now prints: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14

The iteration counter now properly increments, matching the behavior of other solvers.

🤖 Generated with Claude Code

ChrisRackauckas and others added 2 commits July 23, 2025 00:48
Fixes #907 - Added iteration tracking to LBFGS callbacks so that
OptimizationState.iter properly increments during optimization.

Previously, the iteration counter was always 0 in callbacks because
the LBFGS solver wasn't tracking iterations. Now uses a Ref counter
that increments with each function evaluation.

Changes:
- Added iter_count = Ref(0) before _loss function definition
- Increment iter_count[] in _loss function
- Pass iter_count[] to OptimizationState constructor
- Applied fix to both constrained and unconstrained cases

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@ChrisRackauckas ChrisRackauckas merged commit 7a931f0 into master Jul 23, 2025
22 of 27 checks passed
@ChrisRackauckas ChrisRackauckas deleted the fix-lbfgs-iteration-count branch July 23, 2025 11:28
@@ -116,13 +116,15 @@ function SciMLBase.__solve(cache::OptimizationCache{
cache.f.cons(cons_tmp, cache.u0)
ρ = max(1e-6, min(10, 2 * (abs(cache.f(cache.u0, cache.p))) / norm(cons_tmp)))

iter_count = Ref(0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is a simple integer not enough? 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You would need to box it anyways

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LBFGS iteration index is always 0?
2 participants