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