黄金分割搜索
黄金分割搜索是一种通过不断缩小单峰函数的最值的已知范围,从而找到最值的方法。它的名称源于这个算法保持了间距具有黄金分割特性的三个点。这个算法与斐波那契搜索和二分查找关系紧密。黄金分割搜索是由Kiefer提出的,而斐波那契搜索是由Avriel和Wilde所提出。
基本信息
- 中文名
黄金分割搜索
- 外文名
Golden-section search
- 学科
数学、计算机科学
- 性质
名词
- 特点
黄金分割
- 提出者
Kiefer
基本概念
这里讨论的是在一个单峰函数搜索一个最小值(搜索一个最大值也一样),与找零不同,两个具有相反符号的求值函数足以包括一个根。当搜索最小值时,需要三个值。黄金分割搜索是逐步缩小定位最小值的有效方式。关键是要观察,无论有多少点已经被赋值,最小值在由与目前赋值最小的点相邻的两点所界定的区间内。
上图表示了算法中找最小值的一个步骤。f(x)的函数值位于垂直坐标轴上,参数x位于水平坐标轴。已经有三个位于函数f(x)上的点的值被计算出来。:x1,x2, 和x3。可见f2小于f1和f3, 所以很明显的,最小值处于x1和x3之间。
接下来的步骤是通过计算函数位于另一个点x4的值。在最大的区间选择x4会更有效率,例如:x2和x3之间。从图中我们可以看出,如果函数的值落在f4a的话,最小值落于x1和x4之间,并且新的一组点将会是x1和x2和x4。然而如果函数的值为f4b的话,新的一组点将会是x2和x4和x3。因此,无论是哪种情况,我们都可以建立一个新的更狭窄的区间,用于搜索函数的最小值。
点的选择
由图可知,新的区间会介于X1和X4,长度为a+c,或者介于X2和X3,长度为b。黄金分割搜索要求这些区间是相等的。若不是如此,较宽的区间会被使用很多次,降低了收敛率。为了确保b=a+c,算法应确保X4=X1-X2+X3。
然而X2的确定仍是一个问题。我们避免了X2非常接近X1或者X3的情况,确保了每一次迭代区间宽度会缩小同样的比例。
为了确保计算f(X4)后的值与之间的成比例,假设f(X4)的值为f4a,且我们新的一组点为X1,X2和X4,则必须使:
。然而,如果f(X4)的值为f4b ,并且我们新的一组点为X2,X4和X3,则必须使:
。结合b=a+c可解得
![]()
而φ就是黄金比例:
这就是这个算法被成为黄金分割搜索的原因。终止条件由于平滑的函数是平稳的(它们的一阶导数接近于零)接近于最小值,所以必须注意不要太高的定位精度,在书<数值分析C语言》中终止条件基于测试X4,X1,X2,X3之间的差距,在相对精度范围内。
τ是算法的容许参数,| x |是x 的绝对值。检验是基于相对于括号里的值相对于中心值的大小,因为相对误差在x大致与正方形的绝对误差成f(x)正比在典型情况下。出于同样的原因,数值分析建议
,ε是f(x)所需的绝对精度。算法算法包括迭代和递归。如下:迭代'''pythonprogram for golden section search'''gr =(math.sqrt(5) + 1) / 2def gss(f, a, b,tol=1e-5):'''golden section searchto find the minimum of f on [a,b]f: a strictly unimodal function on [a,b]example:>>> f = lambda x: (x-2)**2>>> x = gss(f, 1, 5)>>> x2.000009644875678'''c = b - (b - a) / grd = a + (b - a) / grwhile abs(c - d) > tol:if f(c) < f(d):b = delse:a = c# we recompute both c and d here toavoid loss of precision which may lead to incorrect results or infinite loopc = b - (b - a) / grd = a + (b - a) / grreturn (b + a) / 2递归public static double PHI = (1 +Math.sqrt(5)) / 2; // 0.618...public static double RESPHI = 2 - PHI; // 0.382.../*** Golden section search.** @param x1The left bound of current bounds.* @param x2An interior point between (x1, x3).* @param x3The right bound of current bounds.* @param tau The error tolerance to judgethe convergence, recommended value is e^0.5, where e is is the requiredabsolute precision of f(x).*/public double goldenSectionSearch(doublex1, double x2, double x3, double tau) {double x4;if (x3 - x2 > x2 - x1) { // b > a,右半区间长度较大x4 = x2 + RESPHI * (x3 - x2); // x4安插在右半区间} else {// b <= a,左半区间长度较大x4 = x2 - RESPHI * (x2 - x1); // x4安插在左半区间}if (Math.abs(x3 - x1) < tau *(Math.abs(x2) + Math.abs(x4))) { // 判断是否达到收敛条件return (x3 + x1) / 2; // 达到收敛条件,取区间长度的一半作为极小值点输出}assert (function.func(x4) !=function.func(x2));/* 未达到收敛条件,继续搜索 */if (function.func(x4) <function.func(x2)) { // x4点的函数值如图中f4b所示时if (x3 - x2 > x2 - x1) { // b > a,右半区间长度较大return goldenSectionSearch(x2, x4, x3,tau); // 以x2,x4,x3作为新三点,继续搜索} else {// b <= a,左半区间长度较大return goldenSectionSearch(x1, x4, x2,tau); // 以x1,x4,x2作为新三点,继续搜索}} else {// x4点的函数值如图中f4a所示时if (x3 - x2 > x2 - x1) { // b > a,右半区间长度较大return goldenSectionSearch(x1, x2, x4,tau); // 以x1,x2,x4作为新三点,继续搜索} else {// b <= a,左半区间长度较大return goldenSectionSearch(x4, x2, x3,tau); // 以x4,x2,x3作为新三点,继续搜索}}}斐波那契搜索斐波那契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、····,在数学上,斐波那契被递归方法如下定义:F(1)=1,F(2)=1,F(n)=f(n-1)+F(n-2) (n>=2)。该数列越往后相邻的两个数的比值越趋向于黄金比例值(0.618)。斐波那契查找就是在二分查找的基础上根据斐波那契数列进行分割的。在斐波那契数列找一个等于略大于查找表中元素个数的数F[n],将原查找表扩展为长度为F[n](如果要补充元素,则补充重复最后一个元素,直到满足F[n]个元素),完成后进行斐波那契分割,即F[n]个元素分割为前半部分F[n-1]个元素,后半部分F[n-2]个元素,找出要查找的元素在那一部分并递归,直到找到。斐波那契查找的时间复杂度还是O(log 2 n ),但是与折半查找相比,斐波那契查找的优点是它只涉及加法和减法运算,而不用除法,而除法比加减法要占用更多的时间,因此,斐波那契查找的运行时间理论上比折半查找小,但是还是得视具体情况而定。对于斐波那契数列:1、1、2、3、5、8、13、21、34、55、89……(也可以从0开始),前后两个数字的比值随着数列的增加,越来越接近黄金比值0.618。比如这里的89,把它想象成整个有序表的元素个数,而89是由前面的两个斐波那契数34和55相加之后的和,也就是说把元素个数为89的有序表分成由前55个数据元素组成的前半段和由后34个数据元素组成的后半段,那么前半段元素个数和整个有序表长度的比值就接近黄金比值0.618,假如要查找的元素在前半段,那么继续按照斐波那契数列来看,55 = 34 + 21,所以继续把前半段分成前34个数据元素的前半段和后21个元素的后半段,继续查找,如此反复,直到查找成功或失败,这样就把斐波那契数列应用到查找算法中了。