Using arbitrary precision for linear algebra

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.

Getting ready

For the relevant instructions, refer to the Using arbitrary precision for optimization recipe.

How to do it...

Follow these steps to use arbitrary precision for linear algebra:

  1. The imports are as follows:
    import mpmath
    import dautil as dl
    import numpy as np
    import matplotlib.pyplot as plt
    from IPython.display import HTML
  2. Define the following function to compute the arithmetic mean with mpmath:
    def mpmean(arr):
        mpfs = [mpmath.mpf(a) for a in arr]
    
        return sum(mpfs)/len(arr)
  3. Load the data and solve the system with 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())
  4. Define the following function to evaluate the polynomial we got:
    def poly(x):
        return mpmath.polyval(params[::-1], x)
  5. Use the 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)
  6. Plot the data, model results, and approximation as follows:
    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):

How to do it...

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset