一、TSP简介
旅行商问题,即TSP问题(Traveling Salesman Problem)又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。 TSP的数学模型
二、遗传算法简介
1 引言 2 遗传算法理论 2.1 遗传算法的生物学基础 2.2 遗传算法的理论基础 2.3 遗传算法的基本概念 2.4 标准的遗传算法 2.5 遗传算法的特点 2.6 遗传算法的改进方向 3 遗传算法流程 4 关键参数说明
三、部分源代码
clear;
clc;
tStart = tic; % 算法计时器
%************************初始化参数变量*******************************
[Num,Txt,Raw]=xlsread('provincial_ capital_coordinate12.xlsx'); %经纬度数据%
cities = Num(:,5:6);
cities=cities';
[~,cityNum]=size(cities);
maxGEN = 500;
popSize = 300; % 遗传算法种群大小
crossoverProbabilty = 0.95; %交叉概率
mutationProbabilty = 0.33; %变异概率
%********初始化种群***********
% 计算上述生成的各个城市之间的距离断
distances = calculateDistance(cities);
% 生成种群,每个个体代表一个路径
gbest = Inf;%行:Inf 无穷大
parentPop = zeros(popSize, cityNum);
% 随机打乱种群
for i=1:popSize
parentPop(i,2:cityNum-1) = randperm(cityNum-2); %randperm功能是随机打乱一个数字序列,将1-cityNum数字序列随机打乱
for a=2:cityNum-1
parentPop(i,a)=parentPop(i,a)+1;
end
parentPop(i,1)=1;
parentPop(i,cityNum)=cityNum;
end
% 定义子代种群
childPop = zeros(popSize,cityNum);
%定义每代的最小路径
minPathes = zeros(maxGEN,1);
%****************************
%**********************************************************************
%*********************GA算法选择交叉变异执行过程************************
for genNum=1:maxGEN
% 计算适应度的值,即路径总距离
[fitnessValue, sumDistance, minPath, maxPath] = fitness(distances, parentPop);
tournamentSize=4; %设置大小
for k=1:popSize
%% 以下为联赛选择法
% 随机选择父代
tourPopDistances=zeros( tournamentSize,1);
for i=1:tournamentSize
randomRow = randi(popSize);%行:返回一个介于1到popSize的伪随机整数
tourPopDistances(i,1) = sumDistance(randomRow,1);
end
% 选择最好的,即距离最小的
parent1 = min(tourPopDistances);
[parent1X,parent1Y] = find(sumDistance==parent1,1, 'first');%选出随机的4个中最短距离种群序号
parent1Path = parentPop(parent1X(1,1),:);%%选出随机的4个中最短距离种群路径
for i=1:tournamentSize
randomRow = randi(popSize);
tourPopDistances(i,1) = sumDistance(randomRow,1);
end
parent2 = min(tourPopDistances);
[parent2X,parent2Y] = find(sumDistance==parent2,1, 'first');
parent2Path = parentPop(parent2X(1,1),:);
%% 以上为联赛选择法
function [childPath] = crossover(parent1Path, parent2Path, prob)
% 交叉
random = rand();
if prob >= random %行:随机生成一个01之前的数,和概率值比较,相当于一个轮盘赌的选择,来执行概率选择执行操作
[l, length] = size(parent1Path);
childPath = zeros(l,length);
setSize = floor(length/2) -1; %行:floor 朝负无穷大方向取整
offset = randi(setSize); %行:随机 产生1-setSize之间的整数
parent1OXstart=offset; %行:0X交叉,父代1遗传给子代的片段起点
parent1OXend=setSize+offset-1; %行:0X交叉,父代1遗传给子代的片段终点
for i=parent1OXstart:parent1OXend
childPath(1,i) = parent1Path(1,i);
end
childPath(1,1) = parent1Path(1,1);%行:将路径的起点和终点直接赋给子代,因为起点和终点不变
childPath(1,length) = parent1Path(1,length);
%行:parent2依顺序放入子代位坐标
parent2Point=2;
for x=2:length-1
if childPath(1,x)==0
for y=parent2Point:length-1
if ~any(childPath == parent2Path(1,y))%行:如果子代路径相应元素不等于父代元素
childPath(1,x)=parent2Path(1,y);
parent2Point=y+1;
break;
end
end
end
end
else
childPath = parent1Path;
end
end
function [ bestPopPath ] = paint( cities, pop, minPath, totalDistances,gen)
gNumber=gen;
[~, length] = size(cities);
xDots = cities(1,:);
yDots = cities(2,:);
%figure(1);
%行:先画城市的固定坐标
plot(xDots,yDots, 'p', 'MarkerSize', 10, 'MarkerFaceColor', 'green');
xlabel('经度');
ylabel('纬度');
axis equal
[num,txt,raw]=xlsread('provincial_ capital_coordinate12.xlsx'); %经纬度数据%
text(xDots(1)+0.2,yDots(1)+0.2,txt(1+1,2),'FontSize',9.5,'Color','red','FontWeight','Bold') ; %先画起点,突出起点
for i=2:length-1
text(xDots(i)+0.2,yDots(i)+0.2,txt(i+1,2),'FontSize',8,'Color','blue','FontWeight','Bold') ; %加上0.01使标号和点不重合,可以自己调整
end
function [n_citys,city_position] = Read(filename)
fid = fopen(filename,'rt');%行:“rt”以文本方式读出
location=[];
A = [1 2];
tline = fgetl(fid);%行:从文件中读取一行数据,并去掉行末的换行符。
while ischar(tline)
if(strcmp(tline,'NODE_COORD_SECTION'))
while ~isempty(A)
A=fscanf(fid,'%f',[3,1]);
if isempty(A)
break;
end
location=[location;A(2:3)'];
end
end
tline = fgetl(fid);
if strcmp(tline,'EOF')
break;
end
四、运行结果
五、matlab版本及参考文献
1 matlab版本 2014a
2 参考文献 [1] 包子阳,余继周,杨杉.智能优化算法及其MATLAB实例(第2版)[M].电子工业出版社,2016. [2]张岩,吴水根.MATLAB优化算法源代码[M].清华大学出版社,2017.