这是一篇关于模拟退火算法的总结博客,包括算法思想,算法步骤,Python实现,MATLAB实现,算法进阶等。

目录

  • 1 算法思想
  • 2 算法步骤
  • 3 SA解函数最小值(python实现)
  • 4 SA解旅行商问题(MATLAB实现)
  • 5 算法进阶

1 算法思想

  1. SA是基于Monte-Carlo 迭代求解策略的一种随机寻优算法;出发点是基于物理中固体物质的退火过程与组合最优化问题(NP完全问题)之间的相似性。GA其实也是一种Greedy算法,但它比Greedy改进的地方就在于,它的搜索过程用到了Metropolis准则,也就是以一定的概率来接受一个比当前解要差的解,因此有可能会跳出局部最优解,找到全局最优解。
  2. Monte-Carlo 基本思想:利用大量采样的方法来求解一些难以直接计算得到的积分。例如,假想你有一袋豆子,把豆子均匀地朝一个形状超级不规则的图形上撒,然后数这个图形之中有多少颗豆子,这个豆子的数目就是图形的面积。当你的豆子越小,撒的越多的时候,结果就越精确。借助计算机程序可以生成大量均匀分布坐标点,然后统计出图形内的点数,通过它们占总点数的比例和坐标点生成范围的面积就可以求出图形面积。(这里我没有明白SA中具体哪里用到了Monte-Carlo思想)
  3. 物理中固体物质的退火过程:

    首先物体刚开始处于非晶体状态(左图)。我们将固体加温至充分高,固体内部粒子随温升变为无序状,能量增大,可以自由运动和重新排列(中图)。再让其缓慢冷却,粒子渐趋有序,在每个温度都达到平衡态,最后完全冷却时能量减为最小,物体形成晶体形态,这就是退火(右图)。

2 算法步骤

look这个函数,我们要求它的最小值。

模拟退火算法是这么做的:

  1. 设定初始温度 T0T_0T0​,终止温度TfT_fTf​,降温速度0<rate<10<rate<10<rate<1,T0T_0T0​要取的很高,相当于加温到很高的温度。TfT_fTf​要取的很小,相当于基态,rateraterate越大,降温越慢。取一个起始点x,算出函数值 f(x)。
  2. 当 T0>TfT_0>T_fT0​>Tf​时,随机让 x 移动,计算新的函数值 f(x+1);
  3. 根据Metropolis准则进行判断:
    (1)如果新值 f(x + 1) < 当前值f(x) ,以概率1把当前值更新为新值;这很好理解,如果你发现移动到的新点求出来的值更小,肯定要更新当前值;
    (2)如果f(x + 1) > f(x) ,计算概率P=exp(−f(x+1)−f(x)T0)P = exp(-\frac{f(x + 1)-f(x)}{T_0})P=exp(−T0​f(x+1)−f(x)​)。取一个随机数0<r<10<r<10<r<1,当r<Pr<Pr<P时把当前值更新为新值,否则不更新。可以发现,当前温度T0T_0T0​越大,指数函数括号里的值越大,接受这个新值的概率P越大。随着迭代次数的增加,T0T_0T0​会越来越小,接受新值的概率P也会越来越小,相当于渐渐冷却了下来,趋于稳定的状态。
  4. 进行一次降温:T0=T0∗rateT_0=T_0*rateT0​=T0​∗rate,转到步骤2.

伪代码:

求函数f(x)的最小值
T0:         系统的初始温度(高温状态)
Tf:      温度的下限
rate:       控制降温的速率
f(now):      系统当前状态的评价函数值
f(new):    系统新状态的评价函数值while (T0 > Tf)
{if f(new) - f(now) < 0f(now) = f(new)else if (exp(f(new) - f(now) / T0) > random(0,1))f(now) = f(new)else不更新f(now)T0 = T0 * rate;更新状态new                
}循环结束,得到模拟退火求得的最小值f(now)

3 SA解函数最小值(python实现)

