首页 > 代码库 > 模拟退火

模拟退火

模拟退火首先从某个初始候选解开始,当温度大于0时执行循环。

在循环中,通过随机扰动产生一个新的解,然后求得新解和原解之间的能量差,如果差小于0,则采用新解作为当前解。

如果差大于0,则采用一个当前温度与能量差成比例的概率来选择是否接受新解。温度越低,接受的概率越小,差值越大,同样接受概率越小。

是否接受的概率用此公式计算:p=exp(-ΔE/T)。这里ΔE为新解与原解的差,T为当前的温度。

由于温度随迭代次数逐渐降低,因此获得一个较差的解的概率较小。

典型的模拟退火算法还使用了蒙特卡洛循环,在温度降低之前,通过多次迭代来找到当前温度下比较好的解。

这里使用模拟退火解旅行商问题,因为这个问题本身是一个NP难问题,所以也就求不到最优解,不过应该可以求得一个比较好的解,然后再手工优化。

%% 模拟退火SA
%------------------------------------------------------
%------Kermit.L--------------------------------------
%------------------------------------------------------
%% 清除历史变量
clear all;
close all;
clc;
%% 初始化数据
n = 34;
temperature_high = 1000;
temperature_low = 0.005;
step = 0.99;
iter = 50*n;
LatLon=[116.28,39.54; 121.29,31.14; 117.11,39.09; 106.32,29.32; 126.41,45.45;
125.19,43.52; 123.24,41.50; 111.48,40.49; 114.28,38.02; 112.34,37.52;
117.00,36.38; 113.42,34.48; 108.54,34.16; 103.49,36.03; 106.16,38.20;
101.45,36.38; 87.36,43.48; 117.18,31.51; 118.50,32.02; 120.09,30.14;
113.00,28.11; 115.52,28.41; 114.21,30.37; 104.05,30.39; 106.42,26.35;
119.18,26.05; 113.15,23.08; 110.20,20.02; 108.20,22.48; 102.41,25.00;
90.08,29.39; 114.10,22.18; 113.35,22.14; 121.31,25.03];
x = LatLon(:,1);
y = LatLon(:,2);
h = plot([x;x(1)],[y;y(1)],‘r*-‘,‘markersize‘,5,‘linewidth‘,2);
%% 计算距离
Lon = x/180*pi;
Lat = y/180*pi;
N = length(x);
dis = ones(N);
R = 6378.140;
for i = 1:N
for j = 1:N
dLat=Lat(i)-Lat(j);
dLon=Lon(i)-Lon(j);
dis(i,j)= 2*R*asin(sqrt(sin(dLat/2)^2+sin(dLon/2)^2*cos(Lat(i))*cos(Lat(j))));
end
end
%% SA主程序
rout_number = randperm(n);
city_route = city_route(rout_number,dis);
while temperature_high > temperature_low
for i = 1:iter
[New_route_number,New_route] = change(rout_number ,dis) ;
if New_route < city_route
city_route = New_route;
rout_number = New_route_number;
elseif exp((city_route - New_route)*2/temperature_high) >rand
city_route = New_route;
rout_number = New_route_number;
end
end 
temperature_high = temperature_high *step;
set(h,‘xdata‘,x([rout_number,rout_number(1)]),‘ydata‘,y([rout_number,rout_number(1)]));
xlabel(sprintf(‘Distance=%.1f‘,city_route),‘fontsize‘,13);
title(sprintf(‘Temperature = %.1f‘,temperature_high),‘fontsize‘,13);
drawnow;
end

function [New_route_number,New_route] = change(rout_number ,dis) 
n = length(rout_number);
temp1 = ceil(n*rand);
temp2 = ceil(n*rand);
tem1 = min(temp1,temp2);
tem2 = max(temp1,temp2);
route_tem = fliplr(rout_number(tem1:tem2));
New_route_number = [rout_number(1:(tem1-1)),route_tem,rout_number((tem2+1):n)];
New_route = city_route(New_route_number,dis);
end

 

function city_route = city_route(route_number,dis)
city_route = 0;
n = length(route_number);
for i = 1:n - 1
city_route = city_route + dis(route_number(i),route_number(i+1));
end
city_route = city_route + dis(route_number(n),route_number(1));
end

 

http://www.cnblogs.com/tiandsp/category/348031.html参照

模拟退火