-
-
Notifications
You must be signed in to change notification settings - Fork 487
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix coercion bugs in symbolic functions #17130
Comments
comment:1
Just to clarify, you mean that the precision of the less precise input ( My guess is that this line is to blame.
I don't have time right now to check this out, but I would not be at all surprised. Or it's the |
comment:2
Replying to @kcrisman:
Yes, the less-precise result is converted to the more-precise parent. |
comment:3
Replying to @kcrisman:
Especially the |
comment:4
The following patch fixes the problem diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx
index 408b6da..5beb01d 100644
--- a/src/sage/symbolic/function.pyx
+++ b/src/sage/symbolic/function.pyx
@@ -914,38 +914,6 @@ cdef class BuiltinFunction(Function):
res = super(BuiltinFunction, self).__call__(
*args, coerce=coerce, hold=hold)
- # we want to convert the result to the original parent if the input
- # is not exact, so we store the parent here
- org_parent = parent_c(args[0])
-
- # convert the result back to the original parent previously stored
- # otherwise we end up with
- # sage: arctan(RR(1))
- # 1/4*pi
- # which is surprising, to say the least...
- if org_parent is not SR and \
- (org_parent is float or org_parent is complex or \
- (PY_TYPE_CHECK(org_parent, Parent) and \
- not org_parent.is_exact())):
- try:
- return org_parent(res)
- except (TypeError, ValueError):
- pass
-
- # conversion to the original parent failed
- # we try if it works with the corresponding complex domain
- if org_parent is float or org_parent is complex:
- try:
- from sage.rings.complex_double import CDF
- return complex(CDF(res))
- except (TypeError, ValueError):
- pass
- elif hasattr(org_parent, 'complex_field'):
- try:
- return org_parent.complex_field()(res)
- except (TypeError, ValueError):
- pass
-
return res
cdef _is_registered(self): but with quite a bit of doctest failures. |
This comment has been minimized.
This comment has been minimized.
comment:6
I think a correct result with the wrong parent is better than a wrong result with the correct parent, so I'm inclined to really remove that block of code and fix individual functions instead. |
comment:7
I'm not surprised - the problem is that this kind of code was added at various times to handle certain cases where the output was not the same type as the input (e.g., complex output for real/float input). For instance, does the example mentioned in the code
work properly with this patch? Again, I'm sorry I don't have time to do more than read code for five minutes at this point :( Edit: I see your most recent comment - yes, that would certainly be helpful, though I have a feeling a LOT of functions would have to be fixed... because some probably implicitly rely on this block but aren't thoroughly tested for unusual input/output. Edit by jdemeyer: Sorry, edit instead of reply |
comment:8
Perhaps one could take the coercion mutual parents of all args instead for a minimal change? (Would that work?) I think in principle it's better to handle this all at once rather than having things in each individual function - if possible, of course. |
comment:9
Replying to @kcrisman:
This works as it should, many doctest failures involve Python types:
(I guess this goes through Pynac) |
comment:10
Replying to @kcrisman:
That still wouldn't fix the case where the function is computed to less precision than the inputs. I think the following would fix most issues:
|
comment:11
Not all arguments need to be floating point types, there could be integer or string parameters. So you can't indiscriminately coerce. IMHO we should just add a clause that if output is float and of lower precision then use that lower precision. In an ideal world we would be able to evaluate everything to arbitrary precision, of course. |
This comment has been minimized.
This comment has been minimized.
Author: Jeroen Demeyer |
Branch: u/jdemeyer/ticket/17130 |
New commits:
|
Commit: |
Dependencies: #17131 |
This comment has been minimized.
This comment has been minimized.
comment:21
Wow, that first commit is a nice patch bomb. I hesitate to make so much change to how symbolic functions are evaluated without taking a pretty close look, my apologies for not trying to do that immediately. Also, I think there was an actual reason for calling it |
comment:22
Replying to @kcrisman:
Would you be more willing to review the patch if it would be split up? I could try to do that but only if I have confirmation that it will increase the chances of this ticket being reviewed. |
comment:23
I don't think it is overly long, nor is there a good way of splitting it up. Patch looks good to me. Its somewhat confusing that Is it possible to replace
I'm not super happy with pi being "inexact", though perhaps there is a technical reason for why we need it. |
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:51
Still passes tests in |
comment:52
|
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:55
There may be a followup in a later ticket to deal with an inconsistency, if you agree that the following discrepancy between functions with one and two parameters needs addressing:
EDIT: Ah, never mind, |
Changed branch from u/jdemeyer/ticket/17130 to |
Changed commit from |
comment:57
Question for Jeroen and Ralf - any updating needed in the documentation in sage/symbolic/function_factory.py function |
comment:58
Replying to @kcrisman:
No, this is only about |
This uses coercion correctly:
However, it seems that
__call__()
coerces this result back to the first parent, giving false precision:Same issue with functions which are evaluated using Maxima, which does not support arbitrary precision:
The
gamma_inc()
function also mishandles parents:Apart from this, this branch also removes lots of boilerplate from
_eval_
likeby wrapping
_eval_
inside the new method_evalf_or_eval_
which automatically does this boilerplate.Possible follow-ups: #10133, #14766, #16587, #17122, #15200
Depends on #17131
Depends on #17133
CC: @burcin @rwst
Component: symbolics
Author: Jeroen Demeyer
Branch:
abab222
Reviewer: Ralf Stephan
Issue created by migration from https://trac.sagemath.org/ticket/17130
The text was updated successfully, but these errors were encountered: