-
-
Notifications
You must be signed in to change notification settings - Fork 512
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
define symbolic functions for exponential integrals #11143
Comments
comment:1
As far as I can tell, the general Also, it's possible to get maxima to rewrite the exponential integrals in terms of gamma functions like so: sage: maxima.eval('expintrep:gamma_incomplete')
'gamma_incomplete'
sage: maxima.integrate(exp(-x)*log(x+1), x, 0, oo)
%e*gamma_incomplete(0,1)
sage: N(e*gamma(0,1), digits=18)
0.596347362323194074 But as you see, By the way, the owner on the ticket is @burcin, does that mean they are working on it currently? |
comment:3
Replying to @benjaminfjones:
That's unfortunate. However, mpmath seems to have it. So we could create a symbolic version and have the
Interesting.
That should be ok; the whole point of the table is to convert into the Sage equivalent.
No, that is an automatic thing that happens. It is possible to be designated an 'owner' of a ticket in a given component, which basically means you automatically get updates. If you want to 'own' it, please do! We really have plenty of special functions in Sage, but they are not always well exposed at the top level. Incidentally, once you comment on a ticket, I believe the default is to copy you in on all replies. So you didn't have to cc: yourself specially :) |
comment:4
Replying to @benjaminfjones:
Incomplete gamma is defined in Sage. You can access it directly though
I am not working on it. The ticket status |
comment:5
I guess the point of this ticket is to define symbolic function in Sage to represent exponential integrals, etc. The symbolic function class handles adding stuff to the conversion table automatically. Can we replace this ticket with several beginner tickets? One for each function we are missing. |
comment:6
Replying to @burcin:
Well, that would be nice. But we could also presumably do it directly, if that would solve this problem for now. Well, either is fine as long as it were to happen. If you do split this, be sure to give a good template (I mean a link to the template, not write it yourself). |
comment:7
I'm attempting to write a template for the
Questions:
|
comment:8
Those are good questions. I think the most important thing is to make sure that whatever is implemented has
My sense is that BuiltinFunction would be best. GinacFunction probably is only good for things that in fact evaluate in Ginac. This explains trig.py. This Ginac page shows that the ones which are GinacFunctions are exactly the ones which Ginac in fact has. I don't think it has most of these other functions. As for MaximaFunction, it seems to inherit from BuiltinFunction and lives in the special functions file. This dates from the days when Sage had very few options for symbolic stuff and evaluation, and so it just does a few extra things. If we moved to mpmath for a given function, we would probably use BuiltinFunction and then add evaluation options for Maxima and add to the conversion dictionary as needed. In fact, it wouldn't be a bad idea to have two different eval procedures if possible... As for where such things go, probably it would make sense to separate a lot of these special functions out into a separate file. The distinction between transcendental and special is not totally obvious, for instance :) By the way, we certainly want fewer of the wrapper functions! But that will take a lot of tedious work. |
comment:9
By the way, adding this will really be a great help. Sage has so many of the things almost anybody needs, but if you have to use mpmath or GSL or R or something else directly, it sort of makes Sage a moot point. The idea is having a one-stop shop. |
comment:10
I've uploaded a first shot at a template for the functions we want to add in this ticket. The patch exposes the general complex exponential integral function One of the docstring examples shows that the integral of Any comments or suggestions? |
This comment has been minimized.
This comment has been minimized.
Changed keywords from ei Ei to ei Ei special function maxima |
comment:12
The patch looks great. Thanks for the template. A few suggestions:
I changed the ticket description to limit this to implementing symbolic functions for exponential integrals. We can use the wiki page for a general overview of the progress on symbolic functions. |
Author: Benjamin Jones |
Reviewer: Burcin Erocal |
comment:13
Thanks for the feedback, Burcin! I feel like I'm developing an understanding for how symbolic functions are handled in Sage now. To your suggestions:
Let me know what you think. Once we've agreed on a good template for this one function, I will implement the rest of the exponential integral functions that are now listed on the wiki and upload to this ticket. |
comment:14
Perfect! I can only nitpick about documentation. :)
You're right, we should add an alias Thanks for working on this. |
comment:15
The tests similar to I made a little table below of some timings. In the first table , with ``if z == 0``
============================================= ========
Test Time
============================================= ========
sage: timeit("f = exp_integral_e(n,z)") 1.44 ms
sage: timeit("f = exp_integral_e(n,0)") 929 µs
sage: timeit("f = exp_integral_e(0,z)") 1.41 ms
sage: timeit("f = exp_integral_e(1.0,1.0)") 158 µs
============================================= ========
without ``if z == 0``
============================================= ======
Test Time
============================================= ======
sage: timeit("f = exp_integral_e(n,z)") 541 µs
sage: timeit("f = exp_integral_e(n,0)") 300 µs
sage: timeit("f = exp_integral_e(0,z)") 299 µs
sage: timeit("f = exp_integral_e(1.0,1.0)") 161 µs
============================================= ======
with:
.. code-block:: python
try:
approx_z = ComplexIntervalField()(z)
# if z is zero and n > 1
if bool(approx_z.imag() == 0) and bool(approx_z.real() == 0):
if n > 1:
return 1/(n-1)
except: # z is symbolic
pass
# if n is zero
try:
approx_n = ComplexIntervalField()(n)
if bool(approx_n.imag() == 0) and bool(approx_n.real() == 0):
return exp(-z)/z
except: # n is symbolic
pass
============================================= ======
Test Time
============================================= ======
sage: timeit("f = exp_integral_e(n,z)") 570 µs
sage: timeit("f = exp_integral_e(n,0)") 576 µs
sage: timeit("f = exp_integral_e(0,z)") 1.05 ms
sage: timeit("f = exp_integral_e(1.0,1.0)") 160 µs
============================================= ====== Timings in tables 2 and 3 are close except in the case where Another thing I discovered is that these two special cases that I was
So I think in the interest of speedy evaluation it's best to leave the special I've uploaded a new patch. I'll start implementing the other exponential integrals using this as a template. |
comment:16
The timings are really instructive, we should link to them from wiki page. Thank you for this careful study. Replying to @benjaminfjones:
I think your timings show that using the CIF approximation is not such a big penalty. Note that your timings also reflect the construction of the result and not just including that change. It is better if Sage can do the evaluation automatically without having to pass through a Since this approximation is being called so often, we should make it a method of symbolic expressions. I opened a new ticket for this: #11513. This ticket should depend on that. I will provide a preliminary patch for #11513 soon. |
comment:17
I attached a very simple patch to #11513. Now we can write the check for zero as:
It would be nice if we could simplify this further, but I need to go and do other things now. :) |
comment:18
The patch now depends on #11513 Here are new timings for the .. code-block:: python
# special case: *quickly* test if (z == 0 and n > 1)
if isinstance(z, Expression):
if z._is_numerically_zero():
z_zero = True # for later
if n > 1:
return 1/(n-1)
else:
if not z:
z_zero = True
if n > 1:
return 1/(n-1)
====================================================== =======
Test Time
====================================================== =======
sage: timeit("f = exp_integral_e(n,z)") 535 µs
sage: timeit("f = exp_integral_e(n,0)") 482 µs
sage: assume(n > 1); timeit("f = exp_integral_e(n,0)") 3.56 ms
sage: timeit("f = exp_integral_e(0,z)") 968 µs
sage: timeit("f = exp_integral_e(1.0,1.0)") 160 µs
====================================================== ======= I realized that in row 2 of the previous timings I neglected to assume n > 1 so those timings aren't giving much information since the expression is left unevaluated like in row 1. The new row 3 includes that assumption so that the simplified result I'll update the timings above and move these tables to the wiki. |
Attachment: trac_11143_En.patch.gz added the symbolic function |
comment:19
In the patch, I'm added a function to I was thinking of moving the six new functions to a new file |
comment:88
There is a trivial doctest failure on 32-bit i386 systems (possibly other systems too):
|
Attachment: trac_11143-v2.5-rebased.3.patch.gz fixed failing doctest |
comment:89
Fixed the failing doctest (for the reviewer: this only changed lines 1300--1301 in |
This comment has been minimized.
This comment has been minimized.
comment:90
Wouldn't a relative tolerance be better than an absolute one? With the absolute tolerance, the fourth value can essentially be anything. |
comment:91
Yes, you're right. I'll change that. |
changed |
This comment has been minimized.
This comment has been minimized.
comment:92
Attachment: trac_11143-v2.5-rebased.4.patch.gz |
comment:93
Patchbot, please kindly apply:
Thank you in advance. |
comment:94
I'm happy with the changes to that line. I haven't re-checked the whole patch again, but I thrust that you didn't change anything else. |
Merged: sage-5.3.beta2 |
comment:97
See #14766 for a followup. |
We're missing some conversions from Maxima. Like exponential integrals of various kinds.
See this ask.sagemath post for some details.
Current symbol conversion table
From
sage.symbolic.pynac.symbol_table['maxima']
as of Sage-4.7Summary of missing conversions
Special functions defined in Maxima
(http://maxima.sourceforge.net/docs/manual/en/maxima_16.html#SEC56)
Bessel
class, but no conversions from Maxima's bessel_i etc. to Sage.legendre_P(n, x)
andlegendre_Q(n, x)
both described as Legendre functions. It's not clear to me how there are related to Maxima's versions since the number of arguments differs.hypergeometric(l1, l2, z)
needs a conversion to Sage'shypergeometric_U
. The others can be evaluated using mpmath.slommel
is presumably mpmath'slommels1()
orlommels2()
(or both?). This isn't well documented in Maxima.expintegral_e1
andexpintegral_ei (z)
are calledexponential_integral_1
andEi
resp. in Sage. They both need conversions. The rest needBuiltinFunction
classes defined for them with evaluation handled by mpmath and the symbol table conversion added. Also,erfc
is callederror_fcn
, so also needs a conversion.kelliptic(z)
needs a conversion toelliptic_kc
in Sage andparabolic_cylinder_d (v,z)
does not seem to be exposed at top level. It can be evaluated by mpmath.Apply to the Sage library:
Depends on #13109
Component: symbolics
Keywords: ei Ei special function maxima sd32 sd40.5
Author: Benjamin Jones, Volker Braun
Reviewer: Burcin Erocal, Karl-Dieter Crisman, William Stein
Merged: sage-5.3.beta2
Issue created by migration from https://trac.sagemath.org/ticket/11143
The text was updated successfully, but these errors were encountered: