Source code for k1lib._higher

# AUTOGENERATED FILE! PLEASE DON'T EDIT HERE. EDIT THE SOURCE NOTEBOOKS INSTEAD
"""Higher order functions"""
__all__ = ["Func", "polyfit", "derivative", "optimize", "inverse", "integral"]
from typing import Callable, List
import k1lib, numpy as np, warnings
from functools import partial
import matplotlib.pyplot as plt
Func = Callable[[float], float]
[docs]def polyfit(x:List[float], y:List[float], deg:int=6) -> Func: # polyfit """Returns a function that approximate :math:`f(x) = y`. Example:: xs = [1, 2, 3] ys = [2, 3, 5] f = k1.polyfit(xs, ys, 1) This will create a best-fit function. You can just use it as a regular, normal function. You can even pass in :class:`numpy.ndarray`:: # returns some float f(2) # plots fit function from 0 to 5 xs = np.linspace(0, 5) plt.plot(xs, f(xs)) :param deg: degree of the polynomial of the returned function""" # polyfit params = np.polyfit(x, y, deg) # polyfit def _inner(_x): # polyfit answer = np.zeros_like(_x, dtype=float) # polyfit for expo, param in enumerate(params): # polyfit answer += param * _x**(len(params)-expo-1) # polyfit return answer # polyfit return _inner # polyfit
[docs]def derivative(f:Func, delta:float=1e-6) -> Func: # derivative """Returns the derivative of a function. Example:: f = lambda x: x**2 df = k1lib.derivative(f) df(3) # returns roughly 6 """ # derivative return lambda x: (f(x + delta) - f(x)) / delta # derivative
[docs]def optimize(f:Func, v:float=1, threshold:float=1e-6, **kwargs) -> float: # optimize 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 1.4142 (root 2) k1lib.optimize(f) # returns -1.4142 (negative root 2) k1lib.optimize(f, -1) Interestingly, for some reason, result of this is more accurate than :meth:`derivative`. """ # optimize if len(kwargs) > 0: f = partial(f, **kwargs) # optimize fD = derivative(f) # optimize for i in range(20): # optimize v = v - f(v)/fD(v) # optimize if abs(f(v)) > threshold: warnings.warn("k1lib.optimize not converging") # optimize return v # optimize
[docs]def inverse(f:Func) -> Func: # inverse """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.""" # inverse return lambda y: optimize(lambda x: f(x) - y) # inverse
[docs]def integral(f:Func, _range:k1lib.Range) -> float: # integral """Integrates a function over a range. Example:: f = lambda x: x**2 # returns roughly 9 k1lib.integral(f, [0, 3]) There is also the cli :class:`~k1lib.cli.modifier.integrate` which has a slightly different api.""" # integral _range = k1lib.Range(_range) # integral n = 1000; xs = np.linspace(*_range, n) # integral return sum([f(x)*_range.delta/n for x in xs]) # integral