【MATLAB】遗传算法(GA)求解TSP问题


1. 概述

∙ \bullet 产生:1975念,Holland提出GA

∙ \bullet 来源:生物的进化:自然选择、适者生存;生物的遗传变异。

∙ \bullet 基本思想

▹ \triangleright 根据问题目标函数构造适应度函数(fitness function)

▹ \triangleright 产生一个初始种群(100-1000)

▹ \triangleright 根据适应度函数的好坏,不断的进行选择、交叉、变异、繁衍

▹ \triangleright 若干代后得到适应度函数最好的个体即最优解

∙ \bullet 构成元素

▹ \triangleright 种群(Population),种群大小(Pop-size)

▹ \triangleright 基因编码方法(Gene Representation):一般使用二进制编码方法(就情况而定),生成一连串的二进制串。

▹ \triangleright 遗传算子(Genetic Operator):交叉(Crossover)算子、变异(Mutation)算子。

▹ \triangleright 选择策略:一般为正比选择,选择种群中适应度高的个体,适者生存优胜劣汰。

▹ \triangleright 停止准则(Stopping Rule/Criterion):一般是指定最大迭代次数。


2. 基本GA

∙ \bullet GA流程图

∙ \bullet 解空间与编码空间的转换:一般情况下编码空间为二进制串,而解空间为十进制数字,所以进行遗传操作时,使用二进制串,计算适应度以及返回结果时,转换为十进制数字。

∙ \bullet 对于TSP问题,我们把染色体设置为 n 个城市的随机序列,表示旅游的路线。


3. 具体实现过程

3.1 tsp.m

t s p tsp tsp 函数生成指定城市坐标,并且形成距离矩阵。再这里我们写好了 10、30、48、50、75 城市坐标,用的时候直接调用即可,如果自己有城市坐标,也可以带入自己的城市坐标。

function [DLn,cityn]=tsp(n)
%输入参数n为城市个数,返回参数Dln为n×n的距离矩阵,cityn为n×2的城市坐标矩阵

if n==10
    city10=[0.4 0.4439;0.2439 0.1463;0.1707 0.2293;0.2293 0.761;0.5171 0.9414;
        0.8732 0.6536;0.6878 0.5219;0.8488 0.3609;0.6683 0.2536;0.6195 0.2634];%10 cities d'=2.691
    for i=1:10
        for j=1:10
            DL10(i,j)=((city10(i,1)-city10(j,1))^2+(city10(i,2)-city10(j,2))^2)^0.5;
        end
    end
    DLn=DL10;
    cityn=city10;
end

if n==30
    city30=[41 94;37 84;54 67;25 62;7 64;2 99;68 58;71 44;54 62;83 69;64 60;18 54;22 60;
        83 46;91 38;25 38;24 42;58 69;71 71;74 78;87 76;18 40;13 40;82 7;62 32;58 35;45 21;41 26;44 35;4 50];%30 cities d'=423.741 by D B Fogel
    for i=1:30
        for j=1:30
            DL30(i,j)=((city30(i,1)-city30(j,1))^2+(city30(i,2)-city30(j,2))^2)^0.5;
        end
    end
    DLn=DL30;
    cityn=city30;
end

if n==48
    city48=[6734 1453;2233 10;5530 1424;401 841;3082 1644;7608 4458;7573 3716;7265 1268;6898 1885;
        1112 2049;5468 2606;5989 2873;4706 2674;4612 2035;6347 2683;6107 669;7611 5184;7462 3590;7732 4723;
        5900 3561;4483 3369;6101 1110;5199 2182;1633 2809;4307 2322;675 6;7555 4819;7541 3981;3177 756;7352 4506;
        7545 2801;3245 3305;6426 3173;4608 1198;23 2216;7248 3779;7762 4595;7392 2244;3484 2829;6271 2135;4985 140;
        1916 1569;7280 4899;7509 3239;10 2676;6807 2993;5185 3258;3023 1942;];%48cities d'=  by att48
    for i=1:48
        for j=1:48
            DL48(i,j)=((city48(i,1)-city48(j,1))^2+(city48(i,2)-city48(j,2))^2)^0.5;
        end
    end
    DLn=DL48;
    cityn=city48;
