Opened 7 years ago
Closed 6 years ago
#8983 closed enhancement (fixed)
erf(0) should return 0
Reported by: | rossk | Owned by: | RossK |
---|---|---|---|
Priority: | minor | Milestone: | sage-5.0 |
Component: | symbolics | Keywords: | erf, beginner |
Cc: | burcin, kcrisman | Merged in: | sage-5.0.beta5 |
Authors: | Benjamin Jones | Reviewers: | Burcin Erocal, Douglas McNeil |
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description (last modified by )
Attachments (3)
Change History (24)
comment:1 Changed 7 years ago by
- Priority changed from major to minor
- Type changed from defect to enhancement
comment:2 Changed 7 years ago by
- Cc burcin added; burcin@… removed
- Summary changed from solve(erf(x)==0,x) should return x==0 as a solution to erf(0) should return 0
comment:3 Changed 7 years ago by
- Keywords beginner added; zero removed
comment:4 Changed 7 years ago by
- Cc kcrisman added
comment:5 follow-up: ↓ 6 Changed 7 years ago by
Beginner reporting for duty! So I have a patch which sets erf(0) to 0 -- or, rather, to parent(x)(0) if x==0, so that it's the "right" zero; I think this is the right idiom -- and adds complex arguments from mpmath.
But I have a few questions that came up along the way:
(1) In 4.6.1, solve(erf(x)==0,x) seems to work for me already, before the patch. Did I get my binaries confused somehow, or did something change elsewhere?
(2) It'd be nice if #8720 (fixing str(CC(0))) were finished, it surprised me when writing tests for the zero type preservation. Maybe I should have a look, I think it's mostly fixing some doctests left.
(3) My patch broke a doctest in functions/special.py, which expected erf(0.5) to be evaluated to 0.520499877813047, but the existing doctests for erf demand that erf(2) = erf(2). I can get that behaviour, namely to evaluate for reals and to hold for integers except for zero, but I don't quite follow it.
(4) Since I'm doing a bit more, should I open an enhancement ticket instead?
comment:6 in reply to: ↑ 5 Changed 7 years ago by
- Description modified (diff)
You should always feel free to add patches - it's MUCH easier to tell what people are talking about, even if the patch is really, really preliminary.
(1) In 4.6.1, solve(erf(x)==0,x) seems to work for me already, before the patch. Did I get my binaries confused somehow, or did something change elsewhere?
This must be from an improvement in Maxima during the several recent upgrades. I've updated the description.
(3) My patch broke a doctest in functions/special.py, which expected erf(0.5) to be evaluated to 0.520499877813047, but the existing doctests for erf demand that erf(2) = erf(2). I can get that behaviour, namely to evaluate for reals and to hold for integers except for zero, but I don't quite follow it.
No, the usual practice is to not evaluate (give symbolic back) for "exact" rings and evaluate (give numeric back) for "inexact" rings. There is some disagreement among developers about exactly what these words mean, but basically erf(x),erf(1/2),erf(2),erf(e)
should all return something symbolic and erf(.1),erf(RDF(1))
, etc. should return something numeric. I.e. erf2)!=erf(2.)
.
(4) Since I'm doing a bit more, should I open an enhancement ticket instead?
I believe there already is a ticket for the complex pieces at #1173, similarly at #9044. If you have a good solution to the whole thing, you could do it at one of those and then say this ticket can be closed when they are (if you have also documented that it's fixed.
comment:7 Changed 7 years ago by
@kcrisman: okay, understood. Will propose under #1173.
comment:8 Changed 6 years ago by
comment:9 Changed 6 years ago by
I think the right thing to do here is to depend on #11513. There are several ways one could address the issue in the summary about erf(0) not returning 0, but when a good patch for 11513 appears, the code being touched here would need to be changed again.
comment:10 Changed 6 years ago by
- Status changed from new to needs_review
I uploaded a simple patch now that #11513 is merged.
comment:11 follow-up: ↓ 16 Changed 6 years ago by
Looks good, but I think we should return a Sage zero (or at least match the type):
sage: erf(0) 0 sage: parent(erf(0)) <type 'int'>
comment:12 Changed 6 years ago by
That's a good point, this patch addresses the issue by returning the input x
instead of 0 when a python 0 would have been returned in the previous patch.
sage: erf(0) 0 sage: type(erf(0)) <type 'sage.rings.integer.Integer'> sage: parent(erf(0)) Integer Ring
comment:13 Changed 6 years ago by
- Description modified (diff)
comment:14 Changed 6 years ago by
Okay, looks good to me (or at least none of my obvious tricks could break it).
comment:15 follow-up: ↓ 17 Changed 6 years ago by
- Reviewers set to Burcin Erocal, Douglas McNeil
Thanks for the patch Benjamin. It looks great and gets the job done. However, I'd be much happier if there were a couple more doctests. There are quite a few branches in the new _eval_()
function, but the patch adds only one doctest.
One more suggestion: It might be better to leave the last return None
statement outside the if
s. IMHO, the following is more compact and readable.
if not isinstance(x, Expression): if is_inexact(x): return self._evalf_(x, parent=parent(x)) elif x == 0: return x elif x.is_trivial_zero(): return x return None
comment:16 in reply to: ↑ 11 Changed 6 years ago by
Replying to dsm:
Looks good, but I think we should return a Sage zero (or at least match the type):
Is this what you were referring to at comment:2:ticket:10133, dsm?
More generally, does anyone think the present way of ensuring erf(0)
returns an Integer (or even Symbolic Expression) is a good one for #10133? Or is it better to address this at the Pynac level?
comment:17 in reply to: ↑ 15 ; follow-up: ↓ 19 Changed 6 years ago by
Replying to burcin:
That's a good suggestion. I modified the _eval_
method accordingly and added several doctests verifying that all branches are reached. Maybe that's overkill, but it took me a while to find an input that actually reached the x.is_trivial_zero()
branch.
comment:18 Changed 6 years ago by
- Description modified (diff)
comment:19 in reply to: ↑ 17 Changed 6 years ago by
- Status changed from needs_review to positive_review
Replying to benjaminfjones:
Maybe that's overkill, but it took me a while to find an input that actually reached the
x.is_trivial_zero()
branch.
It's not overkill at all, after adding _a_ doctest to every function, perhaps we will measure the coverage in terms of percentage of lines executed with those tests. Thanks for spending the time and giving this function 100% coverage. :)
BTW, erf(SR(0))
should be a simple way of hitting the is_trivially_zero()
branch.
comment:20 Changed 6 years ago by
Ok, I simplified that last doctest in _eval_
.
comment:21 Changed 6 years ago by
- Merged in set to sage-5.0.beta5
- Resolution set to fixed
- Status changed from positive_review to closed
Here is the relevant thread on sage-devel:
http://groups.google.com/group/sage-devel/t/d236e80bf7826bff
The main problem is this:
We should just return 0.