Skip to content
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 when wrt and count in Derivative are the same #16160

Closed
smichr opened this issue Mar 4, 2019 · 3 comments · Fixed by #16171
Closed

subs when wrt and count in Derivative are the same #16160

smichr opened this issue Mar 4, 2019 · 3 comments · Fixed by #16171
Labels
calculus core good first issue See the "Easy to Fix" label.

Comments

@smichr
Copy link
Member

smichr commented Mar 4, 2019

In a Derivative expressed as Derivative(f(x), (x, x)) the choice of x for wrt and count is allowed but the substitution of x with a value should proceed (I think) along the lines of treating the wrt variable as a bound symbol and the count as a free symbol, so (x**2).diff((x,x)) == Subs((y**2).diff((y, x)), y, x).

When you substitution x->2 you should get the 2nd derivative evaluated at 2. The _eval_subs method of Derivative should sort out the details. I think the following (rather than an error) should be obtained:

>> Derivative(f(x).diff((x,x)).subs(x,3)
Subs(Derivative(f(x),(x,3)),x,3)
diff --git a/sympy/core/function.py b/sympy/core/function.py
index b00718c..74fd41c 100644
--- a/sympy/core/function.py
+++ b/sympy/core/function.py
@@ -1606,6 +1606,11 @@ def _eval_subs(self, old, new):
         # Derivative(expr, vars) for a variety of reasons
         # as handled below.
         if old in self._wrt_variables:
+            # first handle the counts
+            expr = self.func(self.expr, *[(v, c.subs(old, new))
+                for v, c in self.variable_count])
+            if expr != self:
+                return expr._eval_subs(old, new)
             # quick exit case
             if not getattr(new, '_diff_wrt', False):
                 # case (0): new is not a valid variable of
diff --git a/sympy/core/tests/test_diff.py b/sympy/core/tests/test_diff.py
index aadb1f9..422ee4f 100644
--- a/sympy/core/tests/test_diff.py
+++ b/sympy/core/tests/test_diff.py
@@ -1,11 +1,25 @@
-from sympy import (Symbol, Rational, cos, sin, tan, cot, exp, log,
-    Function, Derivative, Expr, symbols, pi, I, S, diff, Piecewise,
-    Eq, ff, Sum, And, factorial, Max, NDimArray, re, im)
+from sympy.concrete.summations import Sum
+from sympy.core.expr import Expr
+from sympy.core.function import (Derivative, Function, diff, Subs)
+from sympy.core.numbers import (I, Rational, pi)
+from sympy.core.relational import Eq
+from sympy.core.singleton import S
+from sympy.core.symbol import Symbol
+from sympy.functions.combinatorial.factorials import (FallingFactorial,
+    factorial)
+from sympy.functions.elementary.complexes import (im, re)
+from sympy.functions.elementary.exponential import (exp, log)
+from sympy.functions.elementary.miscellaneous import Max
+from sympy.functions.elementary.piecewise import Piecewise
+from sympy.functions.elementary.trigonometric import (cos, cot, sin, tan)
+from sympy.logic.boolalg import And
+from sympy.tensor.array.ndim_array import NDimArray
 from sympy.utilities.pytest import raises
 
+from sympy.abc import a, b, c, x, y, z
+
 
 def test_diff():
-    x, y = symbols('x, y')
     assert Rational(1, 3).diff(x) is S.Zero
     assert I.diff(x) is S.Zero
     assert pi.diff(x) is S.Zero
@@ -20,9 +34,6 @@ def test_diff():
     assert (x**2).diff(x, y) == 0
     raises(ValueError, lambda: x.diff(1, x))
 
-    a = Symbol("a")
-    b = Symbol("b")
-    c = Symbol("c")
     p = Rational(5)
     e = a*b + b**p
     assert e.diff(a) == b
@@ -45,7 +56,6 @@ def test_diff2():
     n3 = Rational(3)
     n2 = Rational(2)
     n6 = Rational(6)
-    x, c = map(Symbol, 'xc')
 
     e = n3*(-n2 + x**n2)*cos(x) + x*(-n6 + x**n2)*sin(x)
     assert e == 3*(-2 + x**2)*cos(x) + x*(-6 + x**2)*sin(x)
@@ -60,7 +70,6 @@ def test_diff2():
 
 
 def test_diff3():
-    a, b, c = map(Symbol, 'abc')
     p = Rational(5)
     e = a*b + sin(b**p)
     assert e == a*b + sin(b**5)
@@ -85,7 +94,6 @@ class My(Expr):
         def __new__(cls, x):
             return Expr.__new__(cls, x)
 
-    x, y = symbols('x y')
     # My doesn't have its own _eval_derivative method
     assert My(x).diff(x).func is Derivative
     assert My(x).diff(x, 3).func is Derivative
@@ -98,23 +106,18 @@ def __new__(cls, x):
 
 def test_speed():
     # this should return in 0.0s. If it takes forever, it's wrong.
-    x = Symbol("x")
     assert x.diff(x, 10**8) == 0
 
 
 def test_deriv_noncommutative():
     A = Symbol("A", commutative=False)
     f = Function("f")
-    x = Symbol("x")
     assert A*f(x)*A == f(x)*A**2
     assert A*f(x).diff(x)*A == f(x).diff(x) * A**2
 
 
 def test_diff_nth_derivative():
     f =  Function("f")
-    x = Symbol("x")
-    y = Symbol("y")
-    z = Symbol("z")
     n = Symbol("n", integer=True)
 
     expr = diff(sin(x), (x, n))
@@ -152,3 +155,10 @@ def test_diff_nth_derivative():
 
     assert (cos(x)*sin(y)).diff([[x, y, z]]) == NDimArray([
         -sin(x)*sin(y), cos(x)*cos(y), 0])
+
+
+def test_issue_16160():
+    assert Derivative(x**3, (x, x)).subs(x, 2) == Subs(
+        Derivative(x**3, (x, 2)), x, 2)
+    assert Derivative(1 + x**3, (x, x)).subs(x, 0
+        ) == Derivative(1 + y**3, (y, 0)).subs(y, 0)
@RituRajSingh878
Copy link
Contributor

Derivative(f(x).diff((x,x)))
What about this ,i think it is meaningless.

@oscarbenjamin
Copy link
Contributor

It's confusing because in SymPy we have to use a variable name to indicate differentiation.

SymPy's f(x).diff(x,1) can normally be written as f'(x) with only a single x. Then I can write something like f'(1) and f''(2) and f'''(3). More generally I can write f^n(n) but the way to write that in SymPy would be f(n).diff(n, n).

@smichr
Copy link
Member Author

smichr commented Mar 5, 2019

What about this ,i think it is meaningless.

It means the same thing as Subs(Derivative(f(y), (y, x)), y, x) e.g. f(x).diff(x,x).subs(x,2) -> f(x).diff(x, 2).subs(x, 2). So if f(x) == x**3 then the answer is 12.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
calculus core good first issue See the "Easy to Fix" label.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants