INTERFACE JSUniMin; PROCEDURE Minimize( f: Function; (* Function to minimize *) VAR x: REAL; (* In: starting guess. Out: best point found. *) VAR fx: REAL; (* In/Out: "f(x)". *) VAR dfx: REAL; (* Out: estimate of first deriv. of "f" at "x". *) VAR ddfx: REAL; (* Out: estimate of second deriv. of "f" at "x". *) step: REAL; (* Starting step. *) minStep: REAL; (* Minimum step. *) maxStep: REAL; (* Maximum step. *) maxCalls: CARDINAL; (* Maximum number of calls to "f" *) report: ReportProc := NIL; (* Client procedure to report progress. *) verbose: BOOLEAN := FALSE; (* TRUE to mumble while working. *) Alpha: REAL := 0.01; (* Min splitting ratio. *) ); (* Tries to minimize "f" starting from "x". Assumes "fx" is initialized to "f(x)". Specifically, finds three points "a", "m", "b" such that 1. The points are ordered and not too close: "a + minStep <= m <= b - minStep" 2. The gaps aren't too wide: "a + maxStep >= m >= b - maxStep" 3. The gaps aren't too unequal: "MIN(m-a, b-m) >= Alpha * (b-a)" 4. They bracket at lest one local minimum: "f(m) <= MIN(f(a), f(b))" 5. The gaps can't be split any further: "MAX(m-a, b-m) < 2*minStep" More specifically, "Minimize" starts with "m=x", "a=x-step", "b=x+step"; then replaces one point at a time until the above conditions are satisfied. At that time, "Minimize" returns "m" in "x" and "f(m)" in "fx". It also returns estimates of the first and second drivatives of "f" at the resulting "x", obtained by fitting a parabola through the three final points "a", "m", "b". If a "report" procedure is given, "Minimize" will call "report(m, fm, dfm, ddfm)" every time it the middle point's value "f(m)" decreases; where "fm", "dfm", and "ddfm" are the value of "f(m)" and its estimated derivatives. If "report" returns TRUE, or "f" has been called "maxCalls" times, the minimization is aborted and the current midpoint is returned. That may not be the lowest point found so far, but it is at least the third lowest, and is not higher than the starting point. (However, the function "f" is always called at least twice.) *) TYPE Function = PROCEDURE (x: REAL): REAL; ReportProc = PROCEDURE (x, fx, dfx, ddfx: REAL): BOOLEAN; END JSUniMin.