【TWVRP】基于matlab蚁群算法求解带时间窗的VRP问题【含Matlab源码 921期】

·  阅读 115

一、简介

1 蚁群算法(ant colony algorithm,ACA)起源和发展历程
Marco Dorigo等人在研究新型算法的过程中,发现蚁群在寻找食物时,通过分泌一种称为信息素的生物激素交流觅食信息从而能快速的找到目标,于是在1991年在其博士论文中首次系统地提出一种基于蚂蚁种群的新型智能优化算法“蚂蚁系统(Ant system,简称AS)”,后来,提出者及许多研究者对该算法作了各种改进,将其应用于更为广泛的领域,如图着色问题、二次分配问题、工件排序问题、车辆路径问题、车间作业调度问题、网络路由问题、大规模集成电路设计等。近些年来,M.Dorigo等人把蚂蚁算法进一步发展成一种通用的优化技术“蚁群优化(Ant Colony Optimization,简称ACO)”,并将所有符合ACO框架的算法称为“蚁群优化算法(ACO algorithm)”。

在这里插入图片描述
具体来说,各个蚂蚁在没有事先告知食物在什么地方的前提下开始寻找食物。当一只找到食物以后,它会向环境释放一种挥发性分泌物pheromone (称为信息素,该物质随着时间的推移会逐渐挥发消失,信息素浓度的大小表征路径的远近)信息素能够让其他蚂蚁感知从而起到一个引导的作用。通常多个路径上均有信息素时,蚂蚁会优先选择信息素浓度高的路径,从而使浓度高的路径信息素浓度更高,形成一个正反馈。有些蚂蚁并没有像其它蚂蚁一样总重复同样的路,他们会另辟蹊径,如果另开辟的道路比原来的其他道路更短,那么,渐渐地,更多的蚂蚁被吸引到这条较短的路上来。最后,经过一段时间运行,可能会出现一条最短的路径被大多数蚂蚁重复着。最终,信息素浓度最高的路径即是最终被蚂蚁选中的最优路径。
与其他算法相比,蚁群算法是一种比较年轻的算法,具有分布式计算、无中心控制、个体之间异步间接通信等特点,并且易于与其他优化算法相结合,经过不少仁人志士的不断探索,到今天已经发展出了各式各样的改进蚁群算法,不过蚁群算法的原理仍是主干。

2 蚁群算法的求解原理
基于上述对蚁群觅食行为的描述,该算法主要对觅食行为进行以下几个方面模拟:
(1)模拟的图场景中包含了两种信息素,一种表示家,一种表示食物的地点,并且这两种信息素都在以一定的速率进行挥发。
(2)每个蚂蚁只能感知它周围的小部分地方的信息。蚂蚁在寻找食物的时候,如果在感知范围内,就可以直接过去,如果不在感知范围内,就要朝着信息素多的地方走,蚂蚁可以有一个小概率不往信息素多的地方走,而另辟蹊径,这个小概率事件很重要,代表了一种找路的创新,对于找到更优的解很重要。
(3)蚂蚁回窝的规则与找食物的规则相同。
(4)蚂蚁在移动时候首先会根据信息素的指引,如果没有信息素的指引,会按照自己的移动方向惯性走下去,但也有一定的机率改变方向,蚂蚁还可以记住已经走过的路,避免重复走一个地方。
(5)蚂蚁在找到食物时留下的信息素最多,然后距离食物越远的地方留下的信息素越少。找到窝的信息素留下的量的规则跟食物相同。蚁群算法有以下几个特点:正反馈算法、并发性算法、较强的鲁棒性、概率型全局搜索、不依赖严格的数学性质、搜索时间长,易出现停止现象。
蚂蚁转移概率公式:
在这里插入图片描述
公式中:是蚂蚁k从城市i转移到j的概率;α,β分别为信息素和启发式因子的相对重要程度;为边(i,j)上的信息素量;为启发式因子;为蚂蚁k下步允许选择的城市。上述公式即为蚂蚁系统中的信息素更新公式,是边(i,j)上的信息素量;ρ是信息素蒸发系数,0<ρ<1;为第k只蚂蚁在本次迭代中留在边(i,j)上的信息素量;Q为一正常系数;为第k只蚂蚁在本次周游中的路径长度。
在蚂蚁系统中,信息素更新公式为:
在这里插入图片描述
3 蚁群算法的求解步骤:
(1)初始化参数在计算之初,需要对相关参数进行初始化,如蚁群规模(蚂蚁数量)m、信息素重要程度因子α、启发函数重要程度因子β、信息素会发银子ρ、信息素释放总量Q、最大迭代次数iter_max、迭代次数初值iter=1。
(2)构建解空间将各个蚂蚁随机地置于不同的出发点,对每个蚂蚁k(k=1,2,3…m),按照(2-1)计算其下一个待访问城市,直到所有蚂蚁访问完所有城市。
(3)更新信息苏计算每个蚂蚁经过路径长度Lk(k=1,2,…,m),记录当前迭代次数中的最优解(最短路径)。同时,根据式(2-2)和(2-3)对各个城市连接路径上信息素浓度进行更新。
(4) 判断是否终止若iter<iter_max,则令iter=iter+1,清空蚂蚁经过路径的记录表,并返回步骤2;否则,终止计算,输出最优解。
(5)判断是否终止若iter<iter_max,则令iter=iter+1,清空蚂蚁经过路径的记录表,并返回步骤2;否则,终止计算,输出最优解。3. 判断是否终止若iter<iter_max,则令iter=iter+1,清空蚂蚁经过路径的记录表,并返回步骤2;否则,终止计算,输出最优解。

在这里插入图片描述

二、源代码

