On Sun, Apr 27, 2014 at 7:26 AM, Clifford Wolf <
cliffor...@gmail.com> wrote:
> On Friday, April 25, 2014 11:19:15 PM UTC+2, Aaron Meurer wrote:
>>
>> > I preserved the current behavior of the other classes with
>> > _diff_wrt=True,
>> > but I think the is room for improvement there as well. For example
>> > should
>> > the following code really return "x"?
>>
>> Yes it should. See the docstring of Derivative.
>
>
> That docstring documents that it is this way, but it does not give any
> reason why it _should_ be this way. For example, the docstring states that
>
>>>> (2*sqrt(1 - sin(x)**2)).diff(cos(x))
> 0
>
> but it does not really state why this would be a good idea. Its more like a
> warning, telling my to avoid such expressions. Now consider the following
> code for Function._eval_derivative_wrt:
Oh yes, we need to remove that. See
https://github.com/sympy/sympy/issues/7027.
>
> def _eval_derivative_wrt(self, expr, new_name):
> new_self = Dummy(new_name)
> new_expr = expr.subs(self, new_self)
> if new_expr.free_symbols.isdisjoint(self.free_symbols):
> return (new_expr, new_self)
> return None
>
> This will detect such cases and not attempt to evaluate a derivative wrt
> cos(x) if the expression contains something like sin(x):
>
>>>> from sympy import cos, sin, sqrt
>>>> from sympy.abc import x
>>>> (2*cos(x)).diff(cos(x))
> 2
>>>> (2*sqrt(1 - sin(x)**2)).diff(cos(x))
> Derivative(2*sqrt(-sin(x)**2 + 1), cos(x))
>
> Afics the legit use cases for differentiating wrt a function are those where
> you actually get the right result. And my understanding of the documentation
> is that atm it is my responsibility as user to avoid the other cases. I
> think we should shift as much of this responsibility as possible from the
> user to SymPy.
>
> PS: There may be cases where one would prefer a blind substitution, but I
> think that this should not be the default behavior of diff(), as it will
> return wrong results in some cases and therefore is not really a plain
> derivative anymore.
If you want, you can dig up the discussions about this. There were
quite a few, both on GitHub and the mailing list. We finally decided
that the only way to make sense of diff(expr, f(x)) is to think of
expr as a function of x and f(x), like F(x, f(x)), and that the only
way to think of *that* is to think of it as something like F(x,
y)|y=f(x). The primary motivation is Lagrangians, and in that context,
this is what is meant by that notation.
It's a little odd to think of this in "reverse", i.e., instead of
taking a function F(x, y) evaluating it at F(x, f(x)), you take an
expression in x and f(x) and think of it as a function in x and f(x),
but this all makes sense because there is a very precise way to define
this in SymPy, because each expression is a tree, and f(x) appears in
very precise places in that tree, and can be replaced with some other
symbol, and hence differentiated with respect to (with no thought to
other "trees" that are mathematically but not structurally
equivalent).
Aaron Meurer
>
https://groups.google.com/d/msgid/sympy/f15e5572-06b8-452d-9201-00a7f1a660b6%40googlegroups.com.