求下列函数的最小值:
f(x)=x3−60x2−4x+6f(x)= x^3-60x^2-4x+6 f(x)=x3−60x2−4x+6
定义域为[0,100][0,100][0,100]

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
import math# define aim function
def aimFunction(x):y = x ** 3 - 60 * x ** 2 - 4 * x + 6return yx = [i / 10 for i in range(1000)]
y = [0 for i in range(1000)]
for i in range(1000):y[i] = aimFunction(x[i])plt.plot(x, y)
T = 1000  # initiate temperature
Tmin = 10  # minimum value of terperature
x = np.random.uniform(low=0, high=100)  # initiate x
k = 50  # times of internal circulation
y = 0  # initiate result
t = 0  # time
while T >= Tmin:for i in range(k):# calculate yy = aimFunction(x)# generate a new x in the neighboorhood of x by transform functionxNew = x + np.random.uniform(low=-0.055, high=0.055) * Tif (0 <= xNew and xNew <= 100):yNew = aimFunction(xNew)if yNew - y < 0:x = xNewelse:# metropolis principlep = math.exp(-(yNew - y) / T)r = np.random.uniform(low=0, high=1)if r < p:x = xNewt += 1print(t)T = 1000 / (1 + t)  #降温函数,也可使用T=0.9Tprint(x, aimFunction(x))

通过求导计算得到的精确最小值为 40.033,运行求得的最小值为40.072。

4 SA解旅行商问题(MATLAB实现)

代码来源

  1. 总函数:
%% I. 清空环境变量
clear all
clc%% II. 导入城市位置数据
X = [16.4700   96.100016.4700   94.440020.0900   92.540022.3900   93.370025.2300   97.240022.0000   96.050020.4700   97.020017.2000   96.290016.3000   97.380014.0500   98.120016.5300   97.380021.5200   95.590019.4100   97.130020.0900   92.5500];%% III. 计算距离矩阵
D = Distance(X);  %计算距离矩阵
n = size(D,1);    %城市的个数%% IV. 初始化参数
T0 = 1e10;                                                                  % 初始温度
Tf = 1e-30;                                                                 % 终止温度
q = 0.9;                                                                    % 降温速率
Time = ceil(double(solve([num2str(T0) '*(0.9)^x = ', num2str(Tf)])));       % 计算迭代的次数 T0 * (0.9)^x = Tf
count = 0;                                                                  % 初始化迭代计数
Obj = zeros(Time, 1);                                                       % 目标值矩阵初始化
path = zeros(Time, n);                                                      % 每代的最优路线矩阵初始化%% V. 随机产生一个初始路线
S1 = randperm(n);
DrawPath(S1, X)                                                             % 画出初始路线
disp('初始种群中的一个随机值:')
OutputPath(S1);                                                             % 用箭头的形式表述初始路线
rlength = PathLength(D, S1);                                                % 计算初始路线的总长度
disp(['总距离:', num2str(rlength)]);%% VI. 迭代优化
while T0 > Tfcount = count + 1;                                                      % 更新迭代次数%temp = zeros(L,n+1);% 1. 产生新解S2 = NewAnswer(S1);% 2. Metropolis法则判断是否接受新解[S1, R] = Metropolis(S1, S2, D, T0);                                    % Metropolis 抽样算法% 3. 记录每次迭代过程的最优路线if count == 1 || R < Obj(count-1)                                       % 如果当前温度下的距离小于上个温度的距离,记录当前距离Obj(count) = R;                                                    elseObj(count) = Obj(count-1);                                         endpath(count,:) = S1;                                                     % 记录每次迭代的路线T0 = q * T0;                                                            % 以q的速率降温
end%% VII. 优化过程迭代图
figure
plot(1: count, Obj)
xlabel('迭代次数')
ylabel('距离')
title('优化过程')
grid on%% VIII. 绘制最优路径图
DrawPath(path(end, :), X)                                                   % path矩阵的最后一行一定是最优路线%% IX. 输出最优解的路线和总距离
disp('最优解:')
S = path(end, :);
p = OutputPath(S);
disp(['总距离:', num2str(PathLength(D, S))]);
  1. Metropolis准则判定函数:
function [S,R] = Metropolis(S1, S2, D, T)
%% 输入
% S1:  当前解
% S2:   新解
% D:    距离矩阵(两两城市的之间的距离)
% T:    当前温度
%% 输出
% S:   更新后的当前解
% R:   更新后的路线距离R1 = PathLength(D, S1);         % 计算S1路线长度
n = length(S1);                 % 城市的个数R2 = PathLength(D,S2);          % 计算S2路线长度
dC = R2 - R1;                   % 计算能力之差
if dC < 0                       % 如果能力降低 接受新路线S = S2;                     % 接受新解R = R2;
elseif exp(-dC/T) >= rand       % 以exp(-dC/T)概率接受新路线S = S2;R = R2;
else                            % 不接受新路线S = S1;R = R1;
end
end
  1. 更新新解的函数:
function S2 = NewAnswer(S1)
% 输入:当前解S1
% 输出:新解S2n = length(S1);
S2 = S1;
a = round(rand(1, 2) * (n - 1) + 1);    %产生两个随机位置,用于交换
W = S2(a(1));
S2(a(1)) = S1(a(2));
S2(a(2)) = W;
  1. 计算两两城市之间的距离:
function D = Distance(citys)
% 输入:各城市的位置坐标(citys)
% 输出:两两城市之间的距离(D)n = size(citys, 1);
D = zeros(n, n);
for i = 1: nfor j = i + 1: nD(i, j) = sqrt((citys(i, 1) - citys(j, 1))^2 + (citys(i, 2) - citys(j, 2))^2);D(j, i) = D(i, j);end
end
  1. 画路径函数:
function DrawPath(Route, citys)
%% 画路径函数
% 输入
% Route  待画路径
% citys  各城市坐标位置%画出初始路线
figure
plot([citys(Route, 1); citys(Route(1), 1)], [citys(Route, 2); citys(Route(1), 2)], 'o-');
grid on%给每个地点标上序号
for i = 1: size(citys, 1)text(citys(i, 1), citys(i, 2), ['   ' num2str(i)]);
endtext(citys(Route(1), 1), citys(Route(1), 2), '       起点');
text(citys(Route(end), 1), citys(Route(end), 2), '       终点');
  1. 用箭头的形式描绘出路径方向:
function p = OutputPath(Route)
% 输入: 路径Route
% 输出: 路径函数%给R末端添加起点即R(1)
Route = [Route, Route(1)];
n = length(Route);
p = num2str(Route(1));for i = 2: np = [p, ' —> ', num2str(Route(i))];
end
disp(p)
  1. 计算起点与终点之间的路径长度
function Length = PathLength(D, Route)
%% 输入
% D 两两城市之间的距离
% Route 路线
%% 输出
起点与终点之间的路径长度LengthLength = 0;
n = length(Route);for i = 1: (n - 1)Length = Length + D(Route(i), Route(i + 1));
endLength = Length + D(Route(n), Route(1));

运行了上述代码后,得到的结果如下:

初始解:
11 —> 10 —> 14 —> 9 —> 5 —> 3 —> 7 —> 4 —> 8 —> 1 —> 2 —> 13 —> 12 —> 6 —> 11
总距离:62.7207
SA求得的最优解:
9 —> 11 —> 8 —> 13 —> 7 —> 12 —> 6 —> 5 —> 4 —> 3 —> 14 —> 2 —> 1 —> 10 —> 9
总距离:29.3405

随着迭代次数的增加,SA找到的最短路径变化图如下:

可以看出,随着不断的迭代,距离是一直在不断下降的。我们不能保证最终的答案一定是最短的,迭代的次数越多,得到的结果就越接近正确答案。但是迭代次数过多就会需要很长的计算时间,所以要适当选择迭代次数。

5 算法进阶

1 算法特点:

  1. 如果rateraterate太小,降温就会太快,很可能最终得不到全局最优解。
  2. 理论上来说,只要rateraterate足够大,降温过程足够慢,就一定可以找到全局最优解。但对于计算机来说,rateraterate太大会影响计算速度。所以要找到一个合适的方法来权衡解的性能和计算速度。
  3. 可以为循环结束再加一个条件,当连续m次迭代都没有更新当前最优值时,可以认为已经找到了全局最优值,可以提前结束算法。找到一个合适的m值是一个问题。
  4. 初始温度的选择和可行解的邻域也需要研究。
  5. 模拟退火在求解规模较大的问题时,收敛速度很慢。

2 改进的可行方案:

  1. 设计合适的状态产生函数;
  2. 设计高效的退火历程;
  3. 避免状态的迂回搜索;
  4. 采用并行搜索结构;
  5. 避免陷入局部极小,改进对温度的控制方式;
  6. 选择合适的初始状态;
  7. 设计合适的算法终止准则。

3 改进的方式:

  1. 增加升温或重升温过程,避免陷入局部极小;
  2. 增加记忆功能(记忆“Best so far”状态);
  3. 增加补充搜索过程(以最优结果为初始解);
  4. 对每一当前状态,采用多次搜索策略,以概率接受区域内的最优状态;
  5. 结合其它搜索机制的算法;
  6. 上述各方法的综合。

