Source code for mmfutils.optimize

"""Optimization tools."""


[docs]def bracket_monotonic(f, x0=0.0, x1=1.0, factor=2.0): """Return `(x0, x1)` where `f(x0)*f(x1) < 0`. Assumes that `f` is monotonic and that the root exists. Proceeds by increasing the size of the interval by `factor` in the direction of the root until the root is found. Examples -------- >>> import math >>> bracket_monotonic(lambda x:10 - math.exp(x)) (0.0, 3.0) >>> bracket_monotonic(lambda x:10 - math.exp(-x), factor=1.5) (4.75, -10.875) """ assert abs(x1 - x0) > 0 assert factor > 1.0 f0 = f(x0) f1 = f(x1) if f1 < f0: x0, x1 = x1, x0 f0, f1 = f1, f0 while f0*f1 >= 0: x0, x1 = x1, x0 - factor*(x1-x0) f0, f1 = f1, f(x1) return (x0, x1)
[docs]def usolve(f, a, *v, **kw): """Return the root of `f(x) = 0` with uncertainties propagated. Arguments --------- f : function Function to find root of `f(x) = 0`. Note: this must work with only a single argument even if the solver supports `args` etc. Thus, use `lambda x: f(x, ...)` or `functools.partial` if needed. solver : function Solver function (default is scipy.optimize.brentq). v, kw : Remaining arguments will be passed as `solver(f, a, *v, **kw)`. """ from uncertainties.core import nominal_value, ufloat, AffineScalarFunc import scipy.optimize solver = kw.pop('solver', scipy.optimize.brentq) if not isinstance(f(a), AffineScalarFunc): # Just solve normally which is faster return solver(f, a, *v, **kw) x = solver(lambda _x: nominal_value(f(_x)), a, *v, **kw) _x = ufloat(x, 0) zero = f(_x) params = [_k for _k in zero.derivatives if _k is not _x] return x - sum((_p - nominal_value(_p)) *zero.derivatives[_p]/zero.derivatives[_x] for _p in params)
[docs]def ubrentq(f, a, b, *v, **kw): """Version of `scipy.optimize.brentq` with uncertainty processing using the uncertainties package. """ from uncertainties import nominal_value return usolve(f, nominal_value(a), nominal_value(b), *v, **kw)