例子1:实现最小值的求解,对于求一元方程的最优解
原文:链接https://blog.csdn.net/i_csdn_water/article/details/108171231?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%A8%A1%E6%8B%9F%E9%80%80%E7%81%AB%E7%AE%97%E6%B3%95%E5%8F%AF%E8%A7%86%E5%8C%96&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-4-108171231.pc_search_insert_js_new&spm=1018.2226.3001.4187
#本功能实现最小值的求解,对于求一元方程的最优解#
from matplotlib import pyplot as plt
import numpy as np
import random
import math
plt.ion()#这里需要把matplotlib改为交互状态
#目标函数
def f(x):
#只有x一个变量
return 11*np.sin(x)+7*np.cos(5*x)##注意这里要是np.sin
class SA2():
def __init__(self,hi=3,lo=-3,alf=0.95,T=100):
'''
初始化
:param hi: 产生随机变量x的最大范围
:param lo: 产生随机变量x的最小范围
:param alf: 降温系数
:param T: 初始温度
'''
#初始值设定
#目标函数
self.hi=hi#产生变量的最大范围
self.lo=lo#产生变量的最小范围
self.alf=alf#降温系数
self.T=T#初始温度
# 可视化函数(开始清楚一次然后重复的画)
def visual(self,x):
#清除当前轴
plt.cla()
#初始化画布上的轴(x_min,x_max,y_min,y_max)
plt.axis([self.lo - 1, self.hi + 1, -20, 20])
#图上坐标的x轴变量
m = np.arange(self.lo, self.hi, 0.0001)
#画函数图像
plt.plot(m, f(m))
# print(x)
# print(f(x))
#画函数上的点,这个点是去找最小值的点
plt.plot(x, f(x), marker='o', color='black', markersize='4')
plt.title('temperature={}'.format(self.T))
plt.pause(0.1) # 0.1s
# 新解的随机产生
def new(self,x):
x1 = x + self.T * random.uniform(-1, 1)
if (x1 <= self.hi) & (x1 >= self.lo):
return x1
elif x1 < self.lo:#如果在区间的左边,探索左边有没有比区间局部最小值更小的解
rand = random.uniform(-1, 1)
return rand * self.lo + (1 - rand) * x
else:#如果在区间的左边,探索右边有没有比区间局部最小值更小的解
rand = random.uniform(-1, 1)
return rand *self.hi + (1 - rand) * x
# p函数
def p(self,x, x1):
return math.exp(-abs(f(x) - f(x1)) / self.T)
def test(self):
#随机生成x,范围在(-3,3)之间
x = random.uniform(self.lo,self.hi)
while self.T > 0.0001:
#
self.visual(x)
for i in range(500):
x1 = self.new(x)
if f(x1) <= f(x):
x = x1
else:
if random.random() <= self.p(x, x1):
x = x1
else:
continue
self.T = self.T * self.alf
print('最小值为:{}'.format(f(x)))
if __name__ == '__main__':
sa2=SA2()
sa2.test()
例子2:实现最小值求解,对于二元方程的最优解
原文:链接https://blog.csdn.net/weixin_48241292/article/details/109468947?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163281216716780264076497%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=163281216716780264076497&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-109468947.pc_search_insert_js_new&utm_term=%E6%A8%A1%E6%8B%9F%E9%80%80%E7%81%AB%E7%AE%97%E6%B3%95&spm=1018.2226.3001.4187
import math
from random import random
import numpy as np
#模拟退火算法比较设用于已确定一定边界,求解参数
def func(x_1,x_2):
'''
优化函数(用模拟退火求他的最小)
:param x1: 参数1
:param x2: 参数2
:return:
'''
res=4*x_1**2-2.1*x_1**4+x_1**6/3+x_1*x_2-4*x_2**2+4*x_2**4
return res;
#x为公式里的x1,y为公式里面的x2
class SA:
def __init__(self,func,iter=100,T0=100,Tf=0.01,alpha=0.99):
'''
初始化参数
:param func: 函数
:param iter: 内循环迭代次数,默认=100
:param T0: 初始温度=100
:param Tf: 温度终值Tf0.01
:param alpha:降温系数,alpha=0.99s
'''
self.func=func
self.iter=iter
self.alpha=alpha
self.T0=T0
self.Tf=Tf
self.T=T0
# 随机产生iter个x1,x1和x2的绝对值不超过5(包含整数5和-5)
self.x1=np.array([random()*11-5 for i in range(iter)])
#随机产生iter个x2
self.x2=np.array([random()*11-5 for i in range(iter)])
self.most_best=[]
self.history = {'f': [], 'T': []}
def generate_new(self, x1, x2):
'''
残生新解的过程
:param x1: 参数1
:param x2: 参数2
:return:
'''
while True:
x1_new=x1+self.T*(random()-random())
x2_new=x2+self.T*(random()-random())
if(-5<=x1_new<=5)&(-5<=x2_new<=5):
break
return x1_new,x2_new
def best(self):#获取最有目标数值
f_list=[]
#f_list储存函数的结果
f_list=self.func(self.x1,self.x2)
#获取函数结果的最小值
f_best=min(f_list)
#获取函数结果的最小值下标
idx=np.argmin(f_list,axis=0)
return f_best,idx
def Metrospolis(self,f,f_new):
'''
:param f: 旧的函数最小
:param f_new: 新的x1,x2生成的函数值
:return:
'''
#f_new <= f
if f_new <= f:
return 1
else:
p = math.exp((f - f_new) / self.T)
if random() < p:
return 1
else:
return 0
def genNew(self):
for i in range(self.iter):
# 产生新解
x1_new, x2_new = self.generate_new(self.x1[i], self.x2[i])
# 产生新函数值
f_new = self.func(x1_new, x2_new)
if self.Metrospolis(self.f[i], f_new): # 判断是否接受新值
self.x1[i] = x1_new # 如果接受新值,则把新值的x,y存入x数组和y数组
self.x2[i] = x2_new
self.point .set_data(self.x1[i], self.x2[i], f_new)
def run(self):
count=0
#当当前温度小于终止温度的阈值,循环
while self.T>self.Tf:
# f为迭代一次后的值
self.f=self.func(self.x1,self.x2)
#迭代L次记录在该温度下最优解
ft,_=self.best()
self.history['f'].append(ft)
self.history['T'].append(self.T)
# 温度按照一定的比例下降(冷却)
self.T = self.T * self.alpha
count += 1
# 得到最优解
f_best, idx =self.best()
print(f"F={f_best}, x={self.x1[idx]}, y={self.x2[idx]}")
if __name__ == '__main__':
sa=SA(func)
sa.run()