Sage: Ticket #17445: Missing documentation of derivative operator/notation
https://trac.sagemath.org/ticket/17445
<p>
Taking the derivative of a symbolic function returns the D-notation:
sage: var('x y z')
sage: f(x) = function('f',x,y,z);
sage: f(x).diff(x,y)
D[0, 1](f)(x, y, z)
</p>
<p>
Unfortunately, the meaning of this notation is not documented anywhere, neither in diff(), nor in derivative() nor in function(). There is a ton of tickets about improving ambiguities and malfunctions related to this notation, but it would be very helpful to at least document how it is supposed to work and what it means if a user sees output as above.
</p>
<p>
See here for related tickets:
</p>
<ul><li><a class="closed ticket" href="https://trac.sagemath.org/ticket/6344" title="enhancement: Typesetting partial derivatives in new symbolics (closed: wontfix)">#6344</a> - allow typesetting in "diff" format (possibly only as non-default option)
</li><li><a class="needs_work ticket" href="https://trac.sagemath.org/ticket/6756" title="enhancement: Implement ``diff`` format symbolic derivative in new symbolics (needs_work)">#6756</a> - add <em>input</em> to Sage in "diff" format for derivatives (the most controversial)
</li><li><a class="new ticket" href="https://trac.sagemath.org/ticket/6480" title="defect: Failure with diff(f(x),x).subs(f(x) == g(x)) (new)">#6480</a> - clarify or fix substituting functions inside of symbolic derivatives
</li><li><a class="closed ticket" href="https://trac.sagemath.org/ticket/7401" title="task: Derivative at a point is not translated into Maxima (closed: fixed)">#7401</a> - bug in our interaction with Maxima with evaluating derivative at a point (needs work due to multivariate derivatives not being there)
</li><li><a class="closed ticket" href="https://trac.sagemath.org/ticket/12796" title="enhancement: Allow more general evaluation of FDerivativeOperator (closed: fixed)">#12796</a> - allow evaluation at points
</li></ul><p>
and this discussion:
<a class="ext-link" href="https://groups.google.com/forum/#!topic/sage-devel/_xD5lymnTuo"><span class="icon"></span>https://groups.google.com/forum/#!topic/sage-devel/_xD5lymnTuo</a>
</p>
en-usSagehttps://trac.sagemath.org/chrome/site/logo_sagemath_trac.png
https://trac.sagemath.org/ticket/17445
Trac 1.1.6nbruinThu, 04 Dec 2014 23:31:48 GMT
https://trac.sagemath.org/ticket/17445#comment:1
https://trac.sagemath.org/ticket/17445#comment:1
<p>
OK, I do not know where it should go in the documentation for best visibility (I'd think in "diff" somewhere), but the explanation should be along the lines of:
</p>
<p>
Partial derivatives are represented in sage using differential operators, referencing the position of the variable with respect to which the partial derivative is taken. This means that for a function f in $r+1$ variables we have
</p>
<p>
\[D[i_1,\ldots,i_n](f)(x_0,\ldots,x_r) = \left.\frac{\partial f(t_0,\ldots,t_r)}{\partial t_{i_1}\cdots \partial t_{i_n}} \right|_{t_0=x_0,\ldots,t_r=x_r}\]
</p>
<p>
An advantage of this notation is that it is clear which derivative is taken, regardless of the names of the variables. For instance, if we have
</p>
<pre class="wiki">sage: var("x,y,t")
sage: f(x,y)=function('f',x,y)
sage: g=f(x,y).diff(x,y); g
D[0, 1](f)(x, y)
sage: g.subs(x=1,y=1)
D[0, 1](f)(1, 1)
sage: g.subs(x=t,y=t+1)
D[0, 1](f)(t, t+1)
</pre><p>
Note that in the last two lines are completely unambiguous using operator notation, whereas Leibnitz notation would require the use of some arbitrary explicit choice of auxiliary variable names.
</p>
TicketkcrismanFri, 05 Dec 2014 02:24:02 GMTdescription changed
https://trac.sagemath.org/ticket/17445#comment:2
https://trac.sagemath.org/ticket/17445#comment:2
<ul>
<li><strong>description</strong>
modified (<a href="/ticket/17445?action=diff&version=2">diff</a>)
</li>
</ul>
<p>
Are there times where this notation is ambiguous, though? I seem to recall that being the case.
</p>
<p>
Also, I think something about this should show up at the top of the "sage/calculus/calculus.py" file as well. It's a constant source of questions I don't really know the answer to.
</p>
TicketnbruinFri, 05 Dec 2014 03:13:18 GMT
https://trac.sagemath.org/ticket/17445#comment:3
https://trac.sagemath.org/ticket/17445#comment:3
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:2" title="Comment 2">kcrisman</a>:
</p>
<blockquote class="citation">
<p>
Are there times where this notation is ambiguous, though? I seem to recall that being the case.
</p>
</blockquote>
<p>
I am not aware of any such cases. It's reflecting all information that sage has stored on the object, so an ambiguity would imply that sage is working with an ill-defined object.
</p>
<p>
If you rewrite it in Leibnitz notation using a set of auxiliary variables, you see that any expression has a clear interpretation.
</p>
<p>
Go ahead and put it in the docs!
</p>
TicketkcrismanFri, 05 Dec 2014 03:49:06 GMTdescription changed
https://trac.sagemath.org/ticket/17445#comment:4
https://trac.sagemath.org/ticket/17445#comment:4
<ul>
<li><strong>description</strong>
modified (<a href="/ticket/17445?action=diff&version=4">diff</a>)
</li>
</ul>
<p>
Can you comment on some of the chain-rule type issues in <a class="new ticket" href="https://trac.sagemath.org/ticket/6480" title="defect: Failure with diff(f(x),x).subs(f(x) == g(x)) (new)">#6480</a>, then? I have to say that in particular the stuff at <a class="ext-link" href="http://ask.sagemath.org/question/9932/how-to-substitute-a-function-within-derivatives/"><span class="icon"></span>http://ask.sagemath.org/question/9932/how-to-substitute-a-function-within-derivatives/</a> and <a class="new ticket" href="https://trac.sagemath.org/ticket/6480" title="defect: Failure with diff(f(x),x).subs(f(x) == g(x)) (new)">#6480</a> is massively confusing. Heck, let's add <a class="closed ticket" href="https://trac.sagemath.org/ticket/7401" title="task: Derivative at a point is not translated into Maxima (closed: fixed)">#7401</a> while we're at it.
</p>
<p>
I don't even know whether <em>any</em> of those things are "really" right or wrong at this point. I suppose you shouldn't be allowed to substitute in a function that "isn't there" in 6 and 7, but then why does 8 "work"? In any case, shouldn't there be an error raised if one attempts something like this when it's not "legitimate"?
</p>
<pre class="wiki"># 6. Fails.
x = var('x')
f = function('f', x)
g = function('g', x)
p = f.diff()
print p.substitute_function(f, g) # Outputs "D[0](f)(x)"
# 7. Fails.
x = var('x')
f = function('f', x)
g = function('g', x)
p = f.diff()
print p.substitute_function(f(x), g(x)) # Outputs "D[0](f)(x)"
# 8. Works.
x = var('x')
f = function('f')
g = function('g')
p = f(x).diff()
print p.substitute_function(f, g) # Outputs "D[0](g)(x)"
</pre><p>
These are <em>very</em> subtle differences to anyone who is not in symbolic algebra/expressions, and part of the issue is the difference between expressions and functions, no doubt. So <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:1" title="Comment 1">comment:1</a> is a good start, but definitely only a start.
</p>
TicketkcrismanFri, 05 Dec 2014 04:18:11 GMTdescription changed
https://trac.sagemath.org/ticket/17445#comment:5
https://trac.sagemath.org/ticket/17445#comment:5
<ul>
<li><strong>description</strong>
modified (<a href="/ticket/17445?action=diff&version=5">diff</a>)
</li>
</ul>
<p>
Okay, at least now I actually understand what the different tickets are about. Phew.
</p>
TicketnbruinFri, 05 Dec 2014 05:17:43 GMT
https://trac.sagemath.org/ticket/17445#comment:6
https://trac.sagemath.org/ticket/17445#comment:6
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:4" title="Comment 4">kcrisman</a>:
</p>
<blockquote class="citation">
<p>
I don't even know whether <em>any</em> of those things are "really" right or wrong at this point.
</p>
</blockquote>
<p>
There is an internal logic that explains the behaviour. I don't think this stuff can ever be made "intuitive" to the average calculus afficionado because the tradition in analysis notation is just to irredeemably confuse "function" and "function evaluated at...". Humans can handle this confusion to some extent, but I think it's just too incompatible with how computers represent math.
</p>
<blockquote class="citation">
<pre class="wiki"># 6. Fails.
x = var('x')
f = function('f', x)
g = function('g', x)
p = f.diff()
print p.substitute_function(f, g) # Outputs "D[0](f)(x)"
</pre></blockquote>
<p>
the problem: f is not a function, but a function evaluated at <code>x</code>, whatever <code>x</code> is. I'm not going to defend that <code>function('f', x)</code> doesn't return a function. <strong>THAT is the real source why this example seems confusing</strong>.
</p>
<pre class="wiki">sage: f
f(x)
</pre><p>
The fact that <code>f.diff()</code> doesn't fail is apparently a heuristic, because there's only one variable discernible in the expression. But then you see:
</p>
<pre class="wiki">sage: p
D[0](f)(x)
</pre><p>
as you can see, there's no <code>f(x)</code> appearing in that expression, so of course substituting <code>f(x)</code> for something else has no effect. Really,
</p>
<pre class="wiki">p.substitute_function(f, g)
</pre><p>
should give a <code>TypeError</code>, because the types of the arguments don't match. Indeed:
</p>
<pre class="wiki">sage: p.substitute_function(f.operator(), g)
DeprecationWarning: Substitution using function-call syntax ...
</pre><p>
Apparently sage does try to convert the argument <code>g(x)</code> (that is bound to <code>g</code>) to a function.
</p>
<blockquote class="citation">
<pre class="wiki"># 7. Fails.
x = var('x')
f = function('f', x)
g = function('g', x)
p = f.diff()
print p.substitute_function(f(x), g(x)) # Outputs "D[0](f)(x)"
</pre></blockquote>
<p>
same problem, but even worse: <code>f(x)(x)</code> should have been deprecated already.
</p>
<blockquote class="citation">
<pre class="wiki"># 8. Works.
x = var('x')
f = function('f')
g = function('g')
p = f(x).diff()
print p.substitute_function(f, g) # Outputs "D[0](g)(x)"
</pre></blockquote>
<p>
The fact that <code>function('f')</code> and <code>function('f',x)</code> return different types of arguments is <strong>really</strong> bad. It prevents any convincing explanation of the distinction that is essential here, because the interface <em>itself</em> confuses the two different issues. On top of that, we have a lot of documentation that was written by people who were equally confused, so the calculus doc makes a good effort to confuse any new user too.
</p>
<blockquote class="citation">
<p>
These are <em>very</em> subtle differences to anyone who is not in symbolic algebra/expressions, and part of the issue is the difference between expressions and functions, no doubt. So <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:1" title="Comment 1">comment:1</a> is a good start, but definitely only a start.
</p>
</blockquote>
<p>
It's an entirely different issue, though. Apparently the documentation never <em>explains</em> what <code>D[0](f)(x)</code> means. We can do that independent of whether we go out of our way to confuse users about the distinction between functions and functions evaluated at ...
</p>
TicketeviatarbachFri, 05 Dec 2014 05:42:33 GMTcc changed
https://trac.sagemath.org/ticket/17445#comment:7
https://trac.sagemath.org/ticket/17445#comment:7
<ul>
<li><strong>cc</strong>
<em>eviatarbach</em> added
</li>
</ul>
<p>
It would probably be good to add a note that <code>D[0, 1](f)(x, y)</code> does not in general equal <code>D[1, 0](f)(x, y)</code> (<a class="ext-link" href="https://en.wikipedia.org/wiki/Symmetry_of_second_derivatives"><span class="icon"></span>https://en.wikipedia.org/wiki/Symmetry_of_second_derivatives</a>).
</p>
TicketschymansFri, 05 Dec 2014 09:18:43 GMT
https://trac.sagemath.org/ticket/17445#comment:8
https://trac.sagemath.org/ticket/17445#comment:8
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:6" title="Comment 6">nbruin</a>:
</p>
<blockquote class="citation">
<p>
The fact that <code>function('f')</code> and <code>function('f',x)</code> return different types of arguments is <strong>really</strong> bad. It prevents any convincing explanation of the distinction that is essential here, because the interface <em>itself</em> confuses the two different issues. On top of that, we have a lot of documentation that was written by people who were equally confused, so the calculus doc makes a good effort to confuse any new user too.
</p>
</blockquote>
<p>
Wow, the reason while I hesitated about adding documentation of the D-notation was that I thought it should go into the documentation of function() and then I found out that the documentation of function() itself is already incomplete and confusing. Should we open a ticket for that, too?
For example, none of the methods described in <a href="http://www.sagemath.org/doc/reference/calculus/sage/symbolic/function_factory.html">http://www.sagemath.org/doc/reference/calculus/sage/symbolic/function_factory.html</a> show up when I type:
</p>
<pre class="wiki">function?
</pre><p>
The distinction between
</p>
<pre class="wiki">f = function('f')
</pre><p>
and
</p>
<pre class="wiki">f = function('f', x)
</pre><p>
is also not documented.
Only now I realised that function('f') returns a function, while function('f',x) returns an expression. Furthermore, differentiation of a function is not supported, it needs to be converted to an expression first:
</p>
<pre class="wiki">f = function('f')
fx = function('f', x)
print type(f)
print type(fx)
print type(f(x))
print fx.diff()
print f(x).diff()
print f.diff()
///
<class 'sage.symbolic.function_factory.NewSymbolicFunction'>
<type 'sage.symbolic.expression.Expression'>
<type 'sage.symbolic.expression.Expression'>
D[0](f)(x)
D[0](f)(x)
Traceback (most recent call last): print f(x).diff()
File "", line 1, in <module>
File "/tmp/tmpMe44Jp/___code___.py", line 9, in <module>
exec compile(u'print f.diff()' + '\n', '', 'single')
File "", line 1, in <module>
AttributeError: 'NewSymbolicFunction' object has no attribute 'diff'
</pre><blockquote class="citation">
<p>
It's an entirely different issue, though. Apparently the documentation never <em>explains</em> what <code>D[0](f)(x)</code> means. We can do that independent of whether we go out of our way to confuse users about the distinction between functions and functions evaluated at ...
</p>
</blockquote>
<p>
If we modify the documentation of diff(), though, we should explain why f(x).diff() works but f.diff() does not.
</p>
TicketschymansFri, 05 Dec 2014 09:39:36 GMT
https://trac.sagemath.org/ticket/17445#comment:9
https://trac.sagemath.org/ticket/17445#comment:9
<p>
Following on from the logic about function('f', x) being an expression, not a function, why does this fail, then?
</p>
<pre class="wiki"># If all of f, g and p are expressions, why does this fail?
x = var('x')
f = function('f', x)
print type(f)
g = function('g', x)
print type(g)
p = f.diff()
print type(p)
print p.subs_expr(f==g) # Outputs "D[0](f)(x)"
</pre>
TicketschymansFri, 05 Dec 2014 09:55:08 GMT
https://trac.sagemath.org/ticket/17445#comment:10
https://trac.sagemath.org/ticket/17445#comment:10
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:7" title="Comment 7">eviatarbach</a>:
</p>
<blockquote class="citation">
<p>
It would probably be good to add a note that <code>D[0, 1](f)(x, y)</code> does not in general equal <code>D[1, 0](f)(x, y)</code> (<a class="ext-link" href="https://en.wikipedia.org/wiki/Symmetry_of_second_derivatives"><span class="icon"></span>https://en.wikipedia.org/wiki/Symmetry_of_second_derivatives</a>).
</p>
</blockquote>
<p>
I just wanted to propose the following simple documentation:
</p>
<p>
Partial derivatives are represented in sage using differential operators, referencing the positions of the variables with respect to which consecutive partial derivatives are taken.
</p>
<p>
An advantage of this notation is that it is clear in which order derivatives are taken and on which variables they are performed, regardless of the names of the variables. For instance, if we have
</p>
<pre class="wiki">sage: var("x,y,t")
(x, y, t)
sage: f=function('f',x,y)
sage: g=f.diff(x,y); g
D[0, 1](f)(x, y)
sage: h=f.diff(y,x); g
D[0, 1](f)(x, y)
</pre><p>
I was expecting the second to give either <code>D[0, 1](f)(y, x)</code> or <code>D[1, 0](f)(x, y)</code>. What is going on, is the order of differentiations not honoured in the notation?
</p>
<p>
Interestingly, the following does not return <code>True</code> but two visually indistinguishable expressions. To me, this looks like a bug.
</p>
<pre class="wiki">sage: f.diff(x,y) == f.diff(y,x)
D[0, 1](f)(x, y) == D[0, 1](f)(x, y)
</pre><p>
I would much prefer this behaviour:
</p>
<pre class="wiki">sage: f.diff(x,y) == f.diff(y,x)
f.diff(x,y) == f.diff(y,x)
</pre><p>
It would be unambiguous and shorter. What is the advantage of the D-notation again?
</p>
TicketschymansFri, 05 Dec 2014 10:48:05 GMT
https://trac.sagemath.org/ticket/17445#comment:11
https://trac.sagemath.org/ticket/17445#comment:11
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:6" title="Comment 6">nbruin</a>:
</p>
<blockquote class="citation">
<p>
the problem: f is not a function, but a function evaluated at <code>x</code>, whatever <code>x</code> is. I'm not going to defend that <code>function('f', x)</code> doesn't return a function. <strong>THAT is the real source why this example seems confusing</strong>.
</p>
</blockquote>
<p>
I created a ticket to improve the documentation of function(): <a class="ext-link" href="http://trac.sagemath.org/ticket/17447"><span class="icon"></span>http://trac.sagemath.org/ticket/17447</a>
I put you and kcrisman cc on that ticket, I hope you don't mind.
</p>
TicketkcrismanFri, 05 Dec 2014 14:20:14 GMT
https://trac.sagemath.org/ticket/17445#comment:12
https://trac.sagemath.org/ticket/17445#comment:12
<blockquote class="citation">
<p>
I was expecting the second to give either <code>D[0, 1](f)(y, x)</code> or <code>D[1, 0](f)(x, y)</code>. What is going on, is the order of differentiations not honoured in the notation?
</p>
</blockquote>
<p>
In this case, it is not an example of Eviatar's (good) point. <code>f</code> always has the variables in the same order, so your first option is not possible. The second option would be legitimate but I guess Sage just assumes the <a class="ext-link" href="http://en.wikipedia.org/wiki/Symmetry_of_second_derivatives#Schwarz.27_theorem"><span class="icon"></span>Clairaut/Schwarz Theorem</a> always holds for 'symbolic' functions.
</p>
<blockquote class="citation">
<p>
Interestingly, the following does not return <code>True</code> but two visually indistinguishable expressions. To me, this looks like a bug.
</p>
<pre class="wiki">sage: f.diff(x,y) == f.diff(y,x)
D[0, 1](f)(x, y) == D[0, 1](f)(x, y)
</pre></blockquote>
<p>
See above.
</p>
<blockquote class="citation">
<p>
It would be unambiguous and shorter. What is the advantage of the D-notation again?
</p>
</blockquote>
<p>
I'm still not 100% sold on it, especially since it doesn't LaTeX with subscripts, but this would be a second issue.
</p>
<hr />
<p>
Questions:
</p>
<ul><li>Is it worth trying to distinguish <code>D[0,1]</code> and <code>D[1,0]</code>?
</li><li>Would it be very hard to do so? (I have not looked at this code in a long time.)
</li><li>Is it easy to have the LaTeX be subscripts?
</li><li>Alternately (or with that), would it be possible to just "read off" the actual variable names and put those in, ala <code>D[x,y]</code> and <code>D[y,x]</code>? In principle it should be, since all such functions now have <em>ordered</em> variable names. I don't know how that would combine with the whole <code>D[0,1](f)(x,x+1)</code> thing, so maybe it's a bad idea.
</li></ul>
TicketnbruinFri, 05 Dec 2014 17:02:59 GMT
https://trac.sagemath.org/ticket/17445#comment:13
https://trac.sagemath.org/ticket/17445#comment:13
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:10" title="Comment 10">schymans</a>:
</p>
<blockquote class="citation">
<p>
I would much prefer this behaviour:
</p>
<pre class="wiki">sage: f.diff(x,y) == f.diff(y,x)
f.diff(x,y) == f.diff(y,x)
</pre><p>
It would be unambiguous and shorter. What is the advantage of the D-notation again?
</p>
</blockquote>
<p>
Please write <code>f(x,y)</code> there so that it's clear you're differentiating an expression, not a function:
</p>
<pre class="wiki">sage: var('x,y')
(x, y)
sage: f=function('f')
sage: f.diff(x,y)
AttributeError: 'NewSymbolicFunction' object has no attribute 'diff'
</pre><p>
The advantage is that you can actually represent evaluations of the derivative:
</p>
<pre class="wiki">sage: f(x,y).diff(x,y).subs(x=2,y=3)
D[0, 1](f)(2, 3)
</pre><p>
Would you propose to print that as the (admittedly shorter) <code>f.diff(2,3)</code>? It's absolutely possible to print <code>f(x,y).diff(x,y)</code> for <code>D[0,1](f)(x,y)</code> because at some point we can see we have an expression with an operator that is an <code>FDerivativeOperator</code>, and where the arguments form a list of distinct symbolic variables. But we have to print <code>D[0,1](f)(t,t^2)</code>. Printing <code>f.diff(t,t^2)</code> is just something else entirely.
</p>
TicketnbruinFri, 05 Dec 2014 17:08:50 GMT
https://trac.sagemath.org/ticket/17445#comment:14
https://trac.sagemath.org/ticket/17445#comment:14
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:9" title="Comment 9">schymans</a>:
</p>
<blockquote class="citation">
<pre class="wiki">print p.subs_expr(f==g) # Outputs "D[0](f)(x)"
</pre></blockquote>
<p>
Because you need <code>subs_function</code> there. These are two different routines that take different types of arguments and do different things with them. Objects of type <code>SymbolicFunction</code> cannot be used interchangeably with <code>SymbolicExpression</code>.
</p>
<p>
We could in principle extend <code>subs</code> to differentiate on type of passed argument and dispatch accordingly to <code>subs_function</code> or <code>subs_expression</code> (and raise an error if some impossible combination is tried).
</p>
TicketnbruinFri, 05 Dec 2014 17:23:30 GMT
https://trac.sagemath.org/ticket/17445#comment:15
https://trac.sagemath.org/ticket/17445#comment:15
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:10" title="Comment 10">schymans</a>:
</p>
<blockquote class="citation">
<p>
I was expecting the second to give either <code>D[0, 1](f)(y, x)</code> or <code>D[1, 0](f)(x, y)</code>. What is going on, is the order of differentiations not honoured in the notation?
</p>
</blockquote>
<p>
Correct. Rewriting of differentials apparently assumes symmetry. That's not such a big issue, since in any reasonable application environment it holds anyway (if your functions aren't continuously differentiable you tend to have to use other things, such as distributions, anyway.
</p>
<p>
Illustration:
</p>
<pre class="wiki">sage: D=sage.symbolic.operators.FDerivativeOperator
sage: D(f,[1,0])
D[1, 0](f)
sage: D(f,[0,1])
D[0, 1](f)
sage: D(f,[0,1])(x,y)
D[0, 1](f)(x, y)
sage: D(f,[1,0])(x,y)
D[0, 1](f)(x, y)
</pre><p>
As you can see, the reordering happens on evaluation. It's not an ambiguity in notation, it's an assumption that's been programmed into sage. Perhaps it's already in Pynac?
</p>
TicketnbruinFri, 05 Dec 2014 17:33:07 GMT
https://trac.sagemath.org/ticket/17445#comment:16
https://trac.sagemath.org/ticket/17445#comment:16
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:12" title="Comment 12">kcrisman</a>:
</p>
<blockquote class="citation">
<p>
Questions:
</p>
<ul><li>Is it worth trying to distinguish <code>D[0,1]</code> and <code>D[1,0]</code>?
</li></ul></blockquote>
<p>
I think not, but it's not my field. When do you really work with non-continuously differentiable functions? Don't you use distributions then anyway? I think someone should point out a meaningful calculation where symmetry doesn't hold.
</p>
<blockquote class="citation">
<ul><li>Would it be very hard to do so? (I have not looked at this code in a long time.)
</li></ul></blockquote>
<p>
No. It's in the <code>diff</code> code somewhere. It's probably an explicit "sort" command you can just take out.
</p>
<blockquote class="citation">
<ul><li>Alternately (or with that), would it be possible to just "read off" the actual variable names and put those in, ala <code>D[x,y]</code> and <code>D[y,x]</code>? In principle it should be, since all such functions now have <em>ordered</em> variable names.
</li></ul></blockquote>
<p>
Where would you get the names from in the following example?
</p>
<pre class="wiki">sage: D=sage.symbolic.operators.FDerivativeOperator
sage: D(f,[0,1,0])
D[0, 1, 0](f)
sage: D(f,[0,1,0])(x,y)
D[0, 0, 1](f)(x, y)
</pre><p>
If you're going to bother matching indices and variable names, you'd better go the whole way and recognize that in the last example the arguments are distinct symbolic variables that match up nicely with the differentiation indices, so we can print
</p>
<pre class="wiki">diff(f(x,y),x,x,y)
</pre><p>
I don't know how that would combine with the whole <code>D[0,1](f)(x,x+1)</code> thing, so maybe it's a bad idea.
</p>
TicketeviatarbachFri, 05 Dec 2014 19:35:35 GMT
https://trac.sagemath.org/ticket/17445#comment:17
https://trac.sagemath.org/ticket/17445#comment:17
<p>
I think it is worth distinguishing. The standard counterexample to equality of mixed partials is <code>f(x, y) = x*y*(x^2 - y^2)/(x^2 + y^2)</code>, with <code>f(0, 0) = 0</code>, which is a continuous function but the second derivatives at (0, 0) are unequal. This may not come about often in practice (it doesn't seem like we can run this example without having multivariable piecewise functions), but especially if people are using the formal functions it should have correct mathematical properties.
</p>
TicketschymansTue, 06 Jan 2015 22:59:52 GMT
https://trac.sagemath.org/ticket/17445#comment:18
https://trac.sagemath.org/ticket/17445#comment:18
<p>
Wow, I think the description of this ticket should be changed. It is not any more about the documentation of the D[] notation, but about a meaningful way of using and displaying symbolic differentials.
</p>
<p>
One thing I learned from this post: <a class="ext-link" href="http://trac.sagemath.org/ticket/17447#comment:3"><span class="icon"></span>http://trac.sagemath.org/ticket/17447#comment:3</a> is:
The example I used in the description of the ticket, and most of the examples following, should not be used!
If we avoid this, then we are stuck with the problem that the diff() method is not defined for symbolic functions:
</p>
<pre class="wiki">sage: var('x')
sage: function('f', x)
sage: print type(g)
sage: p = f.diff()
<class 'sage.symbolic.function_factory.NewSymbolicFunction'>
Traceback (click to the left of this block for traceback)
...
AttributeError: 'NewSymbolicFunction' object has no attribute 'diff'
</pre><p>
What is the point of having a notation for differentials of symbolic functions, then? Should the first step not be to actually implement differentiation of symbolic functions and then explain the notation in the documentation of function?
</p>
TicketnbruinWed, 07 Jan 2015 16:40:59 GMT
https://trac.sagemath.org/ticket/17445#comment:19
https://trac.sagemath.org/ticket/17445#comment:19
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:18" title="Comment 18">schymans</a>:
</p>
<blockquote class="citation">
<p>
What is the point of having a notation for differentials of symbolic functions, then? Should the first step not be to actually implement differentiation of symbolic functions and then explain the notation in the documentation of function?
</p>
</blockquote>
<p>
It's already implemented, see <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:16" title="Comment 16">16</a>. It's called <code>FDerivativeOperator</code>. It may be worthwhile having a nicer interface. Being able to write <code>D[0,1](f)</code> might be nice. See <a class="ext-link" href="https://groups.google.com/d/msg/sage-devel/xBHw11qUARg/0eqj3eUFsFkJ"><span class="icon"></span>sage-devel:"D notation input for ODEs"</a>, which has a short and (I think) fully functional code snippet that implements it.
</p>
<p>
If you prefer inputting your derivatives with Leibnitz notation, you're going to need temporary variables, and in that case it's already about a efficient as you can get:
</p>
<pre class="wiki">sage: f=sage.symbolic.function_factory.function('f')
sage: df=diff(f(x),x).operator()
sage: df
D[0](f)
</pre>
TicketschymansWed, 07 Jan 2015 23:34:03 GMT
https://trac.sagemath.org/ticket/17445#comment:20
https://trac.sagemath.org/ticket/17445#comment:20
<p>
Thanks, Nils, I didn't see that. However, I am still not able to achieve what I was hoping for. Let me give a pratical example. I define an expression for pressure following the ideal gas law:
</p>
<pre class="wiki">sage: var('R t p n T V')
sage: eq_p = p == n*R*T/V
</pre><p>
At some point, I would like to differentiate this equation for an open system, i.e. where p, n, T and V are functions of time. I re-defined the respective variables as functions of and time tried taking the derivative, but:
</p>
<pre class="wiki">sage: function('p',t)
sage: function('n', t)
sage: function('T', t)
sage: function('V', t)
sage: diff(eq_p,t)
p == R*T*n/V
0 == 0
</pre><p>
I also didn't find a way to get <a class="missing wiki">FderivativeOperator?</a> to do the trick:
</p>
<pre class="wiki">sage: D = sage.symbolic.operators.FDerivativeOperator
sage: D(eq_p,[0])
D[0](p == R*T*n/V)
</pre><p>
The only way to get the desired outcome seems to be to re-write the whole equation:
</p>
<pre class="wiki">sage: eq_p = p(t) == n(t)*R*T(t)/V(t)
sage: diff(eq_p,t)
D[0](p)(t) == R*n(t)*D[0](T)(t)/V(t) - R*T(t)*n(t)*D[0](V)(t)/V(t)^2 +
R*T(t)*D[0](n)(t)/V(t)
</pre><p>
Alright, I thought, what about a system with constant volume?
</p>
<pre class="wiki">sage: eq_p = p(t) == n(t)*R*T(t)/V
sage: diff(eq_p,t)
Boom!
</pre><p>
Pity, would have been too easy. Interestingly, this works instead:
</p>
<pre class="wiki">sage: eq_p = p(t) == n(t)*R*T(t)/V(x)
sage: diff(eq_p,t)
D[0](p)(t) == R*n(t)*D[0](T)(t)/V(x) + R*T(t)*D[0](n)(t)/V(x)
</pre><p>
I'm still confused. What I want to express by function('V', t) is that V is a function of t and hence needs to be treated as such when taking the derivative with respect to t. By writing V(t) above, I turn the function into an expression again, which does lead to the desired functionality, but you mentioned earlier that V(t) means "Function V evaluated at t", which to me means something different. I don't see the utility of defining function('V', t) in the above at all. I could have equally defined function('V', x), right?
</p>
<p>
What would be the correct way to do the above consistently?
</p>
TicketnbruinThu, 08 Jan 2015 01:26:03 GMT
https://trac.sagemath.org/ticket/17445#comment:21
https://trac.sagemath.org/ticket/17445#comment:21
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:20" title="Comment 20">schymans</a>:
</p>
<blockquote class="citation">
<pre class="wiki">sage: function('p',t)
sage: function('n', t)
sage: function('T', t)
sage: function('V', t)
sage: diff(eq_p,t)
p == R*T*n/V
0 == 0
</pre></blockquote>
<p>
Just by rebinding the names in the global scope, you do not change the identity of the consituents in <code>eq_p</code>. Those are still variables. Pointwise operations aren't supported for functions:
</p>
<pre class="wiki">sage: function('f')
f
sage: function('g')
g
sage: f*g
TypeError: unsupported operand type(s) for *: 'NewSymbolicFunction' and 'NewSymbolicFunction'
</pre><blockquote class="citation">
<p>
Alright, I thought, what about a system with constant volume?
</p>
<pre class="wiki">sage: eq_p = p(t) == n(t)*R*T(t)/V
</pre></blockquote>
<p>
This already fails for me, because <code>V</code> at this point is a function and dividing a symbolic expression by a function isn't supported.
</p>
<blockquote class="citation">
<p>
Pity, would have been too easy. Interestingly, this works instead:
</p>
<pre class="wiki">sage: eq_p = p(t) == n(t)*R*T(t)/V(x)
sage: diff(eq_p,t)
D[0](p)(t) == R*n(t)*D[0](T)(t)/V(x) + R*T(t)*D[0](n)(t)/V(x)
</pre><p>
I'm still confused. What I want to express by function('V', t) is that V is a function of t and hence needs to be treated as such when taking the derivative with respect to t.
</p>
</blockquote>
<p>
I don't think you can, because in sage, symbolic functions have variable *positions*, not *names*.
</p>
<blockquote class="citation">
<p>
By writing V(t) above, I turn the function into an expression again, which does lead to the desired functionality, but you mentioned earlier that V(t) means "Function V evaluated at t", which to me means something different. I don't see the utility of defining function('V', t) in the above at all. I could have equally defined function('V', x), right?
</p>
</blockquote>
<p>
Or as <code>function('V')</code> for that matter. It seems misguided to me that <code>function</code> admits an argument list. It has no meaning other than that <code>function('V',x) == function('V')(x)</code>. I think the RHS syntax is much clearer.
</p>
<blockquote class="citation">
<p>
What would be the correct way to do the above consistently?
</p>
</blockquote>
<p>
A "symbolic function" in sage is simply something that can occur in the "operator" slot of a symbolic expression. I don't think there is much support for algebra on such objects. Hence the need to talk about <code>V(t)</code> and <code>V(x)</code> (but better not in the same expression! Then you should use <code>V(x,t)</code> and be consistent about the order in which <code>x,t</code> occur). If you absolutely need to make the thing into a "function" again, you could turn it into a "callable symbolic expression":
</p>
<pre class="wiki">sage: A = n(t)*R*T(t)/V(x)
sage: p=diff(A,t).function(t)
sage: p
t |--> R*n(t)*D[0](T)(t)/V(x) + R*T(t)*D[0](n)(t)/V(x)
sage: parent(p)
Callable function ring with arguments (t,)
</pre><p>
You do have to decide beforehand if <code>V</code> is going to be a function of <code>x</code> or of <code>t</code> or of both. Also, the expression above should probably be
</p>
<pre class="wiki">sage: p=diff(A,t).function(x,t)
sage: p
(x, t) |--> R*n(t)*D[0](T)(t)/V(x) + R*T(t)*D[0](n)(t)/V(x)
sage: parent(p)
Callable function ring with arguments (x, t)
</pre><p>
The root cause of this is the following: <code>sin</code> is a function, right? You know the meaning of <code>sin(x)</code> and of <code>sin(y)</code>, right? So is <code>sin</code> a function of <code>x</code> or of <code>y</code>? What should <code>diff(sin,x)</code> and <code>diff(sin,y)</code> be?
</p>
<p>
The answer is of course that <code>sin</code> by itself isn't a function of <code>x</code> or <code>y</code>. It simply is a function. It depends on the context what you put into it. In any case <code>D[0](sin)</code> is its derivative,
</p>
<p>
You may wish that sage would treat V differently, but it doesn't. Otherwise, if you do <code>function('V',t)</code>, what should it do if you call <code>V(x)</code>? raise an error? What about <code>V(t+1)</code>? It really has no choice other than to ignore the name of the parameter and only look at its position in the argument list. Indeed, going back to the topic of the ticket, I recommend that the whole <code>function('f',x)</code> syntax gets deprecated or at least gets advised against in the documentation. It pretends that sage can do something with it that it can't.
</p>
TicketschymansThu, 08 Jan 2015 08:45:37 GMT
https://trac.sagemath.org/ticket/17445#comment:22
https://trac.sagemath.org/ticket/17445#comment:22
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:21" title="Comment 21">nbruin</a>:
</p>
<blockquote class="citation">
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/17445#comment:20" title="Comment 20">schymans</a>:
</p>
</blockquote>
<blockquote class="citation">
<p>
Or as <code>function('V')</code> for that matter. It seems misguided to me that <code>function</code> admits an argument list. It has no meaning other than that <code>function('V',x) == function('V')(x)</code>. I think the RHS syntax is much clearer.
</p>
<blockquote class="citation">
<p>
What would be the correct way to do the above consistently?
</p>
</blockquote>
<p>
A "symbolic function" in sage is simply something that can occur in the "operator" slot of a symbolic expression. I don't think there is much support for algebra on such objects. Hence the need to talk about <code>V(t)</code> and <code>V(x)</code> (but better not in the same expression! Then you should use <code>V(x,t)</code> and be consistent about the order in which <code>x,t</code> occur). Indeed, going back to the topic of the ticket, I recommend that the whole <code>function('f',x)</code> syntax gets deprecated or at least gets advised against in the documentation. It pretends that sage can do something with it that it can't.
</p>
</blockquote>
<p>
Thanks, this clarifies a lot for me! I didn't realise I have to think of 'function' as of an operator. I have been thinking about using vars for independent variables and functions for dependent variables, but as you clarified, this was misguided. My thumbs up to deprecate the <code>function('f',x)</code> syntax, then.
Is there another way to write an expression with dependent and independent variables and then transparently differentiate it according to assumptions which of the dependent variables are kept constant?
</p>
Ticket