matlab 车辆路径问题(vrp)局部搜索算子 染色体编码方式

染色体编码方式:有两种,在后面局部搜索算子中我用的不带分隔的染色体编码方式

1.带分隔的01230450670

每一个单元格代表一条染色体

2.不带分隔4532167——在matlab中我用元胞数组来实现

如下面这两张图:客户个数:20    种群规模:zaiyoutu

仅有载重约束 没有时间窗约束

在右图中每一个单元格代表一条路径

生成不带分割的染色体代码我会再重新写一篇文章

一、2-opt


%输入nowDist       距离矩阵
%输入初始种群Popu
% 通过2-opt算子进行局部搜索得到新的种群 %路径内
%随机选择一个配送路线,然后在该路线中随机选择两个客户点,
%对这两个客户点之间的客户序列进行反转。(并未随机)
function opt2_Chromes=opt2_function1(Popu,nowDist)
[pops,~]=size(relocate2_Chromes);
Chromes=relocate2_Chromes;
for j=1:pops
    Chrome=Chromes{j,:};%取出第i条染色体
    midroutes=cell(1,1);
    for k=1:size(Chrome,1)%依次选取该染色体的全部路径
        route=cell2mat(Chrome(k,:));
        midroutes{1,k}=route;
        w=2;
        for i=1:size(route,2)-1
            for s=i+1:size(route,2)
                reverse=fliplr(route(i:s));
                if i==1
                    if s==size(route,2)
                        midroute=reverse;
                    else
                        midroute=[reverse,route(s+1:end)];
                    end
                else
                    if s==size(route,2)
                        midroute=[route(1:i-1),reverse];
                    else
                        midroute=[route(1:i-1),reverse,route(s+1:end)];
                    end
                end
                midroutes{w,k}=midroute;
                w=w+1;
            end
        end
    end
    %计算所有的route的fitness,与原来的chrome中的Route对比,如果更优就代替。
    Fits=cell(1,1);%midroutes{w,k}有很多列
    for q=1:size(midroutes,2)
        A=midroutes(:,q);
        A(cellfun(@isempty,A))=[];
        outfitnesses=fit_routes2(A,nowDist);
        [val,idx]=min(outfitnesses);
        Fits{q,1}=outfitnesses(1,1)-val;%原始路径的目标值-最小的值
        Fits{q,2}=idx;
    end
    [~,idx]=max(cell2mat(Fits(:,1)));
    Route=cell2mat(midroutes(Fits{idx,2},idx));
    Chrome{idx,:}=Route;
    Chromes{j,:}=Chrome;
end
opt2_Chromes=Chromes;
end


二、2-opt*


%输入nowDist       距离矩阵
%demands,cap
%输入种群opt2_Chromes
% 通过2-opt*算子进行局部搜索得到新的种群 %路径间
%随机选择两条配送路线,然后在两条路径分别取1个交换位置,
%将第一条路径位置之后的所有顾客节点与第2条路径交换位置之后的所有顾客节点互换
function opt_2Chromes=opt2_function2(opt2_Chromes,nowDist,demands,cap)
[pops,~]=size(opt2_Chromes);
Chromes=opt2_Chromes;
for j=1:pops
    Chrome=Chromes{j,:};%取出第j条染色体
    Q=randperm(size(Chrome,1),2);%选两条路径 %选两条路径所有的组合方式Q=nchoosek(1:size(Chrome,1),2)
    route1=cell2mat(Chrome(Q(1),:));
    route2=cell2mat(Chrome(Q(2),:));
    midroutes1=cell(1,1);
    midroutes1{1,:}=route1;%保留初始路径1
    midroutes2=cell(1,1);
    midroutes2{1,:}=route2;%保留初始路径2
    w=2;
    for i=1:size(route1,2)-1
        for k=1:size(route2,2)-1
            mid1=route1(i+1:end);
            mid2=route2(k+1:end);
            midroute1=[route1(1:i),mid2];
            midroute2=[route2(1:k),mid1];
            result1=Result2(demands,cap,midroute1);
            result2=
