【问题标题】:Find derivative of a function with Abs in python在 python 中用 Abs 查找函数的导数
【发布时间】:2013-12-28 15:34:42
【问题描述】:

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

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 的新手,所以我想我使用错误的方法来确定导数。

编辑:我打印了 deriv,这就是我得到的:

看完这个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 下的函数的导数,则没有问题。

【问题讨论】:

  • 附带说明:在x=0,您的函数不可微分。我不知道 simpy 是如何处理这个问题的。您是否尝试过其他 x 值?
  • 我做了,但总是一样:全局名称'Derivative'未定义,无论我选择什么 x。 :)
  • 我用我的设置检查了你的初始代码,我得到了错误NameError: global name 'Abs' is not defined,但前提是我选择'numpy'作为模块。没有或有('numpy','sympy') 都可以。但是,您仍然会在x=0 处收到除法错误。
  • 总是错误NameError: global name 'Derivative' is not defined
  • NameError: global name 'Abs' is not defined 是由于我的旧版本 sympy 中的一个错误,可能与您的问题无关。

标签: python-2.7 numpy sympy derivative


【解决方案1】:

这更像是一个数学问题。

>>> 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(我无法解释,因为我不知道复杂的微分)。我猜 sympy 没有实现,因此返回 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

【讨论】:

  • 您使用的是哪个版本的 python/sympy?在您使用 python 2.7 和 sympy 0.7.1.rc1 的第一个代码块中,我得到 re(x)/Abs(x) 作为 dx 的结果,这可能是我无法重现该问题的原因。
  • @Nabla SymPy 版本已经很老了。 0.7.4.1 给出了 Alex 得到的东西。
  • 另外需要注意的是,如果你打算输入数值使得平方根变得复杂,你需要输入一个具有复杂dtype的numpy数组,否则你会得到一个TypeError,因为numpy的sqrt拒绝使用负实数。
  • 这个解决方案更好更简单。谢谢!
  • 我认为我们应该重新打开这个,如果 lambdify 要在 NumPy 数组上工作,我会遇到问题。我总是得到全局名称 Abs 或 MyAbs 未定义。我发布了一个新问题
【解决方案2】:

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

您可以通过子类化和覆盖_eval_derivative 方法,轻松创建自己的Abs 自定义版本,该版本始终使用sign

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    相关资源
    最近更新 更多