defining a derivative

88 views
Skip to first unread message

Riccardo Rossi

unread,
Oct 14, 2016, 4:53:27 AM10/14/16
to sympy, Mataix Ferrandiz Vicente
Dear List,

i am writing since i would like to define the output of the derivative of a function, and i don't have a clue of how to achieve it

to explain what i wish to do, let's consider the following script

from sympy import *

u = symbols('u')
der = symbols('der')
e = symbols('e', cls=Function)(u)
s = symbols('s', cls=Function)(e)
Derivative(e,u) = der #essentially i would like to teach to sympy to use a symbol for the Derivative
---> but here i get "SyntaxError: can't assign to function call"

print(diff(e,u))
print(diff(s,e))
print(diff(s,u)) #here i would like "der" to be replaced within the chain rule

any suggestion would be very welcome...

regards
Riccardo


Vicente Mataix Ferrándiz

unread,
Oct 14, 2016, 9:09:25 AM10/14/16
to sympy, vma...@cimne.upc.edu
What I am using right now dear Riccardo is the following:


Suppose that my variable sigma(define as a symbol) depends of u, but at the same time this u is vectorial variable, which means for example in 3D the variable will be : u = [u_0, u_1, u_2], all the components of u are defined as symbols. Now I only need to do the following:

In: sigma(*u) #so sigma depends of u_0, u_1, u_2, and if we use diff:
In: print(sigma)
Out: sigma(u_0,u_1,u_2)
In: diff(sigma, u_1)
Out: Derivative(sigma(u_0,u_1,u_2), u_1)








Aaron Meurer

unread,
Oct 14, 2016, 11:27:21 AM10/14/16
to sy...@googlegroups.com, Mataix Ferrandiz Vicente
If you want to define advanced things you need to subclass from
Function rather than using symbols(cls=Function). For derivatives, you
should define fdiff, which should return the derivative of the
function without consideration of the chain rule. For example, search
for "fdiff" in this file to see some examples for exp, log, and
LambertW https://github.com/sympy/sympy/blob/master/sympy/functions/elementary/exponential.py.

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/a4511ef2-2a10-4dbe-b6a0-01fe2fc47a05%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Riccardo Rossi

unread,
Oct 16, 2016, 4:59:07 AM10/16/16
to sympy, vma...@cimne.upc.edu
Dear Aaron,

first of all thank you for answering.

before i start subclassing, let me ask if i can do something easier: can i use "subs"?

right now i am failing, but there might be some obvious error in what i do...

in any case i also tried (and failed) with your suggestion, surely due to my lack of understanding of the sympy internals.
here goes my code

regards
Riccardo


from sympy import *

u = symbols('u')
der = symbols('der')
e = Function('e')(u)
s = Function('s')(e)

print(s)

Derivative(e,u)

print(diff(e,u))
print(diff(s,e))
print(diff(s,u)) #here i would like "der" to be replaced within the chain rule

#list of replacements i would like to happen
aaa = { Derivative(e,u):symbols('DeDu'), Derivative(s,e):symbols('DsDe') }

print(diff(s,u).subs(aaa)) #here Derivative(s,e) is not substituted, i would like to get "se*eu" as a result

#the reason for the failure to substitute is here ... how can i do this correctly?
for iter in diff(s,u).atoms(Derivative):
    print("iter = ",iter)
    print(iter == Derivative(s,e))  
    if iter in aaa:
        print ("found")
    else:
        print("not found")
       
     
     
   
   
#####################################################
### TRYING THE SUGGESTION
#####################################################       
class FunctionWithDerivative(Function):
    def __init__(self, x, D):
        super(FunctionWithDerivative, self).__init__()
        self.x = x #this would be the var the function depends on f(x)
        self.D = D #this would be the output i wish for Derivative(FunctionWithDerivative(x,D),x)
       
    def fdiff(self, argindex=1):
        """
        Return the first derivative of this function.
        """
        print("**************",self.args) -------- NOT BEING CALLED!!!!!

        if len(self.args) == 1:
            if(self.args[0] == self.x):
                return self.D
            else:
                return 0
        else:
            raise ArgumentIndexError(self, argindex)

       

u = symbols('u')
e = Function('e')(u)
s = FunctionWithDerivative(symbols('e'), symbols('DsDe') )

print(s)

Derivative(e,u)

Aaron Meurer

