MATLAB中利用最速下降法求解多元函数的局部极小值

来源:互联网 发布:io域名广东备案 编辑:程序博客网 时间:2024/06/08 10:02

主函数(main_steepDescent.m)

% 利用最速下降法求解Rosenbrock函数的局部极小值% Meringue% 2017/4/14% ---------------------------% ---------------------------clcclear allclose allglobal xk dk itererr = 1e-3; % 精度要求iter = 0; % 迭代次数iterMax = 1e5; % 最大迭代次数x0 = [0,0]';% 初始点[~,gk] = Rosenbrock(x0); % 求初始梯度xk(:,1) = x0; while norm(gk) > err % 未达到精度要求    if iter >= iterMax        fprintf('达到最大迭代次数!');        break    end    iter = iter+1;    [~,gk] = Rosenbrock(xk(:,iter));    dk = -gk; % 确定当前搜索方向    % 确定搜索区间(2选1)    % [lambdaMin,lambdaMax,~] = Trial(@Rosenbrock,xk(:,iter),dk,1,1,2,1e-3); % 进退搜索法    lambdaMin = 0; lambdaMax = 10;% 步长一般很小,直接给出粗略区间    % 精确直线搜索确定最优步长(2选1)    % lambdak = P618(@Rosenbrock,xk(:,iter),dk,[lambdaMin,lambdaMax],1e-3); % 黄金分割法    lambdak = fminbnd(@Rosenbrock_t,lambdaMin,lambdaMax); % 调用fminbnd函数    xk(:,iter+1) = xk(:,iter)+lambdak*dk; % 搜索下一点end% 结果显示fprintf('一共迭代了%d次',iter);plot(xk(1,:),xk(2,:))title('最速下降法求Rosenbrock函数的局部极小值')xlabel('x_1'); ylabel('x_2');

确定搜索区间:进退搜索法(Trial.m)

function [a,b,c] = Trial(f_name,xk,dk,a0,h0,t,e)% 进退搜索法寻找在xk处沿dk方向包含函数f_name的极小值点的区间[a,b],及中间某个点c,要求a<c<b% 且f(a)>f(c),f(c)<f(b),(高-低-高)% 函数f_name不能是单调函数% f_name:函数名(句柄)% xk:第k次迭代点% dk:第k次迭代点到第k+1次迭代点的搜索方向% a0:寻找包含极小值区间的初始点% h0:步长% t:加倍系数% e:精度(用于控制函数值相等的情况)MaxIterations = 500;Iteration = 0;f0 = feval(f_name,xk+a0*dk); % 计算初始点函数值a1 = a0+h0;f1 = feval(f_name,xk+a1*dk);while abs(f1-f0)<e    a1 = a1+t*h0;    f1 = feval(f_name,xk+a1*dk);endif f1>f0 % 反向搜索    a2 = a0-h0;    f2 = feval(f_name,xk+a2*dk);    while f2<=f0        a2 = a2-t*h0;        f2 = feval(f_name,xk+a2*dk);        Iteration = Iteration+1;        if Iteration>MaxIterations            break        end    end    a = a2; b = a1; c =a0;elseif f1<f0 % 加大搜索步长正向搜索    a2 = a1+t*h0;    f2 = feval(f_name,xk+a2*dk);    while f2<=f1        a2 = a2+t*h0;        f2 = feval(f_name,xk+a2*dk);        Iteration = Iteration+1;        if Iteration>MaxIterations            break        end    enda = a0; b = a2; c = a1;endfa = feval(f_name,xk+a*dk);fb = feval(f_name,xk+b*dk);fc = feval(f_name,xk+c*dk);if ((fa<fc)&&(fc<fb))||((fa>fc)&&(fc>fb))    fprintf('到达最大迭代次数,这是单调函数,没有包含极小点的区间')end

精确直线搜索:黄金分割法(P618.m)

function [xstar,fstar,iter] = P618(f_name,xk,dk,lambda_range,e)% 黄金分割法求一元函数的极小值% f_name: 函数句柄% xk: 当前搜索点% dk: 当前搜索方向% lambda_range:初始搜索区间(可通过进退搜索法确定)% e: 精度要求if lambda_range(1)<0    lambda_range(1) = 0;endk = 1;a(k) = lambda_range(1); b(k) = lambda_range(2);u(k) = a(k)+0.382*(b(k)-a(k)); v(k) = a(k)+0.618*(b(k)-a(k));m(k) = feval(f_name,xk+u(k)*dk); n(k) = feval(f_name,xk+v(k)*dk);flag = 0;while flag==0    if m(k)>n(k)        if b(k)-u(k)<e            xstar = v(k); fstar = feval(f_name,xk+xstar*dk);            flag = 1;        else            a(k+1) = u(k); b(k+1) = b(k);            u(k+1) = v(k); v(k+1) = a(k+1)+0.618*(b(k+1)-a(k+1));            m(k+1) = n(k); n(k+1) = feval(f_name,xk+v(k+1)*dk);            k = k+1; flag = 0;        end    else        if v(k)-a(k)<e            xstar = u(k); fstar = feval(f_name,xk+xstar*dk);            flag = 1;        else            a(k+1) = a(k); b(k+1) = v(k);            u(k+1) = a(k+1)+0.382*(b(k+1)-a(k+1)); v(k+1) = u(k);            m(k+1) = feval(f_name,xk+u(k+1)*dk); n(k+1) = m(k);            k = k+1; flag = 0;        end    endenditer = k-1;

目标函数:Rosenbrock函数(Rosenbrock.m)

function [f,g] = Rosenbrock(x)f = 100*(x(2)-x(1)^2)^2 +(1-x(1))^2;g1 = 2*x(1) - 400*x(1)*(- x(1)^2 + x(2)) - 2;g2 = - 200*x(1)^2 + 200*x(2);g = [g1,g2]'; 

Rosenbrock函数(Rosenbrock_t.m):用于求最优步长

在调用fminbnd函数求最优步长(精确直线搜索)时调用

function [f,g] = Rosenbrock_t(lambda)global xk dk iter[f,g] = Rosenbrock(xk(:,iter)+lambda*dk);

求解结果

一共迭代了2857次


SteepDescent

0 0
原创粉丝点击