Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion fides/minimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,15 @@ def update_tr_radius(
else:
self.tr_ratio = actual_decrease / predicted_decrease

interior_solution = nsx < self.delta_iter * 0.9
# the radius is only increased if the trust region constraint
# was active. For steps that were stepped back to stay within
# the bounds (step.alpha < 1), this is decided based on the
# proposal before step back. The stepped back step is short
# because of the bounds, not the trust region, e.g., a single
# reflection that is cut short by the next bound.
interior_solution = (
norm(step.og_ss + step.ss0) < self.delta_iter * 0.9
)

if (
self.tr_ratio >= self.get_option(Options.ETA)
Expand Down
35 changes: 35 additions & 0 deletions tests/test_minimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -1537,3 +1537,38 @@ def test_reflected_step_roundoff_stays_in_bounds(subspace_dim):
assert np.all(x <= ub)
assert opt.exitflag > 0
assert np.isclose(fval, 10.913558700882975, rtol=1e-6)


@pytest.mark.parametrize('stepback', list(StepBackStrategy))
@pytest.mark.parametrize('subspace_dim', [SubSpaceDim.TWO, SubSpaceDim.FULL])
def test_several_active_bounds(subspace_dim, stepback):
"""
gh-78: with reflect_single, the reflected segment is cut short by the
second active bound. The step is then shorter than the radius, the
radius was never increased and the run crawled to MAXITER.
"""
hess = np.diag([2.0, 1.0, 1.5, 1.2])
c = np.array([-1000.0, 1000.0, -1000.0, 1000.0])

def fun(x):
d = x - c
g = hess @ d
return 0.5 * d @ g, g, hess

opt = Optimizer(
fun,
ub=np.full(4, np.inf),
lb=np.array([-1.0, -np.inf, -1.0, -np.inf]),
verbose=logging.WARNING,
options={
Options.MAXITER: 100,
Options.SUBSPACE_DIM: subspace_dim,
Options.STEPBACK_STRAT: stepback,
},
)
fval, x, _, _ = opt.minimize(np.array([-1.0, 0.0, -1.0, 0.0]))
# full/refine stops with DELTA_TOO_SMALL at the optimum, as
# the predicted decrease there is below the resolution of fval
assert opt.exitflag != fides.ExitFlag.MAXITER
assert np.isclose(fval, 1746501.75, rtol=1e-8)
assert np.allclose(x, [-1.0, 1000.0, -1.0, 1000.0], rtol=1e-5)