Function and Indexed objects behavior with .has( )

40 views
Skip to first unread message

Francesco Bonazzi

unread,
Jul 19, 2016, 4:52:43 AM7/19/16
to sympy
The SymPy master branch has been recently updated to handle derivatives of Indexed objects. They have the peculiarity of generating a Kronecker delta:

In [8]: A[i].diff(A[j])
Out[8]:
δ  
 i
,j

In [9]: /type _
Out[9]: KroneckerDelta


The solution involved some hacks in the differentiation routine, especially to prevent the .has( ) method from returning False, thus implying a null result to the derivative (if the derivation variable is not present, derivative is zero).

In general, .has( ) is used quite often. A recent fix to the series expansion does not produce a series expansion with Kronecker delta because of .has( ):


In [6]: sin(A[i]).series(A[i])
Out[6]:
           
3       5          
       
A[i]    A[i]        6
A[i] - ───── + ───── + OA[i]
         
6      120            

In [7]: sin(A[i]).series(A[j])
Out[7]: sin(A[i])

I was wondering, is it sound to overload .has( ) in order to return A[i].has(A[j]) ===> True ?

Concerning functions, a similar problem could arise:

In [15]: f(x).diff(f(x))
Out[15]: 1

In [17]: f(x).diff(f(y))
Out[17]: 0


I think that output 17 should be a Dirac delta function: DiracDelta(x - y). What do you think?

In [18]: f(x).has(f(x))
Out[18]: True

In [19]: f(x).has(f(y))
Out[19]: False

Here also, output 19 could be changed to True, as f(x) derived by f(y) would now be nonzero.

What do you think? Shall we proceed this way?

Kalevi Suominen

unread,
Jul 19, 2016, 8:14:19 AM7/19/16
to sympy


On Tuesday, July 19, 2016 at 11:52:43 AM UTC+3, Francesco Bonazzi wrote:

Concerning functions, a similar problem could arise:

In [15]: f(x).diff(f(x))
Out[15]: 1

In [17]: f(x).diff(f(y))
Out[17]: 0


I think that output 17 should be a Dirac delta function: DiracDelta(x - y). What do you think?

It seems to me that Dirac delta is not appropriate here since it is a 'generalized function' of a real
variable only in SymPy. Probably some new class of objects, formally integrable over a complex
 domain, would be needed to implement this idea.

Aaron Meurer

unread,
Jul 19, 2016, 2:49:19 PM7/19/16
to sy...@googlegroups.com
IMHO, has() specifically should operate symbolically (no knowledge of mathematics). 

This old pull request seems relevant here https://github.com/sympy/sympy/pull/7437. I think having methods for objects to tell how to differentiate themselves is better than hacking around the implementation details of the current implementation.

I think f(x).diff(f(y)) should return 0, for the same reason that x.diff(y) should return 0. We've had some in-depth discussions on what differentiating with respect to a function should mean in SymPy, and the thing we agreed on is that expr.diff(f(x)) should be the same as expr.xreplace({f(x): y}).diff(y).xreplace({y: f(x)}). Specifically, xreplace means it only looks at things structurally. 

Aaron Meurer

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at https://groups.google.com/group/sympy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/5c543674-9a8f-461e-955b-44ddc8220476%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Francesco Bonazzi

unread,
Jul 22, 2016, 5:02:39 AM7/22/16
to sympy


On Tuesday, 19 July 2016 20:49:19 UTC+2, Aaron Meurer wrote:
IMHO, has() specifically should operate symbolically (no knowledge of mathematics). 


Well, it's not really about knowledge of mathematics. It's about matching the unapplied element or the element applied with another argument.
 
This old pull request seems relevant here https://github.com/sympy/sympy/pull/7437. I think having methods for objects to tell how to differentiate themselves is better than hacking around the implementation details of the current implementation.

I think f(x).diff(f(y)) should return 0, for the same reason that x.diff(y) should return 0. We've had some in-depth discussions on what differentiating with respect to a function should mean in SymPy, and the thing we agreed on is that expr.diff(f(x)) should be the same as expr.xreplace({f(x): y}).diff(y).xreplace({y: f(x)}). Specifically, xreplace means it only looks at things structurally. 


OK, what about extending Indexed to support continuous indexing? Indexed is meant to represent a set of symbols, I think we could add a continuous=True/False option defaulting to False and have something like this:

>>> A = Indexed("A")

>>> A[i].diff(A[j])
KroneckerDelta(i, j)
>>> B = Indexed("B", continuous=True)
>>> var("x, y", real=True)
>>> B[x].diff(B[y])
DiracDelta(x - y)

The KroneckerDelta is already in the development branch.

Kalevi, I think that generalizing the Dirac delta to complex numbers is a bit out of scope. Besides, do SymPy users really need it?

Kalevi Suominen

unread,
Jul 22, 2016, 5:22:04 AM7/22/16
to sympy


On Friday, July 22, 2016 at 12:02:39 PM UTC+3, Francesco Bonazzi wrote:


Kalevi, I think that generalizing the Dirac delta to complex numbers is a bit out of scope. Besides, do SymPy users really need it?

My thoughts, exactly. I only wanted to point out that Dirac delta should not be used :)

Aaron Meurer

unread,
Jul 22, 2016, 1:56:26 PM7/22/16
to sy...@googlegroups.com
On Fri, Jul 22, 2016 at 5:02 AM, Francesco Bonazzi <franz....@gmail.com> wrote:


On Tuesday, 19 July 2016 20:49:19 UTC+2, Aaron Meurer wrote:
IMHO, has() specifically should operate symbolically (no knowledge of mathematics). 


Well, it's not really about knowledge of mathematics. It's about matching the unapplied element or the element applied with another argument.

It's mathematics in the sense that it's something beyond the internal tree representation of the object. A[j] is not a subexpression of A[i] as expression trees.  A[i].has(A) is different. 

But again, I don't think diff should check for just matching functions in general. So we need an API so that this sort of thing can work with objects like Indexed and matrix expression, but not for everything. Plus, matrix derivatives get more complicated than this, so I suspect a more general API will be needed to fully express them. 

Aaron Meurer
 
 
This old pull request seems relevant here https://github.com/sympy/sympy/pull/7437. I think having methods for objects to tell how to differentiate themselves is better than hacking around the implementation details of the current implementation.

I think f(x).diff(f(y)) should return 0, for the same reason that x.diff(y) should return 0. We've had some in-depth discussions on what differentiating with respect to a function should mean in SymPy, and the thing we agreed on is that expr.diff(f(x)) should be the same as expr.xreplace({f(x): y}).diff(y).xreplace({y: f(x)}). Specifically, xreplace means it only looks at things structurally. 


OK, what about extending Indexed to support continuous indexing? Indexed is meant to represent a set of symbols, I think we could add a continuous=True/False option defaulting to False and have something like this:

>>> A = Indexed("A")
>>> A[i].diff(A[j])
KroneckerDelta(i, j)
>>> B = Indexed("B", continuous=True)
>>> var("x, y", real=True)
>>> B[x].diff(B[y])
DiracDelta(x - y)

The KroneckerDelta is already in the development branch.

Kalevi, I think that generalizing the Dirac delta to complex numbers is a bit out of scope. Besides, do SymPy users really need it?

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at https://groups.google.com/group/sympy.
Reply all
Reply to author
Forward
0 new messages