These find the extremum of a unimodal function (strictly increasing then strictly decreasing, or the reverse) with evaluations. Convex and concave functions are the main source of unimodality.

template<class F> double ternaryMin(F f, double lo, double hi) {
    for (int it = 0; it < 100; it++) {              // (2/3)^100 ~ 1e-18 of the range
        double m1 = lo + (hi - lo) / 3, m2 = hi - (hi - lo) / 3;
        if (f(m1) < f(m2)) hi = m2; else lo = m1;
    }
    return (lo + hi) / 2;
}

Use a fixed iteration count, as in binary search.

Integer domain: binary search the slope

On integers, binary search the first with . That uses one comparison per step and handles plateaus at the optimum. Ternary search on integers needs a final linear scan of the last 3 candidates anyway.

ll lo = L, hi = R;                       // find argmin of convex f on [L, R]
while (lo < hi) {
    ll mid = lo + (hi - lo) / 2;
    if (f(mid) <= f(mid + 1)) hi = mid; else lo = mid + 1;
}

Plateaus

Unimodality must be strict away from the optimum. If on a flat region that isn’t the optimum, neither side can be discarded and ternary search can converge to the wrong place. Convex functions are fine, since a flat part of a convex function is the minimum.

This reuses one evaluation per iteration. The points sit at ratio , and because the surviving point is exactly where the next iteration needs it.

template<class F> double goldenMin(F f, double lo, double hi) {
    const double R = (sqrt(5.0) - 1) / 2;
    double m1 = hi - R * (hi - lo), m2 = lo + R * (hi - lo), f1 = f(m1), f2 = f(m2);
    for (int it = 0; it < 100; it++) {
        if (f1 < f2) { hi = m2; m2 = m1; f2 = f1; m1 = hi - R * (hi - lo); f1 = f(m1); }
        else         { lo = m1; m1 = m2; f1 = f2; m2 = lo + R * (hi - lo); f2 = f(m2); }
    }
    return (lo + hi) / 2;
}
MethodShrink per evaluationEvaluations for relative
ternaryabout 103
golden sectionabout 43

Golden section matters when is expensive: a nested search, a flow or DP per evaluation, or a simulation. The discrete analogue is Fibonacci search: with integer candidates it needs evaluations, which is optimal in the worst case.

Where unimodality comes from

SourceExample
convex function (sum of convex terms), , , distance from a moving point
increasing + decreasing trade-off”spend on upgrades, then the rest of the time working”
minimum over a family of convex functions in a parameterthe lower envelope is not convex, so be careful
cost of groups in partition DPsconvex in (Aliens trick)
extreme point of a convex polygon in a directionunimodal along the boundary (cyclically): binary search on edges
distance between two points moving linearly is convex in

The sum of convex functions is convex, the max of convex functions is convex, and convex composed with affine is convex. The sum of two unimodal functions is not unimodal in general. Prove convexity rather than assuming unimodality.

For a jointly convex , is convex, so

auto g = [&](double x) { return f(x, ternaryMin([&](double y) { return f(x, y); }, ylo, yhi)); };

and a ternary search over finishes the job in evaluations. Typical uses: the geometric median (Weber point), the smallest enclosing circle of moving points, best meeting point under Euclidean distance, best launch angle / minimum-time trajectory problems, and parameter tuning inside a heuristic solver. Each extra dimension multiplies the cost by , so beyond 2-3 dimensions use gradient methods or random restarts plus hill climbing (Heuristics).

Alternatives

SituationMethod
derivative availableNewton’s method or bisection on
discrete and convexbinary search on ; or slope trick if it’s DP-shaped
not unimodal, low dimensiongrid sample, then refine around the best few points
convex in many variables, linear constraintsLP / simplex
piecewise linear convexbreakpoints are candidates: sort them, or use weighted median

Weighted median: is minimised at any weighted median of the . No search needed. In Manhattan geometry, solve and independently.