You can repull, I have fixed the checkodesol thing, as well as some  
other bugs.

Aaron Meurer
On Aug 20, 2009, at 2:58 PM, Vinzent Steinberg wrote:

> 2009/8/20 Aaron S. Meurer <asmeu...@gmail.com>
>
> On Aug 20, 2009, at 11:19 AM, Vinzent Steinberg wrote:
>
>>
>> 2009/8/20 Aaron S. Meurer <asmeu...@gmail.com>
>>
>> On Aug 20, 2009, at 5:23 AM, Vinzent Steinberg 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.
>>
>> Well, the idea is that sometimes an expression will be equivalent  
>> to 0, but simplify() cannot do it.  So we return the result to the  
>> user, who can then do his own checking to see if it is 0.  This is  
>> more or less what Maple's
>>
>> If you read the docstring, you can see that "if checkodesol()" is  
>> bad because it will always be True (unless it fails), but "if  
>> checkodesol() is True" will only evaluate to True if it returns the  
>> bool True.
>>
>> I think this is hacky and misleading, "is True" is not beautiful.  
>> I'd really return just 0, the user can check for this in his code,  
>> and it would be much more consistent. Returning True makes imho no  
>> sense when False can't be returned.
>
> False is returned when the function fails (none of the checking  
> methods can be applied for whatever reason).  I think we need to  
> return the result somehow, because it is actually quite often that  
> the result is 0 but simplify() cannot do it.  I am open to changing  
> the output, but I definitely think we need to maintain this behavior  
> somehow.  Maybe there be some kind of keyword argument that does  
> something.
>
> What's wrong about just returning the result? Be it 0, or something  
> that does not simplify to 0 or is not 0.
>
> I'm also fine with the tuple.
>
>
> Another possibility would be to return a tuple, either (True, 0) or  
> (False, <whatever isn't 0>), though as far as ugly goes, I think  
> that is more ugly than my current result. :)
>>
>>
>>>
>>>
>>>
>>> - 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
>>>
>> Sorry.  Don't worry, this is just a write up I made for this  
>> email.  It is not in the code anywhere. :)
>>
>> No problem, I just thought you might want to reuse it. It makes  
>> sense to add all the things you wrote to a commit message I think.
>>
>>
>> Thanks Vinzent.  I hope you can review this.
>>
>> I'll try to do it tonight, but I'm not an ODE expert, especially  
>> compared to Ondrej. :)
>
> That's OK.  You can tell at least if the code is clean, if there are  
> typos, and so on.  Do you know anything about ODEs at all?
>
> I know what it is, and that a solution should be a function  
> satisfying the equation. And I know what it's used for. So my  
> knowledge is only superficial.
>
>  The methods I have implemented are only ones you would learn in a  
> first semester ODE course anyway (that's all I have taken).
>
> I just don't know the methods (I did never try to solve an ODE,  
> except for direct integration of course).
>
> 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