%进退法求初始搜索区间,在[0,+Inf]中
function [a,b]=ForwardBackward(f,alpha0,gamma0,t,Imax)
%% 输入参数
%f:目标函数,要求单值
%alpha0:初值
%gamma0:初始步长
%t:增长倍数
%Imax:最大迭代次数
%% 输出参数
%a:区间下界
%b:区间上界
alpha_old=alpha0;
gamma=gamma0;
i=1;
while(1)
%循环里alpha_old是alpha_i,alpha是alpha_i+1
while(1)
if i>Imax
break;
end
alpha=alpha_old+gamma;
if alpha<=0%区间不能小于0
alpha=0;
break;
end
if f(alpha)>=f(alpha_old)
break;
end
gamma=t*gamma;
alpha_=alpha_old;
alpha_old=alpha;
i=i+1;
end
if i==1%如果刚开始正向就更大了,就反向搜索
gamma=-gamma;
alpha_=alpha;
i=i+1;
else
a=min([alpha_,alpha]);
b=max([alpha_,alpha]);
return
end
end
end
function [alpha]=Golden_Section(f,a0,b0,epsilon)
%% 输入参数
%f:目标函数,要求单值
%a0:初始区间下界
%b0:初始区间上界
%epsilon:终止残差
%% 输出参数
%a:区间下界
%b:区间上界
a=a0;
b=b0;
tau=(sqrt(5)-1)/2;%0.618
rlostflag=2;%右侧缩减标志,赋初值
while(1)
if (b-a)<epsilon%小于终止残差,返回区间中值
alpha=(a+b)/2;
return
end
%根据上次迭代信息,可以少算一个函数值
if rlostflag==1%上次迭代是右边缩减
ar=al;
al=a+(1-tau)*(b-a);
fr=fl;
fl=f(al);
elseif rlostflag==0%上次迭代是左边缩减
al=ar;
ar=a+tau*(b-a);
fl=fr;
fr=f(ar);
elseif rlostflag==2%赋予初值
al=a+(1-tau)*(b-a);
ar=a+tau*(b-a);
fl=f(al);
fr=f(ar);
end
if fl<fr
b=ar;
rlostflag=1;
else
a=al;
rlostflag=0;
end
end
end
有一说一,网上好多黄金分割代码都是计算两次函数值,计算效率较低,没有体会到0.618这个数的精髓。
参考文献:[1] 高立.数值最优化方法[M].北京:北京大学出版社,2014:1-90