天天看點

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)

%

% 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);

%     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]));

%     numIter = 1e4;

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

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

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

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!')

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);

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();

% 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);

% 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');

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;

   % 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

           hold off

   % 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

               case 7 % Swap, Modify Breaks

               case 8 % Slide, Modify Breaks

               otherwise % Do Nothing

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

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

   popRoute = newPopRoute;

   popBreak = newPopBreak;

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;

   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])]);

% Return Outputs

if nargout

   varargout{1} = optRoute;

   varargout{2} = optBreak;

   varargout{3} = minDist;

   % 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);

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

繼續閱讀