tol, atol and rtol behavior of scipy.sparse.linalg solvers

Ilhan Polat <[email protected]> Mon, 1 May 2023 20:49:12 +0200
Newsgroups gmane.comp.python.scientific.devel
Message-ID <CAEBuzr_6DTh5qAoT0memKbW47KVW-UU-7MHAYDCens_PubEg8w@mail.gmail.com>
Dear all,

Yet another mail about upcoming changes, so apologies for the seemingly
repeating message lately. In [1], we started to remove all the FORTRAN code
and rewrote all solvers in pure Python for various reasons too long to
enumerate here. As a long waiting issue we want to also address the
suboptimal state of providing tolerances for these solvers. As I wrote in
[2], I'd like to mention it again to ask for feedback in case anyone has
better ideas


Currently, we have the following situation;

We have a tol and a strange looking atol keywords. What internally happens
is that all the inputs are now passed to a helper function called get_atol

https://github.com/scipy/scipy/blob/maintenance/1.10.x/scipy/sparse/linalg/_isolve/iterative.py#L78-L116

   1. User didn't provide atol then it first maps to None and that causes a
   warning and internally atol becomes legacy. This means:
   a. tol value is checked against the residual norm Ax - b. Note that
   matvec operation is costly. If the residual norm is already less than tol
   we exit.
   b. Then b norm is checked against 0. Since tol*norm(b) won't do any good
   we return tol
   c. And the typical case is to return tol*norm(b).
   2. User passed legacy all the same as above except the warning.
   3. If atol is actually set to something, then we return max(atol,
   tol*norm(b)). Why max is used I don't understand.

Typically, atol, rtol pair is used as tol = atol + rtol*<some metric>. This
is more or less what everybody expects from this pair and their naming is
chosen to reflect this. But I'm a bit lost in all the issues I could read.

What I propose is the following,

   1. Make default atol=0.
   2. If atol is set to string, fire a warning saying this is going away in
   version 1.13 (hence make the current deprecation on a definite schedule and
   assuming I can make it to 1.11 release). These are the users probably
   wanted to keep old behavior. Document how it can be done to match old
   behavior via atol, rtol.
   3. Introduce a new keyword rtol and map current tol to rtol. Set tol=None
   as the default to weed out the ones who actually set tol value and fire
   deprecation warnings for them to use rtol.
   4. Use the formula tol = atol + rtol*norm(b)


All feedback is welcome.



[1] : https://github.com/scipy/scipy/pull/18391
[2] : https://github.com/scipy/scipy/issues/15738

_______________________________________________
SciPy-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/scipy-dev.python.org/
Member address: [email protected]