Powers of exponents
Dear All, I noticed that exp() functions is not aware of power() method. As a results simple things like pow(exp(a), 2) are not simplified to exp(2*a). I am attaching the corresponding patch. Best wishes, Vladimir -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/
Dear Vladimir, Vladimir V. Kisil wrote:
I noticed that exp() functions is not aware of power() method. As a results simple things like pow(exp(a), 2) are not simplified to exp(2*a). I am attaching the corresponding patch.
The rewriting rule pow(exp(x),a) -> exp(a*x) is not correct in the general complex case. Consider a=1/2 and x=-I*Pi, for instance. This is because, generally, log(exp(x)) -> x is not correct. GiNaC is very careful about *not* doing such simplifications that are not guaranteed to be correct, even in the general complex case. Maybe you are unaware of this file <http://www.ginac.de/ginac.git?a=blob;f=doc/powerlaws.tex;h=ade0547d048a51f65f414c08416a3979ea885ee8;hb=master>. Can you fix your patch to only do this simplification when it cannot be wrong? Best wishes -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Dear Richard,
On Wed, 30 Sep 2009 23:39:25 +0200, "Richard B. Kreckel" <kreckel@ginac.de> said:
RK> The rewriting rule pow(exp(x),a) -> exp(a*x) is not correct in RK> the general complex case. Consider a=1/2 and x=-I*Pi, for RK> instance. Thanks for pointing out this. I am attaching a patch which do the substitution only for real x and a. Best wishes, Vladimir -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/ --- inifcns_trans.cpp 2009-02-17 13:39:22.000000000 +0000 +++ patches/inifcns_trans.cpp 2009-10-01 16:03:58.000000000 +0100 @@ -99,9 +99,18 @@ return exp(GiNaC::real_part(x))*sin(GiNaC::imag_part(x)); } +static ex exp_power(const ex & x, const ex & a) +{ + if (x.info(info_flags::real) && a.info(info_flags::real)) + return exp(x*a); + + return power(exp(x), a).hold(); +} + REGISTER_FUNCTION(exp, eval_func(exp_eval). evalf_func(exp_evalf). derivative_func(exp_deriv). + power_func(exp_power). real_part_func(exp_real_part). imag_part_func(exp_imag_part). latex_name("\\exp"));
Vladimir V. Kisil wrote:
Dear Richard,
On Wed, 30 Sep 2009 23:39:25 +0200, "Richard B. Kreckel" <kreckel@ginac.de> said:
RK> The rewriting rule pow(exp(x),a) -> exp(a*x) is not correct in RK> the general complex case. Consider a=1/2 and x=-I*Pi, for RK> instance.
Thanks for pointing out this. I am attaching a patch which do the substitution only for real x and a.
It will also be true for arbitrary x if a is an integer.
On Thu, 01 Oct 2009 10:49:03 -0500, Stephen Montgomery-Smith <stephen@missouri.edu> said: SMS> It will also be true for arbitrary x if a is an integer.
Good point! The third iteration of the patch is attached. -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/ --- inifcns_trans.cpp 2009-02-17 13:39:22.000000000 +0000 +++ patches/inifcns_trans.cpp 2009-10-01 21:04:09.000000000 +0100 @@ -99,9 +99,19 @@ return exp(GiNaC::real_part(x))*sin(GiNaC::imag_part(x)); } +static ex exp_power(const ex & x, const ex & a) +{ + if (x.info(info_flags::integer) || a.info(info_flags::integer) + || (x.info(info_flags::real) && a.info(info_flags::real))) + return exp(x*a); + + return power(exp(x), a).hold(); +} + REGISTER_FUNCTION(exp, eval_func(exp_eval). evalf_func(exp_evalf). derivative_func(exp_deriv). + power_func(exp_power). real_part_func(exp_real_part). imag_part_func(exp_imag_part). latex_name("\\exp"));
Vladimir V. Kisil wrote:
On Thu, 01 Oct 2009 10:49:03 -0500, Stephen Montgomery-Smith <stephen@missouri.edu> said: SMS> It will also be true for arbitrary x if a is an integer.
Good point! The third iteration of the patch is attached. [...] + if (x.info(info_flags::integer) || a.info(info_flags::integer) + || (x.info(info_flags::real) && a.info(info_flags::real))) + return exp(x*a);
Maybe it is just too late, but I don't see the motivation for the "is x an integer" condition. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On Fri, 02 Oct 2009 00:00:13 +0200, "Richard B. Kreckel" <kreckel@ginac.de> said: RK> Maybe it is just too late, but I don't see the motivation for RK> the "is x an integer" condition.
Why not, if it is a correct substitution. Who know, may be as a result of some evaluation power of the exponents will becomes 2. Best wishes, Vladimir -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/
Vladimir V. Kisil wrote:
On Fri, 02 Oct 2009 00:00:13 +0200, "Richard B. Kreckel" <kreckel@ginac.de> said: RK> Maybe it is just too late, but I don't see the motivation for RK> the "is x an integer" condition.
Why not, if it is a correct substitution. Who know, may be as a result of some evaluation power of the exponents will becomes 2.
I think it is wrong to include "x is an integer." Even 1^i (which is exp(0)^i) is not well defined (it can be any of e^(2 pi n) for all integers).
On Fri, 02 Oct 2009 07:11:51 -0500, Stephen Montgomery-Smith <stephen@missouri.edu> said: SMS> I think it is wrong to include "x is an integer." Even 1^i SMS> (which is exp(0)^i) is not well defined (it can be any of e^(2 SMS> pi n) for all integers).
Alright, here is the patch to stay on the safe side. Best wishes, Vladimir -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/ --- inifcns_trans.cpp 2009-02-17 13:39:22.000000000 +0000 +++ patches/inifcns_trans.cpp 2009-10-02 15:45:17.000000000 +0100 @@ -99,9 +99,18 @@ return exp(GiNaC::real_part(x))*sin(GiNaC::imag_part(x)); } +static ex exp_power(const ex & x, const ex & a) +{ + if (a.info(info_flags::integer) || (x.info(info_flags::real) && a.info(info_flags::real))) + return exp(x*a); + + return power(exp(x), a).hold(); +} + REGISTER_FUNCTION(exp, eval_func(exp_eval). evalf_func(exp_evalf). derivative_func(exp_deriv). + power_func(exp_power). real_part_func(exp_real_part). imag_part_func(exp_imag_part). latex_name("\\exp"));
Hi! Stephen Montgomery-Smith wrote:
Vladimir V. Kisil wrote:
> On Fri, 02 Oct 2009 00:00:13 +0200, "Richard B. Kreckel" > <kreckel@ginac.de> said: RK> Maybe it is just too late, but I don't see the motivation for RK> the "is x an integer" condition.
Why not, if it is a correct substitution. Who know, may be as a result of some evaluation power of the exponents will becomes 2.
Actually, including "x is an integer" turns out to be correct. But we can do even better: it is sufficient to test if a is real. Here is a proof. With arbitrary complex b: pow(exp(a),b) == exp(b*log(exp(a)) Since a is real, we know that exp(a) is real and positive. So log(exp(a))==a and exp(b*log(exp(a))==exp(b*a). q.e.d. I'll push a patch for the exp function and for doc/powerlaws.tex.
I think it is wrong to include "x is an integer." Even 1^i (which is exp(0)^i) is not well defined (it can be any of e^(2 pi n) for all integers).
That argument is confused. After all, we rewrite exp(2*Pi*I) -> 1. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hi! I wrote:
I'll push a patch for the exp function and for doc/powerlaws.tex.
Oh, it is all there in doc/powerlaws.tex! This is another fine example where we saved an hour or so reading the documentation by spending a couple of days arguing back and forth. :-) -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hi! I wrote:
I'll push a patch for the exp function and for doc/powerlaws.tex.
Well, I didn't push it yet because it turns out that it interferes in surprising ways with mul::eval(). We used to have exp(x)/exp(x) -> 1 but that doesn't work any more because exp(x)^(-1) evaluates to exp(-x) first, resulting in exp(x)/exp(x) -> exp(x)*exp(-x). :-( Unless somebody comes up with a convincing idea how to fix eval() in the presence of pow(exp(x),a) -> exp(a*x) I'm not going to apply this patch. Bye -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hello everybody, I'm a new ginac user because I discover sage. So you might excuse my point of view if my arguments are out of ginac purpose. And this message isn't direct reponse for this patch. // 1 // I understand that ginac operates over complex analysis as the other computer algebra systems. In this case it's very curious to write exp(u)^v == exp(u*v). Fine choices of "branch cuts" may allow this point of view for a local study, but it isn't usual mathematics for general purpose. You understand I don't like the exp(u)^v == exp(u*v) // 2 // It' bad if exp(x)/exp(x) remains : sage reduces sin(x)/sin(x) == 1 as usual. I don't know the inner algorithms of ginac but I suppose that all function calls as sin(x) are seen as a new variable in the expression which is a fraction with a lot of variables, even if someones as sin(x) and cos(x) are linked together by cos(x)^2+sin(x)^2==1. So exp(x)/exp(x) must be simplified in 1. // 3 // Look at sin(x) and cos(x). Sometimes the user prefers the expanded formula with Tchebytchev polynomials (cos(2x)+1)/(sin(2x)) == (2 cos(x)^2)/(2 sin(x) cos(x)) == cos(x)/sin(x) == cotan(x). Othertimes the user wants to combine 2 cos(x)^2 into the (almost) linear form cos(2x)+1. Computer algebra systems don't have any automatic transform but the user calls the expand or the combine function for theses opposite purposes. Calculus are similar with exp : both transforms exp(x)^2 <==> exp(2*x) are useful. I observe that ginac respects algebraic user input : by example there are very view transform with x = 2*t/(1-t^2) ; x.subs(t=x) == 4*t / (1 - (2*t/(1-t^2))^2) Then the user calls expand, "simplify_fractions" or others functions if he wants an other form of this input. power and exp functions might be in the same case : exp(x)^2 remains exp(x)^2 and exp(2*x) remains exp(2*x). Then an expand call translates exp(2*x) to exp(x)^2 and a combine (or an other name) translates back exp(x)^2 to exp(2*x) If it does so, ginac respects also the user choice for the exp function as it does for the fractions.
participants (4)
-
Francois Maltey
-
Richard B. Kreckel
-
Stephen Montgomery-Smith
-
Vladimir V. Kisil