On Jun 25, 2009, at 5:51 AM, Fabian Pedregosa wrote:
> > Aaron S. Meurer wrote: >> So before I spend a lot of time implementing this, I figured it would >> be a good idea to get some feedback here on what I plan on doing. >> >> As most of you probably know, my Google Summer of Code project is to >> improve the ordinary differential equation solving capabilities of >> SymPy. So far, I have been able to implement quite a few methods >> (though none of them except for Bernoulli have actually made it in >> yet). Just for 1st order alone, dsolve, in my branch, can solve >> linear, Bernoulli, exact, first order equations with homogeneous >> coefficients, and I am finishing separable equations. Each of these >> is rather simple for the most part. dsolve matches the equation to a >> pattern, and as soon as it finds a pattern that it fits, for example >> a(x)*b(f(x)) + c(x)*d(f(x))*f'(x) for separable, then it applies the >> appropriate solution, which usually just involves rearranging the >> matched terms in an integral. >> >> The thing is that, sometimes, an ODE can fit more than one kind of >> pattern, expecially for first order ODE's. Here is an example: >> >> 2xy + (x**2 + y**2)*dy/dx is exact, because ∂(2xy)/∂y == >> ∂(x**2 + >> y**2)/∂x == 2x (those are partials, in case they don't render). >> Also, the substitutions u == y/x and v == x/y make the equation >> separable, because the terms are homogeneous of the same order (see >> my >> blog: >> http://asmeurersympy.wordpress.com/2009/05/31/first-order-differential-equations-with-homogeneous-coefficients/) >> . These three methods produce the same result written in three >> different ways (the solution is not solvable in y, so SymPy would >> return all three ways as they are). The three ways are: >> exact: x**2*y + y**3/3 == C1 >> substitution u == y/x: x == C2(y**3/x**3+3y/x)**(-1/3) >> substitution u == x/y: y == C3(3x**3/y**3+1)**(-1/3) >> >> These three solutions are all equivalent, though the arbitrary >> constants in each one are not necessarily equal to one another (see >> my >> blog post for a proof of their equivalence). Because the arbitrary >> constants are not equal, SymPy would be unable to recognize their >> equivalence (though I hope to fix this with issue 1336). >> >> So as you can see, many differential equations can be solved in more >> than one way. Currently, dsolve just spits out the solution for the >> first method that it matches the ODE to. I would like to have it so >> that the user can choose to return a different (equivalent) solution >> if he wants to. >> >> So here is what I propose. Please let me know if you think this is a >> good idea and how it could be improved upon: >> >> First, create the function classify_ode. The function will apply >> match patterns to an ode and return a list of strings of possible >> patterns, like ("exact", "1st_homogeneous_coeff", >> "1st_homogeneous_coeff_alt") for the above. The list would be >> ordered >> such that dsolve would use the first hint by default. I would >> determine the default ordering based on testing of many odes to see >> which methods generally return cleaner solutions than others. Also, >> dsolve will call the function as classify_ode(ode, match=True) (what >> is a better word than match?), and it will return a dict with the key >> type set to the first string that would be returned in the list, and >> the other keys are the match keys that dsolve needs to solve the ode >> (that way it doesn't have to match it twice). > > That's nice. It is similar to function guess_solve_strategy in > sympy.solvers (consider naming these two functions is a similar > fashion) > >> >> For hints like "1st_homogeneous_coeff" which always have two possible >> solutions, there will be two hints, one with '_alt' at the end. The >> '_alt' one is chosen so that the one without '_alt' is the better one >> based on a metric (see below). Another option would be to use >> "1st_homogeneous_coeff_f(x)/x" and "1st_homogeneous_coeff_x/f(x)", >> which is more explicit, but doesn't allow classify_ode to place the >> better one first without evaluating integrals (which I don't want to >> do, because the integrals for those problems tend to be hard and >> takes >> SymPy some time). I could also just use all 4. The only >> disadvantage >> with that is that it would be redundant, though I don't think it >> would >> be ambiguously so. >> >> Also, what is the best hint name for "1st_homogeneous_coeff_f(x)/x"? > > Maybe passing a hints dict: {'type': 'homegeneous', 'lst': True, > 'coeff': f, 'args': x} or a tuple ... This seems way more complex than I want. I think if I document that f(x) refers to function and x refers to the independent variable in the docstring of classify_ode that it shouldn't be too ambiguous. > >> The function and independent variable might not necessarily be f and >> x, but I want the hint name to be same regardless of the function. >> Is >> it clear enough that that means "function divided by independent >> variable", regardless of whether those happen to be f and x or not? >> Of course, it would all be in the docstring. >> >> Second, add the following to dsolve: add default argument >> hint="default" (so dsolve(ode, function, hint="default"). If hint is >> set to a different hint from classify_ode, then it will return the >> solution based on that method (of course, if hint is something that >> isn't a supported type or doesn't match the ode, it will raise an >> exception). Also, hint="all" would return a dict of method:solution >> items, and hint="best" would try all fitted methods and return the >> one >> that is the simplest based on a metric (contains no Integral class >> (i.e., unsolvable integrals), solvable in the function, and shortest >> expression, in that order. Any other good ideas for this?). >> >> So what do you think? Is this a good strategy? Are there any good >> features that I could add? Sorry for the kind of long post. >> > > Seems to me a good strategy. Any ideas how do other CAS implement this > classification/solving strategy? Maple has a very expansive ode classification system. If you do with(DEtools); you get among other things a function odeanalyser, which is about the same as my proposed classify_ode. You can add the classifications as arguments to dsolve to have it solve in that way. See also http://www.maplesoft.com/support/help/view.aspx?path=DEtools/odeadvisor and some of the stuff in the side bar under Differential Equations. I have no idea what Mathematica does, as I do not own it. > >> Aaron Meurer >>> >> > > > -- > http://fseoane.net/blog/ > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sympy" 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?hl=en -~----------~----~----~----~------~----~------~--~---
