-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Subs in Derivatives give incorrect results #17032
Comments
I checked this behaviour occurred in a clean install of 1.2, 1.3 and 1.4 using the I then verified that a clean 1.1 install behaved as I expected it to. |
Not sure about the cause but you might find using replace instead of subs a useful workaround: In [9]: Fy = Function('Fy')(x)
In [10]: Derivative(y * sin(x), x).subs(y, Fy).doit()
Out[10]: Fy(x)⋅cos(x)
In [11]: Derivative(y * sin(x), x).replace(y, Fy).doit()
Out[11]:
d
Fy(x)⋅cos(x) + sin(x)⋅──(Fy(x))
dx |
# This might actually be the 'right' way of doing what this method needs to # in the SymPy world, if I understand the method documentations correctly. # The change isn't really a mathematical one, but a syntactic one; just # changing the SymPy representation to allow leverage of the built-in # simplification functionality. # # Related to sympy/sympy#17032
Thanks for this; The result of |
I think that the "proper" solution is that y should have been a function of x in the first place. Then subs and doit commute and all is mathematically correct: In [14]: f1, f2 = symbols('f1, f2', cls=Function)
In [15]: Derivative(f1(x)*sin(x), x).doit().subs(f1, f2)
Out[15]:
d
f₂(x)⋅cos(x) + sin(x)⋅──(f₂(x))
dx
In [16]: Derivative(f1(x)*sin(x), x).subs(f1, f2).doit()
Out[16]:
d
f₂(x)⋅cos(x) + sin(x)⋅──(f₂(x))
dx
In [17]: Derivative(f1(x)*sin(x), x).subs(f1, Lambda(x, x**2)).doit()
Out[17]:
2
x ⋅cos(x) + 2⋅x⋅sin(x) Having y as an implicit function of x is always going to be flaky: In [19]: Derivative(y, x).doit()
Out[19]: 0 |
I have an expression containing symbols and derivatives parsed from text input which amounts to something like
Derivative(y * sin(x), x)
, wherey
is supposed to be a function ofx
but is a plain Symbol object due to the limitations of parsing.In SymPy 1.1 and prior, it was possible to use the
.subs(...)
method to replace a Symbol with a Function and then get the expected result of performing the derivative:where
Fy
is used for clarity to meany(x)
.In SymPy 1.2 onwards, this is no longer possible, and it is not possible to correctly simplify this derivative:
The substitution happens after the
Derivative.doit()
call.There is no way from outside SymPy to ensure it does the substitution before the derivative when calling
.doit()
since that method does as much as it can, recursively. The result is then incorrect. In fact, when you call.doit()
on the outerSubs
it explicitly simplifies anything arguments first; unlike some classes you cannot passdeep=False
as a hint forSubs
to prevent this.A workaround exists by iterating through every
Derivative
object in the expression and performing the substitution onargs[0]
and rebuilding theDerivative
(but that won't work well for nested derivatives).If the outer
Subs
contains variables in any innerDerivative
, then should it not perform the substitution before simplifying the inner value? Or canSubs
support thedeep=False
hint that e.g.Derivative
supports in the.doit()
method?I couldn't quite track the regression down to a specific commit, because I don't quite understand all the behaviour under the hood; but it seems to be unaffected by, and unrelated to, the recent changes to how
Derivative
andSubs
work together.The text was updated successfully, but these errors were encountered: