一维搜索方法:一维搜索,又称一维优化,是指求解一维目标函数 f(X) 最优解的过程,分为试探法和插值法。一维搜索最优化是优化方法中最简单、最基本的方法。
常用的方法有:等步长分割法、黄金分割法(0.168法)、牛顿法、二次插值法等
理论参考链接:
一维搜索的最优方法(黄金分割法)
黄金分割法(Golden Section Search Method)
黄金分割法:属于一维搜索方法中的试探法。
#数学家华罗庚运用黄金分割法提出一种可以尽可能减少做试验次数、尽快地找到最优方案的方法——优选法
使用范围:适用于[a,b]区间上的任何单谷函数求极值问题。
思想:按照固定比例0.618取点,不断压缩极小点所在的区间,直到达到足够的精度水平。
黄金分割的额来源:
算法搜索过程:
黄金分割法计算框图:
例题
求函数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 = b - 0.618*(b-a)
x2 = a + 0.618*(b-a)
if func(x1) > func(x2):
b = x2
elif func(x1) <= func(x2):
a = x1
DX = abs(b-a)
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
结果:
迭代第16次,迭代精度小于等于0.05,最终的搜索区间为:(59.97388749678212, 60.01463097588722),A的最大值:5.19615237054102
确定最大值的两端值为: 5.19615134333327 5.19615208389224
黄金分割法迭代+绘图
仍然是上面的例子。
代码如下:
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 = b - 0.618*(b-a)
x2 = a + 0.618*(b-a)
if func(x1) > func(x2):
b = x2
x_values.append(x2)
elif func(x1) <= func(x2):
a = x1
x_values.append(x1)
DX = abs(b-a)
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('Golden Section Search Method求函数最大值')
# 显示图形
plt.show()
if __name__ == '__main__':
a = 0 # 区间下限
b = 90 # 区间上限
dx = 0.05 # 迭代精度
iteration(a, b, dx)
结果:
迭代第16次,迭代精度小于0.05,最终的搜索区间为:(59.97388749678212, 60.01463097588722),A的最大值:5.19615237054102
确定最大值的两端值为: 5.19615134333327 5.19615208389224