sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.33k stars 453 forks source link

Numerical evaluation should return a complex number if applicable #24428

Open jdemeyer opened 6 years ago

jdemeyer commented 6 years ago

This looks wrong:

sage: arccosh(0.9)
NaN

Especially given all the following:

sage: arccosh(RDF(0.9))
0.45102681179626236*I
sage: arccosh(x).subs(x=0.9)
0.451026811796262*I
sage: sqrt(-2.0)
1.41421356237310*I

A complex number is more useful than a NaN so we shouldn't return NaN in the first example.

The Function code first calls x.arccosh() which returns the NaN. The reason for only the RDF case working is that RDF does not have a arccosh member function so the computation is delegated to Pynac where the complex value is returned.

Depends on #24832

Dependencies: #24832, pynac-0.7.17

CC: @rwst @slel

Component: symbolics

Author: Ralf Stephan

Branch/Commit: u/rws/24428 @ aa041a9

Issue created by migration from https://trac.sagemath.org/ticket/24428

jdemeyer commented 6 years ago

Description changed:

--- 
+++ 
@@ -10,3 +10,5 @@
 sage: arccosh(x).subs(x=0.9)
 0.451026811796262*I

+ +The second result is more useful, so the first should probably return a complex number too.

rwst commented 6 years ago
comment:2

I'm not decided on which result is correct. But see also #15344.

rwst commented 6 years ago
comment:3

so the first should probably return a complex number too

This would mean either 1. changing general evaluation of f(arg) to not try arg.f() first or, 2. changing the interface to mpfr_acosh() (which is responsible for the NaN), i.e. RR.arccosh(), and some others too.

I'm in favor of the latter.

rwst commented 6 years ago
comment:4

Note that RBF(0.9).arccosh() returns nan as well.

mantepse commented 6 years ago
comment:5

Does an expression in SR (like acosh) come with a notion of domain and codomain?

rwst commented 6 years ago
comment:6

Symbolic function expressions have internal restrictions as to their arguments but there is no information associated regarding domains. The function code in sage/functions and in Pynac raises stock Python exceptions and runtime errors if nonsensical arguments are encountered, but just yesterday I wished I could catch them specifically, e.g. by inheriting from domain error---it would enable much better random testing.

mantepse commented 6 years ago
comment:7

It might be important to note that this is a regression:

sage: arccosh(0.9)
NaN
sage: arccosh(x).subs(x=0.9)
NaN
sage: version()
'SageMath version 8.1.beta5, Release Date: 2017-09-11'
mantepse commented 6 years ago
comment:8

in fact, the change must have been introduced in 8.2.beta1, because in 8.2.beta0 it still gives the expected result.

rwst commented 6 years ago
comment:9

That is no surprise as I changed FP evaluation in the commit https://github.com/pynac/pynac/commit/d0f66f94ab4564a9a43aaf5907f7ac2a90047890

It might not be a bug. Still, the necessity of being consistent demands some fix somewhere.

rwst commented 6 years ago
comment:10

For example

sage: arccos(1.1)
NaN
sage: arccos(x).subs(x=1.1)
NaN

(EDITED)

So one of arccos/arccosh should be changed.

mantepse commented 6 years ago
comment:11

Changes in symbolics code are quite likely to produce doctest differences in the fricas interface, so it might make sense to make sure that these doctests are run.

In the case at hand, I guess it would be very important to specify domain and codomain of expressions which can be evaluated numerically, otherwise it will never be clear whether something is a bug or a feature.

Besides, I think that arccosh is terrible language :-)

slel commented 6 years ago

Description changed:

--- 
+++ 
@@ -12,3 +12,10 @@

The second result is more useful, so the first should probably return a complex number too. + +See also + + +sage: arccosh(RDF(0.9)) +0.45102681179626236*I +

slel commented 6 years ago
comment:12

Adding an example:

sage: arccosh(RDF(0.9))
0.45102681179626236*I
jdemeyer commented 6 years ago

Description changed:

--- 
+++ 
@@ -1,21 +1,25 @@
-It is very surprising that these do not give the same result:
+This looks wrong:

sage: arccosh(0.9) NaN

-and
+
+Especially given all the following:
+
+```
+sage: arccosh(RDF(0.9))
+0.45102681179626236*I
+```

sage: arccosh(x).subs(x=0.9) 0.451026811796262*I


-The second result is more useful, so the first should probably return a complex number too.
+```
+sage: sqrt(-2.0)
+1.41421356237310*I
+```

