Source code for k1lib._higher

# AUTOGENERATED FILE! PLEASE DON'T EDIT
"""Higher order functions"""
__all__ = ["Func", "polyfit", "derivative", "optimize", "inverse", "integrate"]
from typing import Callable, List
import k1lib, numpy as np
Func = Callable[[float], float]
[docs]def polyfit(x:List[float], y:List[float], deg:int=6) -> Func: """Returns a function that approximate :math:`f(x) = y`. :param deg: degree of the polynomial of the returned function """ params = np.polyfit(x, y, deg) def _inner(_x): answer = np.zeros_like(_x, dtype=np.float) for expo, param in enumerate(params): answer += param * _x**(len(params)-expo-1) return answer return _inner
[docs]def derivative(f:Func, delta:float=1e-6) -> Func: """Returns the derivative of a function. Example:: f = lambda x: x**2 df = k1lib.derivative(f) df(3) # returns roughly 6 """ return lambda x: (f(x + delta) - f(x)) / delta
[docs]def optimize(f:Func, v:float=1, threshold:float=1e-6) -> float: r"""Given :math:`f(x) = 0`, solves for x using Newton's method with initial value `v`. Example:: f = lambda x: x**2-2 # returns sqrt(2) k1lib.optimize(f) # returns -sqrt(2) k1lib.optimize(f, -1) Interestingly, for some reason, result of this is more accurate than :meth:`derivative`. """ fD = derivative(f) while abs(f(v)) > threshold: v = v - f(v)/fD(v) return v
[docs]def inverse(f:Func) -> Func: """Returns the inverse of a function. Example:: f = lambda x: x**2 fInv = k1lib.inverse(f) # returns roughly 3 fInv(9) .. warning:: The inverse function takes a long time to run, so don't use this where you need lots of speed. Also, as you might imagine, the inverse function isn't really airtight. Should work well with monotonic functions, but all bets are off with other functions.""" return lambda y: optimize(lambda x: f(x) - y)
[docs]def integrate(f:Func, _range:k1lib.Range) -> float: """Integrates a function over a range. Example:: f = lambda x: x**2 # returns roughly 9 k1lib.integrate(f, [0, 3])""" _range = k1lib.Range(_range) n = 1000; xs = np.linspace(*_range, n) return sum([f(x)*_range.delta/n for x in xs])