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 -~----------~----~----~----~------~----~------~--~---