MAT之GA:遗传算法(GA)解决M-TSP多旅行商问题-阿里云开发者社区

开发者社区> 一个处女座的程序猿> 正文

MAT之GA:遗传算法(GA)解决M-TSP多旅行商问题

简介: MTSP_GA Multiple Traveling Salesmen Problem (M-TSP) Genetic Algorithm (GA). Finds a (near) optimal solution to the M-TSP by setting up a GA to search for the shortest route (least distance needed for the salesmen to travel to each city exactly once and return to their starting locations) —————————
+关注继续查看

输出结果

image.png



实现代码


% MTSP_GA Multiple Traveling Salesmen Problem (M-TSP) Genetic Algorithm (GA)

%   Finds a (near) optimal solution to the M-TSP by setting up a GA to search

%   for the shortest route (least distance needed for the salesmen to travel

%   to each city exactly once and return to their starting locations)

%

% Summary:

%     1. Each salesman travels to a unique set of cities and completes the

%        route by returning to the city he started from

%     2. Each city is visited by exactly one salesman

%

% Input:

%     XY (float) is an Nx2 matrix of city locations, where N is the number of cities

%     DMAT (float) is an NxN matrix of city-to-city distances or costs

%     NSALESMEN (scalar integer) is the number of salesmen to visit the cities

%     MINTOUR (scalar integer) is the minimum tour length for any of the salesmen

%     POPSIZE (scalar integer) is the size of the population (should be divisible by 8)

%     NUMITER (scalar integer) is the number of desired iterations for the algorithm to run

%     SHOWPROG (scalar logical) shows the GA progress if true

%     SHOWRESULT (scalar logical) shows the GA results if true

%

% Output:

%     OPTROUTE (integer array) is the best route found by the algorithm

%     OPTBREAK (integer array) is the list of route break points (these specify the indices

%         into the route used to obtain the individual salesman routes)

%     MINDIST (scalar float) is the total distance traveled by the salesmen

%

% Route/Breakpoint Details:

%     If there are 10 cities and 3 salesmen, a possible route/break

%     combination might be: rte = [5 6 9 1 4 2 8 10 3 7], brks = [3 7]

%     Taken together, these represent the solution [5 6 9][1 4 2 8][10 3 7],

%     which designates the routes for the 3 salesmen as follows:

%         . Salesman 1 travels from city 5 to 6 to 9 and back to 5

%         . Salesman 2 travels from city 1 to 4 to 2 to 8 and back to 1

%         . Salesman 3 travels from city 10 to 3 to 7 and back to 10

%

% Example:

%     n = 35;

%     xy = 10*rand(n,2);

%     nSalesmen = 5;

%     minTour = 3;

%     popSize = 80;

%     numIter = 5e3;

%     a = meshgrid(1:n);

%     dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),n,n);

%     [optRoute,optBreak,minDist] = mtsp_ga(xy,dmat,nSalesmen,minTour, ...

%         popSize,numIter,1,1);

%

% Example:

%     n = 50;

%     phi = (sqrt(5)-1)/2;

%     theta = 2*pi*phi*(0:n-1);

%     rho = (1:n).^phi;

%     [x,y] = pol2cart(theta(:),rho(:));

%     xy = 10*([x y]-min([x;y]))/(max([x;y])-min([x;y]));

%     nSalesmen = 5;

%     minTour = 3;

%     popSize = 80;

%     numIter = 1e4;

%     a = meshgrid(1:n);

%     dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),n,n);

%     [optRoute,optBreak,minDist] = mtsp_ga(xy,dmat,nSalesmen,minTour, ...

%         popSize,numIter,1,1);

%

% Example:

%     n = 35;

%     xyz = 10*rand(n,3);

%     nSalesmen = 5;

%     minTour = 3;

%     popSize = 80;

%     numIter = 5e3;

%     a = meshgrid(1:n);

