首页 > 代码库 > 数值算法:无约束优化之一维搜索方法之二分法、牛顿法、割线法

数值算法:无约束优化之一维搜索方法之二分法、牛顿法、割线法

1、二分法(一阶导)

二分法是利用目标函数的一阶导数来连续压缩区间的方法,因此这里除了要求 f 在 [a0,b0] 为单峰函数外,还要去 f(x) 连续可微。

(1)确定初始区间的中点 x(0)=(a0+b0)/2 。然后计算 f(x) 在 x(0) 处的一阶导数 f‘(x(0)), 如果 f‘(x(0)) >0 , 说明极小点位于 x(0) 的左侧,也就是所,极小点所在的区间压缩为[a0,x(0)];反之,如果 f‘(x(0)) <0,说明极小点位于x(0)的右侧,极小点所在的区间压缩为[x(0),b0];如果f‘(x(0)) = 0,说明就是函数 f(x) 的极小点。

(2)根据新的区间构造x(1),以此来推,直到f‘(x(k)) = 0,停止。

可见经过N步迭代之后,整个区间的总压缩比为(1/2)N,这比黄金分割法和斐波那契数列法的总压缩比要小。

2、牛顿法(二阶导)

这里进一步要求f(x)连续二阶可微。对于函数 f(x) 上一点 x(k),我们可以使用泰勒公式构造一个多项式函数 q(x)=f(x(k))+f‘(x(k))(x-x(k))+1/2 * f‘‘(x(k))(x-x(k))2,对 f(x)在 x(k) 附近进行局部二次拟合,q(x)可以看为f(x)的(在x(k)附近的局部)近似,因此求f(x)的极小点可以转化为求q(x)的极小点。

0=q‘(x)=f‘(x(k))+f‘‘(x(k))(x-x(k))  =>   x = x(k)  -  f‘(x(k))/f‘‘(x(k))  因此可以选择 x(k+1) = x(k)  -  f‘(x(k))/f‘‘(x(k))

牛顿法能够不断地迫使目标函数f(x)的一阶导数趋于0。x(k+1)由g(x(k))的切线产生:

技术分享

x(k+1)为g(x(k))的切线与x轴交点。随着x(k) -> x*,  g(x)->0。(g(x)为f(x)的近似)

 

注意1:牛顿法不需要计算函数值,但需要计算一阶导数和二阶导数值,且要求 f‘‘(x)>0,如果f‘‘(x)<0,则可能存在从 x(k) 到 x(k+1)反向调整,收敛到极大点,即越来越偏离极小点。

技术分享

f‘‘(x(k))>0, x(k)->x*

技术分享

f‘‘(x(k))<0, x(k)远离x*

注意2:如果x(k)的调整幅度太大可能会导致x的调整序列在极小点左右波动。

技术分享

初始点g‘(x(0))/g‘‘(x(0))太大,造成算法失效

(3)割线法

 牛顿法需要f(x)的二阶导数,如果二阶导数不存在,可以采用不同点的一阶导数对其近似,如 f‘‘(x(k))=(f‘(x(k))-f‘(x(k-1)))/(x(k)-x(k-1)),将其带入牛顿迭代公式,可以得到新的迭代公式:

 x(k+1) = x(k)  -  f‘(x(k))  *  (x(k)-x(k-1)) /(f‘(x(k))-f‘(x(k-1)))   <=>   x(k+1) = ( f‘(x(k))x(k-1)  - f‘(x(k-1)) x(k)  )    /   (    f‘(x(k))  -  f‘(x(k-1))  )

这个方法需要两个初始点 x(-1)和x(0),可以看出割线法不需要计算函数值f(x(k)),二阶导数值f‘‘(x(k)),它使用x(k)和x(k-1)之间的割线产生x(k+1)

技术分享

x(k+1)由过x(k)和x(k-1)的割线产生

(4)拟抛物线插值法

迭代算法跟割线法类似,不同点为使用三个点的函数值近似公式中的两个一阶导数。

 

 

[测试数据]:fx.dat  minx.dat

[算法代码]:test.cpp  binaryseg.a   binayseg.so   newton.a   newton.so   secant.a   secant.so

数值算法:无约束优化之一维搜索方法之二分法、牛顿法、割线法