Commit a5817c7e authored by Tong Li's avatar Tong Li

bom

parent 60970636
...@@ -690,11 +690,11 @@ public class GeneticDecoder { ...@@ -690,11 +690,11 @@ public class GeneticDecoder {
long slowOpThresholdNs = 500_000_000L; // 500ms long slowOpThresholdNs = 500_000_000L; // 500ms
Map<Integer, Integer> targetGroupEnd=new HashMap<>();
for (int groupId : chromosome.getOperationSequencing()) { for (int groupId : chromosome.getOperationSequencing()) {
int scheduledCount = orderProcessCounter.get(groupId); int scheduledCount = orderProcessCounter.get(groupId);
if(groupId==1) if(groupId==15||groupId==16)
{ {
int i=0; int i=0;
} }
...@@ -723,7 +723,7 @@ public class GeneticDecoder { ...@@ -723,7 +723,7 @@ public class GeneticDecoder {
orderAnchor =bom.computeHybridSemiAnchor(this,groupId, entrysBygroupId, orderAnchor =bom.computeHybridSemiAnchor(this,groupId, entrysBygroupId,
opMachineKeyMap, chromosome, scheduleIndexById, opMachineKeyMap, chromosome, scheduleIndexById,
machineTasksCache, machineIdMap, entryIndexById, machineTasksCache, machineIdMap, entryIndexById,
reForwardFinishedOrderIds,_globalParam,order); reForwardFinishedOrderIds,_globalParam,order,targetGroupEnd);
if (orderAnchor < 0) { if (orderAnchor < 0) {
orderIsJit = false; orderIsJit = false;
...@@ -742,7 +742,7 @@ public class GeneticDecoder { ...@@ -742,7 +742,7 @@ public class GeneticDecoder {
} else { } else {
orderAnchor = bom.computeSemiFinishedAnchor(this, groupId, entrysBygroupId, orderAnchor = bom.computeSemiFinishedAnchor(this, groupId, entrysBygroupId,
opMachineKeyMap, chromosome, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,_globalParam.isIsCheckMp()); scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,_globalParam.isIsCheckMp(),targetGroupEnd);
if (orderAnchor < 0) { if (orderAnchor < 0) {
orderIsJit = false; orderIsJit = false;
orderSchedulingInfo.put(groupId, orderSchedulingInfo.put(groupId,
...@@ -859,6 +859,11 @@ public class GeneticDecoder { ...@@ -859,6 +859,11 @@ public class GeneticDecoder {
opCount++; opCount++;
if(currentOp.getId()==60)
{
int k=0;
}
orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1); orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);
orderLastEndTime.put(groupId, actualEndTime); orderLastEndTime.put(groupId, actualEndTime);
......
...@@ -36,7 +36,10 @@ public class GeneticDecoderBom { ...@@ -36,7 +36,10 @@ public class GeneticDecoderBom {
Map<String, OpMachine> opMachineKeyMap, Map<String, OpMachine> opMachineKeyMap,
Chromosome chromosome, Chromosome chromosome,
Map<Integer, GAScheduleResult> scheduleIndexById, Map<Integer, GAScheduleResult> scheduleIndexById,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Long, Machine> machineIdMap,Map<Integer, Entry> entryIndexById,boolean isCheckMp) { Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache
,Map<Long, Machine> machineIdMap,Map<Integer, Entry> entryIndexById,
boolean isCheckMp,
Map<Integer, Integer> targetGroupEnd) {
List<Entry> semiOps = entrysBygroupId.get(semiGroupId); List<Entry> semiOps = entrysBygroupId.get(semiGroupId);
if (semiOps == null || semiOps.isEmpty()) return 0; if (semiOps == null || semiOps.isEmpty()) return 0;
...@@ -53,18 +56,26 @@ public class GeneticDecoderBom { ...@@ -53,18 +56,26 @@ public class GeneticDecoderBom {
|| lastOp.getTargetFinishedOperationId().isEmpty()) break; || lastOp.getTargetFinishedOperationId().isEmpty()) break;
int targetOpId = lastOp.getTargetFinishedOperationId().get(0); int targetOpId = lastOp.getTargetFinishedOperationId().get(0);
int targetGroupId = findGroupForOperation(targetOpId, entrysBygroupId); int targetGroupId = findGroupForOperation(targetOpId, entrysBygroupId);
Entry targetOp= entryIndexById.get(targetOpId);
List<Integer> simGroupId=targetOp.getDependentOnOrderIds();
if (targetGroupId < 0) break; if (targetGroupId < 0) break;
List<Entry> targetOps = entrysBygroupId.get(targetGroupId); List<Entry> targetOps = entrysBygroupId.get(targetGroupId);
if (targetOps == null || targetOps.isEmpty()) break; if (targetOps == null || targetOps.isEmpty()) break;
Entry firstTargetOp = targetOps.get(0); Entry firstTargetOp = targetOps.get(0);
//半成品对应的成品工序
Entry targetOp = entryIndexById.get(targetOpId);
//成品工序下所有半成品订单
List<Integer> simGroupIds = targetOp != null ? targetOp.getDependentOnOrderIds() : null;
//是否头多半成品
boolean hasMultipleSemi = simGroupIds != null && simGroupIds.size() > 1 ;
if (Entry.SchedulingMode.FORWARD.name().equals( if (Entry.SchedulingMode.FORWARD.name().equals(
firstTargetOp.getSchedulingMode())) { firstTargetOp.getSchedulingMode())) {
int rootStart = forwardEstimateToOperation(decoder,targetOpId, targetGroupId,0, int rootStart = forwardEstimateToOperation(decoder,targetOpId, targetGroupId,0,
entrysBygroupId, opMachineKeyMap, chromosome, entrysBygroupId, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache,machineIdMap,entryIndexById,false); scheduleIndexById, machineTasksCache,machineIdMap,entryIndexById,false,null);
List<Integer> chainGroupIds = new ArrayList<>(intermediateGroupIds); List<Integer> chainGroupIds = new ArrayList<>(intermediateGroupIds);
chainGroupIds.add(targetGroupId); chainGroupIds.add(targetGroupId);
...@@ -73,54 +84,117 @@ public class GeneticDecoderBom { ...@@ -73,54 +84,117 @@ public class GeneticDecoderBom {
int anchor = rootStart; int anchor = rootStart;
// FileHelper.writeLogFile(" 成品开始 "+targetGroupId+" : "+rootStart); // FileHelper.writeLogFile(" 成品开始 "+targetGroupId+" : "+rootStart);
if(anchor==0)
{
return -1;
}
for (int i = intermediateGroupIds.size() - 1; i >= 0; i--) { if(!hasMultipleSemi) {
if(anchor==0)
int sfGroupId= intermediateGroupIds.get(i); {
int start1= forwardEstimateToOperation(decoder,0,sfGroupId ,anchor, return -1;
entrysBygroupId, opMachineKeyMap, chromosome, }
scheduleIndexById, machineTasksCache,machineIdMap,entryIndexById,true); for (int i = intermediateGroupIds.size() - 1; i >= 0; i--) {
// FileHelper.writeLogFile(" 半成品开始 "+sfGroupId+" : "+start1+" - "+anchor);
int sfGroupId = intermediateGroupIds.get(i);
int start1 = forwardEstimateToOperation(decoder, 0, sfGroupId, anchor,
entrysBygroupId, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById, true,null);
// FileHelper.writeLogFile(" 半成品开始 "+sfGroupId+" : "+start1+" - "+anchor);
if(start1<=0) {
isFORWARD=true;
break;
}
if(i!=0) if (start1 <= 0) {
{ isFORWARD = true;
anchor -= start1;
if(anchor<0)
{
isFORWARD=true;
break; break;
} }
}else {
if(anchor-start1<0) if (i != 0) {
{ anchor -= start1;
isFORWARD=true; if (anchor < 0) {
break; isFORWARD = true;
break;
}
} else {
if (anchor - start1 < 0) {
isFORWARD = true;
break;
}
} }
} }
if (isFORWARD) {
for (int i = intermediateGroupIds.size() - 1; i >= 0; i--) {
List<Entry> ops1 = entrysBygroupId.get(intermediateGroupIds.get(i));
ops1.forEach(t -> t.setSchedulingMode(Entry.SchedulingMode.FORWARD.name()));
}
return -1;
}
return Math.max(0, anchor);
} }
else
if(isFORWARD)
{ {
int maxOtherSemiEnd = 0;
if(targetGroupEnd!=null&&targetGroupEnd.get(targetGroupId)!=null)
{
maxOtherSemiEnd=targetGroupEnd.get(targetGroupId);
}else {
// 多半成品:临时设备占用表,跨组追踪设备时间
Map<Long, Integer> tempMachineEnd = new HashMap<>();
for (int otherGroupId : simGroupIds) {
// if (otherGroupId == semiGroupId) continue;
Set<Integer> visited = new HashSet<>();
int chainEnd = estimateChainEnd(decoder, otherGroupId, rootStart,
entrysBygroupId, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,
tempMachineEnd, visited);
if (chainEnd > maxOtherSemiEnd) {
maxOtherSemiEnd = chainEnd;
}
}
targetGroupEnd.put(targetGroupId, maxOtherSemiEnd);
}
anchor = Math.max(anchor, maxOtherSemiEnd);
for (int i = intermediateGroupIds.size() - 1; i >= 0; i--) { for (int i = intermediateGroupIds.size() - 1; i >= 0; i--) {
int sfGroupId = intermediateGroupIds.get(i);
int start1 = forwardEstimateToOperation(decoder, 0, sfGroupId, anchor,
entrysBygroupId, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById, true,null);
if (start1 <= 0) {
isFORWARD = true;
break;
}
if (i != 0) {
anchor -= start1;
if (anchor < 0) {
isFORWARD = true;
break;
}
} else {
if (anchor - start1 < 0) {
isFORWARD = true;
break;
}
}
}
List<Entry> ops1 = entrysBygroupId.get(intermediateGroupIds.get(i)); if (isFORWARD) {
ops1.forEach(t->t.setSchedulingMode(Entry.SchedulingMode.FORWARD.name())); // 倒排失败,尝试延迟对齐
int effectiveAnchor = Math.max(rootStart, maxOtherSemiEnd);
int forwardEnd = forwardEstimateToOperation(decoder, 0, semiGroupId, 0,
entrysBygroupId, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById, false,null);
if (forwardEnd > 0 && forwardEnd <= effectiveAnchor) {
return effectiveAnchor;
}
for (int i = intermediateGroupIds.size() - 1; i >= 0; i--) {
List<Entry> ops1 = entrysBygroupId.get(intermediateGroupIds.get(i));
ops1.forEach(t -> t.setSchedulingMode(Entry.SchedulingMode.FORWARD.name()));
}
return -1;
} }
return -1;
} }
return Math.max(0, anchor); return Math.max(0, anchor);
...@@ -131,6 +205,81 @@ public class GeneticDecoderBom { ...@@ -131,6 +205,81 @@ public class GeneticDecoderBom {
return 0; return 0;
} }
/**
* 递归估算一个组及其所有子依赖链的设备占用时间
* 通过 getDependentOnOrderIds() 找到该组工序依赖的下游半成品组,
* 从最深层的子半成品(先跑)到当前组(后跑),
* 深层组的设备时间累积到 tempMachineEnd,浅层组自然排队
*
* @param groupId 起始组ID
* @param tempMachineEnd 设备占用表(会被更新)
* @param visited 已访问组集合,防止循环依赖
* @return 该组链的最大结束时间
*/
/**
* 递归估算一个组及其所有子依赖链的设备占用时间
* 通过 getDependentOnOrderIds() 找到该组工序依赖的下游半成品组,
* 从最深层的子半成品(先跑)到当前组(后跑),
* 深层组的设备时间累积到 tempMachineEnd,浅层组自然排队
*
* @param groupId 起始组ID
* @param backwardAnchor 倒排目标结束时间,>0时优先尝试倒排,=0则直接正排
* @param tempMachineEnd 设备占用表(会被更新)
* @param visited 已访问组集合,防止循环依赖
* @return 该组链的最大结束时间
*/
private int estimateChainEnd(GeneticDecoder decoder, int groupId, int backwardAnchor,
Map<Integer, List<Entry>> entrysBygroupId,
Map<String, OpMachine> opMachineKeyMap,
Chromosome chromosome,
Map<Integer, GAScheduleResult> scheduleIndexById,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Long, Machine> machineIdMap,
Map<Integer, Entry> entryIndexById,
Map<Long, Integer> tempMachineEnd,
Set<Integer> visited) {
if (!visited.add(groupId)) return 0; // 防止循环依赖
List<Entry> ops = entrysBygroupId.get(groupId);
if (ops == null || ops.isEmpty()) return 0;
// 先递归估算该组依赖的子半成品(子依赖始终正排,找到最小必需结束时间)
int subMaxEnd = 0;
for (Entry op : ops) {
List<Integer> depGroupIds = op.getDependentOnOrderIds();
if (depGroupIds != null) {
for (int depGroupId : depGroupIds) {
if (depGroupId != groupId) {
int subEnd = estimateChainEnd(decoder, depGroupId, 0,
entrysBygroupId, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,
tempMachineEnd, visited);
if (subEnd > subMaxEnd) subMaxEnd = subEnd;
}
}
}
}
// 优先尝试倒排:尽量晚结束,给同层其他半成品留出更大的锚点空间
if (backwardAnchor > 0) {
int backwardStart = forwardEstimateToOperation(decoder, 0, groupId, backwardAnchor,
entrysBygroupId, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,
true, tempMachineEnd);
// 倒排成功(start > 0)且子依赖能在倒排开始前完成
if (backwardStart > 0 && backwardStart >= subMaxEnd) {
return backwardAnchor;
}
}
// 倒排失败或未指定锚点:正排,从子依赖结束时间开始(tempMachineEnd + subMaxEnd 双重保障)
int forwardEnd = forwardEstimateToOperation(decoder, 0, groupId, subMaxEnd,
entrysBygroupId, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,
false, tempMachineEnd);
return Math.max(forwardEnd, subMaxEnd);
}
private int findGroupForOperation(int opId, private int findGroupForOperation(int opId,
Map<Integer, List<Entry>> entrysBygroupId) { Map<Integer, List<Entry>> entrysBygroupId) {
...@@ -148,7 +297,11 @@ public class GeneticDecoderBom { ...@@ -148,7 +297,11 @@ public class GeneticDecoderBom {
Map<Integer, GAScheduleResult> scheduleIndexById, Map<Integer, GAScheduleResult> scheduleIndexById,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache, Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Long, Machine> machineIdMap, Map<Long, Machine> machineIdMap,
Map<Integer, Entry> entryIndexById,boolean isJit) { Map<Integer, Entry> entryIndexById,boolean isJit,Map<Long, Integer> tempMachineEnd) {
if(startSecond<=0&&isJit)
{
return -1;
}
List<Entry> ops = entrysBygroupId.get(groupId); List<Entry> ops = entrysBygroupId.get(groupId);
if (ops == null) return 0; if (ops == null) return 0;
...@@ -169,6 +322,7 @@ if(isJit) ...@@ -169,6 +322,7 @@ if(isJit)
.collect(Collectors.toMap(Machine::getId, m -> m, (a, b) -> a)); .collect(Collectors.toMap(Machine::getId, m -> m, (a, b) -> a));
int nextAvailableStart = startSecond; int nextAvailableStart = startSecond;
Map<Long, Integer> machineLastEndInOrder = new HashMap<>(); Map<Long, Integer> machineLastEndInOrder = new HashMap<>();
boolean useTempMachineEnd = tempMachineEnd != null;
for (Entry op : sorted) { for (Entry op : sorted) {
String key = groupId + "_" + op.getSequence(); String key = groupId + "_" + op.getSequence();
...@@ -196,8 +350,16 @@ if(isJit) ...@@ -196,8 +350,16 @@ if(isJit)
Integer lastInOrder = machineLastEndInOrder.get(mId); Integer lastInOrder = machineLastEndInOrder.get(mId);
if (lastInOrder != null) start = Math.max(start, lastInOrder); if (lastInOrder != null) start = Math.max(start, lastInOrder);
// 临时设备占用表:跨组追踪设备占用
if (useTempMachineEnd) {
Integer lastEnd = tempMachineEnd.get(mId);
if (lastEnd != null) {
start = Math.max(start, lastEnd);
}
}
// 该设备上已排产的其他任务(半成品占位)的结束时间 // 该设备上已排产的其他任务(半成品占位)的结束时间
if (machineTasksCache != null) { if (!useTempMachineEnd && machineTasksCache != null) {
CopyOnWriteArrayList<GAScheduleResult> tasks = machineTasksCache.get(mId); CopyOnWriteArrayList<GAScheduleResult> tasks = machineTasksCache.get(mId);
if (tasks != null) { if (tasks != null) {
for (GAScheduleResult t : tasks) { for (GAScheduleResult t : tasks) {
...@@ -223,7 +385,7 @@ if(isJit) ...@@ -223,7 +385,7 @@ if(isJit)
} }
if (machine != null&&!machine.getCapacityTypeName().equals("Infinite")) { if (machine != null&&!machine.getCapacityTypeName().equals("Infinite")) {
CopyOnWriteArrayList<GAScheduleResult> machineTasks = getMachineTasks(mId, chromosome, machineTasksCache); CopyOnWriteArrayList<GAScheduleResult> machineTasks = getMachineTasks(mId, chromosome, machineTasksCache);
...@@ -235,6 +397,9 @@ if(isJit) ...@@ -235,6 +397,9 @@ if(isJit)
if(result!=null) { if(result!=null) {
start = result.getStartTime()-result.getChangeOverTime(); start = result.getStartTime()-result.getChangeOverTime();
end = result.getEndTime(); end = result.getEndTime();
if (useTempMachineEnd) {
tempMachineEnd.put(mId, end);
}
}else { }else {
return -1; return -1;
} }
...@@ -396,7 +561,7 @@ if(isJit) ...@@ -396,7 +561,7 @@ if(isJit)
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache, Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Long, Machine> machineIdMap, Map<Long, Machine> machineIdMap,
Map<Integer, Entry> entryIndexById, Map<Integer, Entry> entryIndexById,
Set<Integer> reForwardFinishedOrderIds,GlobalParam _globalParam,Order order) { Set<Integer> reForwardFinishedOrderIds,GlobalParam _globalParam,Order order,Map<Integer, Integer> targetGroupEnd) {
List<Entry> sfOps = entrysBygroupId.get(semiOrderId); List<Entry> sfOps = entrysBygroupId.get(semiOrderId);
if (sfOps == null || sfOps.isEmpty()) return 0; if (sfOps == null || sfOps.isEmpty()) return 0;
...@@ -418,7 +583,7 @@ int start=Integer.MAX_VALUE; ...@@ -418,7 +583,7 @@ int start=Integer.MAX_VALUE;
// 成品还没排(不应该发生在JIT模式),降级为原有逻辑 // 成品还没排(不应该发生在JIT模式),降级为原有逻辑
return computeSemiFinishedAnchor(decoder, semiOrderId, entrysBygroupId, return computeSemiFinishedAnchor(decoder, semiOrderId, entrysBygroupId,
opMachineKeyMap, chromosome, scheduleIndexById, machineTasksCache, opMachineKeyMap, chromosome, scheduleIndexById, machineTasksCache,
machineIdMap, entryIndexById,_globalParam.isIsCheckMp()); machineIdMap, entryIndexById,_globalParam.isIsCheckMp(),targetGroupEnd);
} }
......
...@@ -297,7 +297,7 @@ public class PlanResultService { ...@@ -297,7 +297,7 @@ public class PlanResultService {
if (!saved) { if (!saved) {
throw new BusinessException("排产计算结果保存失败,请稍后重试或联系管理员"); throw new BusinessException("排产计算结果保存失败,请稍后重试或联系管理员");
} }
//WriteScheduleSummary(chromosome); WriteScheduleSummary(chromosome);
return chromosome; return chromosome;
......
...@@ -43,9 +43,9 @@ public class PlanResultServiceTest { ...@@ -43,9 +43,9 @@ public class PlanResultServiceTest {
// planResultService.execute2("64E64F6B68094AF38CEDC418630C3CC2");//2000 // planResultService.execute2("64E64F6B68094AF38CEDC418630C3CC2");//2000
// planResultService.execute2("E1448B3C9C8743DEAB39708F2CFE348A");//倒排bomces // planResultService.execute2("E1448B3C9C8743DEAB39708F2CFE348A");//倒排bomces
// planResultService.execute2("85DA28EC5F4643449E65A51253D5F127"); //bom 多半成品 planResultService.execute2("85DA28EC5F4643449E65A51253D5F127"); //bom 多半成品
planResultService.execute2("FB14AF1623CB461D9BEDAFC35DBF0AFC"); //重叠 // planResultService.execute2("FB14AF1623CB461D9BEDAFC35DBF0AFC"); //重叠
// planResultService.execute2("F8F147BD627C47B1A190399DD7A697F6"); // planResultService.execute2("F8F147BD627C47B1A190399DD7A697F6");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment