-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
modified lie_group method #17527
modified lie_group method #17527
Conversation
✅ Hi, I am the SymPy bot (v148). I'm here to help you write a release notes entry. Please read the guide on how to write release notes. Your release notes are in good order. Here is what the release notes will look like:
This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.5. Note: This comment will be updated with the latest check if you edit the pull request. You need to reload the page to see it. Click here to see the pull request description that was parsed.
Update The release notes on the wiki have been updated. |
Codecov Report
@@ Coverage Diff @@
## master #17527 +/- ##
=============================================
+ Coverage 74.712% 74.752% +0.039%
=============================================
Files 633 633
Lines 164497 164745 +248
Branches 38622 38700 +78
=============================================
+ Hits 122900 123151 +251
+ Misses 36204 36189 -15
- Partials 5393 5405 +12 |
This looks good. Can you give an example of what it fixes (and maybe add that as a test)? |
sympy/solvers/ode.py
Outdated
@@ -5788,6 +5789,8 @@ def ode_lie_group(eq, func, order, match): | |||
sol = solve(eq, df) | |||
if sol == []: | |||
raise NotImplementedError | |||
elif len(sol)>1: | |||
return [ode_lie_group(Eq(df, i), func, order, match) for i in sol] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In lie_group method, We are solving an equation in which we need h(x, y)
see the last equation of lie_group method(https://docs.sympy.org/latest/modules/solvers/ode.html#lie-group).
And We are getting h(x, y)
by solving the solve(eq, df) and initially if at least one solution exists it means at least one h(x, y)
(h = sol[0].subs(func, y)
)exists and then we are trying to find the solution for only one of the h(x, y)
but if more than one solution is existing then we will get different values of h(x, y)
and so maybe for different values of h(x, y)
we can get different solution or maybe same. So I am just trying to solve for each of the different values of h(x,y)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think initially, the author wasn't checking for the different values of h(x, y) because of the condition of dsolve(We can't return a list of a solution). But now We can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If one call to ode_lie_group
returns a solution and another raises then this won't return anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, We can try to find the solution by using try
and except
sympy/solvers/ode.py
Outdated
@@ -5838,6 +5841,8 @@ def ode_lie_group(eq, func, order, match): | |||
scoord = newcoord[-1] | |||
try: | |||
sol = solve([r - rcoord, s - scoord], x, y, dict=True) | |||
if sol == []: | |||
raise NotImplementedError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some time solve is returning []
so I am just trying to check this condition and returning NotImplementedError
because we are accessing sol[0]
and if sol = []
then it will return IndexError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here We can solve the differential equation by lie_group
only if at least one solution exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think continue rather than raise NotImplementedError would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The impact will be the same but I think raising NotImplementedError
would be better because theoretically lie_group
can always solve any differential equation then in this method here at this position there should always be a solution for the equation and if solve is not able to give the solution it means method is not implemented in the solve
so we should return NotImplementedError
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know about solve. If solve return an empty list then what it means?
If it means no solution is exiting for the given equation then maybe lie_group
has some bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Lie group method works by trying out different heuristics. None of them is guaranteed to work for any particular ODE so the solver just tries them one after another. That's why we have a loop over the heuristics here. We need to make sure that if a particular heuristic doesn't work (which could be because solve returns an empty list or raises NotImplementedError) then the loop goes on to the next heuristic. Only when all of the heuristics has failed should we go on to raise NotImplementedError at the end.
The solve function will return an empty list if there are no solutions to the equation(s) or if the solution is infinite or possibly if there is an infinite number of solutions e.g.:
In [9]: solve(exp(x))
Out[9]: []
In [10]: solve([x-1, x-2], x)
Out[10]: []
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Lie group method works by trying out different heuristics. None of them is guaranteed to work for any particular ODE so the solver just tries them one after another. That's why we have a loop over the heuristics here. We need to make sure that if a particular heuristic doesn't work (which could be because solve returns an empty list or raises NotImplementedError) then the loop goes on to the next heuristic. Only when all of the heuristics has failed should we go on to raise NotImplementedError at the end.
By raising NotImplementedError
in try
it will go into except
and from there continue
will work and the loop will run and will try for the different heuristics. I was saying that If we will raise an error or do continue, it will have the same effect. I just wanted to know what will be the best idea to write.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the "best" thing would be to factor the body of the loop out into a separate function and use return None
rather than exceptions or continue.
if we will solve this equation by
But now we will get a list of solution
|
sympy/solvers/tests/test_ode.py
Outdated
def test_issue_17322(): | ||
eq = (f(x).diff(x)-f(x)) * (f(x).diff(x)+f(x)) | ||
sol = [Eq(f(x), C1*exp(-x)), Eq(f(x), C1*exp(x))] | ||
assert str(sol) == str(dsolve(eq, hint='lie_group')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you using str
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I want to make it set by mistake I have made it str.
sympy/solvers/ode.py
Outdated
tempsol = [] # Used by solve below | ||
for heuristic in heuristics: | ||
try: | ||
if not inf: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would take the body of this loop out into a separate _ode_lie_group_try_heuristic
function. (and probably move both functions out of ode_lie_group
to top level).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually what makes most sense is to take out the body of the infsim
loop below. There is far too much nesting here. The code below could be simplified if it was in a function and could use return
to exit.
It isn't necessary to change that though in this PR if you don't want to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to complete this pr as soon as possible because my previous prs depends on this pr so I will do this work in other pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay that's fine. The only thing that needs fixing in this PR is to restore the error message.
sympy/solvers/ode.py
Outdated
if isinstance(sol, list): | ||
desols.extend(sol) | ||
else: | ||
desols.append(sol) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you didn't unpack the list above this wouldn't be necessary
sympy/solvers/ode.py
Outdated
raise NotImplementedError("The given ODE " + str(eq) + " cannot be solved by" | ||
+ " the lie group method") | ||
if desols == []: | ||
raise NotImplementedError("Unable...") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will change this in later pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that message should be restored in this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, I mean commit
if isinstance(exprs, list): | ||
rv = [_handle_Integral(expr, func, hint) for expr in exprs] | ||
else: | ||
rv = _handle_Integral(exprs, func, hint) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We really need to clean it up so that solvefunc always returns a list. We shouldn't get into this situation where we don't know if we have a list or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to open a new pr for this because initially dsolve is made in a way that mostly it will return a single equation solution. So almost all of the method return an equation. So I have to change this for many of the methods. For this pr We can go in this way and later I will change it.
sympy/solvers/ode.py
Outdated
try: | ||
return _ode_lie_group_try_heuristic(Eq(df, s), heuristic, func, match, inf) | ||
except ValueError: | ||
continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not obvious to me where this ValueError is coming from. Can we move this inside _ode_lie_group_try_heuristic
and have that function return None
instead of leaking ValueError
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't remove ValueError because it is coming from infinitesimals
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we should catch it when calling infinitesimals
rather than here. It's much better if we can arrange it so that we have functions that return values (e.g. None) to indicate failure rather than raising and catching generic exceptions like ValueError.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
sympy/solvers/ode.py
Outdated
return _ode_lie_group_try_heuristic(Eq(df, s), heuristic, func, match, inf) | ||
except ValueError: | ||
continue | ||
return [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The convention for dsolve
is to raise NotImplementedError
when an ODE can't be solved:
In [8]: dsolve(f(x).diff(x, 2)-exp(f(x)))
---------------------------------------------------------------------------
NotImplementedError
We shouldn't return an empty list unless we know that there are no solutions. That might happen as a result of the initial conditions being inconsistent for example. I don't think we ever know from the Lie group methods that there are no solutions because there could always be more heuristics to try (I might be wrong about that though).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we ever know from the Lie group methods that there are no solutions because there could always be more heuristics to try (I might be wrong about that though).
Yes, we can't say ever that solution doesn't exist if we are not able to solve for the predefined heuristic
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I am returning an empty list (in _ode_lie_group function
) because I am trying to find solutions for every element in sol=solve(eq, df)
so we can't raise NotImplementedError
without checking for every term in sol
.
But in the end, when we are not getting any solutions then I am raising NotImplementedError
(in ode_lie_group
).
And I don't understand why you have given that example and the given example is not solvable by any method.
In [7]: classify_ode(f(x).diff(x, 2)-exp(f(x)))
Out[7]: ()
sympy/solvers/ode.py
Outdated
h = match['h'] | ||
tempsol = [] | ||
if not inf: | ||
inf = infinitesimals(eq, hint=heuristic, func=func, order=1, match=match) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ValueError
is coming from here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we will try to find infinitesimals
and maybe for the heuristic, infinitesimals
doesn't exists so it will raise ValueError.
Looks good. Thanks |
References to other Issues or PRs
Related to #17322 and #17338
Brief description of what is fixed or changed
lie_group has some bug with solution and some modification that I need for the pr #17338
Other comments
Release Notes