一维搜索方法:一维搜索,又称一维优化,是指求解一维目标函数 f(X) 最优解的过程,分为试探法和插值法。一维搜索最优化是优化方法中最简单、最基本的方法。
常用的方法有:等步长分割法、黄金分割法(0.168法)、牛顿法、二次插值法等
等步长分割法(Equal Interval Search Method)
等步长分割法属于试探法,其原理跟二分法一样。
迭代过程中压缩比例不变,只使用目标函数值f(x)。
适用范围:黄金分割法适用于[a,b]区间上任何单谷函数求极小值(存在唯一的局部极小点)问题。
思想:按照固定比例0.5取点,不断压缩极值点所在的区间,直到达到足够的精度水平。
Chapter 09.01 Golden Section Search Method算法搜索过程:
1、给出初始搜索区间[a,b],以及收敛精度ε;
2、按照公式计算下一个迭代点及函数值;
3、根据函数值确定压缩后的新区间;
4、检查新区间是否满足收敛精度b-a<=ε。
计算迭代点公式:
x1 = (a+b)/2 - ε/2
x2 = (a+b)/2 + ε/2
如果 f(x1) > f(x2) —— 搜索区间变为[a,x2] (这里函数求最大值)
如果 f(x1) < f(x2) —— 搜索区间变为[x1,b] (这里函数求最大值)
直到第一次和第二次两端值的误差在所约定的范围内时,求得最大值
此时搜索区间为[A,B],那么函数最大值为f((A+B)/2)
例题:
求函数A = 4*sinx *(1+cosx) 的最大值(x是角度)
x的范围是0~90°
收敛精度ε = 0.05
代码:
from sympy import *
a = 0 #初始下区间
b = 90 #初始上区间
dx = 0.05 #收敛精度
#函数
def func(x):
A = 4*sin(x*pi.evalf()/180)*(1+cos(x*pi.evalf()/180))
return A
#迭代过程
i = 0
while True:
i += 1
x1 = (a + b) / 2 - dx / 2
x2 = (a + b) / 2 + dx / 2
if func(x1) > func(x2):
b = x2
elif func(x1) <= func(x2):
a = x1
DX = round(abs(b - a),3) #(b-a)是不可能小于0.05的,所以让其近似于0.050即可。round()函数是保留小数点以后几位数
if DX <= dx:
print(f'迭代第{i}次,迭代精度小于等于{dx},最终的搜索区间为:{min(a, b), max(a, b)},A的最大值:{func((a + b) / 2)}')
print('确定最大值的两端值为:', func(a), func(b))
break
else:
pass
结果:
迭代第18次,迭代精度小于等于0.05,最终的搜索区间为:(59.97467308044435, 60.02501621246339),A的最大值:5.19615242266843
确定最大值的两端值为: 5.19615140730401 5.19615143223232
等步长分割法迭代+绘图
仍然是上面的例子。
代码如下:
from sympy import *
import matplotlib.pyplot as plt
#函数
def func(x):
A = 4*sin(x*pi.evalf()/180)*(1+cos(x*pi.evalf()/180))
return A
#迭代过程
def iteration(a,b,dx):
x_values = []
x_values.append(a)
x_values.append(b)
i = 0
while True:
i += 1
x1 = (a + b) / 2 - dx / 2
x2 = (a + b) / 2 + dx / 2
if func(x1) > func(x2):
b = x2
x_values.append(x2)
elif func(x1) <= func(x2):
a = x1
x_values.append(x1)
DX = round(abs(b - a),3) #(b-a)是不可能小于0.05的,所以让其近似于0.050即可
if DX <= dx:
print(f'迭代第{i}次,迭代精度小于{dx},最终的搜索区间为:{min(a, b), max(a, b)},A的最大值:{func((a + b) / 2)}')
print('确定最大值的两端值为:', func(a), func(b))
break
else:
pass
draw(x_values)
#绘图
def draw(x_values):
#设置绘图风格
plt.style.use('ggplot')
#处理中文乱码
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
#坐标轴负号的处理
plt.rcParams['axes.unicode_minus']=False
#横坐标是区间
#纵坐标是函数值
y_values = []
x_values.sort() #默认列表中的元素从小到大排列
for x in x_values:
y_values.append(func(x))
#绘制折线图
plt.plot(x_values,
y_values,
color = 'steelblue', # 折线颜色
marker = 'o', # 折线图中添加圆点
markersize = 3, # 点的大小
)
# 修改x轴和y轴标签
plt.xlabel('区间')
plt.ylabel('函数值')
# 添加图形标题
plt.title('Equal Interval Search Method求函数最大值')
# 显示图形
plt.show()
if __name__ == '__main__':
a = 0 # 初始下区间
b = 90 # 初始上区间
dx = 0.05 # 收敛精度
iteration(a,b,dx)
结果:
迭代第18次,迭代精度小于0.05,最终的搜索区间为:(59.97467308044435, 60.02501621246339),A的最大值:5.19615242266843
确定最大值的两端值为: 5.19615140730401 5.19615143223232