end

if n==50
    city50=[31 32;32 39;40 30;37 69;27 68;37 52;38 46;31 62;30 48;21 47;25 55;16 57;
        17 63;42 41;17 33;25 32;5 64;8 52;12 42;7 38;5 25; 10 77;45 35;42 57;32 22;
        27 23;56 37;52 41;49 49;58 48;57 58;39 10;46 10;59 15;51 21;48 28;52 33;
        58 27;61 33;62 63;20 26;5 6;13 13;21 10;30 15;36 16;62 42;63 69;52 64;43 67];%50 cities d'=427.855 by D B Fogel
    for i=1:50
        for j=1:50
            DL50(i,j)=((city50(i,1)-city50(j,1))^2+(city50(i,2)-city50(j,2))^2)^0.5;
        end
    end
    DLn=DL50;
    cityn=city50;
end

if n==75
    city75=[48 21;52 26;55 50;50 50;41 46;51 42;55 45;38 33;33 34;45 35;40 37;50 30;
        55 34;54 38;26 13;15 5;21 48;29 39;33 44;15 19;16 19;12 17;50 40;22 53;21 36;
        20 30;26 29;40 20;36 26;62 48;67 41;62 35;65 27;62 24;55 20;35 51;30 50;
        45 42;21 45;36 6;6 25;11 28;26 59;30 60;22 22;27 24;30 20;35 16;54 10;50 15;
        44 13;35 60;40 60;40 66;31 76;47 66;50 70;57 72;55 65;2 38;7 43;9 56;15 56;
        10 70;17 64;55 57;62 57;70 64;64 4;59 5;50 4;60 15;66 14;66 8;43 26];%75 cities d'=549.18 by D B Fogel
    for i=1:75
        for j=1:75
            DL75(i,j)=((city75(i,1)-city75(j,1))^2+(city75(i,2)-city75(j,2))^2)^0.5;
        end
    end
    DLn=DL75;
    cityn=city75;
end



3.2 CalDist.m

C a l D i s t CalDist CalDist 函数计算了指定序列的总距离,输入参数 d i s l i s t dislist dislist 为距离矩阵, s s s 为城市排序序列,返回结果 F F F 为距离总长度。

function F=CalDist(dislist,s)
%计算总长度,dislist为距离矩阵,s为城市排序序列,F为距离总长度

DistanV=0;
n=size(s,2);
for i=1:(n-1)
    DistanV=DistanV+dislist(s(i),s(i+1));
end
DistanV=DistanV+dislist(s(n),s(1));
F=DistanV;

3.3 objf.m

o b j f objf objf 为计算适应度函数,传入参数 s s s 为种群,包含 i n n ( 种 群 大 小 ) inn(种群大小) inn() 种不同的旅游路线。 d i s l i s t dislist dislist 为距离矩阵。返回 f f f 为种群中每个个体的适应度, p p p 为累计概率,用于下一代的个体选择。

function [f,p]=objf(s,dislist);

inn=size(s,1);  %读取种群大小
for i=1:inn
   f(i)=CalDist(dislist,s(i,:));  %计算函数值,即适应度
end
f=1000./f';
%计算选择概率
fsum=0;
for i=1:inn
   fsum=fsum+f(i)^15;
end
for i=1:inn
   ps(i)=f(i)^15/fsum;
end
%计算累积概率
p(1)=ps(1);
for i=2:inn
   p(i)=p(i-1)+ps(i);
end
p=p';
end

3.4 sel.m

s e l sel sel 函数表示选择操作,参数 s s s 表示种群, p p p 表示累计概率。该函数实现选出两个适应度高个体序号的功能。

function seln=sel(s,p);

inn=size(p,1);
%从种群中选择两个个体
for i=1:2
   r=rand;  %产生一个随机数
   prand=p-r;
   j=1;
   while prand(j)<0  %适应度高,即出现概率大的个体首先被选择出来
       j=j+1;
   end
   seln(i)=j; %选中个体的序号
