这是《The Numerical Solution of Integral Equations of the Second Kind》书上的例题代码实现,课本P37-P41的例题:插值退化核逼近
# -*- coding: utf-8 -*- """ Created on Mon Apr 9 21:42:44 2018 @author: shaowu 本代码主要运用Degenerate kernel method实现Fredholm integral equations of the second kind的求解,方程如下: lamda*x(t)-integrate(K(t,s)*x(s))ds=y(t),a=0<=t<=b,K(t,s)取exp(s*t) 首先,我们给定两个精确解exp(-t)cos(t)和sqrt(t),求出其对应的y(t),然后再来反解x(t).更详细说明可 参见《The Numerical Solution of Integral Equations of the Second Kind》P30-34. """ import sympy as sp import scipy as scp import numpy as np import pandas as pd import numpy.linalg as LA import matplotlib.pyplot as plt from scipy.special.orthogonal import p_roots import time start_time=time.time() def gauss_xw(m=400):##默认用400个点求高斯——勒让德节点xi和权weight,并返回x和w数组 x,w=p_roots(m+1) return x,w def gauss_solve2_b(x,w,lamda,a,b,n): #参数n>=1 """ 求解课本2.3.41式中的右端项, 利用gauss_Legendre """ c=(b-a)/2 s=(b-a)/2*x+(a+b)/2 #把区间变化到[-1,1] h=(b-a)/(n) t=[a+i*h for i in range(0,n+1)] #等距划分a=t0<t1<...<tn=b return [((w*c*lamda*scp.exp(-s)*scp.cos(s)*scp.exp(s*i)).sum()- sum([c*w[k]*sum([c*w[j]*scp.exp(s[k]*s[j])*scp.exp(-s[j])*scp.cos(s[j])*scp.exp(i*s[k]) for j in range(len(s))]) for k in range(len(s))])) for i in t],\ [((w*c*lamda*scp.sqrt(s)*scp.exp(s*i)).sum()- sum([c*w[k]*sum([c*w[j]*scp.exp(s[k]*s[j])*scp.sqrt(s[j])*scp.exp(i*s[k]) for j in range(len(s))]) for k in range(len(s))])) for i in t] def hat_f(j,x,a,b): """ 定义hat函数(下面的积分是直接调用这个函数,建议分段来积分,而不是带有绝对值abs函数在里面) """ h=(b-a)/(n) t=[a+i*h for i in range(0,n+1)] if j==0: if x>=t[0] and x<=t[1]: return 1-abs(x-t[0])/h else: return 0 if j==n: if t[n-1]<=x and x<=t[n]: return 1-abs(x-t[n])/h else: return 0 if j>0 and j<n: if t[j-1]<=x and x<=t[j+1]: return 1-abs(x-t[j])/h else: return 0 def elements_of_matrix(x,w,i,j,t,a,b,n):# """ 求系数矩阵中的元素, (其中的hat_f函数建议分段来积分,这里我直接调用,对第一个解,误差没有影响的,但对第二个的误差有影响) """ #h=(b-a)/(n) if j==0: #c=h/2;s=h/2*x+(t[0]+t[1])/2 #区间变化 return -scp.integrate.quad(lambda x:hat_f(j,x,a,b)*scp.exp(t[i]*x),t[0],t[1])[0] #return -sum([w[k]*c*hat_f(j,s[k],a,b)*scp.exp(t[i]*s[k]) for k in range(len(s))]) elif j==n: #c=h/2;s=h/2*x+(t[n-1]+t[n])/2 #区间变化 return -scp.integrate.quad(lambda x:hat_f(j,x,a,b)*scp.exp(t[i]*x),t[n-1],t[n])[0] #return -sum([w[k]*c*hat_f(j,s[k],a,b)*scp.exp(t[i]*s[k]) for k in range(len(s))]) else: #c=h;s=h*x+(t[j-1]+t[j+1])/2 #区间变化 return -scp.integrate.quad(lambda x:hat_f(j,x,a,b)*scp.exp(t[i]*x),t[j-1],t[j+1])[0] #return -sum([w[k]*c*hat_f(j,s[k],a,b)*scp.exp(t[i]*s[k]) for k in range(len(s))]) def solve2_AC(x,w,lamda,a,b,n,f1,f2): """ 求解C """ A=[] h=(b-a)/(n) t=[a+i*h for i in range(0,n+1)] #等距划分a=t0<t1<...<tn<tn+1=b # A.append([-scp.integrate.quad(lambda x:(1-abs(x-t[j])/h)*scp.exp(t[0]*x),t[0],t[1])[0] for j in range(n+1)]) #计算i=0时的 for i in range(0,n+1): # guodu=[-scp.integrate.quad(lambda x:(1-abs(x-t[0])/h)*scp.exp(t[i]*x),t[0],t[1])[0]]+\ guodu=[elements_of_matrix(x,w,i,j,t,a,b,n) for j in range(0,n+1)]#+\ # [-scp.integrate.quad(lambda x:(1-abs(x-t[n])/h)*scp.exp(t[i]*x),t[n-1],t[n])[0]] A.append(guodu) # A.append([-scp.integrate.quad(lambda x:(1-abs(x-t[j])/h)*scp.exp(t[n]*x),t[n-1],t[n])[0] for j in range(n+1)]) #计算i=n时的 A=np.array(A) for i in range(0,n+1): A[i][i]=lamda+A[i][i] C1=np.linalg.solve(A,f1) #求解C C2=np.linalg.solve(A,f2) return C1,C2 def solve2_xn(lamda,a,b,n,c1,c2): """ 这里计算xn(t);xnt1和xnt2分别对应xt1=exp(-t)*cos(t)和xt2=sqrt(t)的情况. 为了计算范数,这里把t属于[a,b]进了行离散 结果返回误差E1和E2 """ tt=np.array([i for i in np.arange(a+0.1,b,0.1)]) xt1=scp.exp(-tt)*scp.cos(tt) ##第一个精确解xt1 xt2=scp.sqrt(tt) ##第二个精确解xt2 xnt1=[];xnt2=[] #这部分代码是用scipy中的数值积分求对应的y1和y2,和上一部分的相差不大 for j in tt: m1=0;m2=0 for i in range(0,n+1): m1=m1+c1[i]*hat_f(i,j,a,b) m2=m2+c2[i]*hat_f(i,j,a,b) xnt1.append((m1+lamda*scp.exp(-j)*scp.cos(j)- scp.integrate.quad(lambda x:scp.exp(x*j)*scp.exp(-x)*scp.cos(x),a,b)[0])/lamda) xnt2.append((m2+lamda*scp.sqrt(j)- scp.integrate.quad(lambda x:scp.exp(x*j)*scp.sqrt(x),a,b)[0])/lamda) E1=LA.norm(xt1-xnt1,np.inf) ##计算无穷范数 E2=LA.norm(xt2-xnt2,np.inf) """ #如果n=10,那么就画误差图 plt.plot(tt,xt1,'*--',tt,xnt1,'-') plt.plot(t,xt2-xnt2,'--r',label='x2') plt.title('Figure1.(where a=0,b=1,n=10,lambda=5)') plt.xlabel('t') plt.ylabel('error') plt.legend() """ return E1,E2 if __name__ == '__main__': print('******************************程序入口*******************************') lamda=int(input('pleas input lambda:')) n=int(input('please input degree n:')) a=int(input('please input the left value of interval:')) b=int(input('please input the right value of interval:')) m=int(input('please input the node of Gauss_Legendre:')) print('计算中...') x,w=gauss_xw(m) f1,f2=gauss_solve2_b(x,w,lamda,a,b,n) C1,C2=solve2_AC(x,w,lamda,a,b,n,f1,f2) E1,E2=solve2_xn(lamda,a,b,n,C1,C2) print('all_cost_time:',time.time()-start_time)
运行结果:
自己试一试就出来了,,,