Found while closing #123 (round 20 of PR #121), and deliberately not fixed there: it is the
same shape as #123 by a different route, and the fix for #123 does not cover it.
What happens
fitting/gls.py::fit_gls_ar1 on a curve such as 1e-40 * exp(-1.3 t): SciPy's least_squares
meets its absolute ftol/gtol immediately, because every residual is already far below them.
It therefore returns the starting value and reports success=True. The layer accepts that as a
converged fit.
Why the #123 guard does not catch it
#123 is closed by a degeneracy check on the curve's flatness
(ptp(y) <= eps * max|y|). This curve is not flat in that sense — its dynamic range is entirely
normal. What is abnormal is its scale. A guard written against flatness cannot see it.
Why this matters
It is the same class as the three findings of round 20 and of the round before it: a result is
certified by a criterion that never examined the thing it claims about. Here the criterion is
SciPy's convergence flag, and the thing is whether a fit occurred at all.
Acceptance / discrimination requirement
- A fit on
1e-40 * exp(-1.3 t) must not return success=True with the seed as its estimate.
- Positive control, mandatory: the same curve scaled to order 1 must still fit normally, and a
genuinely converged fit must not be rejected. A guard that fails both is not an improvement, it is
the solver switched off.
- The discrimination must be shown at exactly this pair — take the fix back, the new test goes red;
restore, it goes green.
Related: #123 (closed, other route) · #122.
Found while closing #123 (round 20 of PR #121), and deliberately not fixed there: it is the
same shape as #123 by a different route, and the fix for #123 does not cover it.
What happens
fitting/gls.py::fit_gls_ar1on a curve such as1e-40 * exp(-1.3 t): SciPy'sleast_squaresmeets its absolute
ftol/gtolimmediately, because every residual is already far below them.It therefore returns the starting value and reports
success=True. The layer accepts that as aconverged fit.
Why the #123 guard does not catch it
#123 is closed by a degeneracy check on the curve's flatness
(
ptp(y) <= eps * max|y|). This curve is not flat in that sense — its dynamic range is entirelynormal. What is abnormal is its scale. A guard written against flatness cannot see it.
Why this matters
It is the same class as the three findings of round 20 and of the round before it: a result is
certified by a criterion that never examined the thing it claims about. Here the criterion is
SciPy's convergence flag, and the thing is whether a fit occurred at all.
Acceptance / discrimination requirement
1e-40 * exp(-1.3 t)must not returnsuccess=Truewith the seed as its estimate.genuinely converged fit must not be rejected. A guard that fails both is not an improvement, it is
the solver switched off.
restore, it goes green.
Related: #123 (closed, other route) · #122.