There is a bug in qualtran/linalg/polynomial/jacobi_anger_approximations.py. |J_n(t)| for n < t oscillates and crosses zero many times before asymptotic decay. The library function assumes monotone behavior in n, but it isn't monotonic in this region. As such bisect_left lands on the wrong zero.
The bug is in 59–65 of jacobi_anger_approximations.py:
d = 1
while not term_too_small(d):
d *= 2
d = bisect.bisect_left(range(d), True, key=term_too_small) - 1
The doubling loop exits at the first d within epsilon, but that can be a zero crossing in the oscillating region. It can be seen by running the test (jacobi_anger_approximations_test.py) body with different params:
import numpy as np
from qualtran.linalg.polynomial.jacobi_anger_approximations import (
approx_exp_cos_by_jacobi_anger,
degree_jacobi_anger_approximation,
)
t = 50.0
precision = 1e-2
degree = degree_jacobi_anger_approximation(t, precision=precision)
print(f"degree = {degree}")
random_state = np.random.RandomState(42 + int(t))
P = np.polynomial.Polynomial(approx_exp_cos_by_jacobi_anger(t, degree=degree))
theta = 2 * np.pi * random_state.random(1000)
e_itheta = np.exp(1j * theta)
np.testing.assert_allclose(
P(e_itheta) * e_itheta ** (-degree),
np.exp(1j * t * np.cos(theta)),
rtol=precision * 2,
)
The fix would scan monotonically past the oscillating region.
There is a bug in
qualtran/linalg/polynomial/jacobi_anger_approximations.py.|J_n(t)|forn < toscillates and crosses zero many times before asymptotic decay. The library function assumes monotone behavior inn, but it isn't monotonic in this region. As suchbisect_leftlands on the wrong zero.The bug is in 59–65 of
jacobi_anger_approximations.py:The doubling loop exits at the first
dwithin epsilon, but that can be a zero crossing in the oscillating region. It can be seen by running the test (jacobi_anger_approximations_test.py) body with different params:The fix would scan monotonically past the oscillating region.