6.数值微积分与方程求解

数值微分与数值积分

% 数值积分 (有函数式版本定积分) 方法1

% [I,n]=quad(filename,a,b,tol,trace)  基于自适应辛普森方法
% [I,n]=quadl(filename,a,b,tol,trace)  基于自适应Gauss-Lobatto方法
% filename:被积函数名; a/b:定积分下限和上限([a、b]必须是有限的,不能为inf);
% tol:控制积分精度(默认1e-6); trace控制是否展现积分过程(0不展现(默认),非0展现);
% 返回参数I即定积分的值,n为被积函数调用次数

% 分别用quad函数和quadl函数求定积分的近似值
% 并在相同的积分精度下,比较被积函数的调用次数
format long
f=@(x) 4./(1+x.^2);
[I,n]=quad(f,0,1,1e-8)
[I,n]=quadl(f,0,1,1e-8)
(atan(1)-atan(0))*4
format short

% quadl对低精度或非光滑函数效率高
% quadl对高精度和光滑函数效率高 (一般更有效)
 

% 求定积分 方法2 

% I=integral(filename,a,b)
% I:计算积分结果; filename:被积函数; a,b:定积分下限和上限,积分限可以无穷大

f=@(x)1./(x.*sqrt(1-log(x).^2));
I=integral(f,1,exp(1))

% 求定积分 方法3
% [I,err]=quadgk(filename,a,b)
% err返回近似误差范围,其他同quad.
% (a、b可以为inf或复数,若为复数,则在复平面上求积分)


f=@(x)sin(1./x)./x.^2;
I=quadgk(f,2/pi,+Inf)

扫描二维码关注公众号,回复: 2378140 查看本文章

% 数值积分(只有样本数据) 方法4

% I=trapz(x,y)      采用梯形积分法则
% 向量x,y函数关系为y=f(x)


%设x=1:6,y=[6,8,11,7,5,2],用trapz函数计算定积分。
x=1:6;
y=[6,8,11,7,5,2];
plot(x,y,'-ko');
grid on
axis([1,6,0,11]);
I1=trapz(x,y)
% 等价语句:
I2=sum(diff(x).*(y(1:end-1)+y(2:end))/2)

% 数值微分 (数值版本微分) 
% diff(y)./diff(x)即求导
% I2=sum(diff(x).*(y(1:end-1)+y(2:end))/2) 即求面积(定积分)

% 向量元素间的差分,计算后比原向量少1(列、行)
% dx=diff(x) 计算向量x的一阶向前差分,dx(i)=x(i+1)-x(i) i=1,2,3...,n-1
% dx=diff(x,n) 计算向量x的n阶向前差分,如diff(x,2)=diff(diff(x))
% dx=diff(A,n,dim) 计算矩阵A的n阶差分,dim=1(默认)按列,dim=2按行


% 设f(x)=sinx,在[0,2π]范围内随机采样,
% 计算f'(x)的近似值,并与理论值f'(x)=cosx 进行比较。
x=[0,sort(2*pi*rand(1,5000)),2*pi];
y=sin(x);
f1=diff(y)./diff(x);
f2=cos(x(1:end-1));
plot(x(1:end-1),f1,x(1:end-1),f2);
d=norm(f1-f2)   %近似值和理论值之差的范数
 

% 求二重积分的数值解
% I=integral2(filename,a,b,c,d)
% I=quad2d(filename,a,b,c,d)
% I=dblquad(filename,a,b,c,d,tol) 
% 求三重积分的数值解
% I=integral3(filename,a,b,c,d,e,f)
% I=triplequad(filename,a,b,c,d,e,f,tol)


% 分别求二重积分和三重积分
f1=@(x,y) exp(-x.^2/2).*sin(x.^2+y);
I1=quad2d(f1,-2,2,-1,1)
f2=@(x,y,z) 4*x.*z.*exp(-z.*z.*y-x.*x);
I2=integral3(f2,0,pi,0,pi,0,1)

线性方程组求解

