简介
平分法是一种简单有效的一维搜索方法,其优点是每一步的计算量都较小,程序实现简单,并且总能收敛于一个局部极小点,缺点是收敛的速度很慢。其基本思想是:若 f ( x ) f(x) f(x)在区间 [ a , b ] [a,b] [a,b]内连续且可导,即 f ( x ) ∈ C 1 [ a , b ] f(x) \in C^1[a,b] f(x)∈C1[a,b],且 f ′ ( a ) < 0 f^{'}(a)<0 f′(a)<0和 f ′ ( b ) > 0 f^{'}(b)>0 f′(b)>0,则在a,b区间内必定存在一点 x ∗ x^{*} x∗,使得 f ′ ( x ∗ ) = 0 f^{'}(x^{*})=0 f′(x∗)=0。详细的实施步骤如下:
- 令 x 0 = ( a + b ) / 2 x_0=(a+b)/2 x0=(a+b)/2,若 f ′ ( x ) > 0 f^{'}(x)>0 f′(x)>0,则 f ( x ) f(x) f(x)在 [ a , x 0 ] [a, x_0] [a,x0]上有极小点;反之,则 f ( x ) f(x) f(x)在 [ x 0 , b ] [x_0, b] [x0,b]上有极小点。
- 让 [ a , x 0 ] [a, x_0] [a,x0]或 [ x 0 , b ] [x_0, b] [x0,b]取代区间 [ a , b ] [a,b] [a,b],重复步骤1,直至 ( b − a ) < δ (b-a)< \delta (b−a)<δ, δ \delta δ表示给定的收敛精度。
从上面的步骤不难看出,平分法其实与0.618法较为相似,不同的是平分法需要用到导数信息。
优化问题
求
f
(
x
)
=
3
x
4
−
16
x
3
+
30
x
2
−
24
x
+
8
f(x)=3x^{4}-16x^{3}+30x^{2}-24x+8
f(x)=3x4−16x3+30x2−24x+8在
[
0
,
3
]
[0,3]
[0,3]上的极小值点。
计算程序如下:
def bisection_f(a, b, gap):
"""
采用平分法求解区间极小值或极大值点
:param a: 区间左端点
:param b: 区间右端点
:param gap: 收敛精度
"""
# 判断端点导数是否异号
if derivative_cal_f(a)*derivative_cal_f(b) >= 0:
sys.exit("a, b端点导数必须异号!")
if derivative_cal_f(a) < derivative_cal_f(b):
name = "极小值"
else:
name = "极大值"
i = 0
while (b-a) > gap:
d_a = derivative_cal_f(a) # 端点a的导数
d_b = derivative_cal_f(b) # 端点b的导数
x = (a+b)/2
d_x = derivative_cal_f(x)
if d_a < d_b:
if d_x > 0:
a = a
b = x
else:
a = x
b = b
else:
if d_x > 0:
a = x
b = b
else:
a = a
b = x
i += 1
print(f"第{i}次迭代{name}点", (a+b)/2)
def derivative_cal_f(x):
"""
导数计算函数
"""
return 12*x**3-48*x**2+60*x-24
if __name__ == "__main__":
bisection_f(0, 3, 1e-3)
计算结果如下所示:
第1次迭代极小值点 2.25
第2次迭代极小值点 1.875
第3次迭代极小值点 2.0625
第4次迭代极小值点 1.96875
第5次迭代极小值点 2.015625
第6次迭代极小值点 1.9921875
第7次迭代极小值点 2.00390625
第8次迭代极小值点 1.998046875
第9次迭代极小值点 2.0009765625
第10次迭代极小值点 1.99951171875
第11次迭代极小值点 2.000244140625
第12次迭代极小值点 1.9998779296875
当迭代到第12次的时候得到满足收敛精度的极小值点,即2。