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

Robert Kern <[email protected]> Mon, 1 May 2023 20:44:54 -0400
Newsgroups gmane.comp.python.scientific.devel
Message-ID <CAF6FJit7=BDKn=eCAkOvj-RbPOFFjyRiuqasFjxPQMQOZuZCQg@mail.gmail.com>
On Mon, May 1, 2023 at 8:17 PM Robert Kern <[email protected]> wrote:

> On Mon, May 1, 2023 at 7:22 PM Stefan van der Walt <[email protected]>
> wrote:
>
>> On Mon, May 1, 2023, at 11:49, Ilhan Polat wrote:
>>
>> 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.
>>
>>
>> The first formulation — max(atol, rtol*norm(b)) — is what I'd expect.
>> I.e., you use atol when answers are small, or rtol for larger answers.  I'm
>> a bit surprised to see them summed; is this standard?
>>
>
> I concur. `max()` is the appropriate way to combine the two that I'd
> expect to see in almost all circumstances. `+` does have a history in our
> ecosystem as we do use `+` in `np.isclose()`, though, but I think that is a
> bit of a special case of comparing two numbers rather than the size of one
> number, and I've never been really convinced by the arguments for it.
> `math.isclose()` works like `max()` (though it is implemented with explicit
> `||` operations).
>
> Julia's iterative solvers use `max()`.
>
>
> https://github.com/JuliaLinearAlgebra/IterativeSolvers.jl/blob/master/src/cg.jl#L141
>
> MATLAB's numerical integration routines use `max()`.
>
>   https://www.mathworks.com/help/matlab/ref/integral.html#btc_m8o-4
>

That said, `+` is not at all uncommon outside of our own ecosystem either.
Julia's Krylov solvers use it:

  https://docs.juliahub.com/Krylov/0fcC3/0.5.5/solvers/

Here's some numerical analysis course that uses it:

  http://web.mit.edu/10.001/Web/Tips/Converge.htm

I've never really seen any *comparison* between the two outside of some
half-remembered arguments over `np.isclose()` early in development. I think
`max()` is the most justified and interpretable. It's just a way to code
the ORing of the two conditions. If either the absolute tolerance is met OR
the relative tolerance is met, then stop. With `+`, it's a weird mix of
both that's close to the `max()` result in most sane circumstances, but
diverges in some cases. When the user chooses really bad choices for the
two tolerances, neither will work particularly well, but `max()` is easier
to reason about why it doesn't work well in that case.

I strongly suspect `+` gets its lineage either from C codes or pre-F77
codes where there was no builtin `max()` to use.

--
Robert Kern

_______________________________________________
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]