【MATLAB学习笔记】数值方法——一维牛顿法(求极小值)

前言

  牛顿法是一种迭代求解极值问题的数值方法,它可以用来求解一维函数的极小值或极大值。该方法利用函数的一阶导数和二阶导数信息来逼近极值点。具体步骤如下:

  1. 选择初始点 α 0 \alpha_0 α0和允许误差 ε \varepsilon ε,并且令 k = 0 k=0 k=0
  2. 计算函数 f ( x ) f(x) f(x) α k \alpha_k αk处的一阶导数 f ′ ( α k ) f'( \alpha_k) f(αk)和二阶导数 f ′ ′ ( α k ) f''( \alpha_k) f′′(αk);
  3. α k + 1 = α k − f ′ ( α k ) f ′ ′ ( α k ) \alpha_{k+1}=\alpha_k-\frac{f'( \alpha_k)}{f''( \alpha_k)} αk+1=αkf′′(αk)f(αk);
  4. ∣ α k + 1 − α k ∣ ⩽ ε \left| \alpha _{k+1}-\alpha _k \right|\leqslant \varepsilon αk+1αkε,则可求得近似解 α ∗ = α k + 1 \alpha^*=\alpha_{k+1} α=αk+1,停止计算,否则转至步骤5;
  5. k = k + 1 k=k+1 k=k+1,转回步骤2。

算法流程图

在这里插入图片描述

算法代码

function Newton_minValue(f_sym,x0,eps,N)
    % f_sym为所求函数, 符号函数
    % x0为初始点,默认为0
    % eps为允许误差, 默认为1e-4
    % N为最大迭代次数, 默认为500
    if nargin < 2, x0 = 0; end
    if nargin < 3, eps = 1e-4; end
    if nargin < 4, N = 500; end

    f = matlabFunction(f_sym);
    df = matlabFunction(diff(f_sym));
    ddf = matlabFunction(diff(f_sym,2));
    
    k = 0;
    fprintf('函数f=%s迭代开始:\n',f_sym)
    while true
        k = k + 1;

        x1 = x0 - df(x0)/(ddf(x0)+eps);
        fprintf('k=%2.d, x0=%.4f, df=%9.4f, ddf=%9.4f, x1=%.4f\n',k,x0,df(x0),ddf(x0),x1)
        if norm(abs(x1-x0),'fro')<eps
            fprintf('已收敛!结果如下:\nk=%2.d, x0=%.4f, x1=%.4f, f=%.4f',k,x0,x1,f(x1));
            break
        end

        if k > N
            fprintf('已经超出最大迭代次数%d!\n',N)
            break
        end
        x0 = x1;
    end
    fprintf('\n\n')

end

测试

测试函数如下:

syms x
f1_sym = x.^4 - 4*x.^3 - 6*x.^2 - 16*x + 4;
f2_sym = 4*x.^3 - 12*x.^2 - 12*x - 16;
f3_sym = x.^3 - 2*x + 1;
f4_sym = 3*x.^3 - 4*x + 5;

解析解

f1 = diff(f1_sym);
x1_min = double(vpa(solve(f1,x)));
f2 = diff(f2_sym);
x2_min = double(vpa(solve(f2,x)));
f3 = diff(f3_sym);
x3_min = double(vpa(solve(f3,x)));
f4 = diff(f4_sym);
x4_min = double(vpa(solve(f4,x)));
x1_minx2_minx3_minx3_min
4.00002.41420.81650.6667

注:上表格仅展示了局部解。

算法解

x0 = 2;
eps = 1e-2;
N = 100;
Newton_minValue(f1_sym,x0,eps,N)
Newton_minValue(f2_sym,x0,eps,N)
Newton_minValue(f3_sym,x0,eps,N)
Newton_minValue(f4_sym,x0,eps,N)

迭代过程如下:

函数f=x^4 - 6*x^2 - 4*x^3 - 16*x + 4迭代开始:
k= 1, x0=2.0000, df= -56.0000, ddf= -12.0000, x1=-2.6706
k= 2, x0=-2.6706, df=-145.7204, ddf= 137.6760, x1=-1.6122
k= 3, x0=-1.6122, df= -44.6059, ddf=  57.8834, x1=-0.8417
k= 4, x0=-0.8417, df= -16.7867, ddf=  16.7034, x1=0.1627
k= 5, x0=0.1627, df= -18.2523, ddf= -15.5865, x1=-1.0091
k= 6, x0=-1.0091, df= -20.2209, ddf=  24.4388, x1=-0.1820
k= 7, x0=-0.1820, df= -14.2372, ddf=  -7.2331, x1=-2.1531
k= 8, x0=-2.1531, df= -85.7198, ddf=  95.3055, x1=-1.2538
k= 9, x0=-1.2538, df= -27.7020, ddf=  36.9546, x1=-0.5044
k=10, x0=-0.5044, df= -13.5134, ddf=   3.1574, x1=3.7621
k=11, x0=3.7621, df= -18.0024, ddf=  67.5479, x1=4.0285
k=12, x0=4.0285, df=   2.4266, ddf=  86.0645, x1=4.0003
k=13, x0=4.0003, df=   0.0291, ddf=  84.0249, x1=4.0000
已收敛!结果如下:
k=13, x0=4.0003, x1=4.0000, f=-156.0000

函数f=4*x^3 - 12*x^2 - 12*x - 16迭代开始:
k= 1, x0=2.0000, df= -12.0000, ddf=  24.0000, x1=2.4998
k= 2, x0=2.4998, df=   2.9925, ddf=  35.9950, x1=2.4167
k= 3, x0=2.4167, df=   0.0837, ddf=  34.0003, x1=2.4142
已收敛!结果如下:
k= 3, x0=2.4167, x1=2.4142, f=-58.6274

函数f=x^3 - 2*x + 1迭代开始:
k= 1, x0=2.0000, df=  10.0000, ddf=  12.0000, x1=1.1674
k= 2, x0=1.1674, df=   2.0882, ddf=   7.0042, x1=0.8696
k= 3, x0=0.8696, df=   0.2689, ddf=   5.2179, x1=0.8182
k= 4, x0=0.8182, df=   0.0084, ddf=   4.9093, x1=0.8165
已收敛!结果如下:
k= 4, x0=0.8182, x1=0.8165, f=-0.0887

函数f=3*x^3 - 4*x + 5迭代开始:
k= 1, x0=2.0000, df=  32.0000, ddf=  36.0000, x1=1.1114
k= 2, x0=1.1114, df=   7.1160, ddf=  20.0044, x1=0.7558
k= 3, x0=0.7558, df=   1.1413, ddf=  13.6046, x1=0.6720
k= 4, x0=0.6720, df=   0.0641, ddf=  12.0957, x1=0.6667
已收敛!结果如下:
k= 4, x0=0.6720, x1=0.6667, f=3.2222

总代码

clc;clear;close all
%% 
syms x
f1_sym = x.^4 - 4*x.^3 - 6*x.^2 - 16*x + 4;
f2_sym = 4*x.^3 - 12*x.^2 - 12*x - 16;
f3_sym = x.^3 - 2*x + 1;
f4_sym = 3*x.^3 - 4*x + 5;
% 解析解
f1 = diff(f1_sym);
x1_min = double(vpa(solve(f1,x)));
f2 = diff(f2_sym);
x2_min = double(vpa(solve(f2,x)));
f3 = diff(f3_sym);
x3_min = double(vpa(solve(f3,x)));
f4 = diff(f4_sym);
x4_min = double(vpa(solve(f4,x)));

x0 = 2;
eps = 1e-2;
N = 100;
Newton_minValue(f1_sym,x0,eps,N)
Newton_minValue(f2_sym,x0,eps,N)
Newton_minValue(f3_sym,x0,eps,N)
Newton_minValue(f4_sym,x0,eps,N)

%% 
function Newton_minValue(f_sym,x0,eps,N)
    % f_sym为所求函数, 符号函数
    % x0为初始点,默认为0
    % eps为允许误差, 默认为1e-4
    % N为最大迭代次数, 默认为500
    if nargin < 2, x0 = 0; end
    if nargin < 3, eps = 1e-4; end
    if nargin < 4, N = 500; end

    f = matlabFunction(f_sym);
    df = matlabFunction(diff(f_sym));
    ddf = matlabFunction(diff(f_sym,2));
    
    k = 0;
    fprintf('函数f=%s迭代开始:\n',f_sym)
    while true
        k = k + 1;

        x1 = x0 - df(x0)/(ddf(x0)+eps);
        fprintf('k=%2.d, x0=%.4f, df=%9.4f, ddf=%9.4f, x1=%.4f\n',k,x0,df(x0),ddf(x0),x1)
        if norm(abs(x1-x0),'fro')<eps
            fprintf('已收敛!结果如下:\nk=%2.d, x0=%.4f, x1=%.4f, f=%.4f',k,x0,x1,f(x1));
            break
        end

        if k > N
            fprintf('已经超出最大迭代次数%d!\n',N)
            break
        end
        x0 = x1;
    end
    fprintf('\n\n')

end

总结

  这只是一个基础的示例,实际中还会有更具体的、更细致的要求,这就需要再做额外调整;另外本人也仍在学习中,这只是个人的学习笔记,可能还有一些不足之处,欢迎指正。

参考文献

主编白清顺. 机械优化设计.第6版 [M]. 2017.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Infww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值