clc %清空命令行窗口
clear %从当前工作区中删除所有变量,并将它们从系统内存中释放
close all %删除其句柄未隐藏的所有图窗
tic % 保存当前时间
%% 蚁群算法求解VRPTW
%输入:
%City           需求点经纬度
%Distance       距离矩阵
%TravelTime     行驶时间矩阵
%Demand         各需求点需求量
%Travelcon      行程约束
%Capacity       车容量约束
%TimeWindow     各需求点时间窗
%AntNum         种群个数
%Alpha          信息素重要程度因子
%Beta           启发函数重要程度因子
%Rho            信息素挥发因子
%Q              常系数
%Eta            启发函数
%Tau            信息素矩阵
%MaxIter        最大迭代次数

%输出:
%bestroute      最短路径
%mindisever     路径长度

%% 加载数据
load('City.mat')	      %需求点经纬度,用于画实际路径的XY坐标
load('Distance.mat')	  %距离矩阵
load('TravelTime.mat')   %行驶时间矩阵
load('Demand.mat')       %需求量
load('TimeWindow.mat')   %时间窗
load('Travelcon.mat')	  %行程约束
load('Capacity.mat')     %车容量约束

%% 初始化问题参数
CityNum = size(City,1)-1;    %需求点个数

%% 初始化参数
AntNum = 8;                            % 蚂蚁数量
Alpha = 1;                              % 信息素重要程度因子
Beta = 5;                               % 启发函数重要程度因子
Rho = 0.1;                              % 信息素挥发因子
Q = 1;                                  % 常系数
Eta = 1./Distance;                      % 启发函数
Tau = ones(CityNum+1);                  % (CityNum+1)*(CityNum+1)信息素矩阵  初始化全为1
Population = zeros(AntNum,CityNum*2+1);  % AntNum行,(CityNum*2+1)列 的路径记录表
MaxIter = 100;                           % 最大迭代次数
bestind = ones(MaxIter,CityNum*2+1);	% 各代最佳路径
MinDis = zeros(MaxIter,1);              % 各代最佳路径的长度

%% 迭代寻找最佳路径
Iter = 1;                               % 迭代次数初值
while Iter <= MaxIter %当未到达最大迭代次数
	%% 逐个蚂蚁路径选择
    
	for i = 1:AntNum
        TSProute=2:CityNum+1; %生成一条顺序不包括首尾位的升序TSP路线
        VRProute=[]; %初始化VRP路径
        
        while ~isempty(TSProute) %开辟新的子路径
            subpath=1; %先将配送中心放入子路径起点
            DisTraveled=0; %此子路径的距离初始化为零
            CurrentTime=0; %车辆已行驶时间置零
            delivery=0; %此子路径的车辆可配送量初始化为零
            
            delete=subpath; %delete(end)=1给第一次进入内while的P(k)首项用

            while ~isempty(TSProute) %为子路径subpath第二个及以后的位置安排需求点
                %% 计在内while中计算城市间转移概率
                
                P = TSProute; % 为轮盘赌选择建立等于剩余需经过城市数量的长度的向量
                for k = 1:length(TSProute)
                    %delete(end)为刚刚经过的城市,TSProute(k)为剩余可能经过的城市
                    P(k) = Tau(delete(end),TSProute(k))^Alpha * Eta(delete(end),TSProute(k))^Beta; %省略相同分母
                end
                P = P/sum(P);
                % 轮盘赌法选择下一个访问城市
                Pc = cumsum(P); %累加概率
                
                TargetIndex = find(Pc >= rand); %寻找左数第一个大于伪随机数的累加概率的索引
                target = TSProute(TargetIndex(1)); %此索引对应的城市
                %不要强行改变蚂蚁通过轮盘法选到的下一个城市
                %它选到就确定了,然后如果超约束,结束此subpath
                
                %判断行程约束
                if delivery+Demand(target) > Capacity || DisTraveled+Distance(delete(end),target)+Distance(target,1) > Travelcon
                    break
                else
                    DisTraveled=DisTraveled+Distance(delete(end),target); %若符合,则经过的距离累加此距离
                    CurrentTime=max(CurrentTime+TravelTime(delete(end),target),TimeWindow(target,2)); %当前时间累加,并与该需求点早时间窗比较得出开始服务时间
                    delivery = delivery+Demand(target); %车辆已配送量累加
                    
                    %此点加入子路径
                    subpath=[subpath,target];
                    %此点加入要删除的点序列
                    delete=[delete,target];
                    
                    %TSP路径中排除已安排的城市
                    TSProute=setdiff(TSProute,delete);
                end
                function TextOutput(route,Distance,TravelTime,Demand,TimeWindow,Capacity)
%% 输出路径函数
%输入:route 路径
%输出:p 路径文本形式

%% 总路径
len=length(route); %路径长度
disp('Best Route:')

p=num2str(route(1)); %配送中心位先进入路径首位
for i=2:len
    p=[p,' -> ',num2str(route(i))]; %路径依次加入下一个经过的点
end
disp(p)

%% 子路径

route=route+1; %路径值全体+1,为方便下面用向量索引

Vnum=1; %
DisTraveled=0;  % 汽车已经行驶的距离
CurrentTime=0; %本车行驶时间置零
delivery=0;       % 汽车已经送货量,即已经到达点的需求量之和
subpath='0'; %子路径路线
subtime='0'; %经过一子路径各点时间
for j=2:len
    DisTraveled = DisTraveled+Distance(route(j-1),route(j)); %每两点间距离累加
    delivery = delivery+Demand(route(j)); %累加可配送量
复制代码

三、运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、备注

版本:2014a

分类:
人工智能
标签:
分类:
人工智能
标签:
收藏成功!
已添加到「」, 点击更改