1 前言
在线搜索迭代算法中,当迭代方向 d k d^k dk确定后,需要看沿 d k d^k dk 走多远对算法有利,即需要寻找迭代步长。迭代步长通常由精确一维线搜索、非精确一维线搜索、非单调一维线搜索等方式获得。实现精确一维线搜索的方法有很多,其中包括 Fibonacci \text{Fibonacci} Fibonacci 法、黄金分割法、进退法、平分法、抛物线法等。下面只介绍黄金分割法。黄金分割法又称为 0.618 0.618 0.618法。
2 算法内容
算法(黄金分割法) 给定目标函数 f ( x ) , f(x),\; f(x),初始搜索区间 [ a 0 , b 0 ] ⊆ [ 0 , + ∞ ) [a_0,b_0]\subseteq [0,+\infty) [a0,b0]⊆[0,+∞)和精度要求 ε > 0. \varepsilon>0.\; ε>0. 若 b 0 − a 0 < ε , b_0-a_0<\varepsilon,\; b0−a0<ε,那么算法终止 , ,\; ,输出 λ ∗ : = a 0 + b 0 2 . \lambda_*:=\frac{a_0+b_0}{2}. λ∗:=2a0+b0.
步1 置 t 0 = a 0 + 0.382 ( b 0 − a 0 ) , s 0 = a 0 + 0.618 ( b 0 − a 0 ) , t_0=a_0+0.382(b_0-a_0),\;s_0=a_0+0.618(b_0-a_0),\; t0=a0+0.382(b0−a0),s0=a0+0.618(b0−a0),计算 f ( t 0 ) , f ( s 0 ) . f(t_0),f(s_0).\; f(t0),f(s0).置 k : = 0 k:=0 k:=0.
步2 若 f ( t k ) > f ( s k ) , f(t_k)>f(s_k),\; f(tk)>f(sk),则转步3 ; ;\; ;否则转步4.
步3 若 b k − t k < ε , b_k-t_k<\varepsilon,\; bk−tk<ε,则算法终止 , ,\; ,输出 λ ∗ : = s k ; \lambda_*:=s_k;\; λ∗:=sk;否则置 a k + 1 : = t k , b k + 1 : = b k , t k + 1 a_{k+1}:=t_k,\;b_{k+1}:=b_k,\;t_{k+1} ak+1:=tk,bk+1:=bk,tk+1 : = s k , f ( t k + 1 ) : = f ( s k ) , :=s_k,\;f(t_{k+1}):=f(s_k),\; :=sk,f(tk+1):=f(sk),计算 s k + 1 : = a k + 1 + 0.618 ( b k + 1 − a k + 1 ) s_{k+1}:=a_{k+1}+0.618(b_{k+1}-a_{k+1}) sk+1:=ak+1+0.618(bk+1−ak+1)和 f ( s k + 1 ) , f(s_{k+1}),\; f(sk+1),转步5.
步4 若 s k − a k < ε , s_k-a_k<\varepsilon,\; sk−ak<ε,则算法终止 , ,\; ,输出 λ ∗ : = t k ; \lambda_*:=t_k;\; λ∗:=tk;否则置 a k + 1 : = a k , b k + 1 : = s k , s k + 1 a_{k+1}:=a_k,\;b_{k+1}:=s_k,\;s_{k+1} ak+1:=ak,bk+1:=sk,sk+1 : = t k , f ( s k + 1 ) : = f ( t k ) , :=t_k,\;f(s_{k+1}):=f(t_k),\; :=tk,f(sk+1):=f(tk),计算 t k + 1 : = a k + 1 + 0.382 ( b k + 1 − a k + 1 ) t_{k+1}:=a_{k+1}+0.382(b_{k+1}-a_{k+1}) tk+1:=ak+1+0.382(bk+1−ak+1)和 f ( t k + 1 ) , f(t_{k+1}),\; f(tk+1),转步5.
步5 置 k : = k + 1 , k:=k+1,\; k:=k+1,转步2.
3 在Matlab上的实现
3.1 代码
3.1.1 Goldsection.m(函数.m文件)
function [target_value,target_x,k,lambda] = Goldsection(f,epsilon,x,d,upper,lower)
% 黄金分割法
k=0;
kk=k+1;
if (upper-lower)<epsilon
lambda=(lower(kk)+upper(kk))/2;
else
t=lower+0.382*(upper-lower); s=lower+0.618*(upper-lower);
theta_t=f(x+t*d); theta_s=f(x+s*d);
while 1==1
if theta_t(kk)>theta_s(kk)
if (upper(kk)-t(kk))<epsilon
lambda=s(kk);
break
else
lower(kk+1)=t(kk); upper(kk+1)=upper(kk);
t(kk+1)=s(kk);
s(kk+1)=lower(kk+1)+0.618*(upper(kk+1)-lower(kk+1));
theta_t(kk+1)=f(x+t(kk+1)*d);
theta_s(kk+1)=f(x+s(kk+1)*d);
k=k+1;
kk=k+1;
end
else
if (s(kk)-lower(kk))<epsilon
lambda=t(kk);
break
else
lower(kk+1)=lower(kk); upper(kk+1)=s(kk);
s(kk+1)=t(kk);
t(kk+1)=lower(kk+1)+0.382*(upper(kk+1)-lower(kk+1));
theta_t(kk+1)=f(x+t(kk+1)*d);
theta_s(kk+1)=f(x+s(kk+1)*d);
k=k+1;
kk=k+1;
end
end
end
end
target_x=x+lambda*d;
target_value=f(x+lambda*d);
fprintf('算法迭代次数为%d,输出的λ=%f,目标函数值为:%f\n',k,lambda,target_value); %输出结果
target_x
end
main.m
clear all
clc
%% 数据输入
% 创建目标函数的句柄函数
f=@(x)(1-x(1))^2+100*(x(2)-x(1)^2)^2;
%输入起始点
x=[0,0]';
%输入迭代方向
d=[1,0]';
%输入精度
epsilon=0.001;
%初始区间下界
lower=0;
%初始区间上界
upper=1;
%% 通过黄金分割法计算
[target_value,target_x,k,lambda] = Goldsection(f,epsilon,x,d,upper,lower);
%target_value 储存当前精度下目标函数极小值
%target_x 储存当前精度下目标函数为极小值时x的位置,通常是向量
% k 储存迭代次数
%lambda 储存迭代步长
3.2 使用说明
以下题为例:
求Rosenbrock函数
min
f
(
x
)
=
(
1
−
x
1
)
2
+
100
(
x
2
−
x
1
2
)
2
\min f(x)=(1-x_1)^2+100(x_2-x_1^2)^2
minf(x)=(1−x1)2+100(x2−x12)2
在点
x
k
=
(
0
,
0
)
T
x_k=(0,0)^T
xk=(0,0)T处沿方向
d
k
=
(
1
,
0
)
T
d^k=(1,0)^T
dk=(1,0)T的近似步长。其中黄金分割法的初始区间
[
0
,
1
]
[0,1]
[0,1],精度
ϵ
=
0.001
ϵ=0.001
ϵ=0.001.
- 保证main.m和Goldsection.m文件在同一目录下.
- 打开main.m,
输入目标函数句柄函数:f=@(x)(1-x(1))$^2+100*(x(2)-x(1)^2)^2;
修改为起始点x=[0,0]';
修改迭代方向d=[1,0]';
修改精度epsilon=0.001;
修改初始区间下界lower=0;
修改初始区间上界upper=1;
- 运行,即可得到
其中target_x为当前精度下目标函数为极小值时x的位置。