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