%{
直接法:可得方程组精确解,但占用内存大,程序实现复杂;
一般适合求解低阶稠密线性方程组

迭代法:(要考虑算法的收敛性)
逐步逼近精确解,占用空间小,设计简单;
适用于求解大型稀疏矩阵线性方程组
%}

% 直接解法

% 方法一:左除运算法求解:(列主元消去法)
% Ax=b   x=A\b
% 用左除运算符求解下列线性方程组。
A=[2,1,-5,1;1,-5,0,7;0,2,1,-1;1,6,-1,-4];
b=[13,-9,6,0]';
x=A\b

% 方法二:矩阵分解法求解:
% Ax=b   % ①令A=LU,则LUx=b; 令Ux=y,则Ly=b,Ux=y; -> x=U\(L\b)
% ②PAx=Pb,令PA=LU,则LUx=Pb;   -> x=U\(L\P*b)
% [L,U]=lu(A)     矩阵A必须是方阵
% [L,U,P]=lu(A)     矩阵A必须是方阵

% 用LU分解求解上述线性方程组
% 格式①
[L,U]=lu(A);
x1=U\(L\b)  %注意括号
% 格式②
[L,U,P]=lu(A);
x2=U\(L\P*b)
 

% 迭代解法(在函数文件里):
% 方法一: 雅克比(Jacobi)迭代法
% [x,n]=jacobi(A,b,[0,0,0]',1.0e-6)
% 方法二: 高斯-赛德尔(Gauss-Serdel)迭代法
% [x,n]=gauseidel(A,b,[0,0,0]',1.0e-6)

% 分别用雅可比迭代法和高斯-赛德尔迭代法求解线性方程组
% 设迭代初值为0,迭代精度为10^(-6)

A=[4,-2,-1;-2,4,3;-1,-3,3];
b=[1,5,0]';
[x,n]=jacobi(A,b,[0,0,0]',1.0e-6)
[x,n]=gauseidel(A,b,[0,0,0]',1.0e-6)


% 分别用雅可比迭代法和高斯-赛德尔迭代法求解线性方程组
% 看是否收敛

A=[1,2,-2;1,1,1;2,2,1];
b=[9;7;6];
[x,n]=jacobi(A,b,[0;0;0],1.0e-6)
[x,n]=gauseidel(A,b,[0;0;0],1.0e-6)

函数:

% Gauss-Serdel迭代法
function [y,n]=gauseidel(A,b,x0,ep)
D=diag(diag(A));
L=-tril(A,-1); 
U=-triu(A,1);
B=(D-L)\U;
f=(D-L)\b;
y=B*x0+f;
n=1;
while norm(y-x0)>=ep
    x0=y;
    y=B*x0+f;
    n=n+1;
end

函数:

% 雅可比迭代法的函数文件jacobi.m:
% Ax=b     -> (D-L-U)x=b;
% A为非奇异方阵且主对角线元素!=0

function [y,n]=jacobi(A,b,x0,ep)
D=diag(diag(A));
L=-tril(A,-1);
U=-triu(A,1);
B=D\(L+U);
f=D\b;
y=B*x0+f;
n=1;
while norm(y-x0)>=ep
    x0=y;
    y=B*x0+f;
    n=n+1;
end

线性方程组应用举例

% 平面桁架结构受力分析问题
alpha=sqrt(2)/2;
A=[0,1,0,0,0,-1,0,0,0,0,0,0,0;
   0,0,1,0,0,0,0,0,0,0,0,0,0;
   alpha,0,0,-1,-alpha,0,0,0,0,0,0,0,0;
   alpha,0,1,0,alpha,0,0,0,0,0,0,0,0;
   0,0,0,1,0,0,0,-1,0,0,0,0,0;
   0,0,0,0,0,0,1,0,0,0,0,0,0;
   0,0,0,0,alpha,1,0,0,-alpha,-1,0,0,0;
   0,0,0,0,alpha,0,1,0,alpha,0,0,0,0;
   0,0,0,0,0,0,0,0,0,1,0,0,-1;
   0,0,0,0,0,0,0,0,0,0,1,0,0;
   0,0,0,0,0,0,0,1,alpha,0,0,-alpha,0;
   0,0,0,0,0,0,0,0,alpha,0,1,alpha,0;
   0,0,0,0,0,0,0,0,0,0,0,alpha,1];
b=[0;10;0;0;0;0;0;15;0;20;0;0;0];
f=A\b;
disp(f')

% 小行星运行轨道计算问题
xi=[1.02,0.87,0.67,0.44,0.16];
yi=[0.39,0.27,0.18,0.13,0.13];
A=zeros(length(xi));
for i=1:length(xi)
    A(i,:)=[xi(i)*xi(i),2*xi(i)*yi(i),yi(i)*yi(i),2*xi(i),2*yi(i)];
end
b=-ones(length(xi),1);
ai=A\b

% 或者:
xi=[1.02,0.87,0.67,0.44,0.16]';
yi=[0.39,0.27,0.18,0.13,0.13]';
A=[xi.*xi,2*xi.*yi,yi.*yi,2*xi,2*yi];
b=-ones(length(xi),1);
ai=A\b

f=@(x,y) 2.4645*x.^2-0.8846*x.*y+6.4917*y.^2-1.3638*x-7.2016*y+1;
h=ezplot(f,[-0.5,1.2,0,1.2]);

非线性方程组求解与函数极值计算:

% 单变量非线性方程求解
% x=fzero(filename,x0)
% filename是待求根方程左端的函数表达式,x0是迭代初值

% 求f(x)=0在x0=-5和x0=1作为迭代初值时的根。
f=@(x) x-1./x+5;
x1=fzero(f,-5)
x2=fzero(f,1)
x3=fzero(f,0.1)

x4=fsolve(f,-5,optimset('Display','off'))
x5=fsolve(f,1,optimset('Display','off'))
x6=fsolve(f,0.1,optimset('Display','off'))

subplot(1,2,1);
x=-6:0.1:1;
plot(x,f(x));


% f(x)=x^2-1=0的根
f=@(x) x.^2-1;
x=[];
x0=-0.25:0.001:0.25;
for x00=x0
    x=[x,fzero(f,x00)];
end
subplot(1,2,2);
plot(x0,x,'-o')
xlabel('初值');
ylabel('方程的根');
axis([-0.25,0.25,-1,1])
 

% 非线性方程组求解
% x=fsolve(filename,x0,option)
% x:返回的近似解; filename:待求根方程左端的函数表达式
% x0:初值; option用于设置优化工具箱优化参数,可以调用optimset函数完成


% 求下列方程组在(1,1,1)附近的解并对结果进行验证。
f=@(x) [sin(x(1))+x(2)+x(3)^2*exp(x(1)),x(1)+x(2)+x(3),x(1)*x(2)*x(3)];
f([1,1,1])
x=fsolve(f,[1,1,1],optimset('Display','off'))
f(x)   % 验证

函数:

function [c,h]=funny(x)
c=[];
h=x(2)-x(1)^2;
 

% 函数极值的计算:

% 无约束最优化问题:(只求最小值,若求最大值,改为-f(x)即可)
% [xmin,fmin]=fminbnd(filename,x1,x2,option)
% 求一元filename函数,在(x1,x2)上极小值点xmin,最小值fmin
% [xmin,fmin]=fminsearch(filename,x0,option)
% 多元函数,x0是向量,表示极值点的初值 (基于单纯性算法)
% [xmin,fmin]=fminunc(filename,x0,option)
% 多元函数 (基于拟牛顿法)

% 求函数f(x)在区间(-10,-1)和(1,10)上的最小值点。
f=@(x) x-1./x+5;
[xmin,fmin]=fminbnd(f,-10,-1)
[xmin,fmin]=fminbnd(f,1,10)

% 有约束最优化问题:
% [xmin,fmin]=fmincon(filename,x0,A,b,Aeq,beq,lb,ub,NonF,option)
% A, b, beq, lb,和ub为线性不等式约束的上、下界向量,
% A 和 Aeq 为线性不等式约束和等式约束的系数矩阵,
% filename为目标函数,NonF为非线性约束函数
% 若约束不存在,用空矩阵表示

f=@(x) 0.4*x(2)+x(1)^2+x(2)^2-x(1)*x(2)+1/30*x(1)^3;
x0=[0.5;0.5];
A=[-1,-0.5;-0.5,-1];
b=[-0.4;-0.5];
lb=[0;0];
option=optimset('Display','off');
[xmin,fmin]=fmincon(f,x0,A,b,[],[],lb,[],[],option)
 

应用举例:

% 要使每周送货车的里程最小,仓库应建在xy平面的什么位置?
a=[10,30,16.667,0.555,22.2221];
b=[10,50,29,29.888,49.988];
c=[10,18,20,14,25];
f=@(x) sum(c.*sqrt((x(1)-a).^2+(x(2)-b).^2));
[xmin,fmin]=fminsearch(f,[15,30])

% 在例5中,如果由于地域的限制,仓库必须建在曲线y=x^2上,则它应该建在何处?
% 非线性约束的函数文件funny.m:

a=[10,30,16.667,0.555,22.2221];
b=[10,50,29,29.888,49.988];
c=[10,18,20,14,25];
f=@(x) sum(c.*sqrt((x(1)-a).^2+(x(2)-b).^2));
[xmin,fmin]=fmincon(f,[15,30],[],[],[],[],[],[],'funny')

常微分方程数值求解:

% 常微分方程初值问题的数值解法
% [t,y]=ode45(filename,tspan,y0,option)
% t,y分别给出向量和相应的数值解; filename为定义f(t,y)的函数名,必须返回列向量
% tspan形式为[t0,tf],表示求解区间;     y0是初始状态向量

% 求解微分方程初值问题,并与精确解进行比较。 
f=@(t,y) (y^2-t-2)/4/(t+1);
[t,y]=ode23(f,[0,10],2);
y1=sqrt(t+1)+1;
plot(t,y,'b:',t,y1,'r');


% 常微分方程数值求解函数统一命名格式
% odennxx
% ode是Ordinar DIfferential Equation(常微分方程)的缩写
% nn是数字,代表所用方法的阶数
% xx是字母,用于标注方法的专门特征

% 求解高阶常微分方程数值解时
% 需要将它转化为一阶常微分方程组,即状态方程


% 已知一个二阶线性系统的微分方程,
% 取a=2,绘制系统的时间响应曲线和相平面图。
f=@(t,x) [-2,0;0,1]*[x(2);x(1)]; 
[t,x]=ode45(f,[0,20],[1,0]); 
subplot(2,2,1);
plot(t,x(:,2));
subplot(2,2,2);
plot(x(:,2),x(:,1));

刚性问题:

% 假如点燃一个火柴,已知火焰球简化模型,
% 分析λ的大小对方程求解过程的影响。
lamda=0.01;
f=@(t,y) y^2-y^3;
tic;[t,y]=ode45(f,[0,2/lamda],lamda);toc
disp(['ode45计算的点数' num2str(length(t))]);

lamda=1e-5;
f=@(t,y) y^2-y^3;
tic;[t,y]=ode45(f,[0,2/lamda],lamda);toc
disp(['ode45计算的点数' num2str(length(t))]);

lamda=1e-5;
f=@(t,y) y^2-y^3;
tic;[t,y]=ode15s(f,[0,2/lamda],lamda);toc
disp(['ode15s计算的点数' num2str(length(t))]);

应用举例:

% Lotka-Volterra模型
% ①:
rabbitFox=@(t,x) [x(1)*(2-0.01*x(2));x(2)*(-1+0.01*x(1))];
[t,x]=ode45(rabbitFox,[0,30],[300,150])
subplot(2,3,1);
plot(t,x(:,1),'-',t,x(:,2),'-*');
legend('x1(t)','x2(t)');
xlabel('时间');ylabel('物种数量');
grid on
subplot(2,3,2);plot(x(:,1),x(:,2))
grid on

% ②:
% 取λ=0.01, 所以稳定平衡点(1/λ,2/λ)即是(100,200),以此点作为初值时,画出其图像。
rabbitFox=@(t,x) [x(1)*(2-0.01*x(2));...
                  x(2)*(-1+0.01*x(1))];
[t,x]=ode45(rabbitFox,[0,30],[100,200]);
subplot(2,3,3);
plot(t,x(:,1),'-o',t,x(:,2),'-*');
legend('x1(t)-兔子','x2(t)-狐狸');
xlabel('时间');
ylabel('物种数量');

% 当将初始值变为(98,195)时,即向下十分接近平衡点,画出其图像。
rabbitFox=@(t,x) [x(1)*(2-0.01*x(2));...
                  x(2)*(-1+0.01*x(1))];
[t,x]=ode45(rabbitFox,[0,30],[98,195]);
subplot(2,3,4);
plot(t,x(:,1),'-o',t,x(:,2),'-*');
legend('x1(t)-兔子','x2(t)-狐狸');
xlabel('时间');
ylabel('物种数量');

% 当将初始值变为(70,150)时(向下偏离平衡点比较远时),画出其图像。
rabbitFox=@(t,x) [x(1)*(2-0.01*x(2));...
                  x(2)*(-1+0.01*x(1))];
[t,x]=ode45(rabbitFox,[0,30],[70,150]);
subplot(2,3,5);
plot(t,x(:,1),'-o',t,x(:,2),'-*');
legend('x1(t)-兔子','x2(t)-狐狸');
xlabel('时间');
ylabel('物种数量');

% 当将初始值变为(900,1600)时(向上偏离平衡点十分远时),画出其图像。
rabbitFox=@(t,x) [x(1)*(2-0.01*x(2));...
                  x(2)*(-1+0.01*x(1))];
[t,x]=ode45(rabbitFox,[0,500],[900,1600]);
plot(t,x(:,1),t,x(:,2));
legend('x1(t)-兔子','x2(t)-狐狸');
xlabel('时间');
ylabel('物种数量');

% Lotka-Volterra改进模型
% ①:在原模型下,绘制狐狸和兔子数量的时间函数曲线。
rabbitFox=@(t,x) [x(1)*(2-0.01*x(2));...
    x(2)*(-1+0.01*x(1))];
subplot(2,2,1);
plot(t,x(:,1),t,x(:,2));
legend('x1(t)-兔子','x2(t)-狐狸');
xlabel('时间');
ylabel('物种数量');
title('原模型下,狐狸和兔子数量的函数曲线');

% ②:在改进模型下,狐狸和兔子数量的时间函数曲线。
rabbitFox=@(t,x) [2*x(1)*(1-x(1)/400-0.005*x(2));...
    x(2)*(-1+0.01*x(1))];
[t,x]=ode45(rabbitFox,[0,50],[300,150]);
subplot(2,2,2);
plot(t,x(:,1),t,x(:,2));
legend('x1(t)-兔子','x2(t)-狐狸');
xlabel('时间');
ylabel('物种数量');
title('改进模型下,狐狸和兔子数量的函数曲线');

% ③:在原模型下,绘制狐狸数量相对于兔子数量的关系曲线。
rabbitFox=@(t,x) [x(1)*(2-0.01*x(2));...
    x(2)*(-1+0.01*x(1))];
[t,x]=ode45(rabbitFox,[0,50],[300,150]);
subplot(2,2,3);
plot(x(:,1),x(:,2));
xlabel('兔子数量');
ylabel('狐狸数量');
title('原模型下,狐狸数量相对于兔子数量的关系曲线');

% ④:在改进模型下,狐狸数量相对于兔子数量的关系曲线。
rabbitFox=@(t,x) [2*x(1)*(1-x(1)/400-0.005*x(2));...
    x(2)*(-1+0.01*x(1))];
[t,x]=ode45(rabbitFox,[0,50],[300,150]);
subplot(2,2,4);
plot(x(:,1),x(:,2));
xlabel('兔子数量');
ylabel('狐狸数量');
title('改进模型下,狐狸数量相对于兔子数量的关系曲线');

猜你喜欢

转载自blog.csdn.net/qq_36502291/article/details/81208035
今日推荐