• 【Matlab】数值微积分与方程求解


    数值微积分与方程求解

    数值微分

    dx=diff(x):计算向量x的一阶向前差分,dx(i)=x(i+1)-x(i),i=1,2,…,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]; % 确保初始为0,末尾为2Π而已
    y=sin(x);
    f1=diff(y)./diff(x); % 差分模拟实现求导
    f2=cos(x(1:end-1));
    subplot(121)
    plot(x(1:end-1),f2, 'r'); % 数值解
    subplot(122)
    plot(x(1:end-1),f1, 'g'); % 解析解
    d=norm(f1-f2) % 欧氏距离,即平方和开根
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-But936LT-1655005481084)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210905211315389.png)]

    数值积分

    数值积分基本原理:牛顿-莱布尼兹公式$\int_a^b f(x),dx =F(b)-F(a) $

    数值积分的实现:

    • 基于自适应辛普森方法

      [I, n]=quad(filename, a, b, tol, trace)

    • 基于自适应Gauss-Lobatto方法

      [I, n]=quadl(filename, a, b, tol, trace)

      参数解释:

      filename是被积函数名或文件名或句柄;a和b分别是定积分的下限和上限,积分限[a, b]必须是有限的,不能为无穷大( lnf ) ;tol用来控制积分精度,默认时取tol=10e-6;trace控制是否展现积分过程,若取非0则展现积分过程,取0则不展现,默认时取trace=0;返回参数I即定积分的值,n为被积函数的调用次数。

    I = ∫ 0 1 4 1 + x 2   d x I=\int_0^1 \frac{4}{1+x^2}\,dx I=011+x24dx

    format long;
    f = @(x) 4./(1+x.^2);
    [I, n]=quad(f, 0, 1, 1e-8) % quad函数
    [I, n]=quadl(f, 0, 1, 1e-8) % quadl函数
    (atan(1) - atan(0))*4 % 直接求解,解析解
    
    • 1
    • 2
    • 3
    • 4
    • 5

    结果如下:

    I =
    
       3.141592653733437
    
    n =
    
        61 % 调用quad时被积函数执行次数
    
    I =
    
       3.141592653589806
    
    n =
    
        48 % 调用quadl时被积函数执行次数,因此此函数执行效率高
    
    ans =
    
       3.141592653589793
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 基于全局自适应积分方法

      I = integral(filename, a, b)

      参数解释:

      l是计算得到的积分;filename是被积函数;a和b分别是定积分的下限和上限,积分限可以为无穷大。

    求定积分 I = ∫ 1 e 1 x 1 − l n 2 x   d x I = \int_1^e \frac{1}{x\sqrt{1-ln^2x}}\,dx I=1ex1ln2x 1dx

    I = integral(@(x)1./(x.*sqrt(1-log(x).^2)), 1, exp(1)); % 1.570796326795570
    
    • 1
    • 基于自适应高斯-克朗罗德方法

      ll, err]=quadgk(filename, a, b)
      参数解释:err返回近似误差范围,其他参数的含义和用法与quad函数相同。积分上下限可以是无穷大(-Inf或Inf ),也可以是复数。如果积分上下限是复数,则quadgk函数在复平面上求积分。

    • 基于梯形积分法

      应用场景:已知样本点,求样本点构成函数的积分

      调用格式:I = trapz(x, y),向量x、y定义函数关系 y=f(x)

      实现原理:

      ​ 已知 ( x i , y i )   ( i = 1 , 2 , . . . , n ) (x_i, y_i) \space (i=1,2,...,n) (xi,yi) (i=1,2,...,n),且 a = x 1 < x 2 < . . . < x n = b a=x_1<x_2<...<x_n=b a=x1<x2<...<xn=b,求 I = ∫ a b f ( x )   d x I=\int_a^b f(x)\,dx I=abf(x)dx

      ​ trapz函数采用梯形积分法则,积分的近似值为: I = ∑ i = 1 n − 1 h i y i + 1 + y i 2 I=\sum_{i=1}^{n-1} h_i\frac{y_{i+1}+y_i}{2} I=i=1n1hi2yi+1+yi,其中 h i = x i + 1 − x i h_i=x_{i+1}-x_i hi=xi+1xi

      ​ 可以用以下语句实现:sum(diff(x).*(y(1:end-1)+y(2:end))/2)

    %% 设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) % 35
    I2=sum(diff(x).*(y(1:end-1)+y(2:end))/2) % 35
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DwKhTayl-1655005481086)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210905214714468.png)]

    多重积分的数值求解

    求二重积分的数值解

    I = ∫ c d ∫ a b f ( x , y )   d x d y I=\int_c^d\int_a^b f(x, y)\,dxdy I=cdabf(x,y)dxdy

    l=integral2(filename,a,b,c,d)

    l=quad2d(filename,a,b,c,d)

    l=dblquad(filename,a,b,c,d,tol)

    求三重积分的数值解

    I = ∫ e f ∫ c d ∫ a b f ( x , y , z )   d x d y d z I=\int_e^f\int_c^d\int_a^b f(x, y, z)\,dxdydz I=efcdabf(x,y,z)dxdydz

    l=integral3(filename,a,b,c,d,e,f)

    l=triplequad(filename,a,b,c,d,e,f,tol)

    I 1 = ∫ − 1 1 ∫ − 2 2 e − x 2 / 2 s i n ( x 2 + y )   d x d y I1=\int_{-1}^{1}\int_{-2}^2 e^{-x^2/2}sin(x^2+y)\,dxdy I1=1122ex2/2sin(x2+y)dxdy I = ∫ 0 1 ∫ 0 π ∫ 0 π 4 x z e − z 2 y − x 2   d x d y d z I=\int_0^1\int_0^\pi\int_0^\pi 4xze^{-z^2y-x^2}\,dxdydz I=010π0π4xzez2yx2dxdydz

    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)
    
    • 1
    • 2
    • 3
    • 4

    结果如下:

    I1 =
    
       1.574498141468206
    
    I2 =
    
       1.732762223027684
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    线性方程组求解

    直接法

    不考虑舍入误差的情况下,通过有限步的矩阵初等运算来求得方程组的精确解

    1) 利用左除运算符直接求解

    A x = b      ⟶      x = A \ b Ax=b\space\space\space\space\longrightarrow\space\space\space\space x=A\verb|\|b Ax=b        x=A\b

    注意:

    1. 若矩阵 A A A是奇异矩阵或接近奇异,则MATLAB会给予警告。(奇异矩阵,即非满秩矩阵,亦即行列式为0的矩阵)
    2. 尽量不要使用左乘逆矩阵来实现左除,计算量相对大些

    求解方程组 { 2 x 1 + x 2 − 5 x 3 + x 4 = 13 x 1 − 5 x 2 + 7 x 4 = − 9 2 x 2 + x 3 − x 4 = 6 x 1 + 6 x 2 − x 3 − 4 x 4 = 0 \left\{

    2x1+x25x3+x4=13x15x2+7x4=92x2+x3x4=6x1+6x2x34x4=0
    \right. 2x1+x25x3+x4=13x15x2+7x4=92x2+x3x4=6x1+6x2x34x4=0

    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
    
    • 1
    • 2
    • 3

    结果如下:

    x =
    
      -66.5556
       25.6667
      -18.7778
       26.5556
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2) 利用矩阵分解求解线性方程组

    将一个给定的矩阵分解成若干个特殊类型矩阵的乘积,从而将一个一般的矩阵计算问题转化为几个易求的特殊矩阵的计算问题。此方法的优点是运算速度快,节省存储空间。

    LU分解

    (只介绍LU分解)

    基本思想:将一个n阶矩阵表示为一个下三角矩阵和一个上三角矩阵的乘积(线性代数中已经证明只要方阵是非奇异的,LU分解总是可以进行的)

    实现过程:

    ​ 设 A = L U A=LU A=LU是一个LU分解,线性方程组 A x = b Ax=b Ax=b可以写成 L U x = b LUx=b LUx=b

    ​ 令 U x = y Ux=y Ux=y,则原线性方程组转化为两个三角形方程组 { L y = b U x = y \left\{

    Ly=bUx=y
    \right. {Ly=bUx=y

    ​ 对于这个三角方程组,我们先对上面的方程进行求解,得到 y y y,再对下面的方程进行求解,得到 x x x

    lu函数

    • [L,U]=lu(A):产生一个上三角阵U和一个变换形式的下三角阵L,使之满足A=LU。注意,这里的矩阵A必须是方阵。此情况下,得到的L往往不是下三角阵,但可以通过行列交换操作得到下三角阵。

      求解过程: A x = b    ⟶    L U x = b    ⟶    x = U \ ( L \ b ) Ax=b\space\space \longrightarrow\space \space LUx=b \space \space \longrightarrow \space\space x=U\verb|\|(L\verb|\|b) Ax=b    LUx=b    x=U\(L\b)

    • [L,U,P]=lu(A):产生一个上三角阵U和一个下三角阵L以及一个置换矩阵P,使之满足PA=LU。同样,矩阵A必须是方阵。

      求解过程: A x = b    ⟶    P A x = P b    → P A = L U    L U x = P b    ⟶    x = U \ ( L \ P ∗ b ) Ax=b\space\space \longrightarrow\space \space PAx=Pb \space \space \xrightarrow{PA=LU} \space\space LUx=Pb \space \space\longrightarrow \space\space x=U\verb|\|(L\verb|\|P*b) Ax=b    PAx=Pb  PA=LU   LUx=Pb    x=U\(L\Pb)

    求解方程组
    { 2 x 1 + x 2 − 5 x 3 + x 4 = 13 x 1 − 5 x 2 + 7 x 4 = − 9 2 x 2 + x 3 − x 4 = 6 x 1 + 6 x 2 − x 3 − 4 x 4 = 0 \left\{

    2x1+x25x3+x4=13x15x2+7x4=92x2+x3x4=6x1+6x2x34x4=0
    \right. 2x1+x25x3+x4=13x15x2+7x4=92x2+x3x4=6x1+6x2x34x4=0

    A=[2,1,-5,1;1,-5,0,7;0,2,1,-1;1,6,-1,-4];
    b=[13,-9,6,0]';
    [L,U]=lu(A);
    x1 = U\(L\b)
    [L,U,P]=lu(A);
    x2 = U\(L\P*b)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    结果如下:

    x1 =
    
      -66.5556
       25.6667
      -18.7778
       26.5556
    
    x2 =
    
      -66.5556
       25.6667
      -18.7778
       26.5556
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    迭代法

    给定解的初始值,按照一定的迭代算法进行逐步逼近求出更精确的近似解的方法

    雅可比迭代法

    A x = b → A = D − L − U ( D − L − U ) x = b Ax=b\xrightarrow{A=D-L-U}(D-L-U)x=b Ax=bA=DLU (DLU)x=b

    其中, D = [ a 11 a 22 ⋱ a n n ] D=\left[

    a11a22ann
    \right] D=a11a22ann L = − [ 0 a 21 0 ⋮ ⋱ ⋱ a n 1 ⋯ a n , n − 1 0 ] L=-\left[
    0a210an1an,n10
    \right]
    L=0a21an10an,n10
    U = − [ 0 a 12 ⋯ a 1 n 0 ⋱ ⋮ ⋱ a n − 1 , n 0 ] U=-\left[
    0a12a1n0an1,n0
    \right]
    U=0a120a1nan1,n0

    求解公式为 x = D − 1 ( L + U ) x + D − 1 b x=D^{-1}(L+U)x+D^{-1}b x=D1(L+U)x+D1b

    与之对应的迭代公式为 x ( k + 1 ) = D − 1 ( L + U ) x ( k ) + D − 1 b → B = D − 1 ( L + U ) , f = D − 1 b x ( k + 1 ) = B x ( k ) + f x^{(k+1)}=D^{-1}(L+U)x^{(k)}+D^{-1}b \xrightarrow{B=D^{-1}(L+U),f=D^{-1}b} x^{(k+1)}=Bx^{(k)}+f x(k+1)=D1(L+U)x(k)+D1bB=D1(L+U)f=D1b x(k+1)=Bx(k)+f

    % 雅可比迭代法的.m文件
    function [y,n] = jacobi (A,b,x0,ep) % A是系数矩阵,b是列向量,x0是初始向量,ep是控制结束时的精度,y是结果,n是迭代次数
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    代码中的x0参数为初始向量,从此开始迭代,下面对初始向量如何选取进行解释(来自百度网友):

    一般来说初始值只会影响求解问题的速度问题,如果迭代方程没错的话,如果初始解较接近要的结果时,迭代的次数会较少,如果选取的初始解距离满意解远时,只会增加迭代次数而不会说解不出来,所以一般来说可以按经验取初始解,假如真的找不到的话,可以随便带一,俩个进去。

    高斯-赛德尔迭代法

    只附代码

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    用上述两种迭代方式求解方程组 { 4 x 1 − 2 x 2 − x 3 = 1 − 2 x 1 + 4 x 2 + 3 x 4 = 5 − x 2 − 3 x 3 + 3 x 4 = 0 \left\{

    4x12x2x3=12x1+4x2+3x4=5x23x3+3x4=0
    \right. 4x12x2x3=12x1+4x2+3x4=5x23x3+3x4=0

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

    结果如下:

    x =
    
        0.9706
        0.8529
        1.1765
    
    n =
    
        29
    
    x =
    
       -0.9706
       -0.8529
       -1.1765
    
    n =
    
        14
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    一般情况下,高斯-赛德尔迭代的收敛速度比雅可比迭代的收敛速度快,但这不是绝对的,在某些情况下,雅可比迭代收敛而高数-赛德尔迭代不收敛。如下面的例子。

    用上述两种迭代方式求解方程组
    { x 1 + 2 x 2 − 2 x 3 = 9 x 1 + x 2 + x 4 = 7 2 x 2 + 2 x 3 + x 4 = 6 \left\{

    x1+2x22x3=9x1+x2+x4=72x2+2x3+x4=6
    \right. x1+2x22x3=9x1+x2+x4=72x2+2x3+x4=6

    A=[1,2,-2;1,1,1;2,2,1];
    b=[9;7;6];
    [x,n]=jacobi(A,b,[0;0;0],10e-6)
    [x,n]=gauseidel(A,b,[0,0,0]',10e-6)
    
    • 1
    • 2
    • 3
    • 4

    结果如下:

    x =
    
       -27
        26
         8
    
    n =
    
         4
         
    x =
    
       NaN
       NaN
       NaN
    
    n =
    
            1012
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    线性微分方程组应用举例

    小行星运行轨道计算问题

    现在已经在5个不同时刻对某颗小行星进行了5次观测,测得轨道上的5个点的坐标数据如表所示,其单位为天文测量单位。试确定小行星的轨道方程。

    i12345
    xi1.020.870.670.440.16
    yi0.390.270.180.130.13

    由开普勒第一定律知,小行星运行轨道为椭圆方程:
    a 1 x 2 + 2 a 2 x y + a 3 y 2 + 2 a 4 x + 2 a 5 y + 1 = 0 a_1x^2+2a_2xy+a_3y^2+2a_4x+2a_5y+1=0 a1x2+2a2xy+a3y2+2a4x+2a5y+1=0
    需要确定系数 a i ( i = 1 , 2 , 3 , 4 , 5 ) a_i(i=1,2,3,4,5) ai(i=1,2,3,4,5)

    等价于求解下列线性方程组

    [ x 1 2 2 x 1 y 1 y 1 2 2 x 1 2 y 1 x 2 2 2 x 2 y 2 y 2 2 2 x 2 2 y 2 x 3 2 2 x 3 y 3 y 3 2 2 x 3 2 y 3 x 4 2 2 x 4 y 4 y 4 2 2 x 4 2 y 4 x 5 2 2 x 5 y 5 y 5 2 2 x 5 2 y 5 ] [ a 1 a 2 a 3 a 4 a 5 ] = [ − 1 − 1 − 1 − 1 − 1 ] \left[

    x122x1y1y122x12y1x222x2y2y222x22y2x322x3y3y322x32y3x422x4y4y422x42y4x522x5y5y522x52y5
    \right] \left[
    a1a2a3a4a5
    \right] =\left[
    11111
    \right] x12x22x32x42x522x1y12x2y22x3y32x4y42x5y5y12y22y32y42y522x12x22x32x42x52y12y22y32y42y5a1a2a3a4a5=11111

    % 问题就转化成了求解上面的方程组
    
    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);
    
    x = A\b
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    结果如下:

    x =
    
        2.4645
       -0.4423
        6.4917
       -0.6819
       -3.6008
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    绘制小行星运行轨迹:

    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) ai(1).*x.^2 + 2.*ai(2).*x.*y + ai(3).*y.^2 + 2.*ai(4).*x + 2.*ai(5).*y + 1;
    
    x = -0.5:0.01:1.2;
    y = 0:0.01:1.2;
    
    h = ezplot(f, [-0.5, 1.2, 0, 1.2]); % h为句柄
    
    set(h, {'Color'}, {'r'}, {'LineStyle'}, {'--'}) % 设置曲线颜色和样式,因为ezplot没有能设置曲线样式的参数 % 大括号可省略,因为设置的属性值就一个,若多个则不可省略
    title('') % ezplot画出的曲线默认带x、y轴标记和title,这里是去除这些标记
    xlabel('') 
    ylabel('')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-quiegte8-1655005481086)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210906163630390.png)]

    非线性方程求解

    单变量非线性方程求解(fzero函数)

    调用格式:x=fzero(filename, x0)

    参数解释:filename为文件名或函数字符串形式或句柄,x0为初始值。

    %% 求f(x) = x-1/x+5在x0=-5和x0=1作为迭代初值时的根
    f=@(x) x-1./x+5;
    x1 = fzero(f, -5)
    x2 = fzero(f, 1)
    x3 = fzero(f, 0.1) % 显然x3不是根
    xi = -6:0.01:1;
    plot(xi, f(xi), 'm', [-6 1], [0 0], 'b', [x1 x2], [0 0], 'k*')
    axis([-6, 1, -10, 10])
    grid on
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意:fzero函数内部实现决定了初值会影响最终求解的结果,因此我们需要对问题进行多角度分析(“多角度分析”过于笼统,不明白什么意思)

    %% 求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
    plot(x0 ,x,' -*')
    xlabel('初值');
    ylabel('方程的根');
    axis([-0.25,0.25,-1,1])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cepq19KZ-1655005481087)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210906174836492.png)]

    图像表明在零附近相同的根所对应的初值范围并不连续,求得的根也并非是离初值比较近的根,fzero执行的是一个数值搜索的过程,搜索的结果依赖于函数特性和指定的初值。

    非线性方程组的求解(fsolve函数)

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

    %% 求f(x) = x-1/x+5在x0=-5和x0=1作为迭代初值时的根
    f=@(x) x-1./x+5;
    x1=fsolve(f,-5,optimset('Display', 'off'))
    x2=fsolve(f, 1 ,optimset('Display','off'))
    x3=fsolve(f,0.1,optimset('Display', 'off'))
    
    • 1
    • 2
    • 3
    • 4
    • 5

    结果如下:

    x1 =
    
       -5.1926
    
    x2 =
    
        0.1926
    
    x3 =
    
        0.1926
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    发现fsolve函数可以在初值为0.1的情况下得到正确答案,这与此函数的内部实现息息相关。

    求下列方程组在(1,1,1)附近的解并对结果进行验证。
    { s i n x + y + z 2 e z = 0 x + y + z = 0 x y z = 0 \left\{

    sinx+y+z2ez=0x+y+z=0xyz=0
    \right. sinx+y+z2ez=0x+y+z=0xyz=0

    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)
    
    • 1
    • 2
    • 3
    • 4

    结果如下:

    ans =
    
        4.5598    3.0000    1.0000
    
    x =
    
        0.0224   -0.0224   -0.0000
    
    ans =
    
       1.0e-06 *
    
       -0.5931   -0.0000    0.0006
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    函数极值计算

    Matlab只考虑f(x)的最小值(亦为极小值),若要计算f(x)的最大值,则可以计算-f(x)的最小值。

    求函数最小值的问题属于最优化问题。

    无约束最优化问题

    [xmin, fmin] = fminbnd(filename, x1, x2, option):求一元函数在[x1, x2]范围内的极小值点xmin和最小值点fmin

    [xmin, fmin] = fminsearch(filename, x0, option):基于单纯形算法求多元函数的极小值点xmin和最小值fmin

    [xmin, fmin] = fminunc(filename, x0, option):基于拟牛顿法求多元函数的极小值点和最小值点

    参数解释:

    filename是定义的目标函数。第一个函数的输入变量x1、x2分别表示被研究区间的左、右边界。后两个函数的输入变量x0是一个向量,表示极值点的初值。option为优化参数,可以通过optimseti函数来设置。

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

    结果如下:

    xmin =
    
       -9.9999
    
    fmin =
    
       -4.8999
    
    xmin =
    
        1.0001
    
    fmin =
    
        5.0001
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    有约束最优化问题

    约束条件细分为:①线性不等式约束 ②线性等式约束 ③非线性不等式约束 ④非线性等式约束 ⑤x的下界和上界

    fmincon函数用于求解各种约束下的最优化问题。

    [xmin,fmin]=fmincon(filename,x0,A,b,Aeq,beq,Lbnd,Ubnd,NonF,option)

    参数解释:

    xmin、fmin、filename、x0和option的含义与求最小值函数相同。

    A、b为线性不等式约束(转化为 ≤ ≤ );Aeq、beq为线性等式约束;Lbnd、Ubnd为x的上界和下界;NonF为.m文件或函数句柄定义的非线性约束条件;option为优化参数,一般取值为option=optimset(‘Display’, ‘off’),表示不输出迭代过程。如果某个约束不存在,则用空矩阵来表示。

    例题

    例1
    m i n     f ( x ) = x 1 2 + x 2 2 + x 3 2 + 8 s . t . { x 1 2 − x 2 + x 3 2 ≥ 0 x 1 + x 2 2 + x 3 2 ≤ 20 − x 1 − x 2 2 + 2 = 0 x 2 + 2 x 3 2 = 3 x 1 , x 2 , x 3 ≥ 0 min\space\space\space f(x) = x_1^2 + x_2^2 + x_3^2 + 8 \\ s.t. \left\{

    x12x2+x320x1+x22+x3220x1x22+2=0x2+2x32=3x1,x2,x30
    \right. min   f(x)=x12+x22+x32+8s.t.x12x2+x320x1+x22+x3220x1x22+2=0x2+2x32=3x1,x2,x30
    执行文件:

    f = @(x) x(1).^2 + x(2).^2 + x(3).^2 + 8; % 尽量点乘,以防万一
    
    [xmin, fmin] = fmincon(f, zeros(3, 1), [], [], [], [], zeros(3, 1), [], 'fun2') % 初值为[0;0;0],下界为[0;0;0]
    
    • 1
    • 2
    • 3

    fun2.m文件(非线性约束):

    function [g,h]=fun2(x); % 返回值g为非线性不等约束(化为≤形式),h为等式约束,等式右侧保证为0
    g=[-x(1).^2+x(2)-x(3).^2
        x(1)+x(2).^2+x(3).^3-20];
    h=[-x(1)-x(2).^2+2
        x(2)+2*x(3).^2-3];
    
    • 1
    • 2
    • 3
    • 4
    • 5

    结果如下:

    xmin = % 极小值点
    
        0.5522
        1.2033
        0.9478
    
    fmin =
    
       10.6511 % 极小值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意:非线性约束条件文件函数的返回值,第一个为非线性不等约束,要将不等式化为≤的形式;第二个参数为非线性等式约束,等式右侧要化成0。

    例2
    m i n     f ( x ) = 0.4 x 2 + x 1 2 + x 2 2 + x 1 x 2 + 1 30 x 1 3 s . t . { x 1 + 0.5 x 2 ≥ 0.4 0.5 x 1 + x 2 ≥ 0.5 x 1 ≥ 0 , x 2 ≥ 0 min\space\space\space f(x)=0.4x_2+x_1^2+x_2^2+x_1x_2+\frac{1}{30}x_1^3 \\ s.t. \left\{

    x1+0.5x20.40.5x1+x20.5x10,x20
    \right. min   f(x)=0.4x2+x12+x22+x1x2+301x13s.t.x1+0.5x20.40.5x1+x20.5x10,x20

    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]; % 用行向量或列向量均可,x0的形式决定了xmin的形式
    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果如下:

    xmin =
    
        0.3396
        0.3302
    
    fmin =
    
        0.2456
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    例3

    ​ 某公司有A、B、C、D、E5个工厂,分别位于xy平面上的坐标点(10, 10 ),(30, 50),(16.667, 29),(0.555, 29.888) 和 (22.2221, 49.988) 处。设两点之间的距离表示在工厂之间开车的距离,以公里为单位。公司计划在平面上某点处建造一座仓库,预期平均每周到A、B、C、D、E工厂分别有10、18、20、14和25次送货。理想情况下,要使每周送货车的里程最小,仓库应建在xy平面的什么位置?若由于地域限制,仓库必须建在曲线 y = x 2 y=x^2 y=x2上,则它应该建在何处?

    ​ 假设仓库所选点的坐标为(x, y),则总里程表达式为:
    d ( x , y ) = 10 ( x − 10 ) 2 + ( y − 10 ) 2 + 18 ( x − 30 ) 2 + ( y − 50 ) 2 + 20 ( x − 16.667 ) 2 + ( y − 29 ) 2 + 14 ( x − 0.555 ) 2 + ( y − 29.888 ) 2 + 25 ( x − 22.2221 ) 2 + ( y − 49.988 ) 2 d(x, y)=10\sqrt{(x-10)^2+(y-10)^2} + 18\sqrt{(x-30)^2+(y-50)^2}+20\sqrt{(x-16.667)^2+(y-29)^2} + 14\sqrt{(x-0.555)^2+(y-29.888)^2} + 25\sqrt{(x-22.2221)^2+(y-49.988)^2} d(x,y)=10(x10)2+(y10)2 +18(x30)2+(y50)2 +20(x16.667)2+(y29)2 +14(x0.555)2+(y29.888)2 +25(x22.2221)2+(y49.988)2

    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,[0,0])
    
    • 1
    • 2
    • 3
    • 4
    • 5

    结果如下:

    xmin =
    
       19.8143   41.1247
    
    fmin =
    
       1.3618e+03
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    说明建在(19.8143, 41.1247)时每周送货车的里程最小,为1361.8m。

    当添加 y = x 2 y=x^2 y=x2的约束时,相当于添加了非线性等式约束,使用fmincon函数。

    执行文件:

    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, [0,0], [], [], [], [], [], [], 'fun2')
    
    • 1
    • 2
    • 3
    • 4
    • 5

    非线性约束条件fun2.m文件:

    function [c,h]=fun2(x)
    c=[];
    h=x(2)-x(1)^2;
    
    • 1
    • 2
    • 3

    结果如下:

    xmin =
    
        5.9363   35.2402
    
    fmin =
    
       1.6676e+03
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    常微分方程数值求解

    常微分方程定义:

    凡含有参数,未知函数和未知函数导数 (或微分) 的方程,称为微分方程,有时简称为方程,未知函数是一元函数的微分方程称作常微分方程,未知函数是多元函数的微分方程称作偏微分方程。微分方程中出现的未知函数最高阶导数的阶数,称为微分方程的阶。

    一般形式为: F ( x , y , y ′ , y ′ ′ , . . . , y ( n ) ) = 0 F(x,y,y',y'',...,y^{(n)})=0 F(x,y,y,y,...,y(n))=0

    调用格式:

    lt,y] = solver(filename,tspan,y0,option)

    参数解释:

    t和y分别给出时间向量和相应的数值解;solver是用来代指多种常微分方程求解函数的名称的,并不是有个函数叫作solver的意思,下面会讲到有哪些函数是用于求解常微分方程的;filename是定义 f ( t , y ) f(t, y) f(t,y)的函数名,该函数必须返回一个列向量(下面会讲这个列向量如何得到);tspan形式为[t0, tf],表示求解区间; y0是初始状态向量;Option是可选参数,用于设置求解属性,常用的属性包括相对误差值(默认值为10e-3)和绝对误差值(默认值为10e-6)。

    solver可选的函数:常微分方程数值求解函数的统一命名格式: o d e n n x x odennxx odennxx

    ode是Ordinary Differential Equation的缩写,是常微分方程的意思;

    nn是两个数字,代表所用方法的阶数,例如ode23采用二阶龙格库塔算法用三阶公式做误差估计来调节步长具有低等精度,ode45采用4阶龙格库塔算法用5阶公式做误差估计来调节步长,具有中等精度;

    xx是字母,用于标注方法的专门特征,例如ode15s、ode23s中的’s‘代表’stiff,表示函数适用于刚性方程(下面介绍刚性方程与非刚性方程)‘。


    求解微分方程初值问题,并与精确解 y ( t ) = ( t + 1 ) + 1 y(t)=\sqrt{(t+1)}+1 y(t)=(t+1) +1进行比较。
    { y ′ = y 2 − t − 2 4 ( t + 1 ) , 0 ≤ t ≤ 10 y ( 0 ) = 2 \left\{

    y=y2t24(t+1),0t10y(0)=2
    \right. {y=4(t+1)y2t2y(0)=2,0t10

    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');
    
    • 1
    • 2
    • 3
    • 4

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pIwIw125-1655005481088)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907092952989.png)]

    solver函数集中的函数的第一个参数为句柄函数或文件名,此函数的参数为两个,第一个为取样点t(自变量),第二个为函数值y(因变量),返回值为列向量,列向量的项数取决于原常微分方程组经转化得到的项数。对于高阶常微分方程(组)我们需要先将其通过设未知数代换的方式得到一个新的方程(组),新方程(组)保证等式左侧均为系数为1的一阶导数,等式右侧为任意非导数形式。这样每个未知数的一阶导数都可以用非导数形式表示了,列向量就返回每个一阶导数右侧的式子。

    对于上面的例题,我们将未知数y看成一项,是因为 y ′ = y 2 − t − 2 4 ( t + 1 ) y'=\frac{y^2-t-2}{4(t+1)} y=4(t+1)y2t2已经是标准的左侧为导数右侧非导数的形式了,因此我们直接返回一个 1 × 1 1×1 1×1的列向量即可;

    调用ode23函数,第二个参数为t的范围,即[0, 10];

    第三个参数为y的初值,即2;

    绘制数值解曲线和精确解曲线进行比较,发现误差很小。


    解如下方程组,它描述的是无外力作用下的刚体运动:
    { y 1 ′ = y 2 y 3 y 2 ′ = − y 1 y 3 y 3 ′ = − 0.51 y 1 y 2 y 1 ( 0 ) = 0 , y 2 ( 0 ) = 1 , y 3 ( 0 ) = 1 \left\{

    y1=y2y3y2=y1y3y3=0.51y1y2y1(0)=0,y2(0)=1,y3(0)=1
    \right. y1=y2y3y2=y1y3y3=0.51y1y2y1(0)=0,y2(0)=1,y3(0)=1

    f = @(t,y) [y(2)*y(3); -y(1)*y(3); -0.51*y(1)*y(2)];
    tspan = [0,12];
    y0 = [0,1,1];
    [T,Y] = ode45(f, tspan, y0);
    
    plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),'.r')
    legend('x','y','z')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dEW9m9yq-1655005481089)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907103321859.png)]


    已知一个二阶线性系统的微分方程如下,取 a = 2 a=2 a=2绘制系统的时间响应曲线和相平面图。
    { d 2 x d t 2 + a x = 0 , a > 0 x ( 0 ) = 0 , x ′ ( 0 ) = 1 \left\{

    d2xdt2+ax=0,a>0x(0)=0,x(0)=1
    \right. {dt2d2x+ax=0x(0)=0,x(0)=1,a>0
    对于这种高阶常微分方程,我们需要将其化为多个一阶微分方程,方法如下:

    y 2 = x y_2=x y2=x y 1 = x ′ y_1=x' y1=x,则得到系统的状态方程为: { y 2 ′ = y 1 y 1 ′ = − a y 2 y 2 ( 0 ) = 0 , y 1 ( 0 ) = 1 \left\{

    y2=y1y1=ay2y2(0)=0,y1(0)=1
    \right. y2=y1y1=ay2y2(0)=0,y1(0)=1

    将原来方程关于 x x x的高阶常微分方程化为了关于 y 1 y_1 y1 y 2 y_2 y2的一阶常微分方程组了,那么solver函数中的作为第一个参数的函数返回的列向量即为[-2*y(2); y(1)](我猜之所以要将-2*y(2)作为第一项是因为y(1)的一阶导数对应的等式右侧为-2*y(2)

    f=@(t,y) [-2*y(2); y(1)]; % 两个元素分别对应第一个方程右侧和第二个方程右侧
    [t,y]=ode45(f,[0,20],[1,0]); % y1的初值为1 y2的初值为0
    subplot(2,2,1);plot(t,y(:,2));% 时间响应曲线
    subplot(2,2,2);plot(y(:,2),y(:,1)); % 相平面图
    % 时间响应曲线与相平面图具体是什么含义我也不清楚
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里之所以采用y(i)表示,是为了防止有萌新将网课中的x和x(i)搞混。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9qXtR7J8-1655005481089)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907101052821.png)]


    刚性问题: 有一类常微分方程,其解的分量有的变化很快,有的变化很慢,且相差悬殊,这就是所谓的刚性问题(Stiff)。非刚性算法可以求解刚性问题,但需要很长的计算时间

    更详细的解释参考:REF1,REF2

    假如点燃一个火柴,火焰球迅速增大直至某个临界体积,然后维持这一体积不变,原因是火焰球内部燃烧耗费的氧气和从球表面所获氧气达到平衡。

    其简化模型如下:
    y 1 = y 2 − y 3 y ( 0 ) = λ 0 ≤ t ≤ 2 / λ y1=y^2-y^3 \\ y(0) = \lambda \\ 0≤ t≤2/\lambda y1=y2y3y(0)=λ0t2/λ
    其中,y(t)代表火焰球半径,初始半径是 λ \lambda λ,它很小。分析 λ \lambda λ的大小对方程求解过程的影响。

    我们对比三种情况“ λ \lambda λ为0.01时,即不是很刚性时,调用解决非刚性问题的函数ode45”、“ λ \lambda λ为1e-5时,即刚性时,调用解决非刚性问题的函数ode45”和“ λ \lambda λ为1e-5时,即刚性时,调用解决刚性问题的函数ode15s”如下:

    %% lamda为0.01时,即不是很刚性时,调用解决非刚性问题的函数ode45
    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时,即刚性时,调用解决非刚性问题的函数ode45
    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))]);
    
    %% lambda为1e-5时,即刚性时,调用解决刚性问题的函数ode15s
    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))]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    结果如下:

    历时 0.000954 秒。
    ode45计算的点数157
    历时 0.166925 秒。
    ode45计算的点数120565
    历时 0.003878 秒。
    ode15s计算的点数98
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    显然解决刚性问题用ode15s比用ode45要高效。

    各类ode:

    1. 非刚性问题:ode45 / ode23 / ode113

    2. 刚性问题:ode15s / ode23s / ode23t / ode23tb

    3. 优先尝试使用ode45:基于显格式的 (4, 5) 阶龙格— 库塔算法

    4. 如果ode45 计算失败,再尝试其他的 ode 函数

    应用

    Lotka-Volterra模型

    生态系统中,捕食者与被捕食者的数量动态关系模型。

    环境中狐狸与兔子的关系满足一阶微分方程组: { d r d t = 2 r − λ r f , r ( 0 ) = r 0 d f d t = − f + λ r f , f ( 0 ) = f 0 \left\{

    drdt=2rλrf,r(0)=r0dfdt=f+λrf,f(0)=f0
    \right. {dtdr=2rλrfdtdf=f+λrf,r(0)=r0,f(0)=f0

    其中,t为时间,r(t)为兔子数量,f(t)为狐狸数量, λ \lambda λ为一个正常数。该系统解具有周期性,其周期取决于初始条件。也就是说,对于任意数量的r(0)和f(0),总存在一个时间 t = t p t=t_p t=tp ,使这两个种群的数量回归初始值。

    (1)在 r 0 r_0 r0=300、 f 0 f_0 f0=150、 λ \lambda λ=0.01的条件下,求该系统的解,结果会发现 t p t_p tp接近5。进一步绘制 λ = r ( t ) \lambda=r(t) λ=r(t) f ( t ) f(t) f(t)函数的曲线,以及以 r r r f f f为坐标轴画相平面图。

    (2)在 r 0 r_0 r0=15、 f 0 f_0 f0=22、 λ \lambda λ=0.01时求解并绘制图形,会发现 t p t_p tp接近6.62。

    (3)在 r 0 r_0 r0=102、 f 0 f_0 f0=198、 λ \lambda λ=0.01时求解并绘制图形,并确定周期 t p t_p tp

    (4)点( r 0 r_0 r0 f 0 f_0 f0)=( 1 / λ 1/\lambda 1/λ 2 / λ 2/\lambda 2/λ)是一个稳定平衡点。若以此为初值,那么种群数量不发生变化。若初值接近此平衡点,那么数量不会发生大的变化。试做图验证。

    模型分析

    x 1 ( t ) x_1(t) x1(t)一兔子在t时刻的数量
    x 2 ( t ) x_2(t) x2(t)—狐狸在t时刻的数量
    r 1 r_1 r1一兔子独立生存时的增长率
    r 2 r_2 r2—狐狸独自存在时的死亡率
    λ 1 \lambda_1 λ1—狐狸掠取兔子的能力
    λ 2 \lambda_2 λ2—兔子对狐狸的供养能力

    若不考虑自然资源对兔子的限制,则兔子独立生存时以指数规律增长相对增长率为 r 1 r_1 r1,即有 d x 1 d t = x 1 r 1 \frac{dx_1}{dt}=x_1r_1 dtdx1=x1r1

    但是兔子由于狐狸的捕食使其增长率降低,假设降低的程度与狐狸数量成正比,于是需要将原模型 d x 1 d t = x 1 r 1 \frac{dx_1}{dt}=x_1r_1 dtdx1=x1r1转化为 d x 1 d t = x 1 ( r 1 − λ 1 x 2 ) \frac{dx_1}{dt}=x_1(r_1-\lambda_1x_2) dtdx1=x1(r1λ1x2)

    若不考虑人为等其他因素,则狐狸独自存在时的死亡率为 r 2 r_2 r2,即有 d x 2 d t = − x 2 r 2 \frac{dx_2}{dt}=-x_2r_2 dtdx2=x2r2

    但是狐狸由于兔子为它提供食物的作用,使其死亡率降低或使之增长,假定增长的程度与兔子数量成正比,于是关于狐狸数量的模型为 d x 2 d t = x 2 ( − r 2 + λ 2 x 1 ) \frac{dx_2}{dt}=x_2(-r_2+\lambda_2x_1) dtdx2=x2(r2+λ2x1)

    综述, { d x 1 d t = x 1 ( r 1 − λ 1 x 2 ) d x 2 d t = x 2 ( − r 2 + λ 2 x 1 ) \left\{

    dx1dt=x1(r1λ1x2)dx2dt=x2(r2+λ2x1)
    \right. {dtdx1=x1(r1λ1x2)dtdx2=x2(r2+λ2x1)

    (1)兔子数量初始值 x 1 ( 0 ) = 300 x_1(0)=300 x1(0)=300,狐狸数量初始值 x 2 ( 0 ) = 150 x_2(0)=150 x2(0)=150

    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(1,2,1);
    plot(t,x(:,1),'-',t,x(:,2),'-*');
    legend('x1(t)','x2(t)');
    xlabel('时间');
    ylabel('物种数量');
    grid on
    subplot(1,2,2);
    plot(x(:,1),x(:,2))
    grid on
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IuWWZVJw-1655005481090)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907191718980.png)]

    (2)兔子数量初始值 x 1 ( 0 ) = 15 x_1(0)=15 x1(0)=15,狐狸数量初始值 x 2 ( 0 ) = 22 x_2(0)=22 x2(0)=22

    rabbitFox=@(t,x)[x(1)*(2-0.01*x(2)); x(2)*(-1+0.01*x(1))];
    [t,x] = ode45(rabbitFox,[0,30],[15,22]);
    subplot(1,2,1);
    plot(t,x(:,1),'-',t,x(:,2),'-*');
    legend('x1(t)','x2(t)');
    xlabel('时间');
    ylabel('物种数量');
    grid on
    subplot(1,2,2);
    plot(x(:,1),x(:,2))
    grid on
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1IsoQSsa-1655005481091)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907191903237.png)]

    (3)兔子数量初始值 x 1 ( 0 ) = 102 x_1(0)=102 x1(0)=102,狐狸数量初始值 x 2 ( 0 ) = 198 x_2(0)=198 x2(0)=198

    rabbitFox=@(t,x)[x(1)*(2-0.01*x(2)); x(2)*(-1+0.01*x(1))];
    [t,x] = ode45(rabbitFox,[0,30],[102,198]);
    subplot(1,2,1);
    plot(t,x(:,1),'-',t,x(:,2),'-*');
    legend('x1(t)','x2(t)');
    xlabel('时间');
    ylabel('物种数量');
    grid on
    subplot(1,2,2);
    plot(x(:,1),x(:,2))
    grid on
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W5wIPJHo-1655005481091)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907191956430.png)]

    (4)验证( 1 / λ 1/\lambda 1/λ, 2 / λ 2/\lambda 2/λ)是平衡点。

    λ \lambda λ=0.01,所以稳定平衡点( 1 / λ 1/\lambda 1/λ, 2 / λ 2/\lambda 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]);
    plot(t,x(:,1),'-o',t,x(:,2),'-*');
    legend('x1(t)-兔子','x2(t)-狐狸');
    xlabel('时间');
    ylabel('物种数量');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sYHa686p-1655005481092)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907192443216.png)]

    当将初始值变为(98,195)时,即向下十分接近平衡点,画出其图像。(代码与上面类似,只需修改初值)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PbNQ323y-1655005481092)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907192606882.png)]

    当将初始值变为(70,150)时,即向下偏离平衡点比较远时,画出其图像。(代码与上面类似,只需修改初值)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OJrhWOUL-1655005481093)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907192746738.png)]

    当将初始值变为(900,1600)时,即向上偏离平衡点十分远时,画出其图像。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YBLp6POv-1655005481093)(C:\Users\23343\AppData\Roaming\Typora\typora-user-images\image-20210907192911162.png)]

    Lotka-Volterra模型的改进

    修改后的方程:
    { d r d t = 2 ( 1 − r R ) r − λ r f , r ( 0 ) = r 0 d f d t = − f + λ r f , f ( 0 ) = f 0 \left\{

    drdt=2(1rR)rλrf,r(0)=r0dfdt=f+λrf,f(0)=f0
    \right. {dtdr=2(1Rr)rλrfdtdf=f+λrf,r(0)=r0,f(0)=f0
    其中,t为时间; r ( t ) r(t) r(t)为兔子数量, f ( t ) f(t) f(t)为狐狸数量; λ \lambda λ为一个正常数, R R R也是一个正常数,表示兔子的环境容量。改进后的模型考虑了在单种群情况下自然资源能承受的最大数量。

    方程在 r 0 = 300 r_0=300 r0=300 f 0 = 150 f_0=150 f0=150初始条件下的50个时间单位上求解并绘制图形。

    (1)对比原模型与改进后模型下的狐狸数量和兔子数量的时间函数曲线。

    (2)对比原模型与改进后模型下的狐狸数量和兔子数量的时间函数曲线。

    (1)狐狸数量和兔子数量的时间函数曲线如下图所示:

    rabbitFox1=@(t,x) [x(1)*(2-0.01*x(2)); x(2)*(-1+0.01*x(1))];
    [t,x]=ode45(rabbitFox1,[0,30],[300,150]);
    subplot(121)
    plot(t,x(:,1),t,x(:,2));
    legend('x1(t)-兔子','x2(t)-狐狸');
    xlabel('时间');
    ylabel('物种数量');
    title('原模型下,狐狸和兔子数量的函数曲线');
    
    rabbitFox2=@(t,x) [2*x(1)*(1-x(1)/400-0.005*x(2)); x(2)*(-1+0.01*x(1))]; % 假设R=400
    [t,x]=ode45(rabbitFox2,[0,30],[300,150]);
    subplot(122)
    plot(t,x(:,1),t,x(:,2));
    legend('x1(t)-兔子','x2(t)-狐狸');
    xlabel('时间');
    ylabel('物种数量');
    title('改进模型下,狐狸和兔子数量的函数曲线');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    通过对比我们发现原模型,无论经历多长时间狐狸和兔子的数量总是在自己的平衡点之间波动;而改进以后的模型,虽然在先前一段时间有较大的波动,但随着时间的推移它们的波动越来越小,在经历足够长的时间后狐狸和兔子的数量分别达到稳定平衡,这更加接近自然界中的实际情况

    (2)狐狸数量和兔子数量的时间函数曲线如下图所示:

    rabbitFox1=@(t,x) [x(1)*(2-0.01*x(2)); x(2)*(-1+0.01*x(1))];
    [t,x]=ode45(rabbitFox1,[0,30],[300,150]);
    subplot(121)
    plot(x(:,1),x(:,2));
    xlabel('兔子数量');
    ylabel('狐狸数量');
    title('原模型下,狐狸数量相对于兔子数量的关系曲线');
    
    rabbitFox2=@(t,x) [2*x(1)*(1-x(1)/400-0.005*x(2)); x(2)*(-1+0.01*x(1))]; % 假设R=400
    [t,x]=ode45(rabbitFox2,[0,30],[300,150]);
    subplot(122)
    plot(x(:,1),x(:,2));
    xlabel('兔子数量');
    ylabel('狐狸数量');
    title('改进模型下,狐狸数量相对于兔子数量的关系曲线');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    模型还可以进一步改进:①考虑狐狸的环境容纳量 ②考虑到兔子其他天敌和狐狸天敌的影响 ③考虑到自然灾害、人为捕捉等因素。

  • 相关阅读:
    JSD-2204-创建csmall项目-Day02
    定位new
    jdbc连接oracle数据库
    PMP中的T型人才
    Python笔记二之多线程
    数据利器:营销人员的智能助手,助力精准营销,实现业务增长
    docker-compose详解
    如何使用react-router v6快速搭建路由?
    rust 创建多线程web server
    手机网页,输入时 软键盘盖住输入框完整解决方案,兼容安卓、鸿蒙、苹果IOS
  • 原文地址:https://blog.csdn.net/weixin_46221946/article/details/125243660