Thanks for your reply Aaron. I've suggested a possible solution and patch at issue 1685 which does not appear to affect your ode.py code.
http://code.google.com/p/sympy/issues/detail?id=1685&sort=-id This is my first attempt to contribute a patch to sympy (or any other project) so please forgive any errors! If anyone has time to review this issue and offer advice I would be grateful. Cheers, andy (I think the problem is caused by an attempted performace optimisation in simplify.py, which tries to avoid calling a function make_expression (..) but fails to handle the general case.) On Oct 25, 11:07 pm, "Aaron S. Meurer" <asmeu...@gmail.com> wrote: > See ode.py, line 542 for at least one place where the collecting of > derivatives is used. In this case, it says collect(eq, f(x).diff(x)) > Changing this to collect(eq, f(x)) causes almost all tests in > test_ode.py to fail (meaning it doesn't collect in the same way). > > The behavior of collect to collect derivatives existed long before > that line in ode.py (which I wrote), so I wouldn't be surprised if it > is used somewhere else. > > By the way, this issue looks similar to issue 1644 (closed). I don't > know if they are related at all though. > > Also, if you create a fix that breaks line 542 in ode.py, my comment > #4 applies. I was just taking advantage of the existing behavior, so > if it changes the code I used can change too. > > Aaron Meurer > On Oct 25, 2009, at 4:24 PM, andy2O wrote: > > > > > Ok - here's the result of a little digging: In collect(...), which > > lives in simplify.py, an expression is parsed by a sub-function called > > 'parse_expression(...), split, and then recreated. By turning > > SYMPY_DEBUG to True, you find: > > >>>> a=Derivative(f(x),x) > >>>> collect(a,f(x)) > > DEBUG: parsing of expression [(f(x), 1, None, (x, 1))] with symbol f > > (x) > > DEBUG: returned ([], [(f(x), 1, None, (x, 1))], 1, False) > > ^^^^^^ > > This indicates the first order > > derivative w.r.t. x. > > > So parse_expression(...) considers that Derivative(f(x),x) matches the > > pattern f(x). From the 'collect(...)' docstring I guess this is > > deliberate, and sometimes useful? > > > However, in the definition of 'collect' around line 650 of > > simplify.py, the following code is used to rebuild an expression from > > the output of 'parse_expression(...)'. This rebuilding code ignores > > derivatives when it is reconstructing the expression: > > > if result is not None: > > terms, elems, common_expo, has_deriv = result > > > # when there was derivative in current pattern we > > # will need to rebuild its expression from scratch > > if not has_deriv: > > index = 1 > > for elem in elems: > > index *= Pow(elem[0], elem[1]) > > if elem[2] is not None: > > index **= elem[2] > > > Note how elem[3], which contains information about any derivatives, is > > involved is not used at all in rebuilding the expression. Also note > > that the 'if not has_deriv' test applies to the pattern, not the > > expression. > > > I think this is where the error is, but I'm not quite sure what the > > desired fix should be: > > > 1) Should parse_expression(...) be changed to not match derivatives > > when given a function? > > 2) Or should the above code that rebuilds the expression be changed? > > 3) Or something else? > > > I think something needs changing, as: > > >>>> collect(5*f(x)+3*Derivative(f(x),x),f(x)) > > 8*f(x) > > > is clearly wrong!! > > > Thanks for your help. > > Andy > > > On Oct 25, 6:47 pm, andy2O <and...@hotmail.com> wrote: > >> Thanks for your replies. > > >> as_coeff_exponent(...) does the right thing for the (similar) > >> Integral > >> operation on f(x), so I'm not sure big changes are needed to fix this > >> little glitch. > > >> I think this traces back to something slightly strange in > >> sympy.collect > >> (...) which is used by as_coeff_exponent. The behaviour for the > >> fourth > >> line of input below seems odd. > > >> I'll dig a little more and see what I find. > > >> Cheers, > >> andy > > >>>>> Integral(f(x),x).as_coeff_exponent(f(x)) #This is OK > > >> (Integral(f(x), x), 0)>>> Derivative(f(x),x).as_coeff_exponent(f > >> (x)) #This is what I first posted about, seems very odd. > >> (1, 1) > >>>>> collect(Integral(f(x),x),f(x),evaluate=False) #This seems OK. > > >> {1: Integral(f(x), x)}>>> collect(Derivative(f(x),x),f > >> (x),evaluate=False) #This looks odd to me - collect has lost track > >> of the derivative. > > >> {f(x): 1} > > >> also: > > >>>>> collect(Derivative(2*f(x),x,x),f(x),evaluate=False) #Probably > >>>>> OK... > > >> {1: D(2*f(x), x, x)}>>> collect(2*Derivative(f(x),x,x),f > >> (x),evaluate=False) #Weird result again - collect loses derivative > >> operation again. > > >> {f(x): 2} > > >> On Oct 22, 10:47 pm, Ondrej Certik <ond...@certik.cz> wrote: > > >>> On Thu, Oct 22, 2009 at 3:43 PM, Ronan Lamy <ronan.l...@gmail.com> > >>> wrote: > > >>>> Le jeudi 22 octobre 2009 à 14:42 -0700, Ondrej Certik a écrit : > >>>>> On Thu, Oct 22, 2009 at 2:34 PM, andy2O <and...@hotmail.com> > >>>>> wrote: > > >>>>>> Hi all, > > >>>>>> as_coeff_exponent(...) seems to ignore derivatives, as shown > >>>>>> below > > >>>>>> Is this behaviour intended? If so I can report it as an issue > >>>>>> - but > >>>>>> last time recorded an issue it turned out I just misunderstood > >>>>>> atoms > >>>>>> (), so I thought I'd check first here! :) > > >>>>> Sure. :) > > >>>>>> Thanks, > >>>>>> andy > > >>>>>>>>> ================================ RESTART > >>>>>>>>> ================================ > >>>>>>>>> from sympy import * > >>>>>>>>> var('x') > >>>>>> x > >>>>>>>>> f=Function('f') > >>>>>>>>> d=diff(f(x),x) > >>>>>>>>> d > >>>>>> D(f(x), x) > >>>>>>>>> d.as_coeff_exponent(f(x)) > >>>>>> (1, 1) > > >>>>> What do you suggest to be a correct answer? I never used > >>>>> as_coeff_exponent inside a derivative. > > >>>>> Ondrej > > >>>> The correct answer is clearly (D(f(x), x), 0), by analogy with > >>>> cos(x).as_coeff_exponent(sin(x)) == (cos(x), 0). So, yes, Andy, > >>>> you've > >>>> uncovered a real issue. > > >>>> I think that the fundamental problem here is that there is no > >>>> object > >>>> representing the derivative of a function (the current Derivative > >>>> is an > >>>> operation applying to expressions, not functions). > > >>> Yes, I think the Derivative should be improved to be able to > >>> represent > >>> a general derivative of a function f(x). > > >>> Ondrej > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sympy@googlegroups.com To unsubscribe from this group, send email to sympy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sympy?hl=en -~----------~----~----~----~------~----~------~--~---