API — Bounds & Reflection
Internal helpers for Coleman–Li reflective bound handling. These are called automatically during optimize; you only need them if you are extending Retro or writing custom step logic.
Scaling
Retro.compute_scaling! — Function
compute_scaling!(scaling, x, lb, ub, theta1, theta2)Compute the Coleman-Li scaling factors for bound-constrained optimization. The scaling matrix D is diagonal with: D[i,i] = |v[i]|^{1/2} where v[i] reflects distance to bounds in the gradient direction.
This scaling makes the trust-region ellipsoidal in a way that respects bounds.
Retro.scale_gradient! — Function
scale_gradient!(scaled_g, g, scaling)Apply scaling to gradient: scaled_g = D * g
Feasibility
Retro.initialize_away_from_bounds! — Function
initialize_away_from_bounds!(x, lb, ub; epsilon=1e-8)Move initial point away from bounds if too close or exactly on boundary. This prevents degeneracy in the bound-constrained scaling and ensures the initial trust region step has room to explore.
For each variable:
- If x[i] ≤ lb[i] + ε, move to lb[i] + min(ε, (ub[i]-lb[i])/2)
- If x[i] ≥ ub[i] - ε, move to ub[i] - min(ε, (ub[i]-lb[i])/2)
Returns true if any modifications were made.
Retro.project_bounds! — Function
project_bounds!(x, lb, ub)Simple projection onto bounds (hard clamping).
Retro.find_step_to_bound — Function
find_step_to_bound(x, p, lb, ub)Find the maximum step length α ∈ (0, 1] such that x + α*p stays feasible. Returns (α, hitindex, hitbound) where:
- α: maximum feasible step length
- hit_index: index of first bound hit (0 if none)
- hit_bound: :lower, :upper, or :none
Reflection
Retro.reflect_step! — Function
reflect_step!(p, hit_index, hit_bound, g, H_diag)Reflect the step at the boundary. The reflected direction is computed following Coleman & Li: the component hitting the boundary is negated, while other components are adjusted based on local curvature.
If gradient at boundary indicates a local minimum in that direction, the reflection is not performed (return false).
Retro.apply_reflective_bounds! — Function
apply_reflective_bounds!(x_trial, x, p, lb, ub, theta2;
g=nothing, max_reflections=10)Apply multiple reflective bounds following Coleman & Li (1994, 1996) and fides.
The algorithm:
- Take step until hitting a boundary
- Reflect off the boundary (negate component)
- Repeat until no boundary is hit, local minimum found, or max_reflections reached
- Apply safety clamping to ensure strict feasibility
When gradient g is provided, the algorithm checks for local minima at boundaries and stops reflecting if the boundary is optimal in that direction.
Retro.compute_cauchy_boundary_point! — Function
compute_cauchy_boundary_point!(x_cauchy, x, g, lb, ub, Delta)Compute the Cauchy point constrained to bounds: the point along -g direction that minimizes a quadratic model within the trust region and bounds.
This provides a fallback when reflection fails to improve the model.