Search code examples
pythonsympyintegralcalculusdifferentiation

Integrating functions of derivatives in Sympy


I'm tring to do some variational calculus in Python with sympy and I have runned to a problem, and I do not quite understand the origin. I am using the Anaconda suite, Jupyter Notebook and IPython version 5.3.0, with python 3.6.

If I writte

from sympy import Funtion, symbols, integrate
from IPython.display import display

t, s = symbols('t s')
f = Function('f')
c = Function('c')

compute the following expressions (they will be the elements of the part that fails)

display(f(t, s))
display(c(t, s))
display(f(c(t, s)))
display(f(c(t, s), c(t, s).diff(t)))
display(integrate( f(t, s), t))
display(integrate( f(c(t, s)), t))
display(integrate( f(c(t, s).diff(t)), t))
display(integrate( f(c(t, s),c(s,t) ), t))

the expected (latex) expressions appear. I see that it can handle derivation and integration of multiple variables, but when I try to put some things togheter, as in

display(integrate( f(c(t, s), c(t, s).diff(t)), t))

the following error is raised

Can't calculate 1st derivative wrt Derivative(_x1, t).

On the other hand,

display(integrate( f(c(t,s), c(t,s).diff(t)), s))

displays the correct output. Any ideas how one might fix this?

Thank you in advance

EDIT : .doit() hasn't helped.

The error is preceeded by

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-21-66abd1a98aff> in <module>()
   11 display(integrate( f(c(t,s).diff(t)), t))
 12 display(integrate( f(c(t,s), c(s,t)), t))
---> 13 display(integrate( f(c(t,s), c(t,s).diff(t)), t))

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\integrals.py in integrate(*args, **kwargs)
1278     if isinstance(integral, Integral):
1279         return integral.doit(deep=False, meijerg=meijerg, conds=conds,
-> 1280                              risch=risch, manual=manual)
1281     else:
1282         return integral

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\integrals.py in doit(self, **hints)
484                     function, xab[0],
485                     meijerg=meijerg1, risch=risch, manual=manual,
--> 486                     conds=conds)
487                 if antideriv is None and meijerg1 is True:
488                     ret = try_meijerg(function, xab)

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\integrals.py in _eval_integral(self, f, x, meijerg, risch, manual, conds)
885                 try:
886                     if conds == 'piecewise':
--> 887                         h = heurisch_wrapper(g, x, hints=[])
888                     else:
889                         h = heurisch(g, x, hints=[])

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\heurisch.py in heurisch_wrapper(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations)
128 
129     res = heurisch(f, x, rewrite, hints, mappings, retries, degree_offset,
--> 130                    unnecessary_permutations)
131     if not isinstance(res, Basic):
132         return res

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\heurisch.py in heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations)
672     else:
673         if retries >= 0:
--> 674             result = heurisch(f, x, mappings=mappings, rewrite=rewrite, hints=hints, retries=retries - 1, unnecessary_permutations=unnecessary_permutations)
675 
676             if result is not None:

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\heurisch.py in heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations)
672     else:
673         if retries >= 0:
--> 674             result = heurisch(f, x, mappings=mappings, rewrite=rewrite, hints=hints, retries=retries - 1, unnecessary_permutations=unnecessary_permutations)
675 
676             if result is not None:

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\heurisch.py in heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations)
672     else:
673         if retries >= 0:
--> 674             result = heurisch(f, x, mappings=mappings, rewrite=rewrite, hints=hints, retries=retries - 1, unnecessary_permutations=unnecessary_permutations)
675 
676             if result is not None:

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\heurisch.py in heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations)
451         mapping = list(mapping)
452         mapping = mapping + unnecessary_permutations
--> 453         diffs = [ _substitute(dcache.get_diff(g)) for g in terms ]
454         denoms = [ g.as_numer_denom()[1] for g in diffs ]
455         if all(h.is_polynomial(*V) for h in denoms) and _substitute(f).is_rational_function(*V):

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\heurisch.py in <listcomp>(.0)
451         mapping = list(mapping)
452         mapping = mapping + unnecessary_permutations
--> 453         diffs = [ _substitute(dcache.get_diff(g)) for g in terms ]
454         denoms = [ g.as_numer_denom()[1] for g in diffs ]
455         if all(h.is_polynomial(*V) for h in denoms) and _substitute(f).is_rational_function(*V):

....\Anaconda2\envs\Py3\lib\site-packages\sympy\integrals\heurisch.py in _substitute(expr)
446 
447     def _substitute(expr):
--> 448         return expr.subs(mapping)
449 
450     for mapping in mappings:

....\Anaconda2\envs\Py3\lib\site-packages\sympy\core\basic.py in subs(self, *args, **kwargs)
900             rv = self
901             for old, new in sequence:
--> 902                 rv = rv._subs(old, new, **kwargs)
903                 if not isinstance(rv, Basic):
904                     break

....\Anaconda2\envs\Py3\lib\site-packages\sympy\core\cache.py in wrapper(*args, **kwargs)
 91             def wrapper(*args, **kwargs):
 92                 try:
---> 93                     retval = cfunc(*args, **kwargs)
 94                 except TypeError:
 95                     retval = func(*args, **kwargs)

....\Anaconda2\envs\Py3\lib\site-packages\sympy\core\basic.py in _subs(self, old, new, **hints)
1014         rv = self._eval_subs(old, new)
1015         if rv is None:
-> 1016             rv = fallback(self, old, new)
1017         return rv
1018 

....\Anaconda2\envs\Py3\lib\site-packages\sympy\core\basic.py in fallback(self, old, new)
986                 if not hasattr(arg, '_eval_subs'):
987                     continue
--> 988                 arg = arg._subs(old, new, **hints)
989                 if not _aresame(arg, args[i]):
990                     hit = True

....\Anaconda2\envs\Py3\lib\site-packages\sympy\core\cache.py in wrapper(*args, **kwargs)
 91             def wrapper(*args, **kwargs):
 92                 try:
---> 93                     retval = cfunc(*args, **kwargs)
 94                 except TypeError:
 95                     retval = func(*args, **kwargs)

....\Anaconda2\envs\Py3\lib\site-packages\sympy\core\basic.py in _subs(self, old, new, **hints)
1012             return new
1013 
-> 1014         rv = self._eval_subs(old, new)
1015         if rv is None:
1016             rv = fallback(self, old, new)

....\Anaconda2\envs\Py3\lib\site-packages\sympy\core\function.py in _eval_subs(self, old, new)
1340                     variables = self_vars_front + self_vars
1341                     return Derivative(new, *variables)
-> 1342         return Derivative(*(x._subs(old, new) for x in self.args))
1343 
1344     def _eval_lseries(self, x, logx):

....\Anaconda2\envs\Py3\lib\site-packages\sympy\core\function.py in __new__(cls, expr, *variables, **assumptions)
1068                 ordinal = 'st' if last_digit == 1 else 'nd' if last_digit == 2 else 'rd' if last_digit == 3 else 'th'
1069                 raise ValueError(filldedent('''
-> 1070                 Can\'t calculate %s%s derivative wrt %s.''' % (count, ordinal, v)))
1071 
1072             if all_zero and not count == 0:

ValueError: 
Can't calculate 1st derivative wrt Derivative(_x1, t).


Solution

  • I would use Integral for displaying integrals, which only constructs them and does not attempt to compute them (unless your perform a doit()). The following works

    display(Integral( f(c(t, s), c(t, s).diff(t)), t))