Status: Accepted Owner: asmeurer Labels: Type-Enhancement Priority-High NeedsReview
New issue 1611 by asmeurer: New ODEs module http://code.google.com/p/sympy/issues/detail?id=1611 I have finished up my Google Summer of Code 2009 project, which was to implement various ODE solvers in SymPy. Please pull from http://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 - 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. 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. -- You received this message because you are listed in the owner or CC fields of this issue, or because you starred this issue. You may adjust your issue notification preferences at: http://code.google.com/hosting/settings --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sympy-issues" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/sympy-issues?hl=en -~----------~----~----~----~------~----~------~--~---
