其他分享
首页 > 其他分享> > 采用Armjio非精确线搜索求步长的FR非线性共轭梯度法--MATLAB实现

采用Armjio非精确线搜索求步长的FR非线性共轭梯度法--MATLAB实现

作者:互联网

文章目录


前言

多元函数的求解使我们生活中常见的一些问题的缩影,对于多元函数极小点的解法,我们可以利用最优化中的相关算法来求解,本文采用 MATLAB 程序,利用 FR 非线性共轭梯度算法求解 Rosenbrock 函数的极小点。


一、数学原理

可参考此文章:最速下降法/steepest descent,牛顿法/newton,共轭方向法/conjugate direction,共轭梯度法/conjugate gradient 及其他

算法伪码如下:

在这里插入图片描述


二、代码实现

1.Armjio非精确线搜索求步长

详情可参考我的另一篇博客:采用非精确线搜索求步长的Armjio准则–MATLAB实现

function [alpha] = Armjio(fun, grid, x0, dk)
    %
    % Function [alpha, xk, fx, k] = Armjio(fun, grid, x0, dk)
    % 求出函数fun在x0处以dk为下降方向时的步长alpha,同时返回相对应的下
    % 一个下降点xk以及xk处的函数值fx,k为迭代次数
    % -----------------------------------------------------------
    % 输入: 
    % 		fun 	函数名称(字符变量)
    %		grid 	梯度函数名称(字符变量)
    %		x0		迭代点(列向量)
    %		dk		函数在迭代点处的下降方向(列向量)
    %
    % 输出:
    %		alpha	函数在x0处以dk为下降方向时的下降步长
    %		xk		函数在x0处以dk为下降方向,以alpha为步长
    %				求得的下降点
    %		fx		函数在下降点xk处的函数值
    %		k		求步长算法迭代次数
    % -----------------------------------------------------------
    % by Zhi Qiangfeng 
    %
    beta = 0.333; 		% 步长 alpha 的迭代系数,小于 1
    rho = 1e-3; 		% 泰勒展开式补足系数,0 < rho < 1/2
    alpha = 1; 			% 初始步长为 1
    k = 0; 				% 统计迭代次数
    gk = feval(grid, x0);	% x0处的梯度值
    fd = feval(fun, x0 + alpha * dk); 	% 函数在下一个迭代点处的目标函数值
    fk = feval(fun, x0) + alpha * rho * gk' * dk; 	% 函数在下一个迭代点处的泰勒展开值
    while fd > fk
        alpha = beta * alpha;
        fd = feval(fun, x0 + alpha * dk);
        fk = feval(fun, x0) + alpha * rho * gk' * dk;
        k = k + 1;
    end
end

2.FR共轭梯度法

代码如下:

function [f, xk, k] = FRConjudate(x0, fun, grid, eps, kmax)
    %
    % function [f, xk, k] = FRConjudate(x0, fun, grid, eps, kmax)
    % 求出函数fun从初始点x0处以共轭梯度法计算下降方向,
    % 采用 Armjio 准则计算迭代步长,求出函数的极小点
    % -----------------------------------------------------------
    % 输入:
    %     x0    初始点(列向量)
    % 		fun 	函数文件名称(字符变量)
    %		  grid 	梯度函数文件名称(字符变量)
    %		  eps   函数在迭代点处的下降方向(列向量)
    %     kmax  函数的最大迭代次数
    %
    % 输出:
    %		  f	    函数在极小值 xk 处的目标函数值
    %		  xk		函数采用此方法求得的极小点
    %	  	k		  求极小点算法迭代次数
    % -----------------------------------------------------------
    % by Zhi Qiangfeng 
    % 
    k = 0;
    n = length(x0); % n 为未知数个数
    xk = x0;
    gk = feval(grid, xk);
    dk = -gk; % 初始下降方向选为负梯度方向
    while k <= kmax
        if norm(gk) < eps
            break
        end
        gk_ = gk; % gk_ 保存上一个点的梯度值
        gk = feval(grid, xk);
        dk_ = dk; % dk_ 保存上一个下降方向
        if mod(k, n) == 0
            dk = -gk; % 每 n 步重新调整下降方向
        else
            beta = (gk' * gk) / (gk_' * gk_); % FR公式
            dk = -gk + beta * dk_; % 更新下降方向
            if gk' * dk >= 0
                dk = -gk; % 非精确线搜索无法保证迭代方向下降性
            end
        end
        alpha = Armjio(fun, grid, xk, dk);
        xk = xk + alpha * dk;
        k = k + 1;
    end
    f = feval(fun, xk);
end

此处不列出输出结果以及调用方法,调用方式以及方法可参考这篇博客:采用Armjio准则求步长的BFGS/DFP拟牛顿方法–MATLAB实现


附录

最优化相关算法设计数学原理:最优化/Optimization文章合集
最优化相关MATLAB实现程序:Z.Q.Feng的最优化笔记


有帮助可以点赞哦,谢谢大家的支持~

标签:xk,FR,函数,--,步长,fun,alpha,x0,dk
来源: https://blog.csdn.net/weixin_46584887/article/details/117738066