资源受限项目调度问题(Resource-Constrained Project Scheduling Problem,RCPSP)是一种经典的组合优化问题,主要研究在有限资源条件下如何安排项目的各项任务,以达到特定的优化目标,如最小化项目完成时间或最大化项目利润等。
RCPSP的基本元素主要包括:任务、时间、资源和约束。
任务:每个项目都由一系列独立的任务组成,每个任务都有确定的开始时间和结束时间。
时间:每个任务都有固定的持续时间。
资源:在项目中,资源是有限的,可以包括人力、设备、物料等。每个任务在执行过程中都需要消耗一定的资源。
约束:项目中的任务往往存在一定的依赖关系,例如有些任务必须在其他任务完成后才能开始,这就形成了任务之间的约束关系。
在RCPSP中,最核心的问题是如何在满足所有任务约束的前提下,合理分配有限的资源,使得项目可以在最短的时间内完成或者获得最大的利润。
解决RCPSP的方法有很多,包括启发式算法、元启发式算法、精确算法等。其中,遗传算法、模拟退火算法、蚁群算法等元启发式算法因其在解决RCPSP问题上的优异性能,被广泛应用于实际中。
遗传算法是一种通过模拟自然进化过程进行搜索的优化算法。在这种算法中,解决方案(称为"个体")被编码为一种类似于染色体的结构。这些个体组成一个"种群",并通过迭代过程(包括选择、交叉和突变操作)来生成新的种群。最后,优化的解决方案是产生的最优个体。
在资源受限调度的问题中,我们试图找到一种方式来安排任务,以最有效地利用有限的资源,同时满足所有任务的约束。遗传算法可以通过以下步骤来解决这个问题:
初始化:首先,创建一个种群,每个个体代表一个可能的调度方案。每个个体都被编码为染色体,表示任务的执行顺序。
适应度函数:这是一个函数,用于评估每个调度方案的优劣。通常,这个函数会考虑任务的完成时间、资源利用率和满足约束的程度等因素。
选择:根据适应度函数的评估结果,选择性地复制个体到新的种群。优秀的个体有更高的复制概率。
交叉:这是一种模拟遗传中的配对过程,两个个体互换染色体的一部分,生成两个新的个体。
突变:这是一种随机改变个体某部分的过程,增加种群的多样性。
替换:新的种群替换旧的种群,开始新的迭代。
终止:当达到预定的迭代次数,或者找到满意的解决方案时,算法终止。
遗传算法优化资源受限调度的优点在于,它能够在大规模和复杂的搜索空间中找到良好的解决方案。然而,它也有一些缺点,比如可能会陷入局部最优,或者需要大量的计算资源。因此,在实际应用中,可能需要对遗传算法进行一些改进或者与其他优化算法结合使用。
一、目标函数:
二、算例分析
各个任务的执行模式、工期、资源使用量及模式转换成本表
任务 |
执行模式m |
工期 |
资源使用 |
模式转换成本 |
1 |
1 |
0 |
0 |
0 |
2 |
1 |
3 |
6 |
0 |
2 |
9 |
5 |
0 |
|
3 |
10 |
6 |
0 |
|
3 |
1 |
1 |
4 |
0 |
2 |
1 |
7 |
4 |
|
3 |
5 |
4 |
0 |
|
4 |
1 |
3 |
10 |
16 |
2 |
5 |
7 |
4 |
|
3 |
8 |
6 |
0 |
|
5 |
1 |
4 |
9 |
12 |
2 |
6 |
2 |
0 |
|
3 |
10 |
5 |
0 |
|
6 |
1 |
2 |
2 |
0 |
2 |
4 |
8 |
8 |
|
3 |
6 |
2 |
0 |
|
7 |
1 |
3 |
5 |
0 |
2 |
6 |
7 |
4 |
|
3 |
8 |
5 |
0 |
|
8 |
1 |
4 |
6 |
0 |
2 |
10 |
10 |
16 |
|
3 |
10 |
4 |
0 |
|
9 |
1 |
2 |
6 |
0 |
2 |
7 |
8 |
8 |
|
3 |
10 |
7 |
4 |
|
10 |
1 |
1 |
4 |
0 |
2 |
1 |
8 |
8 |
|
3 |
9 |
5 |
0 |
|
11 |
1 |
6 |
2 |
0 |
2 |
9 |
9 |
12 |
|
3 |
10 |
7 |
4 |
|
12 |
1 |
0 |
0 |
0 |
MATLAB主程序如下:
%% 遗传算法优化资源受限的调度
clc;close all; clear all;
%% (1)设置模型的相关参数
data1=[1 1 0 0 0
2 1 3 6 0
2 2 9 5 0
2 3 10 6 0
3 1 1 4 0
3 2 1 7 4
3 3 5 4 0
4 1 3 10 16
4 2 5 7 4
4 3 8 6 0
5 1 4 9 12
5 2 6 2 0
5 3 10 5 0
6 1 2 2 0
6 2 4 8 8
6 3 6 2 0
7 1 3 5 0
7 2 6 7 4
7 3 8 5 0
8 1 4 6 0
8 2 10 10 16
8 3 10 4 0
9 1 2 6 0
9 2 7 8 8
9 3 10 7 4
10 1 1 4 0
10 2 1 8 8
10 3 9 5 0
11 1 6 2 0
11 2 9 9 12
11 3 10 7 4
12 1 0 0 0];
set1=unique(data1(:,1));
jobnumber=length(set1);
UB=zeros(1,jobnumber);
for i=1:jobnumber
H1= data1(:,1)==i;
n=sum(H1);
UB(1,i)=n;
end
R=20;%单位时间资源可用量
S1=0.4;
S2 =0.35;
S3 =0.25;
T0=50;
EL=[0 inf
3 18
1 24
5 28
9 21
9 24
12 28
13 28
18 30
13 30
11 30
0 inf];%设置E和L,第一列是E,第二列是L
E=EL(:,1);%
L=EL(:,2);
lambda=3;%设置lambda
data2=[0 0
0 0
0.3 15
0.3 15
0.6 10
0.6 10
0.3 15
0.6 10
0.6 10
0.3 15
0.6 0
0 0];%惩罚系数和Δt的设置
alpha=data2(:,1);
dt=data2(:,2);
topo=[0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 1 1 0 0 0 0
0 0 1 0 0 1 1 0 0 0 0 0
0 0 1 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 0];%前序关系,一行是一个节点的前序
% data1,N,S1,S2,S3,T0,E,L,lambda,alpha,dt,topo,R
% 遗传算法参数
popsize=50;%遗传算法种群数
ga_max=200;%遗传算法迭代次数
PM=0.05;%变异概率
PC=0.8;%交叉概率
%% 遗传算法主程序
%性能跟踪
trace1=zeros(ga_max,2);
trace2=zeros(ga_max,2);
trace3=zeros(ga_max,2);
trace4=zeros(ga_max,2);
gen=0;
Chrom=genChrome(popsize,jobnumber,UB);% 建立种群
[Value,U,T,F]= decodingFun(Chrom,popsize,data1,jobnumber,S1,S2,S3,T0,E,L,lambda,alpha,dt,topo,R);%解码染色体
%% 遗传算法优化项目的主循环
%进度条
wait_hand = waitbar(0,'正在遗传算法优化……', 'tag', 'TMWWaitbar');
%% 时间外环
while gen<=ga_max
%% 遗传算法选择
FitnV=ranking(Value);%分配适应度值
Chrom=select('sus',Chrom,FitnV,1);%选择
Chrom=mutationGA(Chrom,popsize,PM,jobnumber,UB);% 种群变异,单点变异
Chrom=crossGA(Chrom,popsize,PC,jobnumber);% 种群交叉,单点交叉
[Value,U,T,F]= decodingFun(Chrom,popsize,data1,jobnumber,S1,S2,S3,T0,E,L,lambda,alpha,dt,topo,R);%解码染色体
%% 计算最优
[v1,index1]=min(Value);
gen=gen+1;
trace1(gen,1)=Value(index1);
trace1(gen,2)=mean(Value);
trace2(gen,1)=U(index1);
trace2(gen,2)=mean(U);
trace3(gen,1)=T(index1);
trace3(gen,2)=mean(T);
trace4(gen,1)=F(index1);
trace4(gen,2)=mean(F);
%% 记录最优
if gen==1
bestChrom1=Chrom(index1,:);%记录函数1的最优染色体
bestValue1=v1;%记录函数1的最优值
end
if bestValue1>v1
bestValue1=v1;%记录函数1的最优值
bestChrom1=Chrom(index1,:);
end
waitbar(gen/ga_max,wait_hand);%每循环一次更新一次进步条
end
delete(wait_hand);%执行完后删除该进度条
% 显示结果
bestValue1
bestChrom1
%% 转换为需要的格式和输出文件
% xlswrite('遗传算法优化结果.xls',bestChrom1);
figure;
plot(trace1(:,1),'r*-');
legend('目标函数最优值');
xlabel('迭代次数');
ylabel('目标函数');
title('遗传算法优化');
figure;
plot(trace1(:,2),'bo-');
legend('目标函数均值');
xlabel('迭代次数');
ylabel('目标函数');
title('遗传算法优化');
figure;
plot(trace2(:,1),'r*-');
hold on;
plot(trace2(:,2),'bo-');
legend('U最优值','U均值');
xlabel('迭代次数');
ylabel('U');
title('U迭代曲线');
figure;
plot(trace3(:,1),'r*-');
hold on;
plot(trace3(:,2),'bo-');
legend('T最优值','T均值');
xlabel('迭代次数');
ylabel('T');
title('T迭代曲线');
figure;
plot(trace4(:,1),'r*-');
hold on;
plot(trace4(:,2),'bo-');
legend('F最优值','F均值');
xlabel('迭代次数');
ylabel('F');
title('F迭代曲线');
x=bestChrom1;
[Z,tstart,tend,rremain]=myfun(x,data1,jobnumber,S1,S2,S3,T0,E,L,lambda,alpha,dt,topo,R);
disp('目标函数值');
Z
disp('任务开始时间');
tstart'
disp('任务结束时间');
tend'
disp('任务采用的模式');
bestChrom1
disp('资源使用情况');
rremain
%% 绘制甘特图
drawgantt(tstart,tend,jobnumber,bestChrom1);
%% 绘制资源使用情况
figure;
plot(rremain);
legend('资源剩余量');
xlabel('时间');
ylabel('资源剩余量');
title('资源剩余量');
程序结果如下:
bestValue1 =
11571.6
bestChrom1 =
1 3 3 3 3 3 3 2 3 3 2 1
目标函数值
Z =
11571.6
任务开始时间
ans =
0 0 0 0 10 10 20 20 30 28 37 46
任务结束时间
ans =
0 10 5 8 20 16 28 30 40 37 46 46
任务采用的模式
bestChrom1 =
1 3 3 3 3 3 3 2 3 3 2 1
资源使用情况
rremain =
Columns 1 through 24
4 4 4 4 4 8 8 8 14 14 13 13 13 13 13 13 15 15 15 15 5 5 5 5
Columns 25 through 48
5 5 5 5 5 5 8 8 8 8 8 8 8 4 4 4 11 11 11 11 11 11 20 20
Columns 49 through 72
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
Columns 73 through 96
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
Columns 97 through 100
20 20 20 20
>>