Plot doesn't respect numerical precision specification.

45 views
Skip to first unread message

Emmanuel Charpentier

unread,
Dec 6, 2022, 7:53:54 AM12/6/22
to sage-support
Question already asked on |`ask.sagemath.org`](https://ask.sagemath.org/question/64934/plotting-ill-conditionned-function/), where it didn't attract a lot of attention...

Let

```
sage: f(x)=log(tan(pi/2*tanh(x))).diff(x) ; f
x |--> -1/2*pi*(tan(1/2*pi*tanh(x))^2 + 1)*(tanh(x)^2 - 1)/tan(1/2*pi*tanh(x))
```

It can be shown (see Juanjo's answer [here](https://ask.sagemath.org/question/64794/inconsistentincorrect-value-of-limit-involving-tan-and-tanh/)) that this finction's limit at `x=oo` is 2.

A couple CASes are wrong about it :

```
sage: f(x).limit(x=oo)
0
sage: f(x).limit(x=oo, algorithm="maxima")
0
```

A couple get it right :

```
sage: f(x).limit(x=oo, algorithm="giac")
2
sage: f(x).limit(x=oo, algorithm="mathematica_free")
2
```

And Sympy currently never returns.

A "naïve" way to explore this is to assess the situation is to look for numerical values :

```
plot(f, (1, 30))
```
tmp_bnpx6r7n.png

This plot hints at ill-conditionong of the epression of the function. And it turns out that this ill-conditioning can be overcome by specifying an "absurd" precision :

```
sage: f(30).n()
-0.000000000000000
sage: f(30).n(digits=30)
1.99999483984586167962667231030
```

But `plot` seems to *ignore* this specification :

```
sage: plot(lambda u:f(u).n(digits=30), (1, 30))
```

tmp_jeq3c8ko.png

We can try to "isolate" the precision specification in a Python function, which seems to work :

```
sage: def foo(x): return RR(f(x).n(digits=30))
sage: foo(30)
1.99999483984586
```

but is still defeated byr the inner gears of `plot` :

```
sage: plot(foo, (1, 30))
```

tmp_dg2gelpc.png

Why, Ô why ???


Dima Pasechnik

unread,
Dec 6, 2022, 8:16:56 AM12/6/22
to sage-s...@googlegroups.com
It's plotting via matplotlib, perhaps that's why the precision setting is ignored (or pehaps something like RDF is hardcoded in Sage plotting code)


--
You received this message because you are subscribed to the Google Groups "sage-support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-support...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sage-support/db271244-0ad7-4484-8a46-bdc4b1edd0f0n%40googlegroups.com.

Emmanuel Charpentier

unread,
Dec 6, 2022, 8:23:48 AM12/6/22
to sage-support

Le mardi 6 décembre 2022 à 14:16:56 UTC+1, dim…@gmail.com a écrit :

It's plotting via matplotlib, perhaps that's why the precision setting is ignored (or pehaps something like RDF is hardcoded in Sage plotting code)

That wouldn’t explain why the specification included in the lambda expression in the third example isn’t accepted : matplotlib should see the RR values returned by it (which do accept the precision specification).

Emmanuel Charpentier

unread,
Dec 6, 2022, 8:28:30 AM12/6/22
to sage-support

The same thing happens after :

sage: def foo(x):
....:     return RR(N(-1/2*pi*(tan(1/2*pi*tanh(x))^2 + 1)*(tanh(x)^2 - 1)/tan(1/2*pi*tanh(x)), digits=30))
....: 
sage: foo
<function foo at 0x7fe472aab250>
sage: plot(foo, (1, 30))
Launched png viewer for Graphics object consisting of 1 graphics primitive


Dima Pasechnik

unread,
Dec 6, 2022, 8:41:24 AM12/6/22
to sage-s...@googlegroups.com
I can only say that the precision settings are ignored somewhere, so you get e.g. with digits=20, not 30, the following:
sage: sage: def foo(x):
....: ....:     return RR(N(-1/2*pi*(tan(1/2*pi*tanh(x))^2 + 1)*(tanh(x)^2 - 1)/tan(1/2*pi*tanh(x)), digits
....: =20))
....:
sage: [foo(t) for t in [1..30]]
[1.93774723784661,
 1.96821438642349,
 1.99513501225342,
 1.99933077915401,
 1.99990923138260,
 1.99998771214757,
 1.99999833695304,
 1.99999977492984,
 1.99999996954002,
 1.99999999587773,
 1.99999999944087,
 1.99999999992499,
 1.99999999996552,
 2.00000000042880,
 1.99999999864906,
 1.99999996835578,
 1.99999995885087,
 2.00000113072913,
 2.00001042817460,
 2.00003433318607,
 1.99883239681839,
 1.99062668609516,
 1.94465796436172,
 2.14811194088516,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000]

or wihout digits set:
sage: [foo(t) for t in [1..30]]
[1.93774723784661,
 1.96821438642349,
 1.99513501225340,
 1.99933077915395,
 1.99990923138165,
 1.99998771213936,
 1.99999833692570,
 1.99999977472377,
 1.99999996716508,
 1.99999996314183,
 1.99999991577607,
 1.99999955972581,
 1.99998381431810,
 1.99992717313233,
 1.99985733718347,
 1.99771319132044,
 2.00589700214384,
 1.91808127189615,
 1.23125745353424,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000,
 -0.000000000000000]

if it were able to use the 30 digits, we would not have seen that drop down of the function graph to 0 somewhere just before 20.
 

Oscar Benjamin

unread,
Dec 6, 2022, 8:55:15 AM12/6/22
to sage-s...@googlegroups.com
On Tue, 6 Dec 2022 at 12:53, Emmanuel Charpentier
<emanuel.c...@gmail.com> wrote:
>
>
> And Sympy currently never returns.

With current SymPy master it takes 6 seconds:

In [1]: %time log(tan(pi/2*tanh(x))).diff(x).limit(x, oo)
CPU times: user 5.73 s, sys: 24 ms, total: 5.75 s
Wall time: 5.75 s
Out[1]: 2

The fix was part of a GSOC project this summer and will be in SymPy 1.12:
https://github.com/sympy/sympy/pull/23844

--
Oscar

Dima Pasechnik

unread,
Dec 6, 2022, 10:40:40 AM12/6/22
to sage-s...@googlegroups.com
even more fun can be had by trying to plot the symbolic derivative of the function at hand. It's just making no sense at all what I see...

Dima Pasechnik

unread,
Dec 6, 2022, 10:42:28 AM12/6/22
to sage-s...@googlegroups.com
On Tue, Dec 6, 2022 at 3:40 PM Dima Pasechnik <dim...@gmail.com> wrote:
even more fun can be had by trying to plot the symbolic derivative of the function at hand. It's just making no sense at all what I see...

regarding the original function, perhaps plot is trying to do a numeric derivative of it, but it's so bad that it gets confused...
Reply all
Reply to author
Forward
0 new messages