Search code examples
python-2.7numpysympyderivative

Find derivative of a function with Abs in python


I would like to compute derivative of y=Abs(0.5-0.5*sqrt(1-4*x)) in 0.1, using python. This is my code:

x=Symbol('x')
y=Abs(0.5-0.5*sqrt(1-4*x))
deriv=y.diff(x)
d=lambdify(x,deriv,'numpy')
print d(0.1)

This is what I get:

Traceback (most recent call last):
  File "/home/milossimic/g4/s1/.../optimize.py", line 100, in <module>
    print d(0.1)
  File "<string>", line 1, in <lambda>
NameError: global name 'Derivative' is not defined

I'm a newbie to sympy and numpy, so I guess I'm using the wrong method to determine derivative.

EDIT: I printed deriv and this is what I got:

enter image description here

After reading this http://docs.sympy.org/dev/modules/functions/elementary.html, I've tried fdiff():

x=Symbol('x')
y=Abs(0.5-0.5*sqrt(1-4*x))
deriv=y.fdiff()
d=lambdify(x,deriv,'numpy')
print d(0)

But after experimenting with other values to compute derivative, I figured out that the result is -1, 0 or 1 because deriv is actually sign(-0.5*sqrt(-4*x + 1) + 0.5).

What should I do?

Both numpy and sympy are imported:

from sympy import *
import numpy as np

If I try to find derivative of a function that is not under Abs, there are no problems.


Solution

  • You probably just want the derivative of Abs to be sign. SymPy does do this, but only if it can deduce that the argument to the absolute value is real, which it can't in this case (even if x is real).

    You can make your own custom version of Abs that always uses sign pretty easily by subclassing and overriding the _eval_derivative method:

    class MyAbs(Abs):
        def _eval_derivative(self, x):
            return Derivative(self.args[0], x, evaluate=True)*sign(conjugate(self.args[0]))
    

    .

    In [110]: x = Symbol('x')
    
    In [111]: y = MyAbs(0.5-0.5*sqrt(1-4*x))
    
    In [112]: deriv = y.diff(x)
    
    In [113]: print(deriv)
    1.0*sign(-0.5*conjugate(sqrt(-4*x + 1)) + 0.5)/sqrt(-4*x + 1)
    
    In [114]: lambdify(x, deriv, 'numpy')(0.1)
    Out[114]: 1.29099444874