Source code for pyProximation.rational

from .base import Foundation
from .orthsys import OrthSystem



[docs] class RationalAprox(Foundation): """ ``RationalAprox`` calculates a rational approximation for a given function. ``RationalApprox`` is the preferred public alias; this class name is retained for backward compatibility. It takes one argument `orth` which is an instance of ``OrthSystem`` and does all the computations in the scope of this object. """ def __init__(self, orth): """ initiate a rational approximation framework. """ if not isinstance(orth, OrthSystem): raise TypeError("`orth` must be an `OrthSystem` instance.") self.OrthSys = orth
[docs] def RatLSQ(self, m, n, f): """ Calculates a rational function :math:`\frac{p}{q}` where :math:`p, q` consists of the first :math:`m, n` elements of the orthonormal basis :math:`||f-\frac{p}{q}||_2` is minimized. """ from numpy import diag, array, zeros, vstack, hstack from scipy.linalg import LinAlgError, solve if not isinstance(m, int) or not isinstance(n, int): raise TypeError("`m` and `n` must be integers.") if m < 0 or n < 0: raise ValueError("`m` and `n` must be non-negative.") if self.OrthSys.OrthBase == []: raise ValueError("No orthonormal basis is available. Call `FormBasis()` on the orthogonal system first.") if m >= self.OrthSys.num_base or n >= self.OrthSys.num_base: raise ValueError( "`m` and `n` must both be smaller than the size of the orthonormal basis (%d)." % (self.OrthSys.num_base) ) self.M = diag([1 for _ in range(m + 1)]) self.Z = zeros((m + 1, n)) self.S = zeros((n, n)) self.F = array([self.OrthSys.inner(self.OrthSys.OrthBase[j], f) for j in range(m + 1)]) self.G = array( [-self.OrthSys.inner(self.OrthSys.OrthBase[k], f**2) for k in range(1, n + 1)]) for j in range(m + 1): for k in range(1, n + 1): self.Z[j][ k - 1] = - self.OrthSys.inner(self.OrthSys.OrthBase[j], f * self.OrthSys.OrthBase[k]) for j in range(1, n + 1): for k in range(1, n + 1): self.S[j - 1][k - 1] = self.OrthSys.inner( self.OrthSys.OrthBase[j], f**2 * self.OrthSys.OrthBase[k]) H = vstack((hstack((self.M, self.Z)), hstack((self.Z.T, self.S)))) r = hstack((self.F, self.G)) try: ab = solve(H, r) except LinAlgError as error: raise ValueError( "Failed to solve the rational least-squares system. The basis or target function may lead to a singular system." ) from error a, b = ab[:m + 1], ab[m + 1:] numer = sum([a[i] * self.OrthSys.OrthBase[i] for i in range(m + 1)]) denom = 1 + sum([b[i] * self.OrthSys.OrthBase[i + 1] for i in range(n)]) return numer / denom
RationalApprox = RationalAprox