您的位置:首页 > 编程语言 > Java开发

JSP中求关键路径算法及java实现

2015-05-17 17:03 561 查看
在JSP问题中,关键路径决定着车间作业的完工时间,通过引入基于关键路径的邻域规则,使邻域解大大减少,从而大大减少优化过程的复杂度。

关键块是关键路径中工序在同一台机器连续组成的工序集合。

已知:

int[][] o = new int
[m];  //o代表工序,值为各工序编号,i为工件编号,j为该工件工序编号
int[][] u = new int
[m];   //工件i的第j个工序是第几台机器
int[][] p = new int
[m];   //工件i的第j个工序的处理时间
int[][] startTime = new int
[m];  //startTime[][]存储第i个工件的第j个工序的开始时间
int[][] finishTime = new int
[m]; //finished[][]存储第i个工件的第j个工序的完成时间


算法:

Step 1: 根据最大完工时间,求得最大完工时间所在的工序编号,并将该工序编号加入到关键路径链表中,该工序表示为o

Step 2: 求preJob(o), preMac(o)

Step 3: 若preJob(o) != null && preMac(o) != null,取50%概率选择其一,将新的工序加入插入到关键路径链表,并将该工序表示为o

否则若preJob(o) != null,将preJob(o)插入到关键路径链表,并将该工序表示为o

否则若preMac(o) != null,将preMac(o)插入到关键路径链表,并将该工序表示为o

Step 4: 判断当前关键工序的开始时间是否等于0,如果不是,转Step2, 否则结束

说明:preJob(o):工序o在本工件上的前一工序,且该工序的结束时间等于o的开工时间

preMac(o): 工序o所在机器在o前面紧挨的工序,即该工序的结束时间等于o的开工时间

实现代码:

//接下来计算关键路径
//求得最大时间所在的工序编号
int maxIndex = 0;
for(int i = 0; i < n; ++i){
if(finishTime[i][9] == maxTime){
maxIndex = i * 10 + 9;
}
}

//将这个工序加入关键路径链表中
ArrayList<Integer> keyPath = new ArrayList<Integer>();
keyPath.add(0, maxIndex);

int index_i = maxIndex / n;
int index_j = maxIndex % m;

//开始递推寻找,直到首工序
while(startTime[index_i][index_j] != 0){
int preJobIndex = -1;
int preMacIndex = -1;
if(index_j != 0 && finishTime[index_i][index_j - 1] ==
startTime[index_i][index_j]){//存在前序工序,且结束时间等于当前工序的开始时间
preJobIndex = index_i * 10 + index_j - 1;
}
for(int i = 0; i < n; ++i){
int mac = u[index_i][index_j];
int macOpe = indi.machines[mac].tasks.get(i);
int macOpe_i = macOpe / n;
int macOpe_j = macOpe % m;
if(finishTime[macOpe_i][macOpe_j] == startTime[index_i][index_j]){
//存在所在机器的前一工序
preMacIndex = macOpe;
break;
}
}
if(preJobIndex != -1 && preMacIndex != -1){//同时存在取50%概率选择
if(Math.random() >= 0.5){
keyPath.add(0, preJobIndex);
index_j -= 1;
}
else{
keyPath.add(0, preMacIndex);
index_i = preMacIndex / n;
index_j = preMacIndex % m;
}
}
else if(preJobIndex != -1){//只存在符合要求的工件前序工序
keyPath.add(0, preJobIndex);
index_j -= 1;
}
else if(preMacIndex != -1){//只存在符合要求的机器前序工序
keyPath.add(0, preMacIndex);
index_i = preMacIndex / n;
index_j = preMacIndex % m;
}
}
//接下来对关键路径的工序进行分块
//思路来源于文档倒排索引的Reduce实现
KPB = new ArrayList<KPBlock>();
int preMac = -1;
KPBlock kpblock = new KPBlock();

for(int i = 0; i < keyPath.size(); ++i){
int curOpe = keyPath.get(i);
int cur_i = curOpe / n;
int cur_j = curOpe % m;
int curMac = u[cur_i][cur_j];
if(preMac != curMac && preMac != -1){
KPB.add(kpblock);
kpblock = new KPBlock();
}
preMac = curMac;
kpblock.block.add(curOpe);
}
KPB.add(kpblock); //加上最后一块




class KPBlock{
ArrayList<Integer> block = new ArrayList<Integer>();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: