bundles / scipy 1.17.1 / scipy / interpolate / _bary_rational / AAA
class
scipy.interpolate._bary_rational:AAA
Signature
class AAA ( x , y , * , rtol = None , max_terms = 100 , clean_up = True , clean_up_tol = 1e-13 ) Members
Summary
AAA real or complex rational approximation.
Extended Summary
As described in [1], the AAA algorithm is a greedy algorithm for approximation by rational functions on a real or complex set of points. The rational approximation is represented in a barycentric form from which the roots (zeros), poles, and residues can be computed.
Parameters
x: 1D array_like, shape (n,)1-D array containing values of the independent variable. Values may be real or complex but must be finite.
y: 1D array_like, shape (n,)Function values
f(x). Infinite and NaN values ofvaluesand corresponding values ofpointswill be discarded.rtol: float, optionalRelative tolerance, defaults to
eps**0.75. If a small subset of the entries invaluesare much larger than the rest the default tolerance may be too loose. If the tolerance is too tight then the approximation may contain Froissart doublets or the algorithm may fail to converge entirely.max_terms: int, optionalMaximum number of terms in the barycentric representation, defaults to
100. Must be greater than or equal to one.clean_up: bool, optionalAutomatic removal of Froissart doublets, defaults to
True. See notes for more details.clean_up_tol: float, optionalPoles with residues less than this number times the geometric mean of
valuestimes the minimum distance topointsare deemed spurious by the cleanup procedure, defaults to 1e-13. See notes for more details.
Attributes
support_points: arraySupport points of the approximation. These are a subset of the provided
xat which the approximation strictly interpolatesy. See notes for more details.support_values: arrayValue of the approximation at the support_points.
weights: arrayWeights of the barycentric approximation.
errors: arrayError over
pointsin the successive iterations of AAA.
Warns
: RuntimeWarningIf
rtolis not achieved inmax_termsiterations.
Notes
At iteration (at which point there are terms in the both the numerator and denominator of the approximation), the rational approximation in the AAA algorithm takes the barycentric form
where are real or complex support points selected from x, are the corresponding real or complex data values from y, and are real or complex weights.
Each iteration of the algorithm has two parts: the greedy selection the next support point and the computation of the weights. The first part of each iteration is to select the next support point to be added from the remaining unselected x, such that the nonlinear residual is maximised. The algorithm terminates when this maximum is less than rtol * np.linalg.norm(f, ord=np.inf). This means the interpolation property is only satisfied up to a tolerance, except at the support points where approximation exactly interpolates the supplied data.
In the second part of each iteration, the weights are selected to solve the least-squares problem
over the unselected elements of x.
One of the challenges with working with rational approximations is the presence of Froissart doublets, which are either poles with vanishingly small residues or pole-zero pairs that are close enough together to nearly cancel, see [2]. The greedy nature of the AAA algorithm means Froissart doublets are rare. However, if rtol is set too tight then the approximation will stagnate and many Froissart doublets will appear. Froissart doublets can usually be removed by removing support points and then resolving the least squares problem. The support point , which is the closest support point to the pole with residue , is removed if the following is satisfied
where is the geometric mean of support_values.
Examples
Here we reproduce a number of the numerical examples from [1]_ as a demonstration of the functionality offered by this method.import numpy as np import matplotlib.pyplot as plt from scipy.interpolate import AAA import warnings✓
from scipy.special import gamma sample_points = np.linspace(-1.5, 1.5, num=100) r = AAA(sample_points, gamma(sample_points)) z = np.linspace(-3.5, 4.5, num=1000) fig, ax = plt.subplots()✓
ax.plot(z, gamma(z), label="Gamma") ax.plot(sample_points, gamma(sample_points), label="Sample points") ax.plot(z, r(z).real, '--', label="AAA approximation") ax.set(xlabel="z", ylabel="r(z)", ylim=[-8, 8], xlim=[-3.5, 4.5]) ax.legend()✗
plt.show()
✓
order = np.argsort(r.poles())
✓r.poles()[order] r.residues()[order]✗
z = np.exp(np.linspace(-0.5, 0.5 + 15j*np.pi, 1000)) r = AAA(z, np.tan(np.pi*z/2), rtol=1e-13)✓
r.errors.size
✓r.errors
✗fig, ax = plt.subplots()
✓ax.plot(z.real, z.imag, '.', markersize=2, label="Sample points") ax.plot(r.poles().real, r.poles().imag, '.', markersize=5, label="Computed poles") ax.set(xlim=[-3.5, 3.5], ylim=[-3.5, 3.5], aspect="equal") ax.legend()✗
plt.show()
✓
z = np.exp(1j*2*np.pi*np.linspace(0,1, num=1000)) def f(z): return np.log(2 + z**4)/(1 - 16*z**4) with warnings.catch_warnings(): # filter convergence warning due to rtol=0 warnings.simplefilter('ignore', RuntimeWarning) r = AAA(z, f(z), rtol=0, max_terms=50, clean_up=False) mask = np.abs(r.residues()) < 1e-13 fig, axs = plt.subplots(ncols=2)✓
axs[0].plot(r.poles().real[~mask], r.poles().imag[~mask], '.') axs[0].plot(r.poles().real[mask], r.poles().imag[mask], 'r.')✗
with warnings.catch_warnings(): warnings.simplefilter('ignore', RuntimeWarning) r.clean_up()✗
mask = np.abs(r.residues()) < 1e-13
✓axs[1].plot(r.poles().real[~mask], r.poles().imag[~mask], '.') axs[1].plot(r.poles().real[mask], r.poles().imag[mask], 'r.')✗
plt.show()
✓
See also
- FloaterHormannInterpolator
Floater-Hormann barycentric rational interpolation.
- pade
Padé approximation.
Aliases
-
scipy.interpolate.AAA