Python Tanh-sinh求积数值积分法收敛到错误值

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

我正试图编写一个Python程序,使用Tanh sinh求积计算以下值:

但是,尽管程序收敛到一个合理的值,在任何情况下都没有错误,但它并没有收敛到正确的值(对于这个特定的积分是pi),我也找不到问题

该程序没有要求所需的精度水平,而是要求所需的函数求值数量,以便于与更简单的积分方法进行收敛性比较。由于使用了近似值,评估的数量需要是奇数

有人能告诉我可能做错了什么吗

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))
as
k*h
get large
math.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