一、引言
上篇关于使用matlab编写遗传算法求解车辆路径问题写完后,我发现南柯一梦那篇文章的参考文献应该是一篇《中国管理科学》的文章《用混合遗传算法求解物流配送路径优化问题的研究》,果然期刊水平高,文章的质量还是更有保障。这篇文章提出用爬山算法对遗传算法进行改进,本文将对基于爬山算法的遗传算法进行复现,并用于求解原文中的车辆路径优化问题。问题描述在上一篇文章中,这里不再赘述。
二、算法思路及GA代码
2.0算法思路
本文针对VRP问题所编写代码的核心过程为车辆路径的分配过程,即把哪些顾客安排给第几辆车。不同于上一篇文章,本文代码中的种群个体没有包含虚拟配送中心,只包含了需要配送的需求点。所以首先要做的就是为顾客安排车辆,具体的思路如下。以6-9-4-2-1-3-8-7-5为例,首先将第一个顾客6安排给第一辆车(这里的隐含假设是,不存在需求量或配送距离大于单个车辆限额的顾客),接着计算将第二个顾客9加入第一个路径后的配送距离及载重量,如果都没超过,则将9安排给第一辆车,否则将9安排给下一个车辆,以此类推。
对于一个安排好车辆的个体,如果安排的车辆总数小于等于配送中心的车辆限额,则为可行解。如果安排的车辆总数大于配送中心得车辆限额,则对该个体进行惩罚。具体操作就是给该个体的总路径增加一个较大的惩罚值。接着进行的算法步骤为:选择-交叉-变异-爬山-重插入。爬山操作的思想是,对于通过遗传操作形成的每代群体中的最优个体,通过领域搜索实施爬山操作。具体做法是:(1)在个体中随机选择两个基因,交换其位置;(2)判断基因换位后适应值是否增加,若增加,则以换位后的个体取代原个体;(3)重复操作(1)(2)直到达到指定次数为止。
2.1车辆路径分配及个体总路径距离计算
%% LengthInd函数用于计算个体的总路径长度
% 输入:个体a,车辆数carNum,客户之间的距离里矩阵DL,
% 距离限制disMax,客户重量需求DW,车辆重量限制capMax,客户到需求点距离X
% 输出:个体的总路径长度
%%
% 整体思路是给个体中每个客户赋予对应的车辆编号,从小到大,
% 如果新增加的个体超过当前车辆的距离或重量限制,则分配给下一个车辆,
% 如果被分配的车辆总数超过了给定车辆数,对个体进行惩罚
function lengthInd = LengthInd(a,carNum,DL,disMax,DW,capMax,X)
custNum = length(a); % 记录顾客的数量
matchA = zeros(custNum,4); % 记录顾客和车辆的匹配情况,第一列为顾客的编号,第二列为匹配的车辆编号
% 第三列为子路径总距离只记录在一个路径最后一个顾客对应的位置,第四列为需求重量
matchA(:,1) = a';
matchA(:,4) = DW(a)';
matchA(1,2) = 1; % 第一个顾客一定在第一个路径中
k = 1; % 车辆的编号
for i = 2:custNum
% 对于第i个顾客,首先要计算的是在当前路径加入该顾客后的路径总距离以及总重量
custTemp = find(matchA(:,2)==k); % 先找到第k个路径中包含的顾客
custK = [matchA(custTemp,1)' matchA(i,1)]; % 在第k个路径中加入第i个顾客后的总顾客情况
i1 = custK(1:end-1);
i2 = custK(2:end);
custKL = sum(DL((i1-1)*custNum+i2));
custKL = custKL + X(custK(1)) + X(custK(end)); % 计算第k辆车的总路径
custKW = sum(DW(custK)); % 计算第k辆车的总载重
if (custKL > disMax || custKW > capMax)
k = k + 1;
matchA(i,2) = k;
% 此时判断出了上一辆车的最后一个需求点,因此需要记录上一个路径的距离
custK(end) = [];
i1 = custK(1:end-1);
i2 = custK(2:end);
custKL = sum(DL((i1-1)*custNum+i2));
custKL &