当前位置:   article > 正文

模拟退火算法及Python实现_python退火算法

python退火算法

一、模拟退火算法

        模拟退火算法包含两个部分即Metropolis算法和退火过程,,分别对应内循环和外循环。外循环就是退火过程,将固体达到较高的温度(初始温度T(0)),然后按照降温系数alpha使温度按照一定的比例下降,当达到终止温度Tf时,冷却结束,即退火过程结束。
        Metropolis算法是内循环,即在每次温度下,迭代L次,寻找在该温度下能量的最小值(即最优解)。下图中所示即为在一次温度下,跌代L次,固体能量发生的变化。在该温度下,整个迭代过程中温度不发生变化,能量发生变化,当前一个状态x(n)的能量大于后一个状态x(n+1)的能量时,状态x(n)的解没有状态x(n+1)的解好,所以接受状态x(n+1)。但是如果下一状态的能量比前一个状态的能量高时,该不该接受下一状态呢?在这里设置一个接受概率P,即如果下一状态的能量比前一个状态的能量高,则接受下一状态的概率为P。

二、python实现

  1. """
  2. 模拟退火算法
  3. 问题描述,随机生成解,在解中得到函数y = (-10*x1) - (math.e ** ((-x2/10)-x3))
  4. """
  5. import math
  6. import numpy as np
  7. from random import random
  8. import matplotlib.pyplot as plt
  9. def func(x1,x2,x3): # 所要优化的函数
  10. res = (-10*x1) - (math.e ** ((-x2/10)-x3))
  11. return res
  12. class SA:
  13. def __init__(self,func,iter=100,T0=100,Tf=0.01,alpha=0.9):
  14. self.func = func
  15. self.iter = iter # 内循环迭代次数,本代码中,迭代次数为100
  16. self.alpha = alpha # 降温系数
  17. self.T0 = T0 # 初始温度
  18. self.Tf = Tf # 温度终值
  19. self.T = T0 # 当前温度
  20. self.x1 = np.random.randint(0,2,size=120) # 随机120生成解的值
  21. self.x2 = np.random.randint(0,80,size=120)
  22. self.x3 = np.random.randint(0,120,size=120)
  23. self.most_best = []
  24. """
  25. x1取是否两种可能
  26. x2取0到80的整数
  27. x3取0到120的整数
  28. """
  29. self.history = {"f": [],"T":[]}
  30. def generate_new(self,x1,x2,x3): # 扰动产生新解的过程
  31. while True:
  32. # pro = [(self.T)]
  33. x1_new = np.random.choice([0,1])
  34. x2_new = x2 + np.floor(self.T *(np.random.randint(0,5)-np.random.randint(0,5)))
  35. x3_new = x3 + np.floor(self.T *(np.random.randint(0,5)-np.random.randint(0,5)))
  36. if (x1_new in [0,1]) & (0 <= x2_new <= 80) & (0 <= x3_new <= 120): #重复得到新解。知道产生的解满足约束条件
  37. break
  38. return x1_new,x2_new,x3_new
  39. def Metrospolis(self,f,f_new): # Metrospolis法则
  40. if f_new <= f:
  41. return 1
  42. else:
  43. p = math.exp((f - f_new)/self.T)
  44. if random() < p:
  45. return 1
  46. else:
  47. return 0
  48. def best(self): # 获取最优目标函数值
  49. f_list = [] # f_list数组保存每次迭代之后的值
  50. for i in range(self.iter):
  51. f = self.func(self.x1[i%2],self.x2[i%80],self.x3[i%120])
  52. f_list.append(f)
  53. f_best = min(f_list)
  54. idx = f_list.index(f_best)
  55. return f_best, idx # f_best, idx分别表示在该温度下,迭代L次之后目标函数的最优解和最优解的下标
  56. def run(self):
  57. count = 0
  58. # 外循环迭代,当前温度小于终止温度的阈值
  59. while self.T > self.Tf:
  60. # 内循环迭代100次
  61. for i in range(self.iter):
  62. f = self.func(self.x1[i],self.x2[i],self.x3[i]) # f为迭代一次后的值
  63. x1_new, x2_new, x3_new = self.generate_new(self.x1[i], self.x2[i],self.x3[i]) #产生新解
  64. f_new = self.func(x1_new,x2_new,x3_new) # 产生新解
  65. if self.Metrospolis(f,f_new): # 判断是否接受新值
  66. self.x1[i] = x1_new # 如果接受新值,则把新值存入x数组和y数组
  67. self.x2[i] = x2_new
  68. self.x3[i] = x3_new
  69. # 迭代L次记录在该温度下最优解
  70. ft,_ = self.best()
  71. self.history['f'].append(ft)
  72. self.history['T'].append(self.T)
  73. # 温度按照一定比例下降(冷却)
  74. self.T = self.T*self.alpha
  75. count += 1
  76. # 得到最优解
  77. f_best,idx = self.best()
  78. print(f"F={f_best}, x1={self.x1[idx]}, x2={self.x2[idx]},x3={self.x3[idx]}")
  79. sa = SA(func)
  80. sa.run()
  81. plt.plot(sa.history['T'], sa.history['f'])
  82. plt.title('SA')
  83. plt.xlabel('T')
  84. plt.ylabel('f')
  85. plt.gca().invert_xaxis()
  86. plt.show()

运行结果:

结果和预想中的一致。

鸣谢:模拟退火算法详细讲解(含实例python代码)_退火算法代码详解-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/575789
推荐阅读
相关标签
  

闽ICP备14008679号