Last active
April 4, 2023 16:17
-
-
Save mindcont/61d89e308215a4e41c81 to your computer and use it in GitHub Desktop.
旅行商问题(TSP)利用遗传算法解决-Matlab
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function varargout = tsp_ga(xy,dmat,pop_size,num_iter,show_prog,show_res) | |
%tsp_ga旅行商问题(TSP)的遗传算法(GA) | |
% 查找(近)的最佳解决方案,通过设置一个遗传算法搜索到的旅行商 | |
% 的最短路线(最少的推销员旅行到每个城市准确的一次,回到起点城市) | |
% | |
%概要: | |
% 1、一个单一的推销员旅行到每个城市和完成 | |
% 他从一开始就开始返回城市的路线 | |
% 2、每一个城市都有一次被推销员拜访过 | |
% | |
%输入: | |
% XY(float)是城市位置的NX2矩阵,其中n是城市数量 | |
% DMAT(float)是一个n×n矩阵的点对点的距离 | |
% pop_size(scalar integer)是人口规模(应该是被4整除) | |
% num_iter(scalar integer)是运行该算法所需迭代次数 | |
% show_prog(scalar logical)表明GA进步如果真的 布尔类型 真 /假 | |
% show_res(scalar logical)显示的结果如果真的 | |
% | |
%输出: | |
% opt_rte(整数数组)的算法找到最佳路线 | |
% min_dist(标量浮点)是最优路径的成本 | |
% | |
% 2D Example: | |
% n = 50; | |
% xy = 10*rand(n,2);rand函数产生由在(50, 2)之间均匀分布的随机数组成的数组。 | |
% pop_size = 60; | |
% num_iter = 1e4; | |
% show_prog = 1; | |
% show_res = 1; | |
% a = meshgrid(1:n); | |
% dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),n,n); | |
% [opt_rte,min_dist] = tsp_ga(xy,dmat,pop_size,num_iter,show_prog,show_res); | |
% | |
% 3D Example: | |
% n = 50; | |
% xyz = 10*rand(n,3); | |
% pop_size = 60; | |
% num_iter = 1e4; | |
% show_prog = 1; | |
% show_res = 1; | |
% a = meshgrid(1:n); | |
% dmat = reshape(sqrt(sum((xyz(a,:)-xyz(a',:)).^2,2)),n,n); | |
% [opt_rte,min_dist] = tsp_ga(xyz,dmat,pop_size,num_iter,show_prog,show_res); | |
% | |
% See also: mtsp_ga, tsp_nn, tspo_ga, tspof_ga, tspofs_ga, distmat | |
% | |
% Author: Joseph Kirk | |
% Email: [email protected] | |
% Release: 2.2 | |
% Release Date: 6/2/09 | |
% Process Inputs and Initialize Defaults | |
nargs = 6; | |
% nargin 在函数体内部, nargin是用来判断输入变量个数的函数 | |
for k = nargin:nargs-1 | |
switch k | |
case 0 | |
xy = 10*rand(50,2); | |
case 1 | |
N = size(xy,1);% size:获取数组的行数和列数 | |
a = meshgrid(1:N); % meshgrid MATLAB中用于生成网格采样点的函数 | |
dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),N,N);%n*n 距离矩阵 (任意两点之间的距离) reshape函数重新调整矩阵的行数、列数、维数 | |
case 2 | |
pop_size = 100;% 种群大小 | |
case 3 | |
num_iter = 1e4;% 代数 | |
case 4 | |
show_prog = 1;% 进化有效 | |
case 5 | |
show_res = 1;% 显示结果 | |
otherwise | |
end | |
end | |
% Verify Inputs | |
% 校验输入 | |
[N,dims] = size(xy); | |
[nr,nc] = size(dmat); | |
if N ~= nr || N ~= nc | |
error('Invalid XY or DMAT inputs!') | |
end | |
n = N; | |
% Sanity Checks | |
% 理智检查 | |
pop_size = 4*ceil(pop_size/4);% 种群规模(应该是被4整除) | |
num_iter = max(1,round(real(num_iter(1))));% 运行该算法所需迭代次数 [max] 返回一个数组各不同维中的最大元素 | |
show_prog = logical(show_prog(1));% 表明GA进步如果真的 [L = logical(A)] 输入A为实数数组,返回值L为一个与A同维的逻辑数组,当A中的元素为非零元素时,L中对应的位置返回逻辑1,否则返回逻辑0。 | |
show_res = logical(show_res(1));% 显示的结果如果真的 | |
% Initialize the Population | |
% 初始化种群 | |
pop = zeros(pop_size,n);% [zeros(m,n)]函数功能:产生m×n的double类零矩阵,zeros(n)产生n×n的全0方阵。 | |
for k = 1:pop_size | |
pop(k,:) = randperm(n);% [randperm]函数功能:随机打乱一个数字序列。 | |
end | |
% Run the GA | |
% 运行遗传算法 | |
global_min = Inf;% 最优路径的距离 | |
total_dist = zeros(1,pop_size);% 总距离矩阵 1*种群大小 | |
dist_history = zeros(1,num_iter);% 生成1*代数维的零矩阵 | |
tmp_pop = zeros(4,n);% 缓存种群4*n 维的零矩阵 | |
new_pop = zeros(pop_size,n);% 新种群 种群大小*n维的零矩阵 | |
if show_prog% 当进化有效 | |
pfig = figure('Name','TSP_GA | Current Best Solution','Numbertitle','off');%绘图 | |
end | |
for iter = 1:num_iter | |
% Evaluate Each Population Member (Calculate Total Distance) | |
% 任意两个城市之间的距离和(并计算总距离 d) | |
for p = 1:pop_size | |
d = dmat(pop(p,n),pop(p,1)); % Closed Path 封闭路径 | |
for k = 2:n | |
d = d + dmat(pop(p,k-1),pop(p,k)); | |
end | |
total_dist(p) = d;% 任意两个城市之间的距离和的和 | |
end | |
% Find the Best Route in the Population | |
% 在种群中找到最佳路线 | |
[min_dist,index] = min(total_dist);% [min()]返回一个数组各不同维中的最小元素 | |
dist_history(iter) = min_dist; | |
if min_dist < global_min% 保留距离最小值 | |
global_min = min_dist; | |
opt_rte = pop(index,:); | |
if show_prog | |
% Plot the Best Route | |
% 绘制最佳路线 | |
figure(pfig);% figure 能够创建一个用来显示图形输出的一个窗口对象 | |
rte = opt_rte([1:n 1]); | |
if dims == 3, plot3(xy(rte,1),xy(rte,2),xy(rte,3),'r.-');% 创建一个三维坐标下的图 | |
else plot(xy(rte,1),xy(rte,2),'r.-'); end | |
title(sprintf('Total Distance = %1.4f, Iteration = %d',min_dist,iter)); | |
end | |
end | |
% Genetic Algorithm Operators | |
% 遗传算法 | |
rand_pair = randperm(pop_size);% randperm 函数功能:随机打乱一个数字序列。 | |
for p = 4:4:pop_size | |
rtes = pop(rand_pair(p-3:p),:); | |
dists = total_dist(rand_pair(p-3:p)); | |
[ignore,idx] = min(dists); | |
best_of_4_rte = rtes(idx,:); | |
ins_pts = sort(ceil(n*rand(1,2)));% [sort(A)]若A是向量不管是列还是行向量,默认都是对A进行升序排列 [ceil(n)]的意思是向正方向舍入 | |
I = ins_pts(1);% 取出两个维度的坐标 | |
J = ins_pts(2); | |
% 变异 | |
for k = 1:4 % Mutate the Best to get Three New Routes 变异最好得到第三条路线 | |
tmp_pop(k,:) = best_of_4_rte; | |
switch k | |
case 2 % Flip 翻转 | |
tmp_pop(k,I:J) = fliplr(tmp_pop(k,I:J)); | |
case 3 % Swap 交换 | |
tmp_pop(k,[I J]) = tmp_pop(k,[J I]); | |
case 4 % Slide | |
tmp_pop(k,I:J) = tmp_pop(k,[I+1:J I]); | |
otherwise % Do Nothing | |
end | |
end | |
new_pop(p-3:p,:) = tmp_pop; | |
end | |
pop = new_pop; | |
end | |
if show_res | |
% Plots the GA Results | |
% 绘制遗传算法结果 | |
figure('Name','TSP_GA | Results','Numbertitle','off'); | |
subplot(2,2,1); | |
if dims == 3, plot3(xy(:,1),xy(:,2),xy(:,3),'k.'); | |
else plot(xy(:,1),xy(:,2),'k.'); end | |
% 城市位置 | |
title('City Locations'); | |
subplot(2,2,2); | |
imagesc(dmat(opt_rte,opt_rte)); | |
% 距离矩阵 | |
title('Distance Matrix'); | |
subplot(2,2,3); | |
rte = opt_rte([1:n 1]); | |
if dims == 3, plot3(xy(rte,1),xy(rte,2),xy(rte,3));% plot3(x,y,z)用来绘制3维曲线图 | |
else plot(xy(rte,1),xy(rte,2)); end | |
% 总距离 | |
title(sprintf('Total Distance = %1.4f',min_dist)); | |
subplot(2,2,4); | |
plot(dist_history,'b','LineWidth',2); | |
title('Best Solution History'); | |
% 最佳 | |
set(gca,'XLim',[0 num_iter+1],'YLim',[0 1.1*max([1 dist_history])]); %[set] Matlab中“坐标轴刻度”的不同风格 | |
end | |
% Return Outputs | |
% 返回结果 | |
if nargout | |
varargout{1} = opt_rte;% 通过varargout我们可以得到函数中多个返回值参数的返回值 | |
varargout{2} = min_dist; | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment