-
Notifications
You must be signed in to change notification settings - Fork 5
Description
The script below builds a AAA approximation with very high accuracy. Great!
using LinearAlgebra
using RationalFunctionApproximation
import DoubleFloats: Double64
import ComplexRegions: Segment
f(x) = 1 / (1 + exp(1_000 * x))
bounds = (-10, 10)
segment = Segment{Double64}(bounds...)
# Large refinement and stagnation seem to be required. Are there heuristics
# to pick them or to otherwise mark the near-singular point at x=0?
r = approximate(f, segment, refinement=100, stagnation=100, tol=1e-10)
xs = range(bounds..., length=10_000)
norm(r.(xs) - f.(xs), Inf) # 5.9e-11My ultimate goal is to find poles/residues for a simple pole expansion that maintains this high level of accuracy. Unfortunately, when I try to get that with residues(r) plus an inferred constant shift, there is significant degradation in accuracy (several orders of magnitude).
With the hope of recovering that lost accuracy, I tried building a continued fraction approximation using fixed poles. When f(x) is not too singular, the procedure can work well. However, in this example:
r0 = approximate(f, segment, poles(r), degree=0)
norm(r0.(xs) - f.(xs), Inf) # 1.2e4
r1 = approximate(f, segment, poles(r), degree=0, init=1_000)
norm(r1.(xs) - f.(xs), Inf) # 3.1e0
r2 = approximate(f, segment, poles(r), degree=0, init=10_000)
norm(r2.(xs) - f.(xs), Inf) # 1.0e-6
# ERROR: BoundsError: attempt to access 20000×4 Matrix{Double64} at index [20001, 1]
r3 = approximate(f, segment, poles(r), degree=0, init=50_000)Here the error depends sensitively on the choice of init. The best I could achieve is order 1e-6, which is far worse than the 1e-10 achieved by AAA. Pushing the init value past a threshold generates a BoundsError.
Is there a way to get a simple pole expansion that keeps the high accuracy of the original barycentric approximation?
Another curious phenomenon is that if I rescale x as it appears in both f and bounds, I can get an overall much better approximation. Specifically, the alternative definitions,
(x) = 1 / (1 + exp(10_000 * x)) # Previously exp(1_000 * x)
bounds = (-1, 1) # Previously (-10, 10)yield a significantly improved accuracy. Naively, I would have expected no mathematical difference under this rescaling.
Thanks in advance. This is a very nice package!