考虑一维求极小值问题,假设f(x)在[a, b]内处处有定义,且有极小值,
由于总是假设不知道这个函数确切的函数图像
考虑计算机的特性,选择一系列自变量序列x0, x1, ... , xn,
得到其函数值序列 f(x0), f(x1), ... f(xn)
如果这个函数值序列不断减小,即 f(x0) ≥ f(x1) ≥ ... ≥ f(xn)
当迭代次数足够多时,总是能足够接近f(x)在区间[a, b]上的最小值
图1:初始搜索区间确定的算法示意
下面用两端代码求f(x) = 3x3 - 4x + 2 这个函数的最小值
def oriInterval():
x1 = 0
h1 = 1
h = h1
y1 = objFun(x1)
x2 = x1 + h1
y2 = objFun(x1 + h1)
if y1 > y2:
h = 2 * h1
x3 = x1 + h
y3 = objFun(x3)
while y2 > y3:
x3 = x1 + h
y3 = objFun(x3)
if y2 > y3:
h = 2 * h
x1 = x2
x2 = x3
return minValue(x1, x3), maxValue(x1, x3)
if y1 < y2:
h = -2 * h1
x3 = x1 + h
y3 = objFun(x3)
while y2 > y3:
x3 = x1 + h
y3 = objFun(x3)
if y2 > y3:
h = 2 * h
x1 = x2
x2 = x3
return minValue(x1, x3), maxValue(x1, x3)
if y1 == y2:
return x1, x2
图2:python实现初始搜索区间确定算法
step2: 根据区间消去原理在[a, b]内不断缩小此区间,
区间消去原理说明:
在step1给出的初始搜索区间[a, b],在这个区间内任取两点a1, b1, 其中a < a1 < b1 < b
选取a1, b1的方法有
Met1: 黄金分割法
图3:黄金分割法程序线框图
ret = oriInterval()
print(f'初始搜索区间为:{ret}')
e = 0.2
a = ret[0]
b = ret[1]
print(ret[0])
print(ret[1])
a1 = a + (1 - 0.618) * (b - a)
b1 = a + 0.618 * (b - a)
y1 = objFun(a1)
y2 = objFun(b1)
while (b - a) > e:
if y1 < y2:
b = b1
b1 = a1
y2 = y1
a1 = a + (1 - 0.618) * (b - a)
y1 = objFun(a1)
else:
a = a1
a1 = b1
y1 = y2
b1 = a + 0.618 * (b - a)
y2 = objFun(b1)
midRet = 0.5 * (a + b)
retValue = objFun(midRet)
print(f'最小点是{midRet}, 最小值是{retValue}')
图4:黄金分割法实现在给定初使点x = 0、步长h = 1、误差精度e = 0.2下的函数极小值
分支说明:
case1:
f(a1) < f(b1)
极小点在[a, b1]上
case2:
f(a1) > f(b1)
极小点在[a1, b]上
case3:
f(a1) = f(b1)
极小点在[a1, b1]上