1. 简介
黄金分割法又称 0.618 法,针对在给定区间上的单峰函数,通过不断收缩搜索区间来逼近极值。
2. 算法步骤
-
step1: 确定搜索区间 [a0, b0] 和容许的误差 ε > 0 , 计算初始试探点 f(p0) 、f(q0)
p 0 = a 0 + 0.382 ( b 0 − a 0 ) q 0 = a 0 + 0.618 ( b 0 − a 0 ) p_0 = a_0 + 0.382(b_0 - a_0) \\ q_0 = a_0 + 0.618(b_0 - a_0) p0=a0+0.382(b0−a0)q0=a0+0.618(b0−a0) -
step2: f(pi) <= f(qi) 转 step3, 否者,转 step4。
-
step3: 若 |qi - ai| <= ε ,停止计算,输出 pi 。否则, 令
a i + 1 = a i b i + 1 = q i f ( q i + 1 ) = f ( p i ) q i + 1 = p i p i + 1 = a i + 1 + 0.382 ( b i + 1 − a i + 1 ) a_{i+1} = a_i\ \ \ \ b_{i+1} = q_i\ \ \ \ f(q_{i+1}) = f(p_i) \\ q_{i+1} = p_i\ \ \ \ p_{i+1} = a_i+1 + 0.382(b_{i+1} - a_{i+1}) ai+1=ai bi+1=qi f(qi+1)=f(pi)qi+1=pi pi+1=ai+1+0.382(bi+1−ai+1)
并计算 f(pi+1) , i = i + 1。 -
step4: 若 |bi - pi| <= ε ,停止计算,输出 qi 。否则,令
a i + 1 = p i b i + 1 = b i f ( p i + 1 ) = f ( q i ) p i + 1 = q i q i + 1 = a i + 1 + 0.618 ( b i + 1 − a i + 1 ) a_{i+1} = p_i\ \ \ \ b_{i+1} = b_i\ \ \ \ f(p_{i+1}) = f(q_i)\\ p_{i+1} = q_i\ \ \ \ q_{i+1} = a_{i+1} + 0.618(b_{i+1} - a_{i+1}) ai+1=pi bi+1=bi f(pi+1)=f(qi)pi+1=qi qi+1=ai+1+0.618(bi+1−ai+1)
计算 f(qi+1) ,i = i + 1,转 step2。
3. Matlab 代码
% 黄金分割法
function [xValue, fValue] = method618(domain, thresh)
a = domain(1);
b = domain(2);
p = a + 0.382 * (b - a);
q = a + 0.618 * (b - a);
pValue = f(p);
qValue = f(q);
while true
if (pValue <= qValue)
if q - a < thresh
xValue = (q + a) / 2;
fValue = f(xValue);
break;
end
b = q;
qValue = pValue;
q = p;
p = a + 0.382 * (b - a);
else
if b - p < thresh
xValue = (p + b) / 2;
fValue = f(xValue);
end
a = p;
pValue = qValue;
p = q;
q = a + 0.618 * (b - a);
end
end
end
% 目标函数
function value = f(x)
value = x * x * x - 2 * x + 1;
end
4. 为什么是 0.618
根据 2. 算法步骤 我们知道每次收缩搜索区间只需要计算一个节点的值即可,正式因为 qi+1 = pi 或者 pi+1 = qi 的操作,使得每次计算只需要算一次函数的值,相较于二分法少了一次计算,虽然收敛速度没有二分法快,但是每次收缩时的计算量更小,可见其巧妙行。
qi+1 = pi 或者 pi+1 = qi 这里可能有些同学有疑问,为什么不是 qi+1 = qi 或者 pi+1 = pi 呢,这就是为什么是 0.618 而不是其他数的原因。
1. 来看看正常的收敛步骤:
if f(p_i) <= f(q_i) then a_(i+1) = a_i; b_(i+1) = q_i; ①
if f(p_i) > f(q_i) then a_(i+1) = p_i; b_(i+1) = b_i; ②
每一次收缩都会得到四个点 a_i, p_i, q_i, b_i, 且 p_i - a_i = b_i - q_i;
2. 那么我们可以设 p_i- a_i = (1-t) * (b_i - a_i), 则有如下公式 :
p_i = a_i + (1-t)(b_i - a_i) q_i = a_i + t(b_i - a_i) ③
3. 假设条件 ① 成立,则 [a_(i+1), b_(i+1)] = [a_i, q_i], 则新的试探点
q_(i+1) = a_(i + 1) + t * (b_(i+1) - a_(i + 1));
又因为 ③ 可得
q_(i+1) = a_i + t(q_i - a_i) = a_i + t^2(b_i - a_i)
4. 此时,如果能够时 t^2 = 1 - t,我们就可以达到黄金分割法的效果,少算一个试探点,那么我们来看看 t 应该等于多少
我们只需要解 t^2 = 1 - t 即可, 由于 t > 0 , 则 t = (sqrt(5) - 1) / 2 = 0.618
5. 结论
神奇的 0.618