4 改进的思路:

  1. 记录“Best so far”状态,并即时更新;
  2. 设置双阈值,使得在尽量保持最优性的前提下减少计算量,即在各温度下当前状态连续 m1 步保持不变则认为Metropolis抽样稳定,若连续 m2 次退温过程中所得最优解不变则认为算法收敛。

5 改进的退火过程

  1. 给定初温t0,随机产生初始状态s,令初始最优解s*=s,当前状态为s(0)=s,i=p=0;
  2. 令t=ti,以t,s和s(i)调用改进的抽样过程,返回其所得最优解s’和当前状态s’(k),令当前状态s(i)=s’(k);
  3. 判断C(s*)<C(s*’)? 若是,则令p=p+1;否则,令s*=s*’,p=0;
  4. 退温ti+1=update(ti),令i=i+1;
  5. 判断p>m2? 若是,则转第(6)步;否则,返回第(2)步;
  6. 以最优解s*作为最终解输出,停止算法。

6 改进的抽样过程

  1. 令k=0时的初始当前状态为s’(0)=s(i),q=0;
  2. 由状态s通过状态产生函数产生新状态s’,计算增量∆C’=C(s’)-C(s);
  3. 若∆C’<0,则接受s’作为当前解,并判断C(s*’)>C(s’)? 若是,则令s*’=s’,q=0;否则,令q=q+1。若∆C’>0,则以概率exp(-∆C’/t)接受s’作为下一当前状态;
  4. 令k=k+1,判断q>m1? 若是,则转第(5)步;否则,返回第(2)步;
  5. 将当前最优解s*’和当前状态s’(k)返回改进退火过程。

时间不变的噪声算法(TINA Time-invariant noise algorithm)
状态产生函数中扰动强度不随时间改变,而是和能量大小相关,能量大的扰动大,能量小的扰动小,能量为零,扰动也为零,算法停止。

单调升温(Monotonic temperature rising) SA
在算法退火后期,温度很低且陷入局部极小解的时,算法很难跳出。因此,可以适当重新提高温度,促使算法跳出。

记忆指导SA(Simulated Annealing with Memmory Guidance ,简记为SAMG)
增加一个记忆装置,存储算法计算过程产生的最好的解,以这个解为最终解。

自适应SA算法
根据邻域搜索进展的反馈信息, 自适应确定温度变化和邻域搜索强度特点:

退火过程中温度参数变化符合幅值递减的下降总趋势, 但不排除局部升温的可能, 以保证寻求到合适的温度序列, 避免陷入局部最优;
算法的终止条件依据退火温度和邻域搜索进展状态设计;
每一温度下算法的迭代次数随温度下降而递增, 邻域搜索强度依其对目标函数的贡献动态分配;
温度变化、邻域搜索和终止条件的控制机制由算法过程自动触发。

并行性
操作并行性:各个环节同时处理;
进程并行性:同时多个算法运行;
空间并行性:解空间分解分别处理,最终组合。

传统优化算法与全局优化算法的对比:
全局优化算法:

  1. 不依赖于初始条件;
  2. 不与求解空间有紧密关系,对解域,无可微或连续的要求。求解稳健,但收敛速度慢。能获得全局最优。适合于求解空间不知的情况

传统优化算法:

  1. 依赖于初始条件。
  2. 与求解空间有紧密关系,促使较快地收敛到局部解,但同时对解域有约束,如可微或连续。利用这些约束,收敛快。
  3. 有些方法,如Davison-Fletcher-Powell直接依赖于至少一阶导数;共轭梯度法隐含地依赖于梯度。