end
end

3.5 cro.m

c r o cro cro 函数表示交叉操作,参数 s s s 为种群, s e l n seln seln 为选择操作选中的两个个体序号, p c pc pc 为交叉概率。返回 s c r o scro scro 为交换部分染色体后的两个个体。

function scro=cro(s,seln,pc);

bn=size(s,2);
pcc=pro(pc);  %根据交叉概率决定是否进行交叉操作,1则是,0则否
scro(1,:)=s(seln(1),:);
scro(2,:)=s(seln(2),:);
if pcc==1
   c1=round(rand*(bn-2))+1;  %[1,bn-1]范围内随机产生一个交叉位
   c2=round(rand*(bn-2))+1;
   chb1=min(c1,c2);
   chb2=max(c1,c2);
   middle=scro(1,chb1+1:chb2);
   scro(1,chb1+1:chb2)=scro(2,chb1+1:chb2);
   scro(2,chb1+1:chb2)=middle;
   for i=1:chb1
       while find(scro(1,chb1+1:chb2)==scro(1,i))
           zhi=find(scro(1,chb1+1:chb2)==scro(1,i));
           y=scro(2,chb1+zhi);
           scro(1,i)=y;
       end
       while find(scro(2,chb1+1:chb2)==scro(2,i))
           zhi=find(scro(2,chb1+1:chb2)==scro(2,i));
           y=scro(1,chb1+zhi);
           scro(2,i)=y;
       end
   end
   for i=chb2+1:bn
       while find(scro(1,1:chb2)==scro(1,i))
           zhi=find(scro(1,1:chb2)==scro(1,i));
           y=scro(2,zhi);
           scro(1,i)=y;
       end
       while find(scro(2,1:chb2)==scro(2,i))
           zhi=find(scro(2,1:chb2)==scro(2,i));
           y=scro(1,zhi);
           scro(2,i)=y;
       end
   end
end
end

3.6 mut.m

m u t mut mut 函数表示变异操作,参数 s n e w snew snew 为交叉操作过后的个体, p m pm pm 为变异概率。返回 s n n e w snnew snnew 为变异后的新个体。

function snnew=mut(snew,pm);

bn=size(snew,2);
snnew=snew;

pmm=pro(pm);  %根据变异概率决定是否进行变异操作,1则是,0则否
if pmm==1
   c1=round(rand*(bn-2))+1;  %[1,bn-1]范围内随机产生一个变异位
   c2=round(rand*(bn-2))+1;
   chb1=min(c1,c2);
   chb2=max(c1,c2);
   x=snew(chb1+1:chb2);
   snnew(chb1+1:chb2)=fliplr(x);
end
end

3.7 drawTSP.m

d r a w T S P drawTSP drawTSP 函数为绘制 T S P TSP TSP 路线图以及搜索过程图的函数。

function m=drawTSP(Clist,BSF,bsf,p,f)
CityNum=size(Clist,1);
for i=1:CityNum-1
    plot([Clist(BSF(i),1),Clist(BSF(i+1),1)],[Clist(BSF(i),2),Clist(BSF(i+1),2)],'ms-','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','g');
    hold on;
end
plot([Clist(BSF(CityNum),1),Clist(BSF(1),1)],[Clist(BSF(CityNum),2),Clist(BSF(1),2)],'ms-','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','g');
title([num2str(CityNum),'城市TSP']);
if f==0
    text(5,5,['第 ',int2str(p),' 步','  最短距离为 ',num2str(bsf)]);
else
    text(5,5,['最终搜索结果:最短距离 ',num2str(bsf)]);
end
hold off;
pause(0.05); 

3.8 genetic_algorithm.m

该函数为主函数。

function gaTSP

CityNum=30;
[dislist,Clist]=tsp(CityNum);

inn=100; %初始种群大小
gnmax=1000;  %最大迭代次数
pc=0.8; %交叉概率
pm=0.8; %变异概率

%产生初始种群
for i=1:inn
    s(i,:)=randperm(CityNum);  %随机打乱城市序列,形成个体