Result2(demands,cap,midroute2);
            if result1==1&&result2==1%判断交换两点后的两段路径是否可行(满足载重约束)
                midroutes1{w,:}=midroute1;
                midroutes2{w,:}=midroute2;
                w=w+1;
            end
            route1=cell2mat(Chrome(Q(1),:));
            route2=cell2mat(Chrome(Q(2),:));
        end
    end
    %计算所有两点交叉可能出现的路径的目标值
    outfitness1=fit_routes2(midroutes1,nowDist);
    outfitness2=fit_routes2(midroutes2,nowDist);
     outfitnesses=outfitness2+outfitness1;
      [~,idx]=min(outfitnesses);
    Route1=cell2mat(midroutes1(idx,:));
    Route2=cell2mat(midroutes2(idx,:));
    Chrome{Q(1),:}=Route1;   %路径中目标值最小的替换原本的
    Chrome{Q(2),:}=Route2;
    Chromes{j,:}=Chrome;
end
opt_2Chromes=Chromes;
end

三、exchange算子

路径内

%输入nowDist       距离矩阵
%输入初始种群Popu,
% 通过两点交换算子(路径内)进行局部搜索得到新的种群
%路径内:随机选择一个配送路线,然后在该路线中随机选择两个客户点,交换客户点位置。
function exchange1_Chromes=exchange1_function(Popu,nowDist)
[pops,~]=size(or_optChromes);
Chromes=or_optChromes;
for j=1:pops
    Chrome=Chromes{j,:};
    a=randperm(size(Chrome,1),1);%选第a条路径
    route=cell2mat(Chrome(a,:));%随机选取出一条路径
    %把这条路径中可能出现的两点交换后的路径都储存下来,
    %因为在路径内交换所以载重约束是满足的,
    %然后计算目标值,得到最小的值对应的路径替换该染色体的原路径。
    if size(route,2)~=1 %避免出现某个路径只有一个客户时交换不了
        midroute=cell(1,1);
        midroute{1,:}=route;
        w=2;
        for i=1:size(route,2)-1
            for k=i+1:size(route,2)
                mid=route(i);
                route(i)=route(k);
                route(k)=mid;
                midroute{w,:}=route;
                w=w+1;
                route=cell2mat(Chrome(a,:));
            end
        end
        %计算所有两点交叉可能出现的路径的目标值
        outfitnesses=fit_routes2(midroute,nowDist);
       [~,idx]=min(outfitnesses);
        Route=cell2mat(midroute(idx,:));
        Chrome{a,:}=Route;   %路径中目标值最小的替换原本的
        Chromes{j,:}=Chrome;
    end
end
exchange1_Chromes=Chromes;
end

路径间

%输入nowDist       距离矩阵
%输入种群exchange1_Chromes
% 通过两点交换算子(路径间)进行局部搜索得到新的种群
%路径间:首先随机选择两条配送路线,因为在路径间,所以要判断交换后路径是否可行
%然后在每一条路径中分别随机选择一个客户点,交换两个客户点的位置。
function [exchange2_Chromes,midroute1,midroute2]=
exchange2_function(exchange1_Chromes, nowDist,demands,cap)
[pops,~]=size(exchange1_Chromes);
Chromes=exchange1_Chromes;
for j=1:pops
    Chrome=Chromes{j,:};
    Q=randperm(size(Chrome,1),2);%选两条路径
    route1=cell2mat(Chrome(Q(1),:));
    route2=cell2mat(Chrome(Q(2),:));
    midroute1=cell(1,1);
    midroute2=cell(1,1);
    midroute1{1,:}=route1;
    midroute2{1,:}=route2;
    w=2;
    for i=1:size(route1,2)
        for k=1:size(route2,2)
            mid=route1(i);
            route1(i)=route2(k);
            route2(k)=mid;
            result1=
Result2(demands,cap,route1);
            result2=
