【发布时间】:2016-05-06 22:15:53
【问题描述】:
我正在编写一个具有数学函数作为属性的类,例如 f。
f 是:
- 在实际段上定义 [-w;+w]
- 正且以实 H 为界
- 偶数(对于 [-w;+w] 中的所有 x,f(x)=f(-x))和 f(w)=f(-w)=0
- 在 [-w;+w] 上可微,其导数在 [-w;0] 上为正且连续
我的班级看起来像:
from scipy.misc import derivative
from scipy.integrate import quad
from math import cosh, sqrt
class Function(object):
w = 1.
PRECISION = 1e-6
def f(self, x):
'''This is an example but f could be
any math function matching requirments above.
'''
return 0.5+1.07432*(1-cosh(x/1.07432))
def deriv_f(self, x):
return derivative(self.f, x, self.PRECISION)
def x_to_arc_length(self, x):
def func(x):
return sqrt(1+self.deriv_f(x)**2)
return quad(func, -self.w, x)[0]
def arc_length_to_x(self, L):
bound = [-self.w, self.w]
while bound[1]-bound[0] > self.PRECISION:
mid= sum(bound)/2
bound[(self.x_to_arc_length(mid)-L > 0)] = mid
return sum(bound)/2
我使用二等分法来反转弧长方法,但我正在考虑将其更改为 scipy.optimize 寻根方法之一以提高速度。
我是 scipy 的新手,必须承认我的数学有点生锈......
Scipy 让我在 brentq、brenh、ridder、bisect 和 newton 之间进行选择。
谁能指出最适合这种情况的方法?或者也许有更好的图书馆?
【问题讨论】:
-
试试看?为准确性设置试验,为速度设置路径,并比较各种方法。小心过早的优化。
-
@Evert :澄清一下,f 在我的问题代码中设置为悬链线,但可以设置为符合要求的任何函数。我可以尝试一些函数,但我希望有一个数学方法来解决这个问题。我修改了问题以明确 f 是一个例子。
-
我知道的很少
python,但在数值分析中,通常建议使用布伦特方法来寻找标量函数的根。看起来scipy教程与this suggestion 一起使用(在链接页面中搜索“根查找”)。牛顿法在特定情况下可能更快,但通常更容易出错。请记住,对于所有这些方法,除了 Newton,您需要在输入中提供f更改符号的区间的极值。 -
感谢 DeltaV,我相信这就是我的问题的答案。我在 Wolfram.mathworld 上找到了这个描述:mathworld.wolfram.com/BrentsMethod.html。这看起来比简单的二分法好多了!
brenth是二次方brentq的双曲线版本。看来他们是相当的(docs.scipy.org/doc/scipy-0.14.0/reference/generated/…)。值得对它进行基准测试还是我应该坚持brentq? -
@DeltaIV:非常感谢。我会看看我是否有时间研究这个,因为这些方法现在并不重要,还有很多工作要做......你为什么不发布你的 cmets 作为答案,以便我可以接受它?