Sage: Ticket #6756: Implement ``diff`` format symbolic derivative in new symbolics
https://trac.sagemath.org/ticket/6756
<p>
Implement a diff format symbolic derivative in new symbolics as the second form of abstract derivative to be avialable in Sage. See this long thread
</p>
<p>
<a class="ext-link" href="http://groups.google.com/group/sage-devel/browse_thread/thread/ff10f99729a74eea/73308bf626ae06b3"><span class="icon"></span>http://groups.google.com/group/sage-devel/browse_thread/thread/ff10f99729a74eea/73308bf626ae06b3</a>
</p>
<p>
for rationale behind it.
</p>
<p>
<strong>Implementation:</strong>
</p>
<p>
Instructions for installing these patches (sage-4.1.1)
</p>
<p>
<strong>(1) Pynac patch</strong>
</p>
<blockquote>
<p>
(a) Get the pynac spkg
</p>
</blockquote>
<blockquote>
<p>
<a class="ext-link" href="http://sage.math.washington.edu/home/burcin/pynac/pynac-0.1.8.p2.spkg"><span class="icon"></span>http://sage.math.washington.edu/home/burcin/pynac/pynac-0.1.8.p2.spkg</a>
</p>
</blockquote>
<blockquote>
<p>
(b) Apply the pynac patch implementing diff derivative from
</p>
</blockquote>
<blockquote>
<p>
<a class="ext-link" href="http://www.math.unb.ca/~ghossain/diff-derivative-pynac.patch"><span class="icon"></span>http://www.math.unb.ca/~ghossain/diff-derivative-pynac.patch</a>
</p>
</blockquote>
<blockquote>
<p>
(c) install the patched spkg in Sage.
</p>
</blockquote>
<blockquote>
<p>
<strong>OR</strong> if you are feeling lazy, you can directly install my patched copy of pynac from here
</p>
</blockquote>
<blockquote>
<p>
<a class="ext-link" href="http://www.math.unb.ca/~ghossain/pynac-0.1.8.p2-with-diff.spkg"><span class="icon"></span>http://www.math.unb.ca/~ghossain/pynac-0.1.8.p2-with-diff.spkg</a>
</p>
</blockquote>
<p>
<strong>(2) Sage patch:</strong>
</p>
<blockquote>
<p>
Apply the attached patch in Sage and build the changes ("sage -b").
If everything goes smoothly then you are ready for testing.
</p>
</blockquote>
<p>
<strong>Testing:</strong>
</p>
<p>
Above, patches will provide two new user accessible functions
</p>
<blockquote>
<p>
(a) <code></code>set_diff_derivative_level<code></code>
</p>
</blockquote>
<blockquote>
<p>
(b) <code></code>symbolic_diff<code></code>
</p>
</blockquote>
<p>
Please see the docs for usage of these functions:
</p>
<p>
It would be good to thoroughly test the following features:
</p>
<blockquote>
<p>
(1) Substitution of the function
</p>
</blockquote>
<blockquote>
<p>
(2) Derivative with or without chain rule
</p>
</blockquote>
<blockquote>
<p>
(3) Explicit evaluation of derivative even for some situation where chain rule has been applied and derivative is specified w.r.t. an expression
</p>
</blockquote>
<blockquote>
<p>
(4) Symbolic n-th derivative
</p>
</blockquote>
<blockquote>
<p>
(5) Typesetting
</p>
</blockquote>
<p>
Please test diff implementation against some related bugs
</p>
<p>
<a class="closed ticket" href="https://trac.sagemath.org/ticket/6376" title="defect: serious bug in _maxima_init_ method for formal derivatives with new ... (closed: duplicate)">#6376</a>, <a class="closed ticket" href="https://trac.sagemath.org/ticket/6523" title="defect: .is_zero() method raises error for symbolic expression involving derivative (closed: fixed)">#6523</a>, <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>
</p>
<p>
as new diff implementation should avoid these.
</p>
<p>
<strong>Speed Test:</strong>
</p>
<pre class="wiki">sage: f(x) = function('f',x);
sage: f(x).diff(x)
D[0](f)(x)
sage: timeit('f(x).diff(x)')
625 loops, best of 3: 124 µs per loop
sage: timeit('f(x).diff(x,100)')
125 loops, best of 3: 5.58 ms per loop
sage: set_diff_derivative_level(1)
sage: f(x).diff(x)
diff(f(x), x, 1)
sage: timeit('f(x).diff(x)')
625 loops, best of 3: 116 µs per loop
sage: timeit('f(x).diff(x,100)')
625 loops, best of 3: 1.01 ms per loop
sage: set_diff_derivative_level(2)
sage: f(x).diff(x)
diff(f(x), x, 1)
sage: timeit('f(x).diff(x)')
625 loops, best of 3: 130 µs per loop
sage: timeit('f(x).diff(x,100)')
125 loops, best of 3: 1.85 ms per loop
</pre><p>
<strong>*</strong> This patch removes old "dummy_diff" from
"calculus/calculus" as we now have a _real_ diff.
</p>
en-usSagehttps://trac.sagemath.org/chrome/site/logo_sagemath_trac.png
https://trac.sagemath.org/ticket/6756
Trac 1.1.6gmhossainMon, 17 Aug 2009 16:17:48 GMTsummary, description changed; author set
https://trac.sagemath.org/ticket/6756#comment:1
https://trac.sagemath.org/ticket/6756#comment:1
<ul>
<li><strong>summary</strong>
changed from <em>Implement ``diff`` format symbolic derivative in new symbolics</em> to <em>[with patch, needs review] Implement ``diff`` format symbolic derivative in new symbolics</em>
</li>
<li><strong>description</strong>
modified (<a href="/ticket/6756?action=diff&version=1">diff</a>)
</li>
<li><strong>author</strong>
set to <em>Golam Mortuza Hossain</em>
</li>
</ul>
TicketgmhossainMon, 17 Aug 2009 17:21:10 GMTattachment set
https://trac.sagemath.org/ticket/6756
https://trac.sagemath.org/ticket/6756
<ul>
<li><strong>attachment</strong>
set to <em>trac_6756-diff-derivative-sage.patch</em>
</li>
</ul>
TicketncalexanFri, 21 Aug 2009 17:21:03 GMT
https://trac.sagemath.org/ticket/6756#comment:2
https://trac.sagemath.org/ticket/6756#comment:2
<p>
I am interested in reviewing this, but I'm not sure that I can at this time. I have a heavily modified <code>Sage Version 4.1.rc1, Release Date: 2009-07-07</code> tree that I can't really upgrade right now. I have applied this patch and installed your modified spkg. I am getting the following doctest failures
</p>
<pre class="wiki">-*- mode: sage-test; default-directory: "~/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/" -*-
sage-test started at Fri Aug 21 10:18:46
/Users/ncalexan/bin/sage -b >/dev/null && /Users/ncalexan/bin/sage -tp 4 /Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py
real 0m2.361s
user 0m1.297s
sys 0m0.591s
Global iterations: 1
File iterations: 1
Using cached timings to run longest doctests first.
Doctesting 1 files doing 4 jobs in parallel
sage -t derivative.py
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 51:
sage: f(x).diff(x)
Expected:
diff(f(x), x, 1)
Got:
D[0](f)(x)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 53:
sage: diff(f(x), x, 1)
Expected:
diff(f(x), x, 1)
Got:
D[0](f)(x)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 68:
sage: h.diff(x)
Expected:
diff(f(x), x, n + 1)
Got:
D[0](diff)(f(x), x, n)*D[0](f)(x) + D[1](diff)(f(x), x, n)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 112:
sage: f(x^2).diff(x)
Expected:
diff(f(x^2), x, 1)
Got:
2*x*D[0](f)(x^2)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 118:
sage: f(x^2).diff(x)
Expected:
2*x*diff(f(x^2), x^2, 1)
Got:
2*x*D[0](f)(x^2)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 121:
sage: f(sin(x^2)).diff(x)
Expected:
2*x*cos(x^2)*diff(f(sin(x^2)), sin(x^2), 1)
Got:
2*x*D[0](f)(sin(x^2))*cos(x^2)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 124:
sage: g(x,f(x)).diff(x)
Expected:
diff(f(x), x, 1)*diff(g(x, f(x)), f(x), 1) + diff(g(x, f(x)), x, 1)
Got:
D[0](f)(x)*D[1](g)(x, f(x)) + D[0](g)(x, f(x))
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 129:
sage: symbolic_diff(f(x^2), x, 1)
Expected:
diff(f(x^2), x, 1)
Got:
2*x*D[0](f)(x^2)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 138:
sage: g(x,x).diff(x)
Expected:
2*diff(g(x, x), x, 1)
Got:
D[0](g)(x, x) + D[1](g)(x, x)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 147:
sage: h = f(x).diff(x); h
Expected:
diff(f(x), x, 1)
Got:
D[0](f)(x)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 149:
sage: h.subs(f(x)==x^4)
Expected:
4*x^3
Got:
D[0](f)(x)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 155:
sage: h = f(x^2).diff(x); h
Expected:
2*x*diff(f(x^2), x^2, 1)
Got:
2*x*D[0](f)(x^2)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 157:
sage: h.subs(f(x^2)==x^4)
Expected:
4*x^3
Got:
2*x*D[0](f)(x^2)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 159:
sage: symbolic_diff(f(x)^2, f(x), 1)
Expected:
2*f(x)
Got:
diff(f(x)^2, f(x), 1)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 186:
sage: h = f(x).diff(x) + f(x^2).diff(x); h
Expected:
2*x*diff(f(x^2), x^2, 1) + diff(f(x), x, 1)
Got:
2*x*D[0](f)(x^2) + D[0](f)(x)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 217:
sage: f(x,y).diff(x,y)
Expected:
diff(f(x, y), x, 1, y, 1)
Got:
D[0, 1](f)(x, y)
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 219:
sage: f(x,y).diff(x,2)
Expected:
diff(f(x, y), x, 2)
Got:
D[0, 0](f)(x, y)
**********************************************************************
2 items had failures:
15 of 40 in __main__.example_1
2 of 10 in __main__.example_2
***Test Failed*** 17 failures.
For whitespace errors, see the file /Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/tmp/.doctest_derivative.py
[3.8 s]
----------------------------------------------------------------------
The following tests failed:
sage -t devel/sage-main/sage/symbolic/derivative.py # 17 doctests failed
----------------------------------------------------------------------
Total time for all tests: 4.1 seconds
sage-test finished with failing tests at Fri Aug 21 10:18:53
</pre><p>
When I work from the command line, I get things like
</p>
<pre class="wiki">sage: default_level=set_diff_derivative_level()
sage: set_diff_derivative_level(1)
sage: f(x) = function('f', x)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/Users/ncalexan/.sage/temp/mero.local/93112/_Users_ncalexan__sage_init_sage_1.py in <module>()
/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/local/lib/python2.6/site-packages/sage/calculus/var.so in sage.calculus.var.function (sage/calculus/var.c:709)()
/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/local/lib/python2.6/site-packages/sage/symbolic/function.so in sage.symbolic.function.SFunction.__call__ (sage/symbolic/function.cpp:4655)()
TypeError: Symbolic function f takes exactly 2 arguments (1 given)
</pre><p>
So there must be some calculus or symbolic patches that I'm missing. Any suggestions?
</p>
TicketgmhossainFri, 21 Aug 2009 18:41:37 GMTcc set
https://trac.sagemath.org/ticket/6756#comment:3
https://trac.sagemath.org/ticket/6756#comment:3
<ul>
<li><strong>cc</strong>
<em>ncalexan</em> added
</li>
</ul>
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:2" title="Comment 2">ncalexan</a>:
</p>
<blockquote class="citation">
<p>
I am interested in reviewing this, but I'm not sure that I can at this time. I have a heavily modified <code>Sage Version 4.1.rc1, Release Date: 2009-07-07</code> tree that I can't really upgrade right now. I have applied this patch and installed your modified spkg. I am getting the following doctest failures
</p>
</blockquote>
<pre class="wiki">
**********************************************************************
File "/Users/ncalexan/sage-4.1-OSX-10.5-Intel-64bit-i386-Darwin/devel/sage-main/sage/symbolic/derivative.py", line 51:
sage: f(x).diff(x)
Expected:
diff(f(x), x, 1)
Got:
D[0](f)(x)
</pre><p>
<br />
</p>
<p>
Thanks Nick for trying it out. From this error, it seems "diff_derivative_level" flag wasn't set to
value greater than "0". It could be that "set_diff_derivative_level()" failed to set it properly.
</p>
<p>
<br />
</p>
<blockquote class="citation">
<p>
When I work from the command line, I get things like
</p>
<pre class="wiki">sage: default_level=set_diff_derivative_level()
sage: set_diff_derivative_level(1)
sage: f(x) = function('f', x)
---------------------------------------------------------------------------
TypeError: Symbolic function f takes exactly 2 arguments (1 given)
</pre></blockquote>
<p>
<br />
</p>
<p>
This looks really weired to me. Does it work before calling "set_diff_derivative_level()"?
</p>
<p>
I can suggest you to check three things
</p>
<blockquote>
<p>
(1) Ensure in "symbolic/pynac.pyx" you have a line:
</p>
<pre class="wiki"> "cdef public int diff_derivative_level = 0"
</pre><blockquote>
<p>
May be you can set it to "1", to enable "diff" by default.
</p>
</blockquote>
</blockquote>
<blockquote>
<p>
(2) In "symbolic/all.py" you have a line:
</p>
<pre class="wiki"> "from derivative import symbolic_diff"
</pre><p>
(3) In "calculus/calculus.py" the following line is commented out or removed
</p>
<pre class="wiki"> "syms['diff'] = dummy_diff"
</pre></blockquote>
<p>
If these three lines are fine then it should work. Some doctests may it still
fail if "set_diff_derivative_level()" isn't working properly but you can
always change value in (1) manually without using it.
</p>
<p>
Please let me know if that works.
</p>
<p>
Best,
</p>
<p>
</p>
TicketncalexanWed, 26 Aug 2009 05:00:03 GMT
https://trac.sagemath.org/ticket/6756#comment:4
https://trac.sagemath.org/ticket/6756#comment:4
<p>
Sorry, same problems with a new 4.1.1 binary. It's possible I'm building in the wrong order (patch, failed tests, then new spkg, touch patch, rebuild) but that's two systems not working.
</p>
TicketncalexanWed, 26 Aug 2009 19:01:53 GMTattachment set
https://trac.sagemath.org/ticket/6756
https://trac.sagemath.org/ticket/6756
<ul>
<li><strong>attachment</strong>
set to <em>trac_6756-referee-patch-ncalexan-1.patch</em>
</li>
</ul>
TicketncalexanWed, 26 Aug 2009 19:03:02 GMTreviewer set
https://trac.sagemath.org/ticket/6756#comment:5
https://trac.sagemath.org/ticket/6756#comment:5
<ul>
<li><strong>reviewer</strong>
set to <em>Nick Alexander</em>
</li>
</ul>
<p>
The second patch makes this at least work for me, and fixes (maybe an ordering issue?) a test that doesn't pass on my box. I'm not done reviewing yet, but at least it works as advertised. Question: how do I pattern match on this?
</p>
TicketncalexanWed, 26 Aug 2009 19:16:57 GMT
https://trac.sagemath.org/ticket/6756#comment:6
https://trac.sagemath.org/ticket/6756#comment:6
<p>
Aha, very interesting, you pattern match via the <code>symbolic_diff</code> object. This is pretty slick, but it irritates me that there's no way to match *any* derivative. Ie, handle <code>diff(f(x, y), x, 2)</code> and <code>diff(f(x, y), x, 1, y, 1)</code> uniformly for pattern matching.
</p>
TicketncalexanWed, 26 Aug 2009 19:35:55 GMT
https://trac.sagemath.org/ticket/6756#comment:7
https://trac.sagemath.org/ticket/6756#comment:7
<p>
I would like to evaluate various derivatives numerically, but there's no obvious way to do so.
</p>
<pre class="wiki">sage: def f(v, n): print v; return v**n
....:
sage: g(x, y).derivative(x, 1).subs( symbolic_diff(g(x, y), w0, w1) == f(w0, w1) )
$0
x
</pre><p>
I would like to have my <code>f</code> examine w0 and w1 to determine the correct variable, derivative, etc. But if you look, f gets evaluated with the wild card objects (it must -- that's how python works.)
</p>
<p>
So I need to match the wild cards, then calculate the function, then substitute. Just longer, that's all.
</p>
TicketgmhossainThu, 27 Aug 2009 01:17:23 GMT
https://trac.sagemath.org/ticket/6756#comment:8
https://trac.sagemath.org/ticket/6756#comment:8
<p>
Hi Nick,
</p>
<p>
As you suggested, I moved the "set_diff_derivative_level" into pynac library.
Now I just wrap the function from cython code. I will update the patches,spkg after
you finish your first round of reviewing.
</p>
TicketgmhossainSat, 05 Sep 2009 14:33:45 GMTattachment set
https://trac.sagemath.org/ticket/6756
https://trac.sagemath.org/ticket/6756
<ul>
<li><strong>attachment</strong>
set to <em>trac_6756-diff-derivative-sage-v2.patch</em>
</li>
</ul>
<p>
Apply only this patch and ignore first two patches
</p>
TicketgmhossainSat, 05 Sep 2009 14:46:41 GMT
https://trac.sagemath.org/ticket/6756#comment:9
https://trac.sagemath.org/ticket/6756#comment:9
<p>
Patches updated to include Nick's suggestion to move "set_diff_derivative_level" into pynac library.
</p>
TicketburcinSun, 06 Sep 2009 12:58:51 GMTsummary changed
https://trac.sagemath.org/ticket/6756#comment:10
https://trac.sagemath.org/ticket/6756#comment:10
<ul>
<li><strong>summary</strong>
changed from <em>[with patch, needs review] Implement ``diff`` format symbolic derivative in new symbolics</em> to <em>[with patch, needs work] Implement ``diff`` format symbolic derivative in new symbolics</em>
</li>
</ul>
<p>
It seems that applying chain rule to these inert derivatives can lead to wrong answers:
</p>
<pre class="wiki">sage: f = function('f')
sage: set_diff_derivative_level(2)
sage: f(y,y).diff(y,1)
2*diff(f(y, y), y, 1)
</pre><p>
Compare with the answer we get now:
</p>
<pre class="wiki">sage: set_diff_derivative_level(0)
sage: f(y,y).diff(y,1)
D[0](f)(y, y) + D[1](f)(y, y)
</pre><p>
This example is from p. 26 (second page) in
</p>
<pre class="wiki">Wester, M. and Steinberg, S. 1983. An extension to MACSYMA's concept of functional differentiation.
SIGSAM Bull. 17, 3-4 (Aug. 1983), 25-30.
</pre><p>
You can get the article here: <a class="ext-link" href="http://doi.acm.org/10.1145/1089338.1089343"><span class="icon"></span>http://doi.acm.org/10.1145/1089338.1089343</a>
</p>
<p>
It was the first reference on the paper mentioned by RJF in this post:
</p>
<p>
<a class="ext-link" href="http://groups.google.com/group/sage-devel/msg/6db333cbf8ea0a53"><span class="icon"></span>http://groups.google.com/group/sage-devel/msg/6db333cbf8ea0a53</a>
</p>
<p>
The paper RJF cites is
</p>
<pre class="wiki">Golden, J. P. 1985. Differentiation of unknown functions in MACSYMA.
SIGSAM Bull. 19, 2 (May. 1985), 19-24.
</pre><p>
which you can get here:
</p>
<p>
<a class="ext-link" href="http://doi.acm.org/10.1145/1089402.1089405"><span class="icon"></span>http://doi.acm.org/10.1145/1089402.1089405</a>
</p>
<p>
I suggest removing the chain rule from this implementation altogether and keeping it as an alternative <em>inert</em> derivative. Then the implementation can be moved within the Sage library completely as a subclass of SFunction. We should also implement conversions between the partial derivative format and this one. This page gives a recipe on how this can be done:
</p>
<p>
<a class="ext-link" href="http://209.85.129.132/search?q=cache%3Ahttp%3A%2F%2Fwww.mapleprimes.com%2Fforum%2Fd-diff-conversion%23comment-8243"><span class="icon"></span>http://209.85.129.132/search?q=cache%3Ahttp%3A%2F%2Fwww.mapleprimes.com%2Fforum%2Fd-diff-conversion%23comment-8243</a>
</p>
<p>
(The link points to the google cache since mapleprimes.com is down.)
</p>
<p>
Nick, if you give examples of how you want pattern matching on derivatives to work, we can see how to make the current implementation support these. Pattern matching capabilities of <code>fderivative</code> in GiNaC definitely need to be improved. Looking at what functionality maple and MMA provides could also help.
</p>
TicketgmhossainSun, 06 Sep 2009 20:02:24 GMTsummary changed
https://trac.sagemath.org/ticket/6756#comment:11
https://trac.sagemath.org/ticket/6756#comment:11
<ul>
<li><strong>summary</strong>
changed from <em>[with patch, needs work] Implement ``diff`` format symbolic derivative in new symbolics</em> to <em>[with patch, needs review] Implement ``diff`` format symbolic derivative in new symbolics</em>
</li>
</ul>
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:10" title="Comment 10">burcin</a>:
</p>
<blockquote class="citation">
<p>
It seems that applying chain rule to these inert derivatives can lead to wrong answers:
</p>
</blockquote>
<pre class="wiki">sage: f = function('f')
sage: set_diff_derivative_level(2)
sage: f(y,y).diff(y,1)
2*diff(f(y, y), y, 1)
</pre><blockquote class="citation">
<p>
Compare with the answer we get now:
</p>
</blockquote>
<pre class="wiki">sage: set_diff_derivative_level(0)
sage: f(y,y).diff(y,1)
D[0](f)(y, y) + D[1](f)(y, y)
</pre><blockquote class="citation">
<p>
This example is from p. 26 (second page) in ....
</p>
</blockquote>
<blockquote class="citation">
<p>
I suggest removing the chain rule from this implementation altogether and keeping it as an alternative <em>inert</em>
</p>
</blockquote>
<p>
Thanks for the reference and I am certainly aware of this issue. If you read the
docstring then you will find that I have even documented it. Furthermore, I also
posted this issue for discussion to sage-devel (but without any definite conclusion)
</p>
<p>
<a class="ext-link" href="http://groups.google.com/group/sage-devel/browse_thread/thread/c8d257981e3e3d98"><span class="icon"></span>http://groups.google.com/group/sage-devel/browse_thread/thread/c8d257981e3e3d98</a>
</p>
<p>
Following are my comments:
</p>
<blockquote>
<p>
(1) f(y,y) is not a genuine function of two variables. So asking for its chain rule, pretending it to be a function of multiple variables, is itself incorrect assertion.
</p>
</blockquote>
<blockquote>
<p>
(2) I don't think even D[] derivative output is much better in this regard, specially if you implement and allow substitution of f(y,y). For example. consider the substitution: f(y,y) = y in "D[0](f)(y, y) + D[1](f)(y, y)", then you will get the same wrong answer from D[] as from "diff".
</p>
</blockquote>
<p>
</p>
<blockquote>
<p>
(3) Applying chain rule is just an option in new diff implementation and certainly not the default option. However, this could be useful sometime (for example in computing Euler-Lagrange equation using functional derivative of a formal functional "S(f(y), g(y))" this feature is needed. In fact, this was the reason for implementing this feature.)
</p>
</blockquote>
<p>
So I am sorry to differ from your opinion about removing this feature.
</p>
<p>
<br />
</p>
<blockquote class="citation">
<p>
Then the implementation can be moved within the Sage library completely as a
subclass of SFunction.
</p>
</blockquote>
<p>
<br />
</p>
<p>
As I posted in the sage-devel, I initially implemented this within Sage as SFunction
sub-class (as you suggest). Then I re-implemented this in c++ as pynac native implementation
because this is 10-15 times faster than the Sage implementation.
</p>
<p>
Why do you want to have a slower implementation of diff than a faster one?
</p>
<p>
<br />
</p>
<blockquote class="citation">
<p>
We should also implement conversions between the partial derivative format and this one.
This page gives a recipe on how this can be done:
</p>
<p>
<a class="ext-link" href="http://209.85.129.132/search?q=cache%3Ahttp%3A%2F%2Fwww.mapleprimes.com%2Fforum%2Fd-diff-conversion%23comment-8243"><span class="icon"></span>http://209.85.129.132/search?q=cache%3Ahttp%3A%2F%2Fwww.mapleprimes.com%2Fforum%2Fd-diff-conversion%23comment-8243</a>
</p>
</blockquote>
<p>
<br />
</p>
<p>
I agree that we need this conversion at least to restore compatibility of D[] with Maxima which is badly broken now because of D[] derivative. However, I don't agree that I should implement this conversion and certainly not as a pre-requirement for accepting this patch.
</p>
<p>
Given above arguments, I am reverting back to "needs review" status.
</p>
TicketburcinSun, 06 Sep 2009 21:47:47 GMT
https://trac.sagemath.org/ticket/6756#comment:12
https://trac.sagemath.org/ticket/6756#comment:12
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:11" title="Comment 11">gmhossain</a>:
</p>
<blockquote class="citation">
<blockquote>
<p>
(2) I don't think even D[] derivative output is much better in this regard, specially if you implement and allow substitution of f(y,y). For example. consider the substitution: f(y,y) = y in "D[0](f)(y, y) + D[1](f)(y, y)", then you will get the same wrong answer from D[] as from "diff".
</p>
</blockquote>
</blockquote>
<p>
This substitution doesn't make sense mathematically. D[0](f)(y,y) doesn't contain f(y,y), there is nothing to substitute.
</p>
<p>
Bill Page had answered this point earlier:
</p>
<p>
<a class="ext-link" href="http://groups.google.com/group/sage-devel/msg/e6ded8f5e28a5aab"><span class="icon"></span>http://groups.google.com/group/sage-devel/msg/e6ded8f5e28a5aab</a>
</p>
<p>
This message by him in the same thread might be more helpful:
</p>
<p>
<a class="ext-link" href="http://groups.google.com/group/sage-devel/msg/98cc070640578f0c"><span class="icon"></span>http://groups.google.com/group/sage-devel/msg/98cc070640578f0c</a>
</p>
<p>
Note that with these patches, the result of <code>f(y,y).diff(y)</code> is twice that of the current implementation.
</p>
TicketgmhossainSun, 06 Sep 2009 22:42:44 GMT
https://trac.sagemath.org/ticket/6756#comment:13
https://trac.sagemath.org/ticket/6756#comment:13
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:12" title="Comment 12">burcin</a>:
</p>
<blockquote class="citation">
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:11" title="Comment 11">gmhossain</a>:
</p>
<blockquote>
<p>
For example. consider the substitution: f(y,y) = y
</p>
</blockquote>
<p>
This substitution doesn't make sense mathematically.
</p>
</blockquote>
<p>
Hmm, if you bring mathematical sense into argument then does it
make mathematical sense asking for applying chain rule at the
first place for this case?
</p>
<blockquote class="citation">
<p>
Note that with these patches, the result of <code>f(y,y).diff(y)</code> is twice that of the current implementation.
</p>
</blockquote>
<p>
This is not accurate.
</p>
<p>
Above will happen only when an user wants to apply chain rule by explicitly setting
diff_derivative_level to "2" or more and certainly NOT in default diff level of "1".
If some user wants to use some setting that are not default then its reasonable to
expect users to read the documentation to be aware of the assumptions associated with
the settings.
</p>
TicketburcinSun, 06 Sep 2009 23:01:15 GMT
https://trac.sagemath.org/ticket/6756#comment:14
https://trac.sagemath.org/ticket/6756#comment:14
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:13" title="Comment 13">gmhossain</a>:
</p>
<blockquote class="citation">
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:12" title="Comment 12">burcin</a>:
</p>
<blockquote class="citation">
<p>
Note that with these patches, the result of <code>f(y,y).diff(y)</code> is twice that of the current implementation.
</p>
</blockquote>
<p>
This is not accurate.
</p>
<p>
Above will happen only when an user wants to apply chain rule by explicitly setting
diff_derivative_level to "2" or more and certainly NOT in default diff level of "1".
If some user wants to use some setting that are not default then its reasonable to
expect users to read the documentation to be aware of the assumptions associated with
the settings.
</p>
</blockquote>
<p>
So you agree that setting this level to 2 gives wrong results. In <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:10" title="Comment 10">comment:10</a>, I tried to say that this option that gives wrong results should be removed.
</p>
<p>
We can then merge this <em>inert</em> derivative with the global <code>diff</code> command by adding a keyword option <code>hold</code>. E.g.,
</p>
<pre class="wiki">sage: f(y,y).diff(y,1)
D[0](f)(y, y) + D[1](f)(y, y)
sage: f(y,y).diff(y,1,hold=True)
diff(f(y, y), y, 1)
</pre>
TicketgmhossainMon, 07 Sep 2009 03:34:47 GMT
https://trac.sagemath.org/ticket/6756#comment:15
https://trac.sagemath.org/ticket/6756#comment:15
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:14" title="Comment 14">burcin</a>:
</p>
<blockquote class="citation">
<p>
So you agree that setting this level to 2 gives wrong results.
</p>
</blockquote>
<p>
Yes, but ONLY for mathematically dubious inputs. Please don't generalize, it doesn't help anyone.
</p>
<p>
I have been working on a patch that will check the arguments of the function while applying chain
rule and can warn/raise appropriate errors. However, I am planning to do this in next
revision and after having some feedbacks from its users.
</p>
<blockquote class="citation">
<p>
We can then merge this <em>inert</em> derivative with the global <code>diff</code> command by
adding a keyword option <code>hold</code>. E.g.,
</p>
</blockquote>
<p>
Sure. However, it would be premature to merge this with global "diff" now, given its a
new implementation and there could be issue which are not yet known. So I would prefer
to wait couple of release cycles before considering such a move.
</p>
TicketburcinTue, 08 Sep 2009 08:32:33 GMT
https://trac.sagemath.org/ticket/6756#comment:16
https://trac.sagemath.org/ticket/6756#comment:16
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:15" title="Comment 15">gmhossain</a>:
</p>
<blockquote class="citation">
<p>
Replying to <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:14" title="Comment 14">burcin</a>:
</p>
<blockquote class="citation">
<p>
So you agree that setting this level to 2 gives wrong results.
</p>
</blockquote>
<p>
Yes, but ONLY for mathematically dubious inputs. Please don't generalize, it doesn't help anyone.
</p>
</blockquote>
<p>
What do you think is "mathematically dubious"?
</p>
<p>
Using the notation and definitions for derivatives and partial derivatives from here respectively:
</p>
<p>
<a class="ext-link" href="http://books.google.at/books?id=e54cqeAmf4QC&pg=PA267#v=onepage"><span class="icon"></span>http://books.google.at/books?id=e54cqeAmf4QC&pg=PA267#v=onepage</a>
</p>
<p>
<a class="ext-link" href="http://books.google.at/books?id=e54cqeAmf4QC&pg=PA495#v=onepage"><span class="icon"></span>http://books.google.at/books?id=e54cqeAmf4QC&pg=PA495#v=onepage</a>
</p>
<p>
Let U be an open subset of the complex numbers, f: UxU -> C, y in U. Then by Proposition 3.5 here
</p>
<p>
<a class="ext-link" href="http://books.google.at/books?id=LzhkCF9ZsUgC&&pg=PA10#v=onepage"><span class="icon"></span>http://books.google.at/books?id=LzhkCF9ZsUgC&&pg=PA10#v=onepage</a>
</p>
<p>
we have
</p>
<p>
\frac{df}{dy} (y,y) = D_1 f(y, y) + D_2 f(y, y).
</p>
<p>
Note that on the left hand side there is a <em>total</em> derivative.
</p>
<p>
In the current Sage syntax, "diff" denotes a total derivative, and "D" denotes a partial derivative. The statement above translates to the Sage notation as:
</p>
<p>
diff(f(y,y), y) = D[0](f)(y,y) + D[1](f)(y,y)
</p>
<p>
Which you can also calculate by:
</p>
<pre class="wiki">sage: diff(f(y,y),y)
D[0](f)(y, y) + D[1](f)(y, y)
</pre><hr />
<p>
With your patch we get:
</p>
<pre class="wiki">sage: set_diff_derivative_level(2)
sage: diff(f(y,y),y)
2*diff(f(y, y), y, 1)
sage: latex(diff(f(y,y),y))
2 \, {\frac{\partial}{\partial y}f\left(y, y\right)}
</pre><p>
Can you explain what <code>diff(f(y,y), y, 1)</code> or in typeset form <code>\frac{\partial}{\partial y}f(y,y)</code> means?
</p>
<hr />
<blockquote class="citation">
<p>
I have been working on a patch that will check the arguments of the function while applying chain
rule and can warn/raise appropriate errors. However, I am planning to do this in next
revision and after having some feedbacks from its users.
</p>
</blockquote>
<p>
Are you saying that we should merge this problematic version, and you'll fix things later? This is not how the development process works. We can review and merge the known good parts from your patch, and you can submit the rest in a different ticket later.
</p>
<blockquote class="citation">
<blockquote class="citation">
<p>
We can then merge this <em>inert</em> derivative with the global <code>diff</code> command by
adding a keyword option <code>hold</code>. E.g.,
</p>
</blockquote>
<p>
Sure. However, it would be premature to merge this with global "diff" now, given its a
new implementation and there could be issue which are not yet known. So I would prefer
to wait couple of release cycles before considering such a move.
</p>
</blockquote>
<p>
Should it really be merged into Sage if it's so premature? The point of the review to make sure that it doesn't have these problems.
</p>
<p>
I don't have any more time to waste on this. I suggest you either
</p>
<ul><li>read the references I linked to in <a class="ticket" href="https://trac.sagemath.org/ticket/6756#comment:10" title="Comment 10">comment:10</a>, and explain clearly what you do to remedy the problems discussed there or,
</li><li>remove the problematic parts from your patch.
</li></ul>
TicketmhansenTue, 29 Sep 2009 06:37:33 GMTcc changed
https://trac.sagemath.org/ticket/6756#comment:17
https://trac.sagemath.org/ticket/6756#comment:17
<ul>
<li><strong>cc</strong>
<em>mhansen</em> added
</li>
</ul>
<p>
I tend to agree with the points that Burcin made.
</p>
<p>
It seems a better way to implement this within GiNaC would be to have a class parallel to fderivative which just stores the (evaluated) function as well as the list of symbols. It is trivial to go from this data structure to partial derivative one.
</p>
TicketburcinSun, 07 Feb 2010 14:10:22 GMTstatus, summary changed; upstream set
https://trac.sagemath.org/ticket/6756#comment:18
https://trac.sagemath.org/ticket/6756#comment:18
<ul>
<li><strong>status</strong>
changed from <em>needs_review</em> to <em>needs_work</em>
</li>
<li><strong>upstream</strong>
set to <em>N/A</em>
</li>
<li><strong>summary</strong>
changed from <em>[with patch, needs review] Implement ``diff`` format symbolic derivative in new symbolics</em> to <em>Implement ``diff`` format symbolic derivative in new symbolics</em>
</li>
</ul>
TicketkcrismanTue, 22 Mar 2011 15:20:01 GMTcc changed
https://trac.sagemath.org/ticket/6756#comment:19
https://trac.sagemath.org/ticket/6756#comment:19
<ul>
<li><strong>cc</strong>
<em>kcrisman</em> added
</li>
</ul>
TicketnbruinThu, 23 Sep 2021 17:21:20 GMTstatus changed; milestone set
https://trac.sagemath.org/ticket/6756#comment:20
https://trac.sagemath.org/ticket/6756#comment:20
<ul>
<li><strong>status</strong>
changed from <em>needs_work</em> to <em>needs_review</em>
</li>
<li><strong>milestone</strong>
set to <em>sage-duplicate/invalid/wontfix</em>
</li>
</ul>
<p>
We have this now. Close?
</p>
<pre class="wiki">sage: var('x,y,z')
(x, y, z)
sage: function('f')
f
sage: f(x,y,z).diff(x,z,y,z)
diff(f(x, y, z), x, y, z, z)
</pre>
TicketmhansenThu, 23 Sep 2021 17:52:33 GMT
https://trac.sagemath.org/ticket/6756#comment:21
https://trac.sagemath.org/ticket/6756#comment:21
<p>
It's hard to tell exactly the scope of this ticket, but from the thread, it seems like one of the primary things wanted was a way to represent
</p>
<pre class="wiki">sage: f(g(x)).diff(x)
diff(f(g(x)), x)
</pre><p>
instead of what's in Sage now:
</p>
<pre class="wiki">sage: f(g(x)).diff(x)
D[0](f)(g(x))*diff(g(x), x)
</pre>
TicketkcrismanThu, 23 Sep 2021 17:55:58 GMTstatus changed
https://trac.sagemath.org/ticket/6756#comment:22
https://trac.sagemath.org/ticket/6756#comment:22
<ul>
<li><strong>status</strong>
changed from <em>needs_review</em> to <em>needs_info</em>
</li>
</ul>
<p>
I think Mike has it correct.
</p>
<p>
(Though this ticket is so old, and involved an unresolved discussion, so that it could conceivably be helpful to start over.)
</p>
Ticket