Python Tanh-sinh求积数值积分法收敛到错误值
我正试图编写一个Python程序,使用Tanh sinh求积计算以下值: 但是,尽管程序收敛到一个合理的值,在任何情况下都没有错误,但它并没有收敛到正确的值(对于这个特定的积分是pi),我也找不到问题 该程序没有要求所需的精度水平,而是要求所需的函数求值数量,以便于与更简单的积分方法进行收敛性比较。由于使用了近似值,评估的数量需要是奇数 有人能告诉我可能做错了什么吗Python Tanh-sinh求积数值积分法收敛到错误值,python,python-2.7,numerical-integration,Python,Python 2.7,Numerical Integration,我正试图编写一个Python程序,使用Tanh sinh求积计算以下值: 但是,尽管程序收敛到一个合理的值,在任何情况下都没有错误,但它并没有收敛到正确的值(对于这个特定的积分是pi),我也找不到问题 该程序没有要求所需的精度水平,而是要求所需的函数求值数量,以便于与更简单的积分方法进行收敛性比较。由于使用了近似值,评估的数量需要是奇数 有人能告诉我可能做错了什么吗 import math def func(x): # Function to be integrated, with
import math
def func(x):
# Function to be integrated, with singular points set = 0
if x == 1 or x == -1 :
return 0
else:
return 1 / math.sqrt(1 - x ** 2)
# Input number of evaluations
N = input("Please enter number of evaluations \n")
if N % 2 == 0:
print "The number of evaluations must be odd"
else:
print "N =", N
# Set step size
h = 2.0 / (N - 1)
print "h =", h
# k ranges from -(N-1)/2 to +(N-1)/2
k = -1 * ((N - 1) / 2.0)
k_max = ((N - 1) / 2.0)
sum = 0
# Loop across integration interval
while k < k_max + 1:
# Compute abscissa
x_k = math.tanh(math.pi * 0.5 * math.sinh(k * h))
# Compute weight
numerator = 0.5 * h * math.pi * math.cosh(k * h)
denominator = math.pow(math.cosh(0.5 * math.pi * math.sinh(k * h)),2)
w_k = numerator / denominator
sum += w_k * func(x_k)
k += 1
print "Integral =", sum
导入数学
def func(x):
#要集成的函数,奇点集=0
如果x==1或x==1:
返回0
其他:
返回1/math.sqrt(1-x**2)
#输入评价数
N=输入(“请输入评估数量\N”)
如果N%2==0:
打印“评估数量必须为奇数”
其他:
打印“N=”,N
#设置步长
h=2.0/(N-1)
打印“h=”,h
#k的范围从-(N-1)/2到+(N-1)/2
k=-1*((N-1)/2.0)
k_max=((N-1)/2.0)
总和=0
#跨积分区间的循环
当k
值得一提的是,Scipy具有数值积分功能
比如说,
from scipy import integrate
check = integrate.quad(lambda x: 1 / math.sqrt(1 - x ** 2), -1, 1)
print 'Scipy quad integral = ', check
给出了结果
Scipy四元积分=(3.141592653589591,6.200897573194197e-10)
其中元组中的第二个数字是绝对误差
也就是说,我能够让您的程序进行一些调优(尽管这只是初步尝试):
1) 根据建议将步长h设置为0.0002(大约1/2^12)
但是请注意——这篇论文实际上建议迭代地改变步长——使用固定的步长,您将达到sinh或cosh增长太大而无法获得足够大的kh值的点。可能最好尝试根据该文件的方法实施
但坚持手头的问题
2) 确保设置了足够的迭代次数使积分真正收敛,即足够的迭代次数使math.fabs(w_k*func(x_k))<1.0e-9
通过这些调整,我能够通过30000次以上的迭代,使积分收敛到pi的正确值,即4个有效数字
例如,对于31111次迭代,计算的pi值为3.14159256208
经过修改的示例代码(注意,我将sum替换为thesum,sum是Python内置函数的名称):
导入数学
def func(x):
#要集成的函数,奇点集=0
如果x==1或x==1:
返回0
其他:
返回1/math.sqrt(1-x**2)
#输入评价数
N=输入(“请输入评估数量\N”)
如果N%2==0:
打印“评估数量必须为奇数”
其他:
打印“N=”,N
#设置步长
#h=2.0/(N-1)
h=0.0002#(1/2^12)
打印“h=”,h
#k的范围从-(N-1)/2到+(N-1)/2
k=-1*((N-1)/2.0)
k_max=((N-1)/2.0)
thesum=0
#跨积分区间的循环
实际电阻=0
当kk最大值/2:
打印“迭代=%d,myepsilon=%g”%(实际迭代,myepsilon)
k+=1
实际电阻+=1
打印“实际迭代次数=”,实际迭代次数
打印“Integral=”,thesum
我认为部分问题可能是由于范围和步长。我修改了密码
因此,您可以分别输入范围和步长,并重写一些数学公式。它似乎给出了正确的答案。尝试将示例5和0.1作为输入
一个特殊的问题是计算math.cosh(0.5*math.pi*math.sinh(k*h))
ask*h
get largemath.sinh(k*h)
呈指数增长,计算其中的math.cosh可能很困难。
输入数学
def func(x):
# return 1 # very simple test function
# Function to be integrated, with singular points set = 0
if x == 1 or x == -1 :
return 0
else:
return 1 / math.sqrt(1 - x ** 2)
# Input number of evaluations
N = input("Please enter max value for range \n")
print "N =", N
h = input("Please the step size \n")
print "h =", h
k = -N
k_max = N
sum = 0
count = 0
print "k ", k , " " , k_max
# Loop across integration interval
while k < k_max + 1:
# Compute abscissa
v = k
u = math.pi * 0.5 * math.sinh(v)
x_k = math.tanh(u)
#print u
# Compute weight
numerator = 0.5 * math.pi * math.cosh(v)
csh = math.cosh(u)
denominator = csh*csh
w_k = numerator / denominator
print k, v, x_k , w_k
sum += w_k * func(x_k)
count += 1
k += h # note changed
res = sum * h
print "Integral =", sum * h
def func(x):
#返回1#非常简单的测试函数
#要集成的函数,奇点集=0
如果x==1或x==1:
返回0
其他:
返回1/math.sqrt(1-x**2)
#输入评价数
N=输入(“请输入范围的最大值\N”)
打印“N=”,N
h=输入(“请输入步长\n”)
打印“h=”,h
k=-N
k_max=N
总和=0
计数=0
打印“k”,k,”,k_max
#跨积分区间的循环
当k
您必须意识到+1和-1是被积函数的奇点,f(x)-->+无穷大
为x-->+1,-1
。因此,您可以在远离边界点的地方使用您最喜欢的求积公式,但您必须根据f(x)
在边界点附近的局部展开计算出一个特殊的求积
方法示意图:
epsilon
def func(x):
# return 1 # very simple test function
# Function to be integrated, with singular points set = 0
if x == 1 or x == -1 :
return 0
else:
return 1 / math.sqrt(1 - x ** 2)
# Input number of evaluations
N = input("Please enter max value for range \n")
print "N =", N
h = input("Please the step size \n")
print "h =", h
k = -N
k_max = N
sum = 0
count = 0
print "k ", k , " " , k_max
# Loop across integration interval
while k < k_max + 1:
# Compute abscissa
v = k
u = math.pi * 0.5 * math.sinh(v)
x_k = math.tanh(u)
#print u
# Compute weight
numerator = 0.5 * math.pi * math.cosh(v)
csh = math.cosh(u)
denominator = csh*csh
w_k = numerator / denominator
print k, v, x_k , w_k
sum += w_k * func(x_k)
count += 1
k += h # note changed
res = sum * h
print "Integral =", sum * h
f(x) = 1/sqrt(1-x) * (a0 + a1*(1-x) + a2*(1-x)^2 + ...)
= f0(x-1) + f1(x-1) + f2(x-1) + ..
I = I_smooth + I_singular
from mpmath import *
mp.dps = 100
h = mpf(2**-12);
def weights(k):
num = mpf(0.5)*h*pi*cosh(k*h)
den = cosh(mpf(0.5)*pi*sinh(k*h))**2
return (num/den)
def abscissas(k):
return tanh(mpf(0.5)*pi*sinh(k*h))
def f(x):
return 1/sqrt(1 - mpf(x)**2)
N = 20000
result = 0
for k in range(-N, N+1):
result = result + weights(k)*f(abscissas(k))
print result - pi
-3.751800610920472803216259350430460844457732874052618682441090144344372471319795201134275503228835472e-45
3.1415926533203944 -2.693987255497632e-10