Comment #12 on issue 2753 by [email protected]: series(1/cos(x/log(x)),x,0,5) does not work
http://code.google.com/p/sympy/issues/detail?id=2753

Ok, let me try to give an answer.

First of all, what is logx about? I have tried to document this in the comments. See the beginning of power._eval_nseries and the top comment of functions/elementary/exponential.py. Executive summary: the _eval_nseries function has a dual purpose in sympy: for cooking up enduser series expansions vial the series() function, and for computing limits using the gruntz() algorithm. End users ask for certain shiny features in series() every now and then, and people are tempted to "fix" _eval_nseries. This almost always goes wrong, because the gruntz algorithm has very stringent requirements on said function. So most of the time when you make things look "good" or something then you break one of the gruntz test cases (hopefully...).

One of the particular properties of the gruntz algorithm is that it recursively examines parts of your expression depending on their order of growth. One consequence of this is that when gruntz does series expansions, the functions never contain logs of the independent variable - these have either been taken out as "too slowly growing" or have been simplified away by raising the independent variable to exponentials [*]. The series expansion code has to preserve this property - and so substitutes a dummy for logx, thereby ignoring things which "grow too slowly" [**].

The upshot is that the _eval_nseries functions are designed to work with gruntz, and gruntz calls them with certain special properties enforced. The _eval_nseries functions have to work in very particular ways under these conditions.

Now we come to the series() function. Ideally, what this does is to imitate the gruntz algorithm in calling _eval_nseries, and then brushing up the result in such a way as to be "nice". In practice, we more or less just take some guesses and call _eval_nseries and hope for the best. This is why series() sometimes seems to behave/break in strange ways.



Anyhow, loads of woffling. It seems to me that you are right: series() should pass a dummy logx parameter to _eval_nseries, and substitute back in the end. Unfortunately, as long as _eval_nseries tacks on the order terms, this way we lose logarithmic order factors, as you observed.

This is really related to the fact that there is no clear definition of what series() should do; as I have said before we re-use the _eval_nseries which behaves in very peculiar ways, and these may not always be what we want series() to do. I'm afraid I don't know a good way to overcome this issue, other than "(re-)design series() from scratch, make it first class, and give it a separate implementation". For now, it seems best to me to fix the one failing test (by removing the logx factor from the order) and explain in the series() docstring that this behaviour is expected.

But please mind that I have not been active in the sympy community for quite a while, others may have different opinions.


[*] I'm pretty sure this is not quite true; I don't remember all the details. The main point here is that this algorithm works delicately to avoid infinite recursion.

[**] Again, there is more going on here, most of which I have forgotten. I think you never get exp(logx) terms because of the special way to algorithm is set up, but I would have to check.

--
You received this message because this project is configured to send all issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

--
You received this message because you are subscribed to the Google Groups 
"sympy-issues" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy-issues.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to