bundles / scipy 2.0.0.dev0+git20260907.41eeb59 / scipy / interpolate / _bary_rational / AAA
class
scipy.interpolate._bary_rational:AAA
source: build-install/usr/lib/python3.14/site-packages/scipy/interpolate/_bary_rational.py:218
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 of points will 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 to points are 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 points in 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()✗
<matplotlib.legend.Legend object at 0x7f3f68fda120>
plt.show()
✓
order = np.argsort(r.poles())
✓r.poles()[order] r.residues()[order]✗
array([ 0.04 +0.j , -0.17 -0.j , 0.5 +0.j , -1. +0.j , 1. +0.j ,
-0.81 -2.3j, -0.81 +2.3j, 0.87+10.7j, 0.87-10.7j])
For the second example, we call `AAA` with a spiral of 1000 points that wind 7.5
times around the origin in the complex plane.
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
✓12
r.errors
✗array([2.49e+01, 4.28e+01, 1.71e+01, 8.65e-02, 1.27e-02, 9.91e-04,
5.87e-05, 1.29e-06, 3.57e-08, 6.37e-10, 1.67e-11, 1.25e-13])
We can also plot the computed poles:
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()✗
<matplotlib.legend.Legend object at 0x7f3f6826b8c0>
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.')✗
[<matplotlib.lines.Line2D object at 0x7f3f684f4c20>]Now we call the `clean_up` method to remove Froissart doublets.
with warnings.catch_warnings(): warnings.simplefilter('ignore', RuntimeWarning) r.clean_up()✗
2
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.')✗
[<matplotlib.lines.Line2D object at 0x7f3f684f5010>]
plt.show()
✓
See also
- FloaterHormannInterpolator
Floater-Hormann barycentric rational interpolation.
- pade
Padé approximation.
Aliases
scipy.interpolate.AAA