【Matlab】 遗传算法求解TSP问题

本文介绍了使用Matlab实现遗传算法求解旅行商问题(TSP),详细阐述了问题描述、实验设计,包括读入数据、适应度计算、选择子代等步骤,并展示了实验结果。遗传算法作为一种优化方法,尽管存在收敛慢和可能陷入局部最优的问题,但在解决TSP这类复杂问题上仍表现出优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【Matlab】 遗传算法求解TSP问题


前言

个人实验的一次记录,如有不当欢迎批评指正

TSP(traveling salesman problem,旅行商问题)是典型的NP完全问题,即其最坏情况下的时间复杂度随着问题规模的增大按指数方式增长,到目前为止还未找到一个多项式时间的有效算法。在现实生活中,TSP问题广泛应用于货物零件加工顺序、汽配件喷涂顺序、仓储系统拣货路径规划、光伏板清洁等领域。
自20世纪80年代以来,基于启发式规则的智能优化算法兴起并被快速应用于求解TSP问题,如遗传算法、模拟退火算法、蜂群算法、蚁群算法、萤火虫算法、粒子群算法等,它们普遍具有快速搜索和求解能力,对规模更大的TSP问题也有明显效果。其中,以达尔文进化论、孟德尔遗传变异理论、模式理论为基础的遗传算法逐渐受到重视,它是一种自适应全局优化的概率搜索算法,具有较强的鲁棒性、并行性,容易与其他算法结合等优点,但也存在交叉算子不易操作、容易过早收敛而陷入局部最优、收敛速度慢等缺点

一、问题描述

TSP问题可描述为:已知 m m m个城市相互之间的距离,某一旅行商从某个城市出发访问每个城市有且仅有一次,最后回到出发城市,如何安排才使其所走路线距离最短。也就是寻找一条最短的遍历 n n n个城市的路径,或者说搜索自然子集 X = { 1 , 2 , ⋯   , n } ( X 的元素表示对 n 个城市的编号 ) 的一个排列 X=\left\{ 1,2,\cdots ,n \right\} \left( X\text{的元素表示对}n\text{个城市的编号} \right) \text{的一个排列} X={1,2,,n}(X的元素表示对n个城市的编号)的一个排列
π ( X ) = { V 1 , V 2 , ⋯   , V n } 使得 \pi \left( X \right) =\left\{ V_1,V_2,\cdots ,V_{\mathrm{n}} \right\} \text{使得} π(X)={V1,V2,,Vn}使得 T d = ∑ i = 1 n + 1 d ( V i , V i + 1 ) + d ( V n , V 1 ) T_{\mathrm{d}}=\sum_{i=1}^{n+1}{d\left( V_{\mathrm{i}},V_{\mathrm{i}+1} \right) +d\left( V_{\mathrm{n}},V_1 \right)} Td=i=1n+1d(Vi,Vi+1)+d(Vn,V1)取得最小值,其中 d ( V i , V i + 1 ) d\left( V_{\mathrm{i}},V_{\mathrm{i}+1} \right) d(Vi,Vi+1)表示城市 V i V_{\mathrm{i}} Vi到城市 V i + 1 V_{\mathrm{i+1}} Vi+1的距离。

二、实验设计

1.问题案例

本案例以14个城市为例,假定14个城市的位置坐标如表1所列。寻找出一条最短的遍历14个城市的路径。具体如下:

编号X坐标Y坐标编号X坐标Y坐标
116.4796.10817.2096.29
216.4794.44916.3097.38
320.0992.541014.0598.12
422.3993.371116.5397.38
525.2397.241221.5295.59
622.0096.051319.4197.13
720.4797.021420.0994.55

2.读入数据

代码如下(示例):

function [popinit,distmat,Villes] = file_init(nbrpop)
%读取包含城市坐标的文件
[FileName,~] = uigetfile('*.txt','选择文本文件');

  fid = fopen(FileName,'r');
  Villes = dlmread(FileName,'%d%10.4f%10.4f'); %将文件中的值存储在Cities数组中
  [nbrville,~] = size(Villes);
  fclose(fid);
 
distmat = zeros(nbrville,nbrville); %距离矩阵
popinit = zeros(nbrpop,nbrville);   %初始种群矩阵

%创建初始种群(随机)
for i=1:nbrpop
    popinit(i,:) = randperm(nbrville);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                          % 欧式距离 %
%填充距离矩阵
for i=1:nbrville
    for j=1:nbrville
        distmat(i,j) = sqrt( (Villes(i,2)-Villes(j,2))^2 + (Villes(i,3)-Villes(j,3))^2 );
    end
end

end

将表格内数据保存为文本格式 中间以空格形式隔开,即可通过该函数读入相关信息。

3.适应度计算


% vectfit:向量包含每次行程的总距离(成本)
% best:向量包含迭代中得到的最佳路径当前的
% minVal:本次行程对应的最佳值(最佳)

function [vectfit,best,minVal,indxBest]=calcFitness (nbrpop ,nbrville, distmat ,popinit)

vectfit = zeros(1,nbrpop);

%计算的适应度向量
 for i=1:nbrpop
    tmp = popinit(i,:);
    for j=1:nbrville
        if j==length(tmp)
            vectfit(i) = vectfit(i) + distmat(tmp(j),tmp(1));
            break;
        end
          vectfit(i) = vectfit(i) + distmat(tmp(j),tmp(j+1));
    end
 end
 
[minVal,indxBest]=min(vectfit) ; %min() 给了我们两个值:最小值和这个值的索引
best=popinit(indxBest , : ) ;

end

我们通过欧氏距离矩阵直接获取各个点之间的距离关系,通过距离换算出其适应度,用于后续的计算。

4. 选择子代


% matelec:包含选择进行繁殖的个体的矩阵

function matselec = rouletteSelect(vectfit,popinit)

 Ps = 0.5;
 [nbrpop,nbrville] = size(popinit);
 nbrpopS = floor(nbrpop*Ps);           % 我们选择 Ps*100% 的个人
 matselec = zeros(nbrpopS,nbrville);
cumProb = zeros(1,length(vectfit));     % 包含累积适应度的向量
 s = 0;
         
 
 % 累积概率计算
 for j=1:length(vectfit)
     cumProb(j) = s + vectfit(j);
     s = cumProb(j);
 end
  
 % 填充选择矩阵进行育种
 for i=1:nbrpopS
 r = (max(cumProb)-min(cumProb))*rand() + min(cumProb); % min(cumProb) <= r <= max(cumProb)
 
 for j=1:length(cumProb)
    if r <= cumProb(j)
        matselec(i,:) = popinit(j,:);
        break;
    end
    
 end
 
 end
 
 end

采取精英策略选择相关的适应度较高的个体用于后续的迭代,通过这种方法,不断的迭代直到满足迭代次数或者达到相关精度。

5. 结果输出

轨迹图
对应轨迹图
优化过程
其迭代过程如上
实验源码点击此处


总结

对于实际问题,我们需要采取不同的策略与手段,根据实际问题的需求,设计合理的求解方法,不断地深入的分析问题的本质,才有助于我们解决这些问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱神的箭呵呵

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

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

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

打赏作者

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

抵扣说明:

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

余额充值