The problem is that earlier versions of Python 2.6.2 produce  
expressions that are nested at more than one level, so  
expand_mul(deep=False) does not get it all the way.  I removed  
deep=False.  The only down effect is that you now get things like

exp(-2*x - x*2**(1/2))

instead of the slightly more preferable

exp(-x*(2 - sqrt(2))))

But it is just a prettyness of the results issue, so it is not  
critical.  I will change the code and the tests and repush.  I also  
found out that the except NotImplementedError as detail syntax I was  
using is not supported in Python 2.5, so I will need to fix that too.   
Does anyone have any idea why it would return a differently formatted  
solution for Python's under 2.6.2 (including 2.6.0)?  I think it might  
be the integral engine that is doing it.

Aaron Meurer
On Aug 20, 2009, at 10:49 AM, Andy Ray Terrel wrote:

>
> its commit:bfbd7711354ea4826a231e6712d34f8bb2801d44
>
>
> In [8]: hint = 'nth_linear_constant_coeff_variation_of_parameters'
>
> In [9]: eq6 = f(x).diff(x, 2) - 2*f(x).diff(x) - 8*f(x) - 9*x*exp(x) -
> 10*exp(-x)
>
> In [10]: sol6 = Eq(f(x), -x*exp(x) - 2*exp(-x) + C1*exp(-2*x) +  
> C2*exp(4*x))
>
> In [11]: d6 = dsolve(eq6, f(x), hint=hint)
>
> In [12]: d6 == sol6
> Out[12]: False
>
> In [13]: d6
> Out[13]:
>                         -x              /      -5*x    -3*x      -3*x\
>       /      x\  x   5*e         -2*x   |     e       e       x*e     
> |  4*x
> f(x) = |1/6 - -|*e  - ----- + C1*e     + |C2 - ----- - ----- -  
> -------|*e
>       \      2/        3                \       3       6        2   /
>
> In [14]: sol6
> Out[14]:
>            x      -x       -2*x       4*x
> f(x) = - x*e  - 2*e   + C1*e     + C2*e
>
> -- Andy
>
> On Thu, Aug 20, 2009 at 11:43 AM, Aaron S.  
> Meurer<asmeu...@gmail.com> wrote:
>>
>> What is your SHA1 hash of HEAD?  This test passes just fine on my
>> machine.  Could you maybe copy eq6 from the test file and run
>>
>> dsolve(eq6, f(x),
>> hint='nth_linear_constant_coeff_variation_of_parameters')
>>
>> and paste the result here?
>>
>> Aaron Meurer
>> On Aug 20, 2009, at 9:44 AM, Andy Ray Terrel wrote:
>>
>>>
>>> Running tests on HEAD I get the following error:
>>>
>>> sympy/solvers/tests/
>>> test_ode.py:test_nth_linear_constant_coeff_variation_of_parameters
>>>  File "/Users/aterrel/workspace/sympy/sympy/solvers/tests/
>>> test_ode.py",
>>> line 899, in test_nth_linear_constant_coeff_variation_of_parameters
>>>    assert dsolve(eq6, f(x), hint=hint) == sol6
>>> AssertionError
>>>
>>> tests finished: 1615 passed, 1 failed, 2 skipped, 44 xfailed, 1
>>> xpassed in 333.83 seconds
>>>
>>>
>>> -- Andy
>>>
>>> On Thu, Aug 20, 2009 at 6:23 AM, Vinzent
>>> Steinberg<vinzent.steinb...@googlemail.com> wrote:
>>>> Thank you, this is an impressive result. :)
>>>>
>>>> 2009/8/20 Aaron S. Meurer <asmeu...@gmail.com>
>>>>>
>>>>> I have finished up my Google Summer of Code 2009 project, which
>>>>> was to
>>>>> implement various ODE solvers in SymPy.  Please pull
>>>>> fromhttp://github.com/asmeurer/sympy/tree/odes-review
>>>>> .  Note that I have elected to do only moderate rebasing from my
>>>>> original tree (branch odes), so you should really only be  
>>>>> reviewing
>>>>> the HEAD.
>>>>>
>>>>> This includes the following features:
>>>>>
>>>>> - All ODE solving now happens in ode.py, instead of solvers.py  
>>>>> where
>>>>> it was crowding stuff.
>>>>> - dsolve() remains the function to use to solve an ODE.  The
>>>>> syntax is
>>>>> the same for default solving: dsolve(ode, func).
>>>>> For example:
>>>>>  >>> dsolve(diff(f(x), x, 2) - 1, f(x))
>>>>> f(x) == C1 + C2*x + x**2/2
>>>>>
>>>>> dsolve() always returns an Equality instance, because it very  
>>>>> often
>>>>> cannot solve for f(x) and must return an implicit solution.
>>>>>
>>>>> - The function classify_ode() was added.  This function classifies
>>>>> ODEs into the various methods (or "hints", as I also call them)  
>>>>> that
>>>>> dsolve() can use to solve them.
>>>>> For example:
>>>>>  >>> classify_ode(f(x).diff(x) - 1, f(x))
>>>>> ('separable', '1st_exact', '1st_linear', 'Bernoulli',
>>>>> '1st_homogeneous_coeff_best',
>>>>> '1st_homogeneous_coeff_subs_indep_div_dep',
>>>>> '1st_homogeneous_coeff_subs_dep_div_indep',
>>>>> 'nth_linear_constant_coeff_undetermined_coefficients',
>>>>> 'nth_linear_constant_coeff_variation_of_parameters',
>>>>> 'separable_Integral', '1st_exact_Integral', '1st_linear_Integral',
>>>>> 'Bernoulli_Integral',
>>>>> '1st_homogeneous_coeff_subs_indep_div_dep_Integral',
>>>>> '1st_homogeneous_coeff_subs_dep_div_indep_Integral',
>>>>> 'nth_linear_constant_coeff_variation_of_parameters_Integral')
>>>>>
>>>>> - The function deriv_degree() remains the function to use for
>>>>> determining the degree, or order, of an ODE.
>>>>> For example:
>>>>>  >>> deriv_degree(f(x).diff(x, 5) + sin(x) + f(x).diff(x, 2),  
>>>>> f(x))
>>>>> 5
>>>>>
>>>>> - The new function checkodesol() checks if a solution to an ODE is
>>>>> valid by substituting it in and either returning True if it  
>>>>> finds 0
>>>>> equivalence or the expression that it could not reduce to 0.
>>>>> For example:
>>>>>  >>> checkodesol(f(x).diff(x, 2) - 1, f(x), Eq(f(x), C1 + C2*x +
>>>>> x**2/2))
>>>>> True
>>>>>  >>> checkodesol(f(x).diff(x, 2) - 1, f(x), Eq(f(x), C1 + C2*x +
>>>>> x**2))
>>>>> 1
>>>>
>>>> This is problematic, because this way
>>>>
>>>> if not checkodesol(...):
>>>>     print 'not a solution'
>>>>
>>>> does not work, because most expressions evaluate to True. I'd  
>>>> prefer
>>>> returning just 0 instead of True, this is more consistent and  
>>>> useful.
>>>>
>>>>>
>>>>> - The function separatevars(), which I wrote to help with the 1st
>>>>> order separable method, attempts to intelligently separate  
>>>>> variables
>>>>> an expression  multiplicatively.
>>>>> For example:
>>>>>  >>> separatevars(x**2 + x**2*sin(y))
>>>>> x**2*(1 + sin(y))
>>>>>  >>> separatevars(exp(x + y))
>>>>> exp(x)*exp(y)
>>>>>
>>>>> This function resides in simplify.py.
>>>>>
>>>>> - The new function homogeneous_order(), which I wrote to help with
>>>>> the
>>>>> 1st order ODE with homogeneous coefficients method, determines the
>>>>> homogeneous order of an expression.  An expression F(x, y, ...) is
>>>>> homogeneous of order n if F(x*t, y*t, t*...) == t**n*F(x, y, ...).
>>>>> For example:
>>>>>  >>> homogeneous_order(x**2*sqrt(x**2 + y**2) + x*y**2*sin(x/y),
>>>>> x, y)
>>>>> 3
>>>>>
>>>>> - dsolve() will simplify arbitrary constants, and renumber them in
>>>>> order in the expression.  You should never see something like x +
>>>>> 2*C1
>>>>> or 1 + C2*x + C1*x**2 returned from dsolve().  You can disable
>>>>> this by
>>>>> using simplify=False in dsolve().
>>>>>
>>>>> - Internally, the solving engine has been completely refactored.
>>>>> The
>>>>> old way was to match the ODE to various solvers in a predetermined
>>>>> order, and as soon as it matched one, it would solve it using that
>>>>> method and return a result.  This had several problems with it.
>>>>>
>>>>> First, several ODEs can be solved with more than one method (c.f.
>>>>> the
>>>>> simple ODE in the classify_ode() example above), and sometimes you
>>>>> want to see the result from a different method.
>>>>>
>>>>> Second, sometimes the default solver would return a result that  
>>>>> was
>>>>> much more complex than another one would have returned if the ODE
>>>>> had
>>>>> gotten to it.  For example, it may return an implicit solution
>>>>> that is
>>>>> difficult for solve() to solve, whereas the other method would
>>>>> return
>>>>> the equation already solver.
>>>>
>>>>
>>>> typo
>>>>
>>>>>
>>>>>  Another common case is that one method
>>>>> would set up an integral that integrate() could not do, whereas
>>>>> another method would set up a simpler integral.  That leads to the
>>>>> third point.
>>>>>
>>>>> Third, whenever a solver would set up a hard integral, integrate()
>>>>> would either hand for a while then return an Integral, or it would
>>>>> hang forever.  Either way, you would get an unevaluatable (by  
>>>>> SymPy)
>>>>> integral, when sometimes another method might not give you that.
>>>>>
>>>>> Fourth, there was a lot of code duplicated this way.  For example,
>>>>> whenever a method had the potential to return an implicit
>>>>> solution, it
>>>>> had to duplicate the same code chunk that tried to solve it and
>>>>> return
>>>>> a solved solution if it could be solved or else an implicit
>>>>> solution.
>>>>>
>>>>> The new way is for dsolve to have an optional hint argument that  
>>>>> you
>>>>> can use to specify whatever method you want to use, if it fits.
>>>>> dsolve() calls classify_ode() on the ODE and gets all of the
>>>>> possible
>>>>> hints.  By default, hint="default" is used, which uses a
>>>>> predetermined
>>>>> order, much like the old way.  But you can easily use something  
>>>>> like
>>>>> hint="1st_exact" to change the hint from the default method to the
>>>>> 1st
>>>>> order exact ODE solver.  Aside from "default", there are also some
>>>>> other 'meta-hints' that you can use.  "all" will return a  
>>>>> dictionary
>>>>> of hint: solution terms for all matching hints.  "best" will use a
>>>>> heuristic to return the simplest of all possible solutions.  This
>>>>> heuristic is based on whether the solution has unevaluated  
>>>>> Integrals
>>>>> in it, whether it can be solved explicitly, and finally, just  
>>>>> which
>>>>> one is the shortest.  All hints that set up integrals also have a
>>>>> coresponding "hint_Integral" hint, which will not attempt to
>>>>> evaluate
>>>>> the integrals but instead return unevaluated Integrals in the
>>>>> solution.  "all_Integral" acts like "all", but it skips hints that
>>>>> attempt to evaluate integrals.  This is so you can quickly get an
>>>>> unevaluated integral of something you know SymPy cannot do,
>>>>> instead of
>>>>> letting integrate() hang.  It also lets you discover how the  
>>>>> solvers
>>>>> work by showing you what integrals they do.
>>>>>
>>>>> - Along with extensive documentation on all of the functions, I  
>>>>> have
>>>>> included a guide in the module docstring on how to add more
>>>>> methods to
>>>>> the module using the hints system.  It can give you an idea of how
>>>>> the
>>>>> system works internally.
>>>>>
>>>>>
>>>>> The following ODE solving methods have been implemented.  See the
>>>>> internal docstrings for more information on each method:
>>>>> - 1st order separable differential equations
>>>>> - 1st order differential equations whose coefficients or dx and dy
>>>>>  are functions homogeneous of the same order.
>>>>> - 1st order exact differential equations.
>>>>> - 1st order linear differential equations.  (this is already
>>>>> implemented in the current SymPy)
>>>>> - 1st order Bernoulli differential equations. (this is already
>>>>> implemented in the current SymPy by a patch I sent in in the  
>>>>> spring)
>>>>> - 2nd order Liouville differential equations.
>>>>> - nth order linear homogeneous differential equation with constant
>>>>>  coefficients.
>>>>> - nth order linear inhomogeneous differential equation with  
>>>>> constant
>>>>>  coefficients using the method of undetermined coefficients.
>>>>> - nth order linear inhomogeneous differential equation with  
>>>>> constant
>>>>>  coefficients using the method of variation of parameters.
>>>>>
>>>>> In addition to the ode module, this branch includes fixes to the
>>>>> following issues, which were necessary for me throughout my work:
>>>>> - Issues 1582, 1566, 1530, and 1429 (the first part only).
>>>>> - Integral.__getnewargs__ now properly works.  If r is an Integral
>>>>> instance, then r == r.new(r.__getnewargs__(r.args)) should  
>>>>> always be
>>>>> True.
>>>>> - Changed two assertions and one raise TypeError in solve() to  
>>>>> raise
>>>>> NotImplementedError.  This way, you do not have to check for
>>>>> AssertionError or TypeError to see if solve() has failed, only
>>>>> NotImplementedError.  See issues 1425 and 1338.
>>>>
>>>> I'll have to play around with this. :)
>>>>
>>>> Vinzent
>>>>
>>>>>
>>>>
>>>
>>>>
>>
>>
>>>
>>
>
> >


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sympy-patches" group.
To post to this group, send email to sympy-patches@googlegroups.com
To unsubscribe from this group, send email to 
sympy-patches+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sympy-patches?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to