【最优化理论与算法】Newton法

syms x1 x2 x
import='输入原函数:';
f=input(import);
A=[0,0];                    
prompt='请输入初始点:';
A=input(prompt);             %初始点A
prompt='请输入允许误差:';
e=input(prompt);             %允许误差e
fx1=diff(f,'x1');            %计算梯度函数 [fx1,fx2]
fx2=diff(f,'x2');
fx1x1=diff(fx1,'x1');        % 计算黑塞矩阵函数 [fx1x1,fx1x2;fx2x1,fx2x2]
fx1x2=diff(fx1,'x2');
fx2x1=diff(fx2,'x1');
fx2x2=diff(fx2,'x2');
f1=subs(fx1,[x1,x2],[A(1),A(2)]);  %将A代入梯度函数 得到梯度df=[f1,f2]
f2=subs(fx2,[x1,x2],[A(1),A(2)]);
D=sqrt(f1^2+f2^2);   %计算误差D= || df ||
i=1;                 %迭代次数i
while D>e           %若误差D>精度e 继续迭代
    fprintf('第%d次迭代\n',i);
    i=i+1;
    f11=subs(fx1x1,[x1,x2],[A(1),A(2)]);  % 将A的值代入黑塞矩阵函数 得到矩阵的值
    f12=subs(fx1x2,[x1,x2],[A(1),A(2)]);
    f21=subs(fx2x1,[x1,x2],[A(1),A(2)]);
    f22=subs(fx2x2,[x1,x2],[A(1),A(2)]);
    df=[f1,f2];            %设梯度 df=[f1,f2];
    d2f=[f11,f12;f21,f22]; %黑塞矩阵 d2f=[f11,f12;f21,f22]
    d2f_n=inv(d2f);        %黑塞矩阵的逆d2f_n
    d=-df*d2f_n;           %计算搜索方向d
    fprintf('梯度为(%.6f,%.6f),搜索方向为(%.6f,%.6f),进行一维搜索\n',f1,f2,d(1),d(2));
    func=subs(f,[x1,x2],[A(1)+x*d(1),A(2)+x*d(2)]);  %得到沿d方向的一维搜索函数 func= min(A+x*d)
    k=One_dimensional_search(func);                  %用0.618法对函数一维搜索得到 k=λ
    A(1)=A(1)+k*d(1);                                %更新搜索初始点A
    A(2)=A(2)+k*d(2);
    fprintf('得到新的搜索点(%.6f,%.6f)\n',A(1),A(2));
    f1=subs(fx1,[x1,x2],[A(1),A(2)]);                %用新的A 更新梯度
    f2=subs(fx2,[x1,x2],[A(1),A(2)]);
    D=sqrt(f1^2+f2^2);                               %计算误差D= || df ||
    fprintf('误差为%.6f\n\n',D);
end
fprintf('误差小于允许误差,得到最优点(%.6f , %.6f)\n',A(1),A(2));
% (x1-1)^4+x2^2

function [y]=One_dimensional_search(func)  %% 使用0.618法的一维搜索函数,初始搜索区间由进退法获得
    [min_f,max_f]=fb(func,1);   % 进退法获得搜索区间 (min_f,max_f) 这里步长设置为1
    [u,v]=f_618(func,min_f,max_f,0.000001); % 0.618法获得符合精度的最优值区间 (u,v)  精度为10^-6
    y=(u+v)/2;   % 取平均值为函数最优点
    %%% 进退法,0.618法 函数代码块均在一维搜索函数内

    function [min_f,max_f]=fb(func,h0)   %%%%%%进退法函数代码块  func为函数,h0为步长
        h=h0;                     % 进退法step1  初始化
        x1=1;
        k=0;
        while 1
            x4 = x1 + h;          % 进退法step2  计算f(x4) f(x1)
            k = k + 1;
            f4 = subs(func,x4);
            f1 = subs(func,x1);
            if f4 < f1            % 进退法step4  f4<f1时执行 加大步长
                x2 = x1;
                x1 = x4;
                h = 2*h;
            else                  % 进退法step5  f4>f1时执行
                if k==1        % 进退法step6  改变步长方向
                    h = -h;       
                    x2 = x4;
                else           % 进退法step7  找到区间,退出函数
                    x3=x2;
                    x2=x1;
                    x1=x4;
                    min_f = min(x1, x3);
                    max_f = max(x1, x3);
                    break;  
                end
            end
        end
    end

    function [x1,x2]=f_618(func,a,b,L)  %%%%%     0.618法函数代码块 a,b为初始区间,由进退法获得,L为精度
        r=a+0.382*(b-a);           % step1 初始化
        s=a+0.618*(b-a);
        while 1    %重复以下过程,直至符合精度要求
            if b-a<L               %step2 达到精度要求,退出函数
                x1=a;
                x2=b;
                break;
            else                   %step2  未达到精度要求
                if(subs(func,r)>subs(func,s)) %step3 f(r)>f(s)时执行
                    a=r;
                    b=b;
                    r=s;
                    s=a+0.618*(b-a);
                else                          %step4 f(r)<f(s)时执行
                    a=a;
                    b=s;
                    s=r;
                    r=a+0.382*(b-a);
                end
            end
        end
    end
end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值