%     dmat = reshape(sqrt(sum((xyz(a,:)-xyz(a',:)).^2,2)),n,n);

%     [optRoute,optBreak,minDist] = mtsp_ga(xyz,dmat,nSalesmen,minTour, ...

%         popSize,numIter,1,1);

%

%

function varargout = mtsp_ga(xy,dmat,nSalesmen,minTour,popSize,numIter,showProg,showResult)


% Process Inputs and Initialize Defaults

nargs = 8;

for k = nargin:nargs-1

   switch k

       case 0

           xy = 10*rand(40,2);

       case 1

           N = size(xy,1);

           a = meshgrid(1:N);

           dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),N,N);

       case 2

           nSalesmen = 5;

       case 3

           minTour = 3;

       case 4

           popSize = 80;

       case 5

           numIter = 5e3;

       case 6

           showProg = 1;

       case 7

           showResult = 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

nSalesmen = max(1,min(n,round(real(nSalesmen(1)))));

minTour = max(1,min(floor(n/nSalesmen),round(real(minTour(1)))));

popSize = max(8,8*ceil(popSize(1)/8));

numIter = max(1,round(real(numIter(1))));

showProg = logical(showProg(1));

showResult = logical(showResult(1));


% Initializations for Route Break Point Selection

nBreaks = nSalesmen-1;

dof = n - minTour*nSalesmen;          % degrees of freedom

addto = ones(1,dof+1);

for k = 2:nBreaks

   addto = cumsum(addto);

end

cumProb = cumsum(addto)/sum(addto);


% Initialize the Populations

popRoute = zeros(popSize,n);         % population of routes

popBreak = zeros(popSize,nBreaks);   % population of breaks

popRoute(1,:) = (1:n);

popBreak(1,:) = rand_breaks();

for k = 2:popSize

   popRoute(k,:) = randperm(n);

   popBreak(k,:) = rand_breaks();

end


% Select the Colors for the Plotted Routes

pclr = ~get(0,'DefaultAxesColor');

clr = [1 0 0; 0 0 1; 0.67 0 1; 0 1 0; 1 0.5 0];

if nSalesmen > 5

   clr = hsv(nSalesmen);

end


% Run the GA

globalMin = Inf;

totalDist = zeros(1,popSize);

distHistory = zeros(1,numIter);

tmpPopRoute = zeros(8,n);

tmpPopBreak = zeros(8,nBreaks);

newPopRoute = zeros(popSize,n);

newPopBreak = zeros(popSize,nBreaks);

if showProg

   pfig = figure('Name','MTSP_GA | Current Best Solution','Numbertitle','off');

end

for iter = 1:numIter

   % Evaluate Members of the Population

   for p = 1:popSize

       d = 0;

       pRoute = popRoute(p,:);

       pBreak = popBreak(p,:);

       rng = [[1 pBreak+1];[pBreak n]]';

       for s = 1:nSalesmen

           d = d + dmat(pRoute(rng(s,2)),pRoute(rng(s,1)));

           for k = rng(s,1):rng(s,2)-1

               d = d + dmat(pRoute(k),pRoute(k+1));

           end

       end

       totalDist(p) = d;

   end


   % Find the Best Route in the Population

   [minDist,index] = min(totalDist);

   distHistory(iter) = minDist;

   if minDist < globalMin

       globalMin = minDist;

       optRoute = popRoute(index,:);

       optBreak = popBreak(index,:);

       rng = [[1 optBreak+1];[optBreak n]]';

       if showProg

           % Plot the Best Route

           figure(pfig);

           for s = 1:nSalesmen

               rte = optRoute([rng(s,1):rng(s,2) rng(s,1)]);

               if dims > 2, plot3(xy(rte,1),xy(rte,2),xy(rte,3),'.-','Color',clr(s,:));

               else plot(xy(rte,1),xy(rte,2),'.-','Color',clr(s,:)); end

               title(sprintf('Total Distance = %1.4f, Iteration = %d',minDist,iter));

               hold on

           end

           hold off

       end

   end


   % Genetic Algorithm Operators

   randomOrder = randperm(popSize);

   for p = 8:8:popSize

       rtes = popRoute(randomOrder(p-7:p),:);

       brks = popBreak(randomOrder(p-7:p),:);

       dists = totalDist(randomOrder(p-7:p));

       [ignore,idx] = min(dists); %#ok

       bestOf8Route = rtes(idx,:);

       bestOf8Break = brks(idx,:);

       routeInsertionPoints = sort(ceil(n*rand(1,2)));

       I = routeInsertionPoints(1);

       J = routeInsertionPoints(2);

       for k = 1:8 % Generate New Solutions

           tmpPopRoute(k,:) = bestOf8Route;

           tmpPopBreak(k,:) = bestOf8Break;

           switch k

               case 2 % Flip

                   tmpPopRoute(k,I:J) = tmpPopRoute(k,J:-1:I);

               case 3 % Swap

                   tmpPopRoute(k,[I J]) = tmpPopRoute(k,[J I]);

               case 4 % Slide

                   tmpPopRoute(k,I:J) = tmpPopRoute(k,[I+1:J I]);

               case 5 % Modify Breaks

                   tmpPopBreak(k,:) = rand_breaks();

               case 6 % Flip, Modify Breaks

                   tmpPopRoute(k,I:J) = tmpPopRoute(k,J:-1:I);

                   tmpPopBreak(k,:) = rand_breaks();

               case 7 % Swap, Modify Breaks

                   tmpPopRoute(k,[I J]) = tmpPopRoute(k,[J I]);

                   tmpPopBreak(k,:) = rand_breaks();

               case 8 % Slide, Modify Breaks

                   tmpPopRoute(k,I:J) = tmpPopRoute(k,[I+1:J I]);

                   tmpPopBreak(k,:) = rand_breaks();

               otherwise % Do Nothing

           end

       end

       newPopRoute(p-7:p,:) = tmpPopRoute;

       newPopBreak(p-7:p,:) = tmpPopBreak;

   end

   popRoute = newPopRoute;

   popBreak = newPopBreak;

end


if showResult

% Plots

   figure('Name','MTSP_GA | Results','Numbertitle','off');

   subplot(2,2,1);

   if dims > 2, plot3(xy(:,1),xy(:,2),xy(:,3),'.','Color',pclr);

   else plot(xy(:,1),xy(:,2),'.','Color',pclr); end

   title('City Locations');

   subplot(2,2,2);

   imagesc(dmat(optRoute,optRoute));

   title('Distance Matrix');

   subplot(2,2,3);

   rng = [[1 optBreak+1];[optBreak n]]';

   for s = 1:nSalesmen

       rte = optRoute([rng(s,1):rng(s,2) rng(s,1)]);

       if dims > 2, plot3(xy(rte,1),xy(rte,2),xy(rte,3),'.-','Color',clr(s,:));

       else plot(xy(rte,1),xy(rte,2),'.-','Color',clr(s,:)); end

       title(sprintf('Total Distance = %1.4f',minDist));

       hold on;

   end

   subplot(2,2,4);

   plot(distHistory,'b','LineWidth',2);

   title('Best Solution History');

   set(gca,'XLim',[0 numIter+1],'YLim',[0 1.1*max([1 distHistory])]);

end


% Return Outputs

if nargout

   varargout{1} = optRoute;

   varargout{2} = optBreak;

   varargout{3} = minDist;

end


   % Generate Random Set of Break Points

   function breaks = rand_breaks()

       if minTour == 1 % No Constraints on Breaks

           tmpBreaks = randperm(n-1);

           breaks = sort(tmpBreaks(1:nBreaks));

       else % Force Breaks to be at Least the Minimum Tour Length

           nAdjust = find(rand < cumProb,1)-1;

           spaces = ceil(nBreaks*rand(1,nAdjust));

           adjust = zeros(1,nBreaks);

           for kk = 1:nBreaks

               adjust(kk) = sum(spaces == kk);

           end

           breaks = minTour*(1:nBreaks) + cumsum(adjust);

       end

   end

end


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
JAVA常见算法题(十八)
package com.xiaowu.demo; /** * 两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人,以抽签决定比赛名单。 有人向队员打听比赛的名单:a说他不和x比,c说他不和x、 * z比。
555 0
JAVA常见算法题(十九)
package com.xiaowu.demo; /** * * 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。 * * * @author WQ * */ public class Demo19 { public...
581 0
JAVA常见算法题(十)
package com.xiaowu.demo; /** * 一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下……求它在第10次落地时,共经过多少米?第10次反弹多高? * * @author WQ * */ public class Demo10 { pub...
601 0
JAVA常见算法题(十二)
package com.xiaowu.demo; /** * 完全平方即用一个整数乘以自己例如1*1,2*2,3*3等,依此类推。若一个数能表示成某个整数的平方的形式,则称这个数为完全平方数。 * 完全平方数是非负数,而一个完全平方数的项有两个。
635 0
JAVA常见算法题(十五)
package com.xiaowu.demo; /** * * 输入三个整数x,y,z,请把这三个数由小到大输出。 * * @author WQ * */ public class Demo15 { public static void main(String[] ar...
533 0
JAVA常见算法题(十四)
package com.xiaowu.demo; /** * 输入某年某月某日,判断这一天是这一年的第几天? * * * @author WQ * */ public class Demo14 { public static void main(String[] arg...
703 0
JAVA常见算法题(十一)
package com.xiaowu.demo; /** * 有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? * * * @author WQ * */ public class Demo11 { public static void ma...
548 0
+关注
一个处女座的程序猿
国内互联网圈知名博主、人工智能领域优秀创作者,全球最大中文IT社区博客专家、CSDN开发者联盟生态成员、中国开源社区专家、华为云社区专家、51CTO社区专家、Python社区专家等,曾受邀采访和评审十多次。仅在国内的CSDN平台,博客文章浏览量超过2500万,拥有超过57万的粉丝。
1701
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载