随手分享一个退火算法求tsp的matlab代码
主函数
clear;clc;
load china; % 加载地图中各个城市的经度和纬度
plotcities(province, border, city); % 绘制中国地图
numberofcities = length(city); % 城市的数量
%dis(i,j)指的是i和j之间的距离
dis = distancematrix(city);
temperature = 1000; % 初始化温度
cooling_rate = 0.92; % 冷却速率 0.8——0.99
iterations = 1; % 初始化初值
% 获取一个确定的随机数
rand('seed',0);
% 随机组合:numberofcities
route = randperm(numberofcities);
% 计算总路程
previous_distance = totaldistance(route,dis);
% 初始化温度迭代次数,当迭代温度达到100时,进行降温
temperature_iterations = 1;
% This is a flag used to plot the current route after 200 iterations
plot_iterations = 1;
% 绘制现在的路径
plotroute(city, route, previous_distance, temperature);
while 1.0 < temperature
%随机生成相邻解
temp_route = perturb(route,'reverse');
% 计算相邻解的总路程
current_distance = totaldistance(temp_route, dis);
% 计算改变的路程差
diff = current_distance - previous_distance;
% diff < 0说明当前的路程比之前的更优,换
%rand < exp(-diff/(temperature)) 以一定概率选中此解
if (diff < 0) || (rand < exp(-diff/(temperature)))
route = temp_route; %accept new route
previous_distance = current_distance;
% 更新温度和绘图、计数迭代次数
temperature_iterations = temperature_iterations + 1;
plot_iterations = plot_iterations + 1;
iterations = iterations + 1;
end
% 当温度迭代次数达到100时,进行降温
if temperature_iterations >= 100
temperature = cooling_rate*temperature;
temperature_iterations = 0;
end
% 当绘图迭代达到200次时,取当前最优解
if plot_iterations >= 200
plotroute(city, route, previous_distance,temperature);
plot_iterations = 0;
end
end
% 绘制当前最优解
plotroute(city, route, previous_distance,temperature);
距离计算
function dis = distancematrix(city)
numberofcities = length(city);
R = 6378.137; %地球半径
for i = 1:numberofcities
for j = i+1:numberofcities
dis(i,j) = distance(city(i).lat, city(i).long, ...
city(j).lat, city(j).long, R);
dis(j,i) = dis(i,j);
end
end
function d = distance(lat1, long1, lat2, long2, R)
% DISTANCE
% d = DISTANCE(lat1, long1, lat2, long2, R) compute distance between points
% on sphere with radians R.
y1 = lat1/180*pi; x1 = long1/180*pi;
y2 = lat2/180*pi; x2 = long2/180*pi;
dy = y1-y2; dx = x1-x2;
d = 2*R*asin(sqrt(sin(dy/2)^2+sin(dx/2)^2*cos(y1)*cos(y2)));
function route = perturb(route_old, method)
% ___________ ___________
% 1. reverse: [1 2 3 4 5 6 7 8 9] -> [1 2 8 7 6 5 4 3 9]
% _ _ _ _
% 2. swap: [1 2 3 4 5 6 7 8 9] -> [1 2 8 4 5 6 7 3 9]
route = route_old;
numbercities = length(route);
%rand函数随机取:0-1
%ceil函数朝正无穷大方向取整
city1 = ceil(numbercities*rand);
city2 = ceil(numbercities*rand);
switch method
case 'reverse'
citymin = min(city1,city2);
citymax = max(city1,city2);
route(citymin:citymax) = route(citymax:-1:citymin);
case 'swap'
route([city1, city2]) = route([city2, city1]);
end
根据数据绘制地图
function h = plotcities(province, border, city)
% PLOTCITIES
% h = PLOTCITIES(province, border, city) draw the map of China, and return
% the route handle.
global h;
% 绘制中国地图
plot(province.long, province.lat, 'color', [0.7,0.7,0.7])
hold on
plot(border.long , border.lat , 'color', [0.5,0.5,0.5], 'linewidth', 1.5);
% 绘制各省之间的连线,设置为无穷,因为我们并不知道它连线的长度
h = plot(NaN, NaN, 'b-', 'linewidth', 1);
% 以绿色的点来描绘需要计算的城市
plot([city(2:end).long], [city(2:end).lat], 'o', 'markersize', 3, ...
'MarkerEdgeColor','b','MarkerFaceColor','g');
% 以北京作为出发点
plot([city(1).long],[city(1).lat],'p','markersize',5, ...
'MarkerEdgeColor','r','MarkerFaceColor','g');
%控制坐标轴axis([XMIN XMAX YMIN YMAX ZMIN ZMAX]) 设置当前所绘图像的x轴、y轴和z轴的范围。
axis([70 140 15 55]);
function plotroute(city, route, current_distance, temperature)
global h;
cycle = route([1:end, 1]);%将路线赋值给cycle 例如:1,2,3...34,1
%给每种对象的每一个属性规定了一个名字,称为属性名
% set(句柄,属性名1,属性值1,属性名2,属性值2,…)
set(h,'Xdata',[city(cycle).long],'Ydata',[city(cycle).lat]);%绘制当前
%输出现在的温度和路程
xlabel(sprintf('T = %6.1f Total Distance = %6.1f', ...
temperature, current_distance));
drawnow %将还未处理完的图像实时的显示出来
function d = totaldistance(route, dis)
d = dis(route(end),route(1)); % 返回路径,第一个城市与最后一个城市的距离route(34)-route(1)
%计算route(1)-route(2),route(2)-route(3)...route(33)-route(34)
for k = 1:length(route)-1
i = route(k);
j = route(k+1);
d = d + dis(i,j);
end