好的,@HYRY,这是一个很大程度上基于你的代码片段。您给了我成功所需的提示:使用“quad”而不是“quadrature”。所以我至少会投票给你的答案,但我想补充一下。
首先,您的代码运行速度很快,但比我所追求的精度差了大约 5 个位置。我在您的示例中添加了 quadtol 和 opttol 以尝试说明求积和求根精度的相互作用。我还添加了一个基于默认高容差的循环以暴露速度差异。
sin 示例在准确性方面比圆圈更敏感。我还添加了一条参数化曲线,其弧长由超几何函数给出,并且注释掉了“brentq”选项,因为 fsolve 在此示例中失败,并且在任何情况下,甚至 brentq 在此任务中都相等或更好。
“正交”很慢,但表现出预期的行为:求根速度、准确性和成功随正交容差而变化。
相比之下,“quad”似乎忽略了所要求的容差并总是产生更准确的答案。这种未经要求的准确性会很烦人或需要解释,但它在示例上的运行速度也非常快,以至于我不确定我的问题是否有趣了。谢谢!
from scipy.integrate import quad, quadrature
from scipy.optimize import fsolve, brentq
from math import cos, sin, sqrt, pi, pow
def circle_diff(t):
dx = -sin(t)
dy = cos(t)
return sqrt(dx*dx+dy*dy)
def sin_diff(t):
dx = 1
dy = cos(t)
return sqrt(dx*dx+dy*dy)
def hypergeom_diff(t):
""" y = t^5 x = t^3 """
dx = 3*t*t
dy = 5*pow(t,4)
return sqrt(dx*dx+dy*dy)
def curve_length(t0, S, length,quadtol):
integral = quad(S, 0, t0,epsabs=quadtol,epsrel=quadtol)
#integral = quadrature(S, 0, t0,tol=quadtol,rtol=quadtol, vec_func = False)
return integral[0] - length
def solve_t(curve_diff, length,opttol=1.e-15,quadtol=1e-10):
return fsolve(curve_length, 0.0, (curve_diff, length,quadtol), xtol = opttol)[0]
#return brentq(curve_length, 0.0, 3.2*pi,(curve_diff, length, quadtol), rtol = opttol)
for i in range(1000):
y = solve_t(circle_diff, 2*pi)
print 2*pi
print solve_t(circle_diff, 2*pi)
print solve_t(sin_diff, 7.640395578)
print solve_t(circle_diff, 2*pi,opttol=1e-5,quadtol=1e-3)
print solve_t(sin_diff, 7.640395578,opttol = 1e-12,quadtol=1e-6)
print "hypergeom"
print solve_t(hypergeom_diff, 2.0,opttol = 1e-12,quadtol=1e-12)
print solve_t(hypergeom_diff, 2.0,opttol = 1e-12,quadtol=1e-6)