模拟退火算法(Simulated Annealing,SA)相关推荐

  1. 数学建模——模拟退火算法(Simulated Annealing,SA)

    模拟退火算法 一.模拟退火算法概述 二.算法步骤 三.算法特点 四.模拟退火算法理解(图解) 五.Metropolis准则 六.模拟退火算法的应用 七.模拟退火算法Matlab代码 工具箱求解非线性函 ...

  2. 【opencv450-samples】旅行商问题(模拟退火算法Simulated Annealing,SA)

    运行结果 视频演示 源码: #include <opencv2/core.hpp> #include <opencv2/imgproc.hpp> #include <op ...

  3. 一文搞懂什么是模拟退火算法SImulated Annealing【附应用举例】

    本文参考了很多张军老师<计算智能>的第十章知识. 本文来源:https://blog.csdn.net/qq_44186838/article/details/109181453 模拟退火 ...

  4. 模拟退火算法(Simulated Annealing)

    模拟退火算法 说说什么是算法?有人理解是输入数据经过一些步骤的处理,最后输出.在我理解来看就是一种优化问题或者说是数值分析,无论机器学习中的算法还是深度学习的算法,寻找最优模型都是解最小损失的函数.最 ...

  5. 模拟退火(Simulated Annealing, SA)算法简介与MATLAB实现

    目录 模拟退火算法概述 算法步骤 算法特点 模拟退火算法MATLAB实现 [例1]一元/多元函数优化 [例2]TSP问题 模拟退火算法概述 模拟退火算法(Simulated Annealing,简称S ...

  6. 用模拟退火算法(simulated annealing / SA)求函数最小值

    #用模拟退火算法(simulated annealing / SA)求函数最小值 已知函数 f(x) = (x-1)^2 + 3,是求其在[ -2,2 ]的最小值时刻的解 下面为运用模拟退火算法求解上 ...

  7. 模拟退火(simulated annealing)算法详解

    模拟退火(simulated annealing)算法详解 模拟退火算法来源于固体退火原理,得益于材料统计力学的研究成果,并且该算法也是一种基于概率的算法.该算法主要用于求解最优解问题,如巡航问题.函 ...

  8. Python使用模拟退火(Simulated Annealing)算法构建优化器获取机器学习模型最优超参数组合(hyperparameter)实战+代码

    Python使用模拟退火(Simulated Annealing)算法构建优化器获取机器学习模型最优超参数组合(hyperparameter)实战+代码 目录

  9. R语言基于模拟退火(Simulated Annealing)进行特征筛选(feature selection)

    R语言基于模拟退火(Simulated Annealing)进行特征筛选(feature selection) 特征选择的目的 1.简化模型,使模型更易于理解:去除不相关的特征会降低学习任务的难度.并 ...

  10. 优化算法----模拟退火算法(Simulated Annealing,SA)

    简介 \quad\quad 模拟退火算法是80年代初发展起来的一种基于Monte Carlo迭代求解策略的随机性寻优算法.其思想最早由Metropolis等人于1953年提出,由Krikpatrick ...

最新文章

  1. Java防止Xss注入json_XSS的两种攻击方式及五种防御方式
  2. C# 获取可执行文件路径的上上级目录的方法
  3. [转]敏捷开发中编写高质量Java代码
  4. LeetCode之Longest Common Prefix
  5. linux内核相关知识
  6. NAACL 2019 | 怎样生成语言才能更自然,斯坦福提出超越Perplexity的评估新方法
  7. Linux学习十七、正规表达式练习题
  8. 连续七天熬夜3D建模师终于出手,让老板增加薪资待遇,3D建模初学者的4个技巧
  9. JDBC 编程的分析
  10. 批处理bat脚本自动配置java的jdk环境变量
  11. 音乐后期处理:音乐失真效果制作
  12. 煤岩分析仪测定煤的镜质体反射率和煤显微组分
  13. 2019写给对象的话_数组方法写给女友的一系列 JS 数组操作(建议收藏 | 内附思维导图)...
  14. 金三银四,冰河为你整理了这份20万字134页的面试圣经!!
  15. 手机端自动播放网页背景音乐代码
  16. 生成一个6位数的随机密码,且需要包括字符、数字、特殊符号
  17. PSPICE报错ERROR(ORPSIM-16276): Can‘t find library
  18. DataX二次开发——(6)kafkareader、kafkawriter的开发
  19. 论文的主要观点怎么写?
  20. MathType 6.9 安装提示关闭软件再试一次

热门文章

  1. 3ds Android emulator,【【安卓版3ds模拟器】】
  2. 鸿蒙系统开发工具DevEco Studio 2.2下载/安装教程
  3. Python缩进快捷键
  4. CSS--ps的常见操作
  5. 恒星物联-排水管网有害气体监测系统 有害气体监测
  6. 电子传真虚拟化助企业降低成本
  7. C51精简版教程(AT89C51/STC89C52)
  8. URL编码表,URL编码大全
  9. 一、使用UltraISO制作Ubuntu 系统U盘及安装
  10. 汽车 Flexry总线-笔记