問題描述:m個旅行商去旅游 n個城市,規定都必須從同一個出發點出發,而且返回原出發點,需要將所有的城市遍歷完畢,每個城市只能游歷一次,但是為了路徑最短可以路過這個城市多次。這個就是多旅行商問題。是在TSP問題的基礎上進行了擴展。
問題解決方案:
明確M-TSP與TSP的區別在哪里?
TSP指的是單個旅行商遍歷一圈,將所有城市旅行一遍,
MTSP指的是將城市群划分成M個組,每組采用TSP得到最短的旅行路線,所以問題的關鍵在於如何確定城市群的分組。
改良圈算法——可得到優化解但不是最優解
先得到一個哈密頓圈,然后修改權值路徑,得到新的哈密頓圈,如果新的哈密頓圈路徑權值小於初始的圈,就替換掉原來的圈,直到路徑權值最小。
用於得到一個較好的初始化種群;然后用到遺傳算法中
代碼:
clear,clc load sj.txt; x=sj(:,1:2:8);x=x(:);%將25*4矩陣變為100*1矩陣 y=sj(:,2:2:8);y=y(:); sj=[x,y]; d1=[70,40];%初始起飛基地 sj0=[d1;sj;d1];%102個基地 %計算距離矩陣d sj=sj0*pi/180; d=zeros(102); for i=1:101 for j=i+1:102 temp=cos(sj(i,1)-sj(j,1))*cos(sj(i,2))*cos(sj(j,2))+sin(sj(i,2))*sin(sj(j,2)); d(i,j)=6370*acos(temp); end end d=d+d';%對稱矩陣 L=102;w=50;dai=100; %通過改良圈算法選取優良父代A for k=1:w c=randperm(100);%把1到100這些數隨機打亂得到的一個數字序列 c1=[1,c+1,102];%染色體 flag=1; while flag>0 flag=0; for m=1:L-3 for n=m+2:L-1 if(d(c1(m),c1(n))+d(c1(m+1),c1(n+1))<d(c1(m),c1(m+1))+d(c1(n),c1(n+1))) flag=1; c1(m+1:n)=c1(n:-1:m+1); end end end end J(k,c1)=1:102; end J=J/102; J(:,1)=0;J(:,102)=1; rand('state',sum(clock)); %遺傳算法實現過程 A=J; for k=1:dai %產生 0~1 間隨機數列進行編碼 %交配產生子代 B B=A; c=randperm(w); %產生1~50隨機數 for i=1:2:w %從1到50依次兩兩配對,即i與(i+1)配對 F=2+floor(100*rand(1)); %隨機產生交叉點 temp=B(c(i),F:102); B(c(i),F:102)=B(c(i+1),F:102); B(c(i+1),F:102)=temp; %交叉更換完畢 end %變異產生子代 C by=find(rand(1,w)<0.1); %返回隨機數<0.1的位置 if length(by)==0 %如果上一步找不到,則隨機產生一個變異點 by=floor(w*rand(1))+1; end C=A(by,:); L3=length(by); for j=1:L3 bw=2+floor(100*rand(1,3)); %隨機選取三個整數 bw=sort(bw); %滿足1<u<v<w<102 C(j,:)=C(j,[1:bw(1)-1,bw(2)+1:bw(3),bw(1):bw(2),bw(3)+1:102]); %把u,v之間(包括u和v)的基因段插到w后面 end G=[A;B;C]; %獲得父代、交叉子代、變異子代合集G %在父代和子代中選擇優良品種作為新的父代 TL=size(G,1); [dd,IX]=sort(G,2);%dd為升序后的G,IX為索引 temp(1:TL)=0; for j=1:TL for i=1:101 temp(j)=temp(j)+d(IX(j,i),IX(j,i+1)); %按照新的序列重新獲得距離矩陣 end end [DZ,IZ]=sort(temp); A=G(IZ(1:w),:); %選擇目標函數值最小的w個個體進化到下一代 end path=IX(IZ(1),:) ; long=DZ(1) ; %toc xx=sj0(path,1); yy=sj0(path,2); plot(xx,yy,'-o'); --------------------- 作者:越溪 來源:CSDN 原文:https://blog.csdn.net/longxinghaofeng/article/details/77504212 版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
經典的求解MTSP問題的(起始點為同一點)的matlab代碼為:
function varargout = mtspf_ga(xy,dmat,salesmen,min_tour,pop_size,num_iter,show_prog,show_res) % MTSPF_GA Fixed Multiple Traveling Salesmen Problem (M-TSP) Genetic Algorithm (GA) % Finds a (near) optimal solution to a variation of the M-TSP by setting % up a GA to search for the shortest route (least distance needed for % each salesman to travel from the start location to individual cities % and back to the original starting place) % % Summary: % 1. Each salesman starts at the first point, and ends at the first % point, but travels to a unique set of cities in between % 2. Except for the first, each city is visited by exactly one salesman % % Note: The Fixed Start/End location is taken to be the first XY point % % 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 % SALESMEN (scalar integer) is the number of salesmen to visit the cities % MIN_TOUR (scalar integer) is the minimum tour length for any of the % salesmen, NOT including the start/end point % POP_SIZE (scalar integer) is the size of the population (should be divisible by 8) % NUM_ITER (scalar integer) is the number of desired iterations for the algorithm to run % SHOW_PROG (scalar logical) shows the GA progress if true % SHOW_RES (scalar logical) shows the GA results if true % % Output: % OPT_RTE (integer array) is the best route found by the algorithm % OPT_BRK (integer array) is the list of route break points (these specify the indices % into the route used to obtain the individual salesman routes) % MIN_DIST (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 4 2 8 10 3 7], brks = [3 7] % Taken together, these represent the solution [1 5 6 9 1][1 4 2 8 1][1 10 3 7 1], % which designates the routes for the 3 salesmen as follows: % . Salesman 1 travels from city 1 to 5 to 6 to 9 and back to 1 % . Salesman 2 travels from city 1 to 4 to 2 to 8 and back to 1 % . Salesman 3 travels from city 1 to 10 to 3 to 7 and back to 1 % % 2D Example: % n = 35; % xy = 10*rand(n,2); % salesmen = 5; % min_tour = 3; % pop_size = 80; % num_iter = 5e3; % a = meshgrid(1:n); % dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),n,n); % [opt_rte,opt_brk,min_dist] = mtspf_ga(xy,dmat,salesmen,min_tour, ... % pop_size,num_iter,1,1); % % 3D Example: % n = 35; % xyz = 10*rand(n,3); % salesmen = 5; % min_tour = 3; % pop_size = 80; % num_iter = 5e3; % a = meshgrid(1:n); % dmat = reshape(sqrt(sum((xyz(a,:)-xyz(a',:)).^2,2)),n,n); % [opt_rte,opt_brk,min_dist] = mtspf_ga(xyz,dmat,salesmen,min_tour, ... % pop_size,num_iter,1,1); % % See also: mtsp_ga, mtspo_ga, mtspof_ga, mtspofs_ga, mtspv_ga, distmat % % Author: Joseph Kirk % Email: jdkirk630@gmail.com % Release: 1.3 % Release Date: 6/2/09 % 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 salesmen = 5; case 3 min_tour = 5; case 4 pop_size = 160; case 5 num_iter = 5e3; case 6 show_prog = 1; case 7 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 - 1; % Separate Start/End City % Sanity Checks salesmen = max(1,min(n,round(real(salesmen(1))))); min_tour = max(1,min(floor(n/salesmen),round(real(min_tour(1))))); pop_size = max(8,8*ceil(pop_size(1)/8)); num_iter = max(1,round(real(num_iter(1)))); show_prog = logical(show_prog(1)); show_res = logical(show_res(1)); % Initializations for Route Break Point Selection num_brks = salesmen-1; dof = n - min_tour*salesmen; % degrees of freedom addto = ones(1,dof+1); for k = 2:num_brks addto = cumsum(addto); end cum_prob = cumsum(addto)/sum(addto); % Initialize the Populations pop_rte = zeros(pop_size,n); % population of routes pop_brk = zeros(pop_size,num_brks); % population of breaks for k = 1:pop_size pop_rte(k,:) = randperm(n)+1; pop_brk(k,:) = randbreaks(); end % Select the Colors for the Plotted Routes clr = [1 0 0; 0 0 1; 0.67 0 1; 0 1 0; 1 0.5 0]; if salesmen > 5 clr = hsv(salesmen); end % Run the GA global_min = Inf; total_dist = zeros(1,pop_size); dist_history = zeros(1,num_iter); tmp_pop_rte = zeros(8,n); tmp_pop_brk = zeros(8,num_brks); new_pop_rte = zeros(pop_size,n); new_pop_brk = zeros(pop_size,num_brks); if show_prog pfig = figure('Name','MTSPF_GA | Current Best Solution','Numbertitle','off'); end for iter = 1:num_iter % Evaluate Members of the Population for p = 1:pop_size d = 0; p_rte = pop_rte(p,:); p_brk = pop_brk(p,:); rng = [[1 p_brk+1];[p_brk n]]'; for s = 1:salesmen d = d + dmat(1,p_rte(rng(s,1))); % Add Start Distance for k = rng(s,1):rng(s,2)-1 d = d + dmat(p_rte(k),p_rte(k+1)); end d = d + dmat(p_rte(rng(s,2)),1); % Add End Distance end total_dist(p) = d; end % Find the Best Route in the Population [min_dist,index] = min(total_dist); dist_history(iter) = min_dist; if min_dist < global_min global_min = min_dist; opt_rte = pop_rte(index,:); opt_brk = pop_brk(index,:); rng = [[1 opt_brk+1];[opt_brk n]]'; if show_prog % Plot the Best Route figure(pfig); for s = 1:salesmen rte = [1 opt_rte(rng(s,1):rng(s,2)) 1]; if dims == 3, 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',min_dist,iter)); hold on end if dims == 3, plot3(xy(1,1),xy(1,2),xy(1,3),'ko'); else plot(xy(1,1),xy(1,2),'ko'); end hold off end end % Genetic Algorithm Operators rand_grouping = randperm(pop_size); for p = 8:8:pop_size rtes = pop_rte(rand_grouping(p-7:p),:); brks = pop_brk(rand_grouping(p-7:p),:); dists = total_dist(rand_grouping(p-7:p)); [ignore,idx] = min(dists); best_of_8_rte = rtes(idx,:); best_of_8_brk = brks(idx,:); rte_ins_pts = sort(ceil(n*rand(1,2))); I = rte_ins_pts(1); J = rte_ins_pts(2); for k = 1:8 % Generate New Solutions tmp_pop_rte(k,:) = best_of_8_rte; tmp_pop_brk(k,:) = best_of_8_brk; switch k case 2 % Flip tmp_pop_rte(k,I:J) = fliplr(tmp_pop_rte(k,I:J)); case 3 % Swap tmp_pop_rte(k,[I J]) = tmp_pop_rte(k,[J I]); case 4 % Slide tmp_pop_rte(k,I:J) = tmp_pop_rte(k,[I+1:J I]); case 5 % Modify Breaks tmp_pop_brk(k,:) = randbreaks(); case 6 % Flip, Modify Breaks tmp_pop_rte(k,I:J) = fliplr(tmp_pop_rte(k,I:J)); tmp_pop_brk(k,:) = randbreaks(); case 7 % Swap, Modify Breaks tmp_pop_rte(k,[I J]) = tmp_pop_rte(k,[J I]); tmp_pop_brk(k,:) = randbreaks(); case 8 % Slide, Modify Breaks tmp_pop_rte(k,I:J) = tmp_pop_rte(k,[I+1:J I]); tmp_pop_brk(k,:) = randbreaks(); otherwise % Do Nothing end end new_pop_rte(p-7:p,:) = tmp_pop_rte; new_pop_brk(p-7:p,:) = tmp_pop_brk; end pop_rte = new_pop_rte; pop_brk = new_pop_brk; end if show_res % Plots figure('Name','MTSPF_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(' Locations'); subplot(2,2,2); imagesc(dmat([1 opt_rte],[1 opt_rte])); title('Distance Matrix'); subplot(2,2,3); rng = [[1 opt_brk+1];[opt_brk n]]'; for s = 1:salesmen rte = [1 opt_rte(rng(s,1):rng(s,2)) 1] if dims == 3, 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 time = %1.4f',min_dist)); hold on; end if dims == 3, plot3(xy(1,1),xy(1,2),xy(1,3),'ko'); else plot(xy(1,1),xy(1,2),'ko'); end 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])]); end % Return Outputs if nargout varargout{1} = opt_rte; varargout{2} = opt_brk; varargout{3} = min_dist; end % Generate Random Set of Break Points function breaks = randbreaks() if min_tour == 1 % No Constraints on Breaks tmp_brks = randperm(n-1); breaks = sort(tmp_brks(1:num_brks)); else % Force Breaks to be at Least the Minimum Tour Length num_adjust = find(rand < cum_prob,1)-1; spaces = ceil(num_brks*rand(1,num_adjust)); adjust = zeros(1,num_brks); for kk = 1:num_brks adjust(kk) = sum(spaces == kk); end breaks = min_tour*(1:num_brks) + cumsum(adjust); end end end