一、原理简介
蚁群算法的基本原理
1、蚂蚁在路径上释放信息素。
2、碰到还没走过的路口,就随机挑选一条路走。同时,释放与路径长度有关的信息素。
3、信息素浓度与路径长度成反比。后来的蚂蚁再次碰到该路口时,就选择信息素浓度较高路径。
4、最优路径上的信息素浓度越来越大。
5、最终蚁群找到最优寻食路径。
蚁群走过较短的那一侧的蚂蚁数数量会多于较长那一侧的,所以留下的信息素就会多,渐渐的蚂蚁就只走较短的那一侧了。
蚁群算法对TSP的求解主要有两大步骤:(TSP问题就是要找到最短哈密尔顿回路)
1、路径构建
AS中的随机比例规则;对于每只蚂蚁k,路径记忆向量R^k.按照访问顺序记录了所有k已经经过的城市序号。设蚂蚁k当前所在城市为i,则其选择城市j作为下一个访问对象的概率为:
2、信息素更新
这里m是蚂蚁个数, ρ是信息素的蒸发率,规定0≤ ρ≤1,在AS中通常设置为 ρ =0.5,Δτij是第k只蚂蚁在它经过的边上释放的信息素量,它等于蚂蚁k本轮构建路径长度的倒数。C^k表示路径长度,它是R^k中所有边的长度和。
构建图:构建图与问题描述图是一致的,成份的集合C对应着点的集合(即:C=N),连接对应着边的集合(即L=A),且每一条边都带有一个权值,代表点i和j之间的距离。
约束条件:所有城市都要被访问且每个城市最多只能被访问一次。
信息素和启发式信息:TSP 问题中的信息素表示在访问城市i后直接访问城市j的期望度。启发式信息值一般与城市i和城市j的距离成反比。
解的构建:每只蚂蚁最初都从随机选择出来的城市出发,每经过一次迭代蚂蚁就向解中添加一个还没有访问过的城市。当所有城市都被蚂蚁访问过之后,解的构建就终止。
蚁群算法存在缺陷:
蚁群算法在解决小规模TSP问题是勉强能用,稍加时间就能发现最优解,但是若问题规模很大,蚁群算法的性能会极低,甚至卡死。所以可以进行改进,例如精英蚂蚁系统。
精英蚂蚁系统是对基础蚁群算法的一次改进,它在原AS信息素更新原则的基础上增加了一个对至今最优路径的强化手段。在每轮信息素更新完毕后,搜索到至今最优路径的那只蚂蚁将会为这条路径添加额外的信息素。精英蚂蚁系统引入 这种额外的信息素强化手段有助于更好的引导蚂蚁搜索的偏向,使算法更快收敛
二、实例及代码
Excel exp12_3_2.xls内容:
function []=antvrptwwithjamminallcost()
clear all; %清除所有变量
close all; %清图
clc ; %清屏
tic%开始计时。考虑拥堵时间段,以总费用作为比较目标
%%SOLOMON问题数据
wenjian=textread('RXx201.txt');%%调用文件
changdu=size(wenjian,1);%%调用文件的长度
city_coordinate=zeros(changdu,2);%%需求点坐标
demands=zeros(1,changdu);%%需求
earlytime=zeros(1,changdu);%%需求点时间最早服务限制
windowtime=zeros(1,changdu);%%需求点时间限制
servicetime=zeros(1,changdu);%服务时间
for i=1:changdu
city_coordinate(i,1)=(wenjian(i,2));%坐标
city_coordinate(i,2)=(wenjian(i,3));%坐标
demands(i)=(wenjian(i,4));%需求量
earlytime(i)=10;%(wenjian(i,5))-30;%时间限制,最早时间窗
windowtime(i)=(wenjian(i,6))+60;%时间限制
servicetime(i)=(wenjian(i,7));%服务时间
end
% city_coordinate %需求点坐标
% demands%需求量
% earlytime%%需求点时间最早服务限制
% windowtime%时间窗限制
% servicetime%服务时间
% city_coordinate=[42,59;6,17;37,19;22,76;28,11;21,16;12,65;35,18;38,29];%坐标
% demands=[0,90,40,60,70,70,40,20,40];%需求量
% windowtime=[0,100,200,300,300,300,300,300,300];%时间窗限制
% earlytime=[0,20,40,230,110,220,40,220,40];%服务时间
% servicetime=[0,20,40,30,10,20,40,20,40];%服务时间
%%初始化变量
m=40;% m 蚂蚁个数
NC_max=10;% 最大允许运行次数
Alpha=1;% Alpha 表征信息素重要程度的参数
Beta=3;% Beta 表征启发式因子重要程度的参数
Rho=0.25;% Rho 信息素蒸发系数
Q=20;% Q 信息素增加强度系数
vehiclecapacity=200;%车辆容量
C=city_coordinate;
n=size(C,1);%n需求点个数
%%计算节点之间的距离
D=zeros(n,n);%D距离矩阵
for i=1:n
for j=1:n
if i~=j
D(i,j)=((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2)^0.5;
else
D(i,j)=eps;
end
D(j,i)=D(i,j);
end
end
D;%距离矩阵
%%
carspeed=60;%运输车辆正常行驶速度
jamcarspeed=20;%拥堵时段的车辆行驶速度
load_w=0;%车辆载重
Eta=1./D;% %Eta为启发因子矩阵,这里设为距离的倒数
Tau=ones(n,n);%%Tau为信息素矩阵
Tabu=zeros(m,n);%存储并记录路径的生成,禁忌表
NC=1;%当前运行次数
G_best_route=[NC_max,n*2];%各代最佳路线
G_best_length=inf.*ones(1,NC_max);%%各代最佳路线的长度
length_ave=zeros(1,NC_max);%%各代路线的平均长度
%iterbestlength=zeros(1,NC_max);%每次迭代最优距离的长度
dividelength=2;%道路分阶段的长度
%%定义计算碳排放的变量
bestfuelconsumptionofcar=0;%该车辆的碳排放量;
iterbestroute=zeros(1,n*2);%各代最佳路线
dangqianroute=zeros(1,n*2);%当前的各代最佳路线
bestroute=zeros(1,n*2);%最佳路线
bestjuli=0;%最佳路线长度
bijiaomubiao=0;%每次的比较目标
minmubiao=0;
qiyoujiage=7.5;%汽油价格
fixfeeofvehicle=200;%汽车固定使用费用
varityfeeofvehicle=2;%汽车变动使用费用:单位:元/单位距离
carbonunitoffuel=2.32;%每升汽油的碳排放标准,单位:公斤
unitcarbonfee=0.0528;%每公斤碳的收费价格
renlifeeunit=0.5;%每分钟的人力资源成本
besttravletime=0;%所有服务车辆的行驶时间
bestcarfee=0;%所有服务车辆的费用,车辆固定费用+变动使用费用+人力成本
bestcarbon=0;%%所有服务车辆的碳排放数量
bestqiyoufee=0;%%所有服务车辆的汽油费用
Delta_Tau=zeros(n,n);%%信息素矩阵
%% %停止条件之一:达到最大迭代次数,停止
while NC<=NC_max%循环控制
%如randi(2,3,[1 6]),就是产生一个2*3随机矩阵,这个矩阵的元素是区间[1 6]的随机数。
Tabu(:,1)=randi(1,m,1);
factfuelconsumptionofcar=zeros(1,m);%每次只蚂蚁访问所有路径的所有油耗
totaltimeofvehicletravle=zeros(1,m);%每次只蚂蚁访问所有路径的所有时间
anttraveldistance=zeros(1,m);%每次只蚂蚁访问所有节点的距离
factantcarbon=zeros(1,m);%蚂蚁访问所有路径的视角产生的碳排放量
routejuli=0;%%路线距离
bestmubiao=0;%最优的比较目标
%%m只蚂蚁的访问遍历情况
for i=1:m
% disp('===========新的蚂蚁开始访问============')
% disp('蚂蚁所用时间')
% totaltimeofvehicletravle(i)
visited=Tabu(i,:);%已经访问的需求点
visited=visited(visited>0);
to_visit=setdiff(1:n,visited);%比较2个数组内不同的值,得出还没有访问的需求点
%%蚂蚁开始访问
load_w=0;%%
vehicletime=0;%%车辆时间控制
dangqianvehiclevisittime=0;
carcarbon=0;%蚂蚁访问所有路径的可能产生的碳排放量
fuelconsumptionofcar=0;%蚂蚁访问所有路径的可能产生的油耗量
j=1;
while j<=n
% disp('访问当前节点的具体时间,新的节点')
% vehicletime
if ~isempty(to_visit)%如果还有没有访问的需求点
to_visit ;
%% 判断选择哪个需求点
for k=1:length(to_visit)%对每一个将要访问的需求点进行信息素计算
x(k)=(Tau(visited(end),to_visit(k))^Alpha)*(Eta(visited(end),to_visit(k))^Beta); %Tau为信息素矩阵,% Alpha 表征信息素重要程度的参数,%Eta为启发因子矩阵,这里设为距离的倒数,%% Beta 表征启发式因子重要程度的参数
end
%%需求点选择方法
ww=rand;%随机生成一个概率
x=x/(sum(x));
xcum=cumsum(x);
Select=find(xcum>=ww);%若计算的概率大于原来的就选择这条路线%要选择其中总概率大于等于某一个随机数,找到大于等于这个随机数的需求点的在未访问需求点中的位置
%%选择到的节点
% disp('访问当前节点')
% to_visit(Select(1))
load_w=load_w+demands(to_visit(Select(1)));%车辆装载量计算
r=load_w/vehiclecapacity;%汽车载重与车辆容量的比例
Tabu(i,length(visited));%当前已经访问节点
to_visit(Select(1));%当前将要访问节点
% disp('访问当前节点的距离')
% D(Tabu(i,length(visited)),to_visit(Select(1)))%节点之间的距离
%开始该路段的时间计算
pathlength=D(Tabu(i,length(visited)),to_visit(Select(1))); %该路段长度
kk=ceil(pathlength/dividelength);%ceil表示向上取整,得出该路段分得的所有段数
currentcartime=zeros(1,kk);%%车辆行驶在路段K的当前行驶时间
%%拥堵时间判断
if kk==1 & dividelength>pathlength %第一个路段非常小
if (vehicletime>=60 & vehicletime<=120) || (vehicletime>=720 & vehicletime<=840)
currentcartime(1)=(pathlength/jamcarspeed)*60;%拥堵时间段行驶的各个路段时间
currentfuel(1)=pathlength*(0.0617*jamcarspeed*jamcarspeed-7.8227*jamcarspeed+429.51)/1000;%车辆油耗
carbonxiuzhengbili=1.27+0.0614*r-0.0011*r*r-0.00235/jamcarspeed-1.33/jamcarspeed;
else
currentcartime(1)=(pathlength/jamcarspeed)*60;%正常行驶的各个路段时间
currentfuel(1)=pathlength*(0.0617*carspeed*carspeed-7.8227*carspeed+429.51)/1000;%车辆油耗
carbonxiuzhengbili=1.27+0.0614*r-0.0011*r*r-0.00235/carspeed-1.33/carspeed;
end
vehicletime= vehicletime+currentcartime(1);
fuelconsumptionofcar=fuelconsumptionofcar+currentfuel(1);
carcarbon=carcarbon+currentfuel(1)*carbonxiuzhengbili*carbonunitoffuel;%%这只蚂蚁的碳排放量
else
currentcartime(1)=(dividelength/carspeed)*60;%正常行驶的各个路段时间
vehicletime= vehicletime+currentcartime(1);
currentfuel(1)=dividelength*(0.0617*carspeed*carspeed-7.8227*carspeed+429.51)/1000;%车辆油耗
fuelconsumptionofcar=fuelconsumptionofcar+currentfuel(1);
carbonxiuzhengbili=1.27+0.0614*r-0.0011*r*r-0.00235/carspeed-1.33/carspeed;
carcarbon=carcarbon+currentfuel(1)*carbonxiuzhengbili*carbonunitoffuel;%%这只蚂蚁的碳排放量
end
for ii=2:kk%计算每一段路段的行驶速度与行驶时间
if ii<kk
if (vehicletime>=60 & vehicletime<=120) || (vehicletime>=720 & vehicletime<=840)
currentcartime(ii)=dividelength/jamcarspeed*60;%正常时间段行驶的各个路段时间
currentfuel(ii)=dividelength*(0.0617*jamcarspeed*jamcarspeed-7.8227*jamcarspeed+429.51)/1000;%车辆油耗
carbonxiuzhengbili=1.27+0.0614*r-0.0011*r*r-0.00235/jamcarspeed-1.33/jamcarspeed;
else
currentcartime(ii)=dividelength/carspeed*60;%正常时间段行驶的各个路段时间
currentfuel(ii)=dividelength*(0.0617*carspeed*carspeed-7.8227*carspeed+429.51)/1000;%车辆油耗
carbonxiuzhengbili=1.27+0.0614*r-0.0011*r*r-0.00235/carspeed-1.33/carspeed;
end
vehicletime=vehicletime+currentcartime(ii);
fuelconsumptionofcar=fuelconsumptionofcar+currentfuel(ii);
carcarbon=carcarbon+currentfuel(ii)*carbonxiuzhengbili*carbonunitoffuel;%%这只蚂蚁的碳排放量
end
if (ii==kk) %最后一个路段的各个路段时间
if (vehicletime>=60 & vehicletime<=120) || (vehicletime>=720 & vehicletime<=840)
currentcartime(ii)=dividelength/jamcarspeed*60;%正常时间段行驶的各个路段时间
currentfuel(ii)=dividelength*(0.0617*jamcarspeed*jamcarspeed-7.8227*jamcarspeed+429.51)/1000;%车辆油耗
carbonxiuzhengbili=1.27+0.0614*r-0.0011*r*r-0.00235/jamcarspeed-1.33/jamcarspeed;
else
currentcartime(ii)=dividelength/carspeed*60;%正常时间段行驶的各个路段时间
currentfuel(ii)=dividelength*(0.0617*carspeed*carspeed-7.8227*carspeed+429.51)/1000;%车辆油耗
carbonxiuzhengbili=1.27+0.0614*r-0.0011*r*r-0.00235/carspeed-1.33/carspeed;
end
vehicletime=vehicletime+currentcartime(ii);
fuelconsumptionofcar=fuelconsumptionofcar+currentfuel(ii);
carcarbon=carcarbon+currentfuel(ii)*carbonxiuzhengbili*carbonunitoffuel;%%这只蚂蚁的碳排放量
end
end
% disp('+++++随机需求点:车辆行驶该路段的行驶时间')
% vehicletime
%
vehicletime= vehicletime+servicetime(to_visit(Select(1))); %将要访问的需求点的服务时间计算
% disp('车辆行驶该路段的行驶时间++加上服务时间')
% servicetime(to_visit(Select(1)))
% vehicletime
dangqianvehiclevisittime=dangqianvehiclevisittime+vehicletime;
%%%容量和时间判断
if (load_w<=vehiclecapacity && dangqianvehiclevisittime<=windowtime(to_visit(Select(1))) ) && dangqianvehiclevisittime>=earlytime(to_visit(Select(1)))
%if dangqianvehiclevisittime<=windowtime(to_visit(Select(1))) && dangqianvehiclevisittime>=earlytime(to_visit(Select(1)))
Tabu(i,length(visited)+1)=to_visit(Select(1)); %访问的节点
totaltimeofvehicletravle(i)=totaltimeofvehicletravle(i)+vehicletime;%%蚂蚁i所有的车辆行驶时间
% disp('+++++++++车辆的行驶时间之和+++++++++++++')
% totaltimeofvehicletravle(i)
anttraveldistance(i)=anttraveldistance(i)+pathlength;%%蚂蚁i所有车辆的行驶距离
factantcarbon(i)=factantcarbon(i)+carcarbon;%%蚂蚁i所有车辆的实际产生的碳排放
factfuelconsumptionofcar(i)=factfuelconsumptionofcar(i)+fuelconsumptionofcar;
vehicletime=0;%服务时间归零
fuelconsumptionofcar=0;
carcarbon=0;
else
% disp('该车辆服务完毕的的行驶时间')
% vehicletime
j=j-1;%没有选择到需求点,因此循环计数器减少一次
load_w=0;%车辆装载量归零
vehicletime=0;%服务时间归零
carcarbon=0;%碳排放归零
fuelconsumptionofcar=0;
Tabu(i,length(visited)+1)=1; %返回了起点
dangqianvehiclevisittime=0;
end
end %%访问了需求点
% %if (load_w>vehiclecapacity) || ((dangqianvehiclevisittime>windowtime(to_visit(Select(1))))&&(dangqianvehiclevisittime<earlytime(to_visit(Select(1)))))
% if (load_w>vehiclecapacity) || (dangqianvehiclevisittime>windowtime(to_visit(Select(1))))
% % disp('该车辆服务完毕的的行驶时间')
% % vehicletime
% j=j-1;%没有选择到需求点,因此循环计数器减少一次
% load_w=0;%车辆装载量归零
% vehicletime=0;%服务时间归零
% carcarbon=0;%碳排放归零
% fuelconsumptionofcar=0;
% Tabu(i,length(visited)+1)=1; %返回了起点
% dangqianvehiclevisittime=0;
% else
%
% Tabu(i,length(visited)+1)=to_visit(Select(1)); %访问的节点
% totaltimeofvehicletravle(i)=totaltimeofvehicletravle(i)+vehicletime;%%蚂蚁i所有的车辆行驶时间
% % disp('+++++++++车辆的行驶时间之和+++++++++++++')
% % totaltimeofvehicletravle(i)
% anttraveldistance(i)=anttraveldistance(i)+pathlength;%%蚂蚁i所有车辆的行驶距离
% factantcarbon(i)=factantcarbon(i)+carcarbon;%%蚂蚁i所有车辆的实际产生的碳排放
% factfuelconsumptionofcar(i)=factfuelconsumptionofcar(i)+fuelconsumptionofcar;
% vehicletime=0;%服务时间归零
% fuelconsumptionofcar=0;
% carcarbon=0;
% end
% disp('实际车辆行驶的时间')
% vehicletime
% totaltimeofvehicletravle(i)
j=j+1;
visited=Tabu(i,:);%已经访问的需求点
visited=visited(visited>0);
to_visit=setdiff(1:n,visited);%比较2个数组内不同的值,得出还没有访问的需求点
x=[];%清空没有访问的需求点的信息
if visited(end)~=1
Tabu(i,1:(length(visited)+1))=[visited,1];
end
end
% disp('车辆实际行驶的总时间')
% totaltimeofvehicletravle(i)
% disp('车辆实际行驶的路线')
% Tabu(i,:)
end %%全部M只蚂蚁循环访问控制
factfuelconsumptionofcar;
factantcarbon;
totaltimeofvehicletravle;
anttraveldistance;
Tabu;
%%计算m只蚂蚁的各自的耗油量、行驶时间、行驶距离带来的总费用
vehiclenumofeachant=zeros(1,m);%各只蚂蚁的总费用车辆数量
anttotalcost=zeros(1,m);%各只蚂蚁的总费用初始化
for i=1:m
nn=Tabu(i,:);
for j=2:length(nn)
if nn(j)==1
vehiclenumofeachant(i)=vehiclenumofeachant(i)+1;
end
end
anttotalcost(i)=anttraveldistance(i)*varityfeeofvehicle+vehiclenumofeachant(i)*fixfeeofvehicle+totaltimeofvehicletravle(i)*renlifeeunit+factfuelconsumptionofcar(i)*qiyoujiage+factantcarbon(i)*unitcarbonfee;%
end
bestcost=min(anttotalcost);%%找出总费用最优的路线
weizhi=find(bestcost==anttotalcost); %%找出总费用最优的路线的位置
kk=Tabu(weizhi,:);
for x=1:length(kk)
iterbestroute(x)=kk(x);
end
%%每次最好的计算结果记录
if NC>=2
for x=1:length(kk)
Tabu(1,x)=iterbestroute(x);
end
end
dangqianbestroute=iterbestroute(iterbestroute>0);
%length_ave(NC)=mean(anttotalcost);%%以总费用作为目标的平均值
length_ave(NC)=bestcost;%%以总费用作为目标的平均值
bijiaomubiao=bestcost; %%本次程序的比较目标
if NC==1
bestfuelconsumptionofcar=factfuelconsumptionofcar(weizhi);
bestroute=dangqianbestroute;
bestjuli=anttraveldistance(weizhi);
minmubiao=bijiaomubiao;
besttravletime=totaltimeofvehicletravle(weizhi);
bestcarbon=factantcarbon(weizhi);
else if bijiaomubiao<minmubiao
bestfuelconsumptionofcar=factfuelconsumptionofcar(weizhi);
bestroute=dangqianbestroute;
bestjuli=anttraveldistance(weizhi);
minmubiao=bijiaomubiao;
besttravletime=totaltimeofvehicletravle(weizhi);
bestcarbon=factantcarbon(weizhi);
end
end
%% 第四步记录本代各种参数
L=zeros(m,1);
for i=1:m
MM=Tabu(i,:);
R=MM(MM>0);
for j=1:(length(R)-1)
L(i)=L(i)+D(R(j),R(j+1));
end
end
NC=NC+1 %迭代计数器
%% 全局信息素更新
%Delta_Tau=zeros(n,n);
for i=1:m
MM=Tabu(i,:);
R=MM(MM>0);
cd=length(R);
for j=1:cd
Tabu(i,j)=R(j);
end
for j=1:(cd-1)
%Delta_Tau(R(j),R(j+1))=Delta_Tau(R(j),R(j+1))+Q/L(i);
Delta_Tau(Tabu(i,j),Tabu(i,j+1))=Delta_Tau(Tabu(i,j),Tabu(i,j+1))+Q/L(i); %此次循环在路径(i,j)上的信息素增量
end
%此次循环在整个路径上的信息素增量
end
Tau=(1-Rho).*Tau+Delta_Tau; %考虑信息素挥发,更新后的信息素
%% ?????????
Tabu=zeros(m,n);
load_w=0;
end
%%输出最优路线的相关信息
minmubiao
bestfuelconsumptionofcar
bestroute
bestjuli
besttravletime
bestcarbon
%% 画图画出路线
subplot(1,2,1)
plot([C(bestroute,1)],[C(bestroute,2)],'-*')%最优路径
subplot(1,2,2) %绘制第二个子图形
% plot(iterbestlength)%各代的最短距离
% hold on
plot(length_ave,'r')%各代的平均距离
% title('平均距离和最短距离') %标题
toc
end