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.

source

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.

source
Retro.find_step_to_boundFunction
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
source

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).

source
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:

  1. Take step until hitting a boundary
  2. Reflect off the boundary (negate component)
  3. Repeat until no boundary is hit, local minimum found, or max_reflections reached
  4. 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.

source
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.

source