Repository navigation
Grow the trust region for stepped-back steps whose proposal hit the radius - #90
Merged
Merged
Conversation
update_tr_radius only increased the radius for steps with norm >= 0.9 * delta. Steps that were stepped back to stay within the bounds are shorter than the radius because of the bounds, so the radius never grew for them, even at tr_ratio ~1. With reflect_single and several active bounds, every step is a single reflection cut short by the next bound and runs crawled to MAXITER. Decide whether the trust region constraint was active based on the proposal before step back (og_ss + ss0). This is unchanged for steps that were not stepped back. Steps whose proposal was interior to the trust region (e.g. a Newton step that hits a bound) still do not increase the radius, which avoids unbounded radius growth while steps are bound-limited. Fixes #78 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2D/refine also crawled to MAXITER on the gh-78 reproducer before the radius fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #90 +/- ##
=======================================
Coverage 97.03% 97.03%
=======================================
Files 10 10
Lines 1179 1179
=======================================
Hits 1144 1144
Misses 35 35 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #78
Problem
update_tr_radiusonly increases the radius when the step is at least0.9 * deltalong. A step that was stepped back to stay within the bounds (step.alpha < 1) is shorter than that because of the bounds, not because of the trust region. So the radius never grew for such steps, even attr_ratio ≈ 1. Withreflect_singleand several active bounds, every iteration's best step is a single reflection that the next bound cuts short. On the 4-D reproducer from the issue, the radius stays at 2 and the run crawls toMAXITER(1000 steps, medianalpha0.13).Change
fides/minimize.py, one line inupdate_tr_radius. Whether the trust-region constraint was active is now decided on the proposal before step back,norm(step.og_ss + step.ss0), instead of on the step that is taken:alpha == 1, soog_ss == ss): unchanged.reflect_singlecase.Why not option 1 from the issue (
alpha < 1⇒ boundary step)Option 1 fixes the 2D reproducer but makes the radius grow without bound whenever bound-limited steps keep a good ratio. With
scg+reflect_singleon the issue's reproducer, the radius doubles every iteration while the step stays about 1 long. It reaches 1e301 at iteration 1000 andinfat about 1024, and the run still hitsMAXITER. In the fuzz run below (first 33 problems), option 1 also changed the exit of the other strategies, fromFTOL/GTOLtoDELTA_TOO_SMALL, with many more rejected steps:DELTA_TOO_SMALLThis partial run still used a wall-clock time limit. The
refinerow excludes the runs that hit it: 4 on main, 13 with option 1, 11 with this PR. The full comparison below re-runs those with a CPU-time limit.Fuzz: main vs this PR
300 random problems (seeds 100–399 of the #75 fuzz set: bounded quadratics and Rosenbrock, n = 1–12, five box types, four start types) × 42 configurations (
2D/full/scg× all step-back strategies × exact/BFGS/SR1;scghas norefine),maxiter = 500. That makes 12,600 runs per side. Runs that hit the time limit on either side were re-run on both sides with a 60 s CPU-time limit (70 per side, none timed out). "Optimum" meansf - fref <= 1e-6 + 1e-4 |fref|, against a scipy BVLS / L-BFGS-B reference.MAXITERmain → PRBy solver,
MAXITERforreflect_singlegoes 18 → 7 (2D), 29 → 29 (full) and 51 → 20 (scg). Forreflectonscgit goes 16 → 13. No exceptions, NaN returns or bound violations on either side.The one broken run (seed 172, Rosenbrock,
2D/refine/BFGS,FTOL→MAXITER) and the single-run changes fortruncate/reflect(seeds 229 and 346, nonconvex Rosenbrock with quasi-Newton updates) come from trajectory divergence. In each, the new rule changed the radius decision at 1–4 iterations and the rest of the path differs. Neither side reached the optimum in thetruncate/reflectcases.Not fixed here
scg+reflect_singleon the issue's reproducer still stalls. Steihaug CG stops after one iteration there (residual tolerance0.5 |g|, #77), so the CG step is the gradient step. That step is dominated by the two variables on their bounds and is cut atalpha ~ 1e-3, and its single reflection hits the other bound. The step length does not depend on the radius, so no radius rule helps. The new regression test therefore covers2D/full.Tests
test_several_active_bounds: the issue's 4-D reproducer for2D/full× all step-back strategies,maxiter = 100. It asserts noMAXITERand the optimum infandx. On main,2D-reflect_singleand2D-refinefail (MAXITERfar from the optimum); here they converge in 12 and 15 iterations. The test does not require a positive exit flag becausefull/refinestops withDELTA_TOO_SMALLat the optimum, on main as well. The predicted decrease there is below the resolution off, which is unrelated to this change.pytest tests: 1229 passed, 3 skipped (after merging current main).🤖 Generated with Claude Code