A wind-tunnel simulator gives the drag of a model wing, f(params), for a list of shape parameters. Nobody has a formula for it: you can only call it. Before tuning the shape you want to know how the drag changes when each parameter moves a little.
Write numerical_gradient(f, params, h) that returns a list of floats, one per parameter. Entry i is the estimate
(f(params with params[i] + h) - f(params with params[i] - h)) / (2 * h)
where every other parameter keeps its value. Call f with a list of the same length as params. The list params itself must not be changed.
Examples
Input: f = lambda p: p[0] ** 2 + 3 * p[1], params = [1.0, 2.0], h = 1e-4
Output: [2.0, 3.0]
Explanation: the slope of p0² at p0 = 1 is 2 and the slope of 3·p1 is 3 (up to rounding).
Input: f = lambda p: p[0] ** 3, params = [1.0], h = 0.1
Output: [3.01]
Explanation: (1.1³ - 0.9³) / 0.2 = 3.01. The true slope is 3; you return the estimate.
Constraints
0 <= len(params) <= 50,1e-6 <= h <= 1freturns a float for any list of floats of the right length- floats are compared with a tolerance of
1e-6
Goals
- Estimate every partial derivative of a function you can only evaluate
- Nudge one parameter at a time, in both directions, and leave the others unchanged
- Never modify the caller's parameter list