A lot of models can be reduced to systems of linear equations, which are the domain of linear algebra. The mpmath library mentioned in the Using arbitrary precision for optimization recipe can do arbitrary precision linear algebra too.
Theoretically, we can approximate any differentiable function as a polynomial series. To find the coefficients of the polynomial, we can define a system of linear equations, basically taking powers of a data vector (vector as mathematical term) and using a vector of ones to represent the constant in the polynomial. We will solve such a system with the mpmath lu_solve()
function. As example data, we will use wind speed data grouped by the day of year.
For the relevant instructions, refer to the Using arbitrary precision for optimization recipe.
Follow these steps to use arbitrary precision for linear algebra:
import mpmath import dautil as dl import numpy as np import matplotlib.pyplot as plt from IPython.display import HTML
def mpmean(arr): mpfs = [mpmath.mpf(a) for a in arr] return sum(mpfs)/len(arr)
lu_solve()
:vals = dl.data.Weather.load()['WIND_SPEED'].dropna() vals = dl.ts.groupby_yday(vals).apply(mpmean) days = np.arange(1, 367, dtype=int) A = [[], [], []] A[0] = np.ones_like(days, dtype=int).tolist() A[1] = days.tolist() A[2] = (days ** 2).tolist() A = mpmath.matrix(A).transpose() params = mpmath.lu_solve(A, vals) result = dl.report.HTMLBuilder() result.h1('Arbitrary Precision Linear Algebra') result.h2('Polynomial fit') dfb = dl.report.DFBuilder(['Coefficient 0', 'Coefficient 1', 'Coefficient 2']) dfb.row(params) result.add_df(dfb.build())
def poly(x): return mpmath.polyval(params[::-1], x)
fourier()
function to get a trigonometric approximation:cs = mpmath.fourier(poly, days.tolist(), 1) result.h2('Cosine and sine terms') dfb = dl.report.DFBuilder(['Coefficient 1', 'Coefficient 2']) dfb.row(cs[0]) dfb.row(cs[1]) result.add_df(dfb.build(index=['Cosine', 'Sine']), index=True)
sp = dl.plotting.Subplotter(2, 1, context) cp = dl.plotting.CyclePlotter(sp.ax) cp.plot(days, vals, label='Data') cp.plot(days, poly(days), label='Fit') yvar = dl.data.Weather.get_header('WIND_SPEED') sp.label(ylabel_params=yvar) cp = dl.plotting.CyclePlotter(sp.next_ax()) cp.plot(days, vals, label='Data') cp.plot(days, [mpmath.fourierval(cs, days, d) for d in days], label='Approximation') sp.label(ylabel_params=yvar) plt.tight_layout() HTML(result.html)
Refer to the following screenshot for the end result (refer to the mpmath_linalg.ipynb
file in this book's code bundle):
fourier()
function documented at https://mpmath.readthedocs.org/en/latest/calculus/approximation.html?highlight=fourier#mpmath.fourier (retrieved August 2015)lu_solve()
function documented at https://mpmath.readthedocs.org/en/latest/matrices.html?highlight=lu_solve (retrieved August 2015)