-See also
-
-```
-sage: arccosh(RDF(0.9))
-0.45102681179626236*I
-```
+A complex number is more useful than a `NaN` so we shouldn't return `NaN` in the first example.
videlec commented 6 years ago
comment:14

I don't care what you do with the function arccosh but all of

sage: RR(0.9).arccosh()
NaN
sage: RBF(0.9).arccosh()
nan
sage: RIF(0.9).arccosh()
[.. NaN ..]

must not change.

rwst commented 6 years ago
comment:15

With pynac-0.7.17:

sage: acos(SR(1.1))
0.443568254385115*I
sage: acosh(SR(0.9))
0.451026811796262*I
sage: acos(x).subs(x=1.1)
0.443568254385115*I
sage: acosh(x).subs(x=0.9)
0.451026811796262*I

Replying to @videlec:

I don't care what you do with the function arccosh but all of

sage: RR(0.9).arccosh()
NaN
sage: RBF(0.9).arccosh()
nan
sage: RIF(0.9).arccosh()
[.. NaN ..]

must not change.

That is however the reason for

sage: acos(1.1)
NaN

and all the others because here (1.1).acos() is called first.

rwst commented 6 years ago
comment:16

Replying to @slel:

Adding an example:

sage: arccosh(RDF(0.9))
0.45102681179626236*I

Note that this only works because RDF has no arccosh member function, so the computation is delegated to Pynac.

videlec commented 6 years ago
comment:17

Replying to @rwst:

Replying to @slel:

Adding an example:

sage: arccosh(RDF(0.9))
0.45102681179626236*I

Note that this only works because RDF has no arccosh member function, so the computation is delegated to Pynac.

In this situation you could just fallback to acosh

sage: RDF(0.9).acosh()
NaN
rwst commented 6 years ago
comment:18

Replying to @videlec:

sage: arccosh(RDF(0.9))
0.45102681179626236*I

Note that this only works because RDF has no arccosh member function, so the computation is delegated to Pynac.

In this situation you could just fallback to acosh

sage: RDF(0.9).acosh()
NaN

Instead of special casing I'd rather change the name of the inverse hyperbolic functions away from all the wrong arcs (arcus) to the as and have ar (area) aliases which would be the correct prefix.

Moreover, if I get a review on the change to always delegate to _eval_() (EDITED) if NaN is returned then I'd change that too.

rwst commented 6 years ago

Description changed:

--- 
+++ 
@@ -23,3 +23,5 @@

A complex number is more useful than a NaN so we shouldn't return NaN in the first example. + +The Function code first calls x.arccosh() which returns the NaN. The reason for only the RDF case working is that RDF does not have a arccosh member function so the computation is delegated to Pynac where the complex value is returned.

rwst commented 6 years ago
comment:20

So why is this not a bug?!

sage: RR(-2).sqrt()
1.41421356237310*I
rwst commented 6 years ago
comment:21

See https://groups.google.com/forum/#!topic/sage-devel/4GwCuJ_-TaQ

videlec commented 6 years ago
comment:22

Replying to @rwst:

Replying to @slel:

Adding an example:

sage: arccosh(RDF(0.9))
0.45102681179626236*I

Note that this only works because RDF has no arccosh member function, so the computation is delegated to Pynac.

In this situation you could just fallback to

sage: RDF(0.9).acosh()
NaN
videlec commented 6 years ago
comment:23

Replying to @rwst:

So why is this not a bug?!

sage: RR(-2).sqrt()
1.41421356237310*I

It is a bug.

rwst commented 6 years ago
comment:24

Following your answer in Groups I think then, instead of calling x.func() in the symbolic function code, x.func(extend=True) should be called, or alternatively, have data in the Function when to call x.func() and when to call parent.complex_field(x).func().

rwst commented 6 years ago

Dependencies: #24832

rwst commented 6 years ago

Branch: u/rws/24428

rwst commented 6 years ago

Author: Ralf Stephan

rwst commented 6 years ago

Changed dependencies from #24832 to #24832, pynac-0.7.17

rwst commented 6 years ago

Commit: aa041a9

rwst commented 6 years ago
comment:27

This needs fixes from pynac-0.7.17. To fix RR(-1).log I'd suggest a similar change in functions/log.py to enable the fix of RR.log().


New commits:

ff8c67224832: Extend function domain with some symbolic function calls
3bfcc8824832: add doctest
aa041a924428: Numerical evaluation should return a complex number if applicable
kliem commented 4 years ago
comment:28

Merge failed.