我正在编写一个具有数学函数作为属性的类,例如f。
f是:
我的班级看起来像:
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
Run Code Online (Sandbox Code Playgroud)
我使用二分法来反转弧长方法,但我正在考虑更改此方法以使用一种scipy.optimize求根方法来提高速度。我是 scipy 的新手,必须承认我的数学有点生锈了...Scipy 让我在brentq、brenh、ridder和bisect之间进行选择newton。
有人能为我指出最适合这种情况的方法吗?或者也许有一个更好的图书馆?
我不是 Python 专家,但我从数值分析中知道,在您列出的方法(Brent、二分法、Ridder 方法和 Newton-Raphson)中,Brent 方法通常是单个实变量的通用实标量函数f的首选X。正如您可以在此处阅读的那样,如果f是连续的并且该方法应用于f(a)f(b) <0 的区间 [a,b],则布伦特方法可以保证收敛到零,就像二分法一样。对于许多表现良好的函数,Brent 方法的收敛速度比二分法快得多,但在某些不幸的情况下,它可能需要N^2次迭代,其中N是达到给定容差的二分法迭代次数。
另一方面,牛顿法收敛时通常比布伦特法收敛得更快,但也有根本不收敛的情况。对于相同的函数,牛顿法可能会也可能不会收敛,这也取决于起点和根之间的距离。因此,在通用代码中使用它的风险更大。
brentq关于和 之间的选择brenth,看起来它们应该非常相似,第一个经过了更严格的测试。因此,您可以选择brentq,或者,如果您有时间,可以在它们之间进行一些基准测试。