Scalar optimization
The Nautilus.Optim module provides four 1D minimization methods. All
take function-typed arguments and return the approximate minimizer (or
NaN on failure).
Functions
Section titled “Functions”| Function | Signature |
|---|---|
golden_section_search | (f: f32 -> f32, lo, hi: f32, tol: f32, max_iters: i64) -> f32 |
brent_minimize | (f: f32 -> f32, lo, hi: f32, tol: f32, max_iters: i64) -> f32 |
gradient_descent_1d | (f, df: f32 -> f32, x0, lr: f32, max_iters: i64) -> f32 |
newton_minimize_1d | (f, df, ddf: f32 -> f32, x0: f32, tol: f32, max_iters: i64) -> f32 |
Choosing a method
Section titled “Choosing a method”- golden_section_search: Requires only function evaluations on a bracket [lo, hi] where f is unimodal. Linear convergence (golden ratio reduction per step).
- brent_minimize: Alternates parabolic interpolation with golden section fallback. Superlinear convergence for smooth functions while staying within [lo, hi]. Use it when derivatives are unavailable.
- gradient_descent_1d: Uses a fixed learning rate and needs the derivative
df. Each step isx - lr * df(x). Returns NaN on divergence (|x| > 1e15). Useful when you have analytic gradients and want to tune learning rate. - newton_minimize_1d: Uses both first and second derivatives
(
df,ddf). Quadratic convergence near a minimum with positive curvature. Returns NaN if the Hessian is non-positive or below 0.01 at the point it stops on.
Example
Section titled “Example”import Nautilus.Optim (golden_section_search, brent_minimize, newton_minimize_1d, gradient_descent_1d)
def parabola(x: f32) -> f32 = { d = sub(x, 3.0f32) add(mul(d, d), 7.0f32)}def d_parabola(x: f32) -> f32 = mul(2.0f32, sub(x, 3.0f32))def dd_parabola(x: f32) -> f32 = 2.0f32golden = golden_section_search(parabola, 0.0f32, 10.0f32, 1.0e-6f32, 200i64)brent = brent_minimize(parabola, 0.0f32, 10.0f32, 1.0e-6f32, 200i64)newton = newton_minimize_1d(parabola, d_parabola, dd_parabola, 0.0f32, 1.0e-6f32, 50i64)gd = gradient_descent_1d(parabola, d_parabola, 0.0f32, 0.1f32, 500i64)golden = 3.000132brent = 2.9998934newton = 3.0gd = 2.9999995All four find the minimum of (x - 3)^2 + 7. Newton lands on 3 exactly in
one step because the objective is quadratic. The two bracketing methods stop
on bracket width, so their answers are within about 1e-4 of 3 for this
tol: the minimum of a smooth function is flat, and an f32 objective cannot
distinguish points closer than about sqrt(ulp) of the minimum.
gradient_descent_1d contract
Section titled “gradient_descent_1d contract”lr must be positive and small enough for the iteration to contract:
below 2 / f''(x) near the minimum, so below 1 for this parabola. It is not
checked. With the parabola above and x0 = 0:
lr and budget | Result | Why |
|---|---|---|
0.1, 500 iterations | 2.9999995 | converged |
0.01, 10 iterations | 0.5487816 | budget exhausted; the last iterate, with no signal |
0.0 | 0.0 | the first step leaves x unchanged, which ends the search |
-0.1 | NaN | ascends until |x| > 1e15 |
1.5 | NaN | overshoots with growing amplitude until |x| > 1e15 |
Gradient descent stops when |df(x)| < 1e-10, when a step leaves x
unchanged, or when the budget runs out; only divergence returns NaN. Check
df at the result when convergence matters.
golden_section_searchandbrent_minimizeassume unimodality on [lo, hi]. Multiple local minima may cause convergence to any one of them.gradient_descent_1dstops when|df(x)| < 1e-10(hard-coded).- Newton stops when
|df(x)| < tolordf(x)is exactly zero. The exact-zero test still works whentolis zero, negative, or NaN. It also stops whenx - df(x)/ddf(x)rounds back tox. Both exits require a finite point and positive curvature at least at the0.01floor; NaN curvature fails. - At a gradient-based stop, Newton accepts
ddf(x) = +inf. At a rounding stall it requires finite curvature. Infinite curvature can make the step zero even when the gradient is large, so such a stall returns NaN. Negative infinite curvature fails at either exit. - A finite rounding stall can occur near a minimum with a nonzero gradient.
For
(x^2-2)^2fromx0 = 1.2, the iterate stalls atsqrt(2.0f32)with gradient-6.74e-7and step-4.2e-8. Rejecting every nonzero gradient would also reject this result. The finite-curvature check does not prove stationarity, however; a very large finiteddfcan also make a step vanish. - Curvature overflow near a minimum can therefore produce NaN. A
tolabove the gradient magnitude uses the gradient-based exit instead, but must be appropriate to the calculation. One ULP above the minimum of(x-3)^2, the gradient is4.8e-7, sotol = 1e-6accepts it andtol = 1e-9does not. Scaling to2e38*(x-3)^2givesddf = 4e38, which overflows f32, and a gradient of9.5e31at that point. A tolerance useful for resolving this minimum cannot recover it. Scale the objective so its curvature is representable, or use derivative-freebrent_minimize. - The curvature floor also rejects flat minima. For
3.1e-4*(x^2-2)^2, Newton stalls atsqrt(2.0f32)with curvature0.00496and gradient-2.09e-10. It returns NaN withtol = 1e-10,tol = 0, ortol = 1e-6. Changing tolerance cannot bypass the floor; usebrent_minimizeorgolden_section_searchfor flat objectives. - Newton does not check that
ddfis the derivative ofdf. Inconsistent derivatives can produce a finite stall at a nonstationary point that passes the curvature check. Supply consistent derivatives or use a derivative-free method. - A NaN endpoint, starting point, or evaluated function result gives NaN.
golden_section_searchandbrent_minimizeevaluatef;gradient_descent_1dandnewton_minimize_1devaluate only the supplied derivatives and never callf. A NaN objective therefore does not reach the derivative-based methods. - No method detects NaN in regions it never evaluates.
brent_minimizeinitially samples the quarter, midpoint, and three-quarter points;golden_section_searchsamples different points. One can return NaN while the other returns a finite point for the same partially defined objective. tolfor the bracketing methods is a bracket width in x and should be positive.brent_minimizeraises anytolbelow 1e-6 to 1e-6.golden_section_searchdoes not: withtol <= 0the width test never passes, and it returns the bracket midpoint aftermax_itersiterations, or earlier iffreturns equal values at its two probe points.- A NaN
tolis not rejected. For the bracketing methods, it disables width stopping; the method can still return at its iteration budget or an f32 stall. Validate a computed tolerance before calling. - All methods are pure Chelis. AD flows through the objective function
but you must supply
df/ddfexplicitly. The optimizer does not callgradinternally.