unread,
Oct 16, 2016, 10:34:43 PM10/16/16
to sy...@googlegroups.com, Mataix Ferrandiz Vicente
On Sun, Oct 16, 2016 at 4:59 AM, Riccardo Rossi <roug...@gmail.com> wrote:
> Dear Aaron,
>
> first of all thank you for answering.
>
> before i start subclassing, let me ask if i can do something easier: can i
> use "subs"?
>
> right now i am failing, but there might be some obvious error in what i
> do...
>
> in any case i also tried (and failed) with your suggestion, surely due to my
> lack of understanding of the sympy internals.
> here goes my code
>
> regards
> Riccardo
>
> from sympy import *
>
> u = symbols('u')
> der = symbols('der')
> e = Function('e')(u)
> s = Function('s')(e)
>
> print(s)
>
> Derivative(e,u)
>
> print(diff(e,u))
> print(diff(s,e))
> print(diff(s,u)) #here i would like "der" to be replaced within the chain
> rule

The chain rule is used. The output is

Derivative(e(u), u)*Subs(Derivative(s(_xi_1), _xi_1), (_xi_1,), (e(u),))

You can also call doit on this to get

Derivative(e(u), u)*Derivative(s(e(u)), e(u))

Your issue below is that there are two different ways of representing
ds/de, using subs and the direct way. The direct way is only returned
when using doit. Honestly it would be simpler if diff always returned
a Derivative instance when it could. I opened
https://github.com/sympy/sympy/issues/11737 for this.

Aaron Meurer
> https://groups.google.com/d/msgid/sympy/939b99f4-b75e-4f76-992e-28a92015e926%40googlegroups.com.

Riccardo Rossi

unread,
Oct 17, 2016, 2:26:04 AM10/17/16
to sympy, vma...@cimne.upc.edu
Dear Aaron,

your suggestion did work, HOWEVER i had to upgrade sympy to 1.0. It did nothing on 0.7.6 (the default one on ubuntu 16.04)

only writing here to "document" this behaviour

regards
Riccardo

Riccardo Rossi

unread,
Oct 17, 2016, 3:19:45 AM10/17/16
to sympy, vma...@cimne.upc.edu
iterating a little more,

unfortunately the "doit" fails at the next bend...

this code

from sympy import *

u,B = symbols('u B')
e = B*u #here i use an expression instead of a function

s = Function('s')(e)
print(diff(s,u).doit())

is expected to give somethign like

B*Derivative(s(e),e)

instead it fails with the output

rrossi@PCCB076:~/data/examples$ python3 test_derivatives2.py
B*Subs(Derivative(s(_xi_1), _xi_1), (_xi_1,), (B*u,))
Traceback (most recent call last):
  File "test_derivatives2.py", line 8, in <module>

    aaa = { Derivative(e,u):symbols('DeDu'), Derivative(s,e):symbols('DsDe') }
  File "/home/rrossi/.local/lib/python3.5/site-packages/sympy/core/function.py", line 1070, in __new__
    Can\'t calculate %s%s derivative wrt %s.''' % (count, ordinal, v)))
ValueError:
Can't calculate 1st derivative wrt B*u.



i guess what i should really do is to subfunction the class as your propose. However i do not get how to make it to work. in my case "fdiff" is simply not being called

class FunctionWithDerivative(Function):
    nargs = 3
   
    #first argument  --> the expression
    #second argument --> the variable it depends on
    #second argument --> the derivative      
    @classmethod
    def eval(cls,expression,x,D):
        print("--------- in eval -----------------. Looks like here it is not creating the object ...")
        cls.expression = expression
        cls.x = x
        cls.D = D
        return cls.expression

    def fdiff(self, argindex=1):
        print("********** inside fdiff ****",self.args)

       

u = symbols('u')
e = Function('e')(u)
s = FunctionWithDerivative(symbols('e'), symbols('e'), symbols('DsDe') )

print(diff(s,e).doit())

returns

rrossi@PCCB076:~/data/examples$ python3 test_derivatives2.py
--------- in eval -----------------. Looks like here it is not creating the object ...
s =  s
diff(s,e).doit() =  0


and what is the worst... fdiff is NOT being called...

regards
Riccardo

Riccardo Rossi

unread,
Nov 11, 2016, 1:15:27 PM11/11/16
to sympy
ping!

any more possible feedback on this?

thx in advance
Riccardo

Aaron Meurer

unread,
Nov 11, 2016, 3:37:18 PM11/11/16
to sy...@googlegroups.com
Regarding the ValueError, this is expected behavior. You can only take
derivatives with respect to symbols and simple undefined functions
(like f(x)). See
http://docs.sympy.org/latest/modules/core.html#sympy.core.function.Derivative

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/7211b6bb-a8cc-48f5-8252-3faf94dcceb0%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages