【遗传算法解决旅行商问题】附MATLAB代码

使用遗传算法解决tsp问题代码

%% 1.清空环境变量
clear all;
clc;

%% 2.导入数据
load citys_data.mat;          %数据集的变量名为citys

%% 3.计算城市间相互距离
n=size(citys,1);
D=zeros(n,n);

for i=1:n
    for j=i+1:n
        D(i,j)=sqrt(sum((citys(i,:)-citys(j,:)).^2));
        D(j,i)=D(i,j);
    end
end

%% 4.初始化参数
m=2000;                         %种群个数
pop=zeros(m,n);                 %种群
crospro=0.8;                    %交叉概率
mutpro=0.1;                     %变异概率
gen=1;                          %迭代计数器
genmax=1;                    %最大迭代次数
fitness=zeros(m,1);             %适应度函数值
Route_best=zeros(genmax,n);     %各代最佳路径
Length_best=zeros(genmax,1);    %各代最佳路径的长度
Length_ave=zeros(genmax,1);     %各代路径的平均长度

%% 5.产生初始种群
% 5.1随机产生初始种群
for i=1:m
    pop(i,:)=randperm(n);
end

% 5.2计算初始种群适应度函数值
for i=1:m
    for j=1:n-1
        fitness(i)=fitness(i) + D(pop(i,j),pop(i,j+1));
    end
    fitness(i)=fitness(i) + D(pop(i,end),pop(i,1));
end

% 5.3计算最短路径及平均距离
[min_Length,min_index]=min(fitness);
Length_best(1)=min_Length;
Route_best(1,:)=pop(min_index,:);
Length_ave(1)=mean(fitness);

%% 6.迭代寻找最佳路径
while gen<=genmax
    % 6.1更新迭代次数
    gen=gen+1;

    % 6.2选择算子(轮盘赌法)
    P=1./fitness;
    P=P/sum(P);        %计算每一个城市的概率
    Pc=cumsum(P);      %计算累积概率

    popnew=zeros(m,n);
    for i=1:m
        target_index=find(Pc>=rand);
        target=pop(target_index(1),:);
        popnew(i,:)=target;
    end

    % 6.3交叉算子(部分匹配交叉)
    for i=1:2:n   %两两之间相互交叉
        if crospro>rand  %判断是否进行交叉
            child1path=zeros(1,n);
            child2path=zeros(1,n);

            setsize=floor(n/2)-1;      %匹配区域城市的数量
            offset1=randi(setsize);    %匹配区域的下边界
            offset2=offset1+setsize-1; %匹配区域的上边界

            %匹配区域
            for j=offset1:offset2
                child1path(j)=popnew(i+1,j);
                child2path(j)=popnew(i,j);
            end

            % 非匹配区域
            for j=1:offset1-1
                child1path(j)=popnew(i,j);
                child2path(j)=popnew(i+1,j);
            end

            for j=offset2+1:n
                child1path(j)=popnew(i,j);
                child2path(j)=popnew(i+1,j);
            end

            % 子代1冲突检测
            for j=offset1:offset2
                if ~ismember(child1path(j),popnew(i,offset1:offset2)) %不在交叉段内
                    %寻找映射关系
                    a1=child1path(j);
                    a2=popnew(i,j);
                    while ismember(a2,child1path(offset1:offset2))
                        temp_index=find(popnew(i+1,:)==a2);
                        a1=a2;
                        a2=popnew(i,temp_index);  
                    end 
                    %寻找重复数字位置
                    b1=find(child1path==child1path(j));
                    if length(b1)>1
                        if b1(1)>offset2||b1(1)<offset1
                            change_index=b1(1);
                        else
                            change_index=b1(2);
                        end
                    end
                    %替代重复数字
                    child1path(change_index)=a2;                
                end
            end

            % 子代2冲突检测(同上)
            for j=offset1:offset2
                if ~ismember(child2path(j),popnew(i+1,offset1:offset2)) %不在交叉段内
                    %寻找映射关系
                    a1=child2path(j);
                    a2=popnew(i+1,j);
                    while ismember(a2,child2path(offset1:offset2))
                        temp_index=find(popnew(i,:)==a2);
                        a1=a2;
                        a2=popnew(i+1,temp_index);  
                    end 
                    %寻找重复数字位置
                    b2=find(child2path==child2path(j));
                    if length(b2)>1
                        if b2(1)>offset2||b2(1)<offset1
                            change_index=b2(1);
                        else
                            change_index=b2(2);
                        end
                    end
                    %替代重复数字
                    child2path(change_index)=a2;                
                end
            end

            popnew(i,:)=child1path;
            popnew(i+1,:)=child2path;
        end
    end

    % 6.4变异算子
    for i=1:m
        if mutpro>rand %判断是否变异
            %随机抽两个数字
            y=round(rand(1,2)*(n-1)+1);
            %交换位置
            temp=popnew(i,y(1));
            popnew(i,y(1))=popnew(i,y(2));
            popnew(i,y(2))=temp;
        end
    end

    % 6.5计算新一代种群适应度函数值
    pop=popnew;
    fitness=zeros(m,1);
    for i=1:m
        for j=1:n-1
            fitness(i)=fitness(i) + D(pop(i,j),pop(i,j+1));
        end
        fitness(i)=fitness(i) + D(pop(i,end),pop(i,1));
    end

    % 6.6计算最短路径及平均距离
    [min_Length,min_index]=min(fitness);
    Length_ave(gen)=mean(fitness);
    if min_Length<Length_best(gen-1)
        Length_best(gen)=min_Length;
        Route_best(gen,:)=pop(min_index,:);
    else
        Length_best(gen)=Length_best(gen-1);
        Route_best(gen,:)=Route_best(gen-1,:);
    end

end

%% 7.结果显示
best_route=Route_best(end,:);
best_length=Length_best(end,:);
disp(['最短距离: ' num2str(best_length)]);
disp(['最短路径: ' num2str(best_route)]);

%% 8.绘图
figure(1)
plot([citys(best_route,1);citys(best_route(1),1)],[citys(best_route,2);citys(best_route(1),2)],'o-')
for i=1:size(citys,1)
    text(citys(i,1),citys(i,2),[' ' num2str(i)]); 
end
text(citys(best_route(1),1),citys(best_route(1),2),'     起点');
text(citys(best_route(end),1),citys(best_route(end),2),'     终点');
xlabel('城市位置横坐标')
ylabel('城市位置纵坐标')
title(['遗传算法优化路径(最短距离:' num2str(best_length) ')'])

figure(2)
plot(1:genmax+1,Length_ave,'r:',1:genmax+1,Length_best,'b-')
legend('平均距离','最短距离')
xlabel('迭代次数')
ylabel('距离')
title('各代最短距离与平均距离对比')

请添加图片描述

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值