Result2(demands,cap,route2);
           if result1==1&&result2==1%判断exchange后的路径是否可行(满足载重约束)
            midroute1{w,:}=route1;
            midroute2{w,:}=route2;
            w=w+1;
            end
            route1=cell2mat(Chrome(Q(1),:));
            route2=cell2mat(Chrome(Q(2),:));
        end
    end
    %计算所有两点交叉可能出现的路径的目标值
    outfitness1=
fit_routes2(midroute1,nowDist);
    outfitness2=
fit_routes2(midroute2,nowDist);
  outfitnesses=outfitness2+outfitness1;
  [~,idx]=min(outfitnesses);
    Route1=cell2mat(midroute1(idx,:));
    Route2=cell2mat(midroute2(idx,:));
    Chrome{Q(1),:}=Route1;   %路径中目标值最小的替换原本的
    Chrome{Q(2),:}=Route2;
    Chromes{j,:}=Chrome;
end
exchange2_Chromes=Chromes;
end

四、or-opt

%输入nowDist       距离矩阵
%输入种群Popu
% 通过or-opt算子进行局部搜索得到新的种群
%随机选择一个配送路线,然后在该路线中随机选择一个连续客户点序列,
%将其放在路线中的其他任意位置。
function or_optChromes=or_optfunction(Popu,nowDist)
[pops,~]=size(Popu);
Chromes=Popu;
for i=1:pops
    Chrome=Chromes{i,:};
    a=randperm(size(Chrome,1),1);%选第a条路径
    route=cell2mat(Chrome(a,:));%随机选取出一条路径、or-opt也可以选取最长的路径进行下一步的操作
    m=randperm(size(route,2),1)-1;%通过路径长度随机出or-opt所需要的m个连续的顾客
    if m~=0
    s=0;
    w=1;
    midroute=cell(1,1);
    while s+m<=size(route,2)
        partRoute=route(:,s+1:s+m);%m个连续的顾客的路径
        route(:,s+1:s+m)=[];
        for v=1:length(route)+1                %m个连续的顾客插入各个位置的方案
            if v==1
                Route=[partRoute,route];
            elseif v==length(route)+1
                Route=[route(1:v-1),partRoute];
            else
                Route=[route(1:v-1),partRoute,route(v:end)];
            end
            midroute{w,:}=Route;
            w=w+1;
        end
        s=s+1;
        route=cell2mat(Chrome(a,:));
    end
    routes=midroute;    %计算全部路径方案的目标值,选择最小的
    outfitnesses=fit_routes2(routes,nowDist);
    [~,idx]=min(outfitnesses);
    Route=cell2mat(midroute(idx,:));
    Chrome{a,:}=Route;   %路径(仍是那几位顾客,所以载重约束是满足的)中目标值最小的替换原本的
    Chromes{i,:}=Chrome;
    end
end
or_optChromes=Chromes;
end

五、涉及到的两个函数

Result2:

%输入单个路径
%输入demands       每个顾客的需求量
%输入cap           车辆最大载货量
% 判断载重约束
function result=
Result2(demands,cap,route)
w=0;
for i=1:length(route)
    w=w+demands(route(i));
    if w>cap
        result=0;
        break
    end
    result=1;
end
end

fit_routes2

%输入nowDist  距离矩阵
%midroute-元胞数组 多个路径
% 计算routes目标函数值
function outfitnesses=
fit_routes2(midroute,nowDist)
[pops,~]=size(midroute);
    fitnesses=[];
    for i=1:pops
        midfitness=0;
        b=1;
        route=midroute{i,:};
        route=[0,route,0];
        for s=1:length(route)
            midfitness=midfitness+nowDist(b,route(s)+1);
            b=route(s)+1;
        end
        fitnesses=[fitnesses,midfitness];
    end
    outfitnesses=fitnesses';
end

 

其实这几个局部搜索的算子写代码的过程中有很多相同的地方

这里就不放这些算子详细信息,大家可以自行百度

新手小白,欢迎大家批评指正!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值