智能优化算法之模拟退火算法(SA)的实现(Python附源码)

一、模拟退火算法的实现思路

模拟退火算法(Simulated Annealing Algorithm,简称SA)是一种基于蒙特卡洛迭代求解策略的随机优化算法,其思想起源是于1953年由Metropolis等人提出的。由于模拟退火算法在理论上具有概率全局最优化的能力,因此它在工程控制、生产调度、信号处理、机器学习等诸多领域都得到了广泛的应用。
模拟退火算法中涉及到的概念主要有三个,这三个分别为目标函数、接受概率以及冷却进度表。
(1)目标函数
模拟退火算法的整个降温过程可以类比于在目标范围内求取最优解的过程,将金属固体的内能类比于目标函数值,当温度这个控制参数在变化时,金属固体的内能在不断改变,此时通过一定概率判断是否接受这个新的内能,即最优解。
(2)接受概率
接受概率即为判断是否接受新的内能的概率,模拟退火算法中通常使用Metropolis接受准则进行接受概率的计算,在此准则中,倘若内能朝着想要的趋势发生变化(若为求解最小值,则∆E<0,若为求解最大值,则∆E>0),则接受新的状态,否则将使用概率exp⁡(-∆E/kT)来判断是否接受新的状态,其中k为Boltzmann常数,通常取值为1.3806×10^(-23)。
(3)冷却进度表
在每个状态的变化过程中,温度值起到至关重要的作用,尤其是Metropolis接受准则中是否接受新的状态的概率直接与温度值相关,而温度应当处于一个不断降低的状态,即温度越低时,出现内能改变的可能性也会降低,因此在这里采用冷却进度表来控制温度的变化。冷却进度表是指用来控制从某高温状态T开始进行降温的幅度和趋势的管理表,假设t时刻的温度为T,那么在经典的模拟退火算法中,温度随着时间的变化趋势可以表示为T/lg⁡(1+t),而在快速模拟退火算法中,温度随着时间的变化趋势可以表示为T/⁡(1+t),这二者的区别主要表现在变化的速度上,但它们都可以帮助算法有效收敛到全局最优值处。另外在实际的应用中,时刻t可以使用迭代次数来代替。
在上述模拟退火算法原理中主要涉及到的参数分别为:初始温度T;温度下限T_min,此值主要控制温度的最低值,当达到此值时将不再进行状态的改变。

二、算法步骤

使用模拟退火算法对优化问题进行求解时的具体步骤可以归纳如下:

  1. 设置初始温度T、温度下限T_min、初始的解状态、每个温度T值下的迭代次数L以及算法停止迭代条件(一般设为当连续多个新解都没有被接受时停止算法);
  2. 根据目标函数,对初始解对应的目标函数值(适应度值)进行计算;
  3. 对初始的解进行变换,产生一个目标范围内的新解,通常采用简单的变换产生新解,例如对旧解中的全部或部分元素进行置换、互换、与随机数相加等;
  4. 根据目标函数,对新解对应的目标函数值(适应度值)进行计算;
  5. 通过新解与旧解的目标函数值(适应度值)计算它们之间的差值,然后使用Metropolis接受准则判断是否接受新解,若接受,则舍弃旧解,使用新解替代旧解;
  6. 重复上述步骤2到步骤5,直至达到迭代次数L;
  7. 判断此时是否满足停止迭代条件,若满足则输出此时的解,若不满足,则使用冷却进度表对温度进行更新;
  8. 对温度进行更新后判断是否达到温度下限值,若达到则输出此时的解,若不满足,则重复步骤6到步骤7;
  9. 当满足停止迭代条件或温度达到温度下限值时,停止算法寻优,输出此时的解状态及其对应的目标函数值。

三、实例

待求解问题:
Rosenbrock’s,取值范围为[-10,10],取值范围内的理想最优解为0,将其搜索的空间维度设为20。
在这里插入图片描述

实现源码:

#库的导入
import numpy as np
import math
import matplotlib.pyplot as plt
#待求解问题
def function(x):
    y1 = 0
    for i in range(len(x) - 1):
        y2 = 100 * ((x[i + 1] - x[i] ** 2) ** 2) + (x[i] - 1) ** 2
        y1 = y1 + y2
    y = abs(0 - y1)
    return y

def Metropolis(T, f, f_new):   #Metropolis准则
    if f_new <= f:
        return 1
    else:
        p = math.exp((f - f_new) / T)
        if np.random.rand() < p:
            return 1
        else:
            return 0


rangepop=[-10,10]    #取值范围
pn=30  #解的数量
iterators = 1000    #迭代数
alpha=0.99 #降温系数
T0=100   #初始温度
Tf=0.01 #温度终值
T=T0 #当前温度
#a1用于多个解的信息,fitness用于存储解对应的适应度值
a1=np.zeros((pn,20))
fitness=np.zeros(pn)

#对问题解进行初始化,计算初始适应度值
for j in range(pn):
    a1[j] = np.random.uniform(low=-10, high=10,size=(1, 20))
    fitness[j] = function(a1[j])
#allpg,bestpg分别表示历史最优解和适应度值
allpg,bestpg=a1[fitness.argmin()].copy(),fitness.min()
#bestfitness用于存储每次迭代时的种群历史最优适应度值
bestfitness=np.zeros(iterators)

#外循环迭代,当前温度小于终止温度的阈值
while T>Tf:
    #内循环开始迭代100次
    for i in range(iterators):
        print("generation:",i)
        #生成新的解
        for m in range(pn):
            r1 = np.random.rand()
            r2 = np.random.rand()
            a1new=a1[m]+T*(r1-r2)
            # 确保更新后的解在取值范围内
            a1new[a1new < rangepop[0]] = rangepop[0]
            a1new[a1new > rangepop[1]] = rangepop[1]
            # 计算适应度值
            fitnessnew = function(a1new)
            # Metropolis准则判断是否接受新解
            if Metropolis(T,fitness[m], fitnessnew):  # 判断是否接受新解
                a1[m] = a1new  # 如果接受新解,则进行替换
                fitness[m] = fitnessnew  #对适应度值进行替换
            # 更新历史最优解以及对应的适应度值
            if fitness[m] < bestpg:
                    bestpg = fitness[m]
                    allpg = a1[m]
        bestfitness[i]=bestpg
        print("the best fitness is:",bestfitness[i])
        # 温度按照一定的比例下降(冷却)
        T = T*alpha

#将结果进行绘图
fig=plt.figure(figsize=(12, 10), dpi=100)
plt.title('The change of best fitness',fontdict={'weight':'normal','size': 30})
x=range(1,1001,1)
plt.plot(x,bestfitness,color="red",label="SA",linewidth=3.0, linestyle="-")
plt.tick_params(labelsize=25)
plt.xlabel("Epoch",fontdict={'weight':'normal','size': 30})
plt.ylabel("Fitness value",fontdict={'weight':'normal','size': 30})
plt.xticks(range(0,1001,100))
plt.legend(loc="upper right",prop={'size':20})
plt.savefig("SA.png")
plt.show()

图中横轴为迭代次数,纵轴为最优适应度值。
智能优化算法之模拟退火算法(SA)的实现(Python附源码)_第1张图片
参考源码

你可能感兴趣的:(智能优化算法,python,模拟退火算法,人工智能)