end
[f,p]=objf(s,dislist);

gn=1; %迭代次数
while gn<gnmax+1
   for j=1:2:inn
      seln=sel(s,p);  %选择操作
      scro=cro(s,seln,pc);  %交叉操作
      scnew(j,:)=scro(1,:);
      scnew(j+1,:)=scro(2,:);
      smnew(j,:)=mut(scnew(j,:),pm);  %变异操作
      smnew(j+1,:)=mut(scnew(j+1,:),pm);
   end
   s=smnew;  %产生了新的种群
   [f,p]=objf(s,dislist);  %计算新种群的适应度
   %记录当前代最好和平均的适应度
   [fmax,nmax]=max(f);
   ymean(gn)=1000/mean(f);
   ymax(gn)=1000/fmax;
   %记录当前代的最佳个体
   x=s(nmax,:);
   drawTSP(Clist,x,ymax(gn),gn,0);
   gn=gn+1;
   %pause;
end
gn=gn-1;

figure(2);
plot(ymax,'r'); hold on;
plot(ymean,'b');grid;
title('搜索过程');
legend('最优解','平均解');
end
%--------------------------------------------------
function pcc=pro(pc);

test(1:100)=0;
l=round(100*pc);
test(1:l)=1;
n=round(rand*99)+1;
pcc=test(n);   
end

4. 结果

  • 13
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
遗传算法是一种启发式搜索算法,用于求解组合优化问题。其中,旅行商问题TSP)是一个经典的组合优化问题,通过遗传算法求解TSP问题可以得到较好的结果。 以下是用Python代码表示遗传算法求解TSP问题,将走过的城市坐标用图表示的过程: ```python import numpy as np import random import matplotlib.pyplot as plt #城市坐标 city_coords = np.array([[0, 0], [1, 2], [3, 1], [5, 3], [4, 6]]) #计算城市间距离 def distance(coords, order): dist = 0 for i in range(len(order) - 1): dist += np.linalg.norm(coords[order[i]] - coords[order[i+1]]) dist += np.linalg.norm(coords[order[-1]] - coords[order[0]]) return dist #初始化种群 def init_population(size, num_cities): population = [] for i in range(size): order = list(range(num_cities)) random.shuffle(order) population.append(order) return population #遗传算子-交叉 def crossover(parent1, parent2): ind1 = random.randint(0, len(parent1)-1) ind2 = random.randint(0, len(parent1)-1) start = min(ind1, ind2) end = max(ind1, ind2) child = [-1] * len(parent1) child[start:end] = parent1[start:end] rest = [item for item in parent2 if item not in child] rest_index = 0 for i in range(len(parent1)): if child[i] == -1: child[i] = rest[rest_index] rest_index += 1 return child #遗传算子-变异 def mutate(order, mutation_rate): if random.random() < mutation_rate: ind1 = random.randint(0, len(order)-1) ind2 = random.randint(0, len(order)-1) order[ind1], order[ind2] = order[ind2], order[ind1] return order #遗传算法求解TSP问题 def genetic_algorithm(city_coords, population_size, num_generations, mutation_rate): population = init_population(population_size, len(city_coords)) for generation in range(num_generations): fitness = [1/distance(city_coords, individual) for individual in population] new_population = [] for i in range(population_size): parent1 = random.choices(population, weights=fitness)[0] parent2 = random.choices(population, weights=fitness)[0] child = crossover(parent1, parent2) child = mutate(child, mutation_rate) new_population.append(child) population = new_population best_individual = population[np.argmax(fitness)] return best_individual #求解TSP问题 best_path = genetic_algorithm(city_coords, 100, 1000, 0.01) #绘制结果 x = [city_coords[i][0] for i in best_path] y = [city_coords[i][1] for i in best_path] plt.plot(x, y, 'bo-') plt.show() ``` 上述代码中,首先定义了城市坐标,并实现了计算城市间距离的函数。然后定义了初始化种群、交叉和变异等遗传算子。最后利用遗传算法求解TSP问题,并根据最优解路径绘制了城市坐标的图示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

比奇堡咻飞兜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值