目录
最近研究了新的柔性作业车间相关问题,但是由于没有标准算例,所以只能用自己的算法和CPLEX求解结果进行对比,奈何网上的CPLEX求解车间调度的讲解实在是太少了,已有的也晦涩难懂,于是经过不懈的努力,跑通了FJSP问题,打算和大家分享一下。
一、柔性作业车间概念
1.1柔性作业车间调度问题简介
柔性作业车间是指假设有n个工件,工件集合为:;每个工件的工序数为
,
的工序为
,在m个机器上加工,机器集合
上加工。
表示工件i的第j道工序,可以选择其可用的机器集合中的任意机器进行加工,每道工序的加工时间与加工机器相关。柔性作业车间在作业车间的基础上增加了机器选择子问题。
1.2柔性作业车间数学模型
要想在CPLEX上进行柔性作业车间求解,就得建立正确的数学模型,本文的数学模型主要参考论文Mathematical modeling and heuristic approaches to flexible job shop scheduling problems和教材《柔性作业车间调度智能算法及其应用》。
Notation:(i表示机器索引,j表示工件索引,h表示工序索引)
n:工件总数;
m:机器总数;
:工件j的工序数;
:表示工件j的工序h的可选机器集中的机器i;
:表示工件j的工序h在机器i上加工时间;
L:A large number;
variables(for i =1..m , j=1..n , h=1..hj)
:最大完工时间;
:工件j的工序h选择机器i加工;
:工件j的工序h选择机器后的加工时间;
:工件j的工序h开始加工时间;
:工件j的工序h加工完成时间;
:如果工序
在机器i上先于
加工则为1,否则为0;
数学模型:
二、CPLEX软件
2.1CPLEX简介
- Cplex是IBM公司开发的一个优化工具引擎,可以用其求解线性规划、二次规划、整数规划等问题;能够快速解决一些行业难题。
- 自带IBM ILOG Cplex Optimization Studio既能使用自带语言进行编程,也提供了众多流行语言的接口,具有广泛的应用前景
2.2CPLEX基础语法
CPLEX的语法可以参考这篇文章:
三、CPLEX求解柔性作业车间调度问题
假设有3个工件,3个机器,具体信息如下表:
表1 柔性作业车间案例
M1 | M2 | M3 | ||
J1 | O11 | 1 | 0 | 3 |
O12 | 2 | 3 | 0 | |
O13 | 4 | 1 | 4 | |
J2 | O21 | 3 | 2 | 4 |
O22 | 0 | 5 | 3 | |
O23 | 4 | 0 | 2 | |
J3 | O31 | 4 | 0 | 1 |
O32 | 4 | 2 | 0 |
下面是已知数据,需要自己传入:
//柔性作业车间FJSP数学模型求解
//已知参数
int n=...; //工件数
int m=...; //机器数
int H[0..n]=...; //每个工件的工序数
int hmax=...; //工序的最大值
range i1=1..m; //机器索引i
range j1=1..n; //工件索引j
range k1=1..n;int a[i1][j1][1..hmax]=...; //如果工件j的第h个工序可以再机器i上加工,则为1,否则为0
int p[i1][j1][1..hmax]=...; //工件j的第h个工序在机器i上的加工时间;
int bigL=1000; //A Large Number
接下来是设置的变量:
dvar int Cmax in 0..maxint; //最大完工时间
dvar boolean y[i1][j1][1..hmax]; //如果工件j的第h个工序选择机器i,则为true
dvar int+ Ps[j1][1..hmax]; //工件j的第h个工序选择机器后的加工时间
dvar int t[j1][1..hmax] in 0..maxint; //工件j的第h个工序的加工开始时间
dvar int c[j1][1..hmax] in 0..maxint; //工件j的第h个工件的加工完成时间
dvar boolean x[i1][0..n][0..hmax][0..n][0..hmax];
最后是目标函数和约束条件:
//目标函数
minimize Cmax;//约束条件:
subject to
{
forall(j in j1)
Cmax>=c[j][H[j]];
forall(j in j1,h in 1..H[j])
t[j][h]+Ps[j][h]==c[j][h];
forall(j in j1,h in 1..(H[j]-1))
c[j][h]<=t[j][h+1];
forall(i in i1,j in j1,h in 1..H[j])
y[i][j][h]<=a[i][j][h];
forall(j in j1,h in 1..H[j])
Ps[j][h]==sum(i in i1) y[i][j][h]*p[i][j][h];
forall(j in j1,h in 1..H[j])
sum(i in i1)
y[i][j][h]==1;
forall(i in i1)
sum(k in j1,l in 1..H[k])
x[i][0][0][k][l]==1;
forall(i in i1,k in j1,l in 1..H[k])
sum(j in 0..n,h in 0..H[j])
x[i][j][h][k][l]==y[i][k][l];
forall(i in i1,j in j1,h in 1..H[j])
sum(k in 0..n,l in 0..H[k])
x[i][j][h][k][l]==y[i][j][h];
forall(i in i1,j in j1,h in 1..H[j],k in j1,l in 1..H[k])
x[i][j][h][k][l]+x[i][k][l][j][h]<=1;
forall(i in i1,j in 0..n,h in 0..H[j])
x[i][j][h][j][h]==0;
forall(i in i1,j in j1,k in j1,l in 1..H[k])
x[i][j][0][k][l]==0;
forall(i in i1,j in j1,h in 1..H[j],k in j1)
x[i][j][h][k][0]==0;
forall(i in i1,j in j1,h in 1..H[j],k in j1,l in 1..H[k])
t[j][h]+Ps[j][h]<=t[k][l]+bigL*(1-x[i][j][h][k][l]);
}
数据长这样:
n=3; //工件数
m=3; //机器数
H=[0,3,3,2]; //每个工件的工序数
hmax=3; //工件工序的最大值
a=
[
[[1,1,1],[1,0,1],[1,1,0]],
[[0,1,1],[1,1,0],[0,1,0]],
[[1,0,1],[1,1,1],[1,0,0]],
];p=
[
[[1,2,4],[3,0,4],[4,4,0]], //机器1
[[0,3,1],[2,5,0],[0,2,0]], //机器2
[[3,0,4],[4,3,2],[1,0,0]], //机器3
];
总结:需要建立正确的模型,这样在CPLEX就可以直接写代码,但是CPLEX的变量索引不能处理一下求解过程中的未知变量...。
第一次写,希望大家批评指正!