A pricing service exposes a cost curve F(x) only through an expensive API call: each evaluation takes seconds. All you know is that F is convex on [a, b] (the chord between any two points on the curve lies on or above the curve). You need to find where the minimum is, while spending as few calls as possible.
Write minimize(evaluate, a: float, b: float, eps: float) -> float that returns a point x in [a, b] within eps of a minimiser of F:
evaluate(x)returnsF(x)for anya <= x <= b. Calling it outside[a, b]is an error.- A convex function may be flat at the bottom, so it can have a whole interval
[L, R]of minimisers (a single point is the caseL == R). Your answerxmust satisfyL - eps <= x <= R + eps, and alsoa <= x <= b. - The minimum may sit at an end of the interval (for a function that only goes down or only goes up).
- Budget: you may call
evaluateat mostceil(log_phi((b - a) / eps)) + 2times, wherephi = (1 + sqrt(5)) / 2 ≈ 1.618. Ifb - a <= 2 * epsthe budget is 0: return the midpoint(a + b) / 2without callingevaluateat all. The tests count.
minimize(lambda x: (x - 3) ** 2, 0.0, 10.0, 1e-6) # about 3.0
minimize(lambda x: abs(x + 2) + abs(x - 2), -5.0, 5.0, 1e-6) # anything in [-2, 2]
minimize(lambda x: 2 * x, -1.0, 1.0, 1e-6) # about -1.0 (the left end)
Constraints: a <= b, b - a <= 10^6, eps >= 1e-6, and F's values are well-conditioned for comparing (no precision tricks).
A method that spends two new calls per round to cut the interval to 2/3 keeps about 0.82 of it per call, which blows the budget.
Show hint
The budget allows keeping only about 1 / phi ≈ 0.618 of the interval per call. Place two interior probes at golden-ratio positions (c = b - (b - a) / phi, d = a + (b - a) / phi) and compare them to discard one side; the surviving probe then sits exactly where one of the next round's probes must go, so it can be reused.