在python中找到具有Abs的函数的导数

时间:2013-12-28 15:34:43

标签: python-2.7 numpy sympy derivative

我想用0.1来计算y=Abs(0.5-0.5*sqrt(1-4*x))的导数,使用python。 这是我的代码:

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)

这就是我得到的:

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

我是sympynumpy的新手,所以我想我使用错误的方法来确定派生词。

编辑:我打印了衍生物,这就是我得到的:

enter image description here

阅读此http://docs.sympy.org/dev/modules/functions/elementary.html后,我已尝试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)

但在尝试使用其他值来计算导数后,我发现结果是-1,0或1,因为deriv实际上是sign(-0.5*sqrt(-4*x + 1) + 0.5)

我该怎么办?

导入numpy和sympy:

from sympy import *
import numpy as np

如果我试图找到不属于Abs的函数的导数,则没有问题。

2 个答案:

答案 0 :(得分:4)

这是一个数学问题,而不是其他任何问题。

>>> import sympy
>>> x = sympy.symbols('x')
>>> def f(x):
...  return abs(x)
... 
>>> dx = f(x).diff(x)
>>> dx
(re(x)*Derivative(re(x), x) + im(x)*Derivative(im(x), x))/Abs(x)

请注意,有一个真实的部分和一个想象的部分。 abs(x)在每个实数x处是可微分的,但是为零。然而,当涉及到复杂的值时,我有issues(由于我不知道复杂的区分,我无法解释)。我猜syy没有实现,因此返回Derivative(f)而不是f的实际导数。

如果您只使用实数,请使用x = sympy.symbols('x', real=True)

>>> import sympy
>>> x = sympy.symbols('x', real=True)
>>> def f(x):
...  return abs(0.5-0.5*(1-4*x)**0.5)
... 
>>> dx = f(x).diff(x)
>>> dx
(1.0*(-0.5*re((-4*x + 1)**0.5) + 0.5)*re((-4*x + 1)**(-0.5)) - 0.5*im((-4*x + 1)**(-0.5))*im((-4*x + 1)**0.5))/Abs(-0.5*(-4*x + 1)**0.5 + 0.5)
>>> dx_ = sympy.lambdify(x, dx)
>>> dx_(0.1)
1.2909944487358056

答案 1 :(得分:0)

您可能只希望Abs的衍生产品为sign。 SymPy确实这样做了,但前提是它可以推断出绝对值的参数是真实的,在这种情况下它是不可能的(即使x是真的)。

您可以通过继承和覆盖Abs方法轻松制作自己的sign自定义版本,并始终轻松使用_eval_derivative

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