Commit 813959ca authored by Tong Li's avatar Tong Li

Merge remote-tracking branch 'origin/tl'

parents bc529e67 78d8bf59
package com.aps.entity.Algorithm;
/**
* 作者:佟礼
* 时间:2026-05-27
*/
public class DraftScheduleResult {
private int operationId;
private int idealStartTime;
private int idealEndTime;
private Long selectedMachineId;
private double processTime;
private int groupId;
private int sequence;
public DraftScheduleResult(int operationId, int idealStartTime, int idealEndTime,
Long selectedMachineId, double processTime, int groupId, int sequence) {
this.operationId = operationId;
this.idealStartTime = idealStartTime;
this.idealEndTime = idealEndTime;
this.selectedMachineId = selectedMachineId;
this.processTime = processTime;
this.groupId = groupId;
this.sequence = sequence;
}
public int getOperationId() { return operationId; }
public int getIdealStartTime() { return idealStartTime; }
public int getIdealEndTime() { return idealEndTime; }
public Long getSelectedMachineId() { return selectedMachineId; }
public double getProcessTime() { return processTime; }
public int getGroupId() { return groupId; }
public int getSequence() { return sequence; }
}
...@@ -175,6 +175,12 @@ private Long isInterrupt = 1l; ...@@ -175,6 +175,12 @@ private Long isInterrupt = 1l;
private int anchorTimeSecond = 0; private int anchorTimeSecond = 0;
private transient boolean backwardFailed = false;
private transient boolean scheduled = false;
private transient Integer actualFinishTime;
public enum SchedulingMode { public enum SchedulingMode {
FORWARD, BACKWARD FORWARD, BACKWARD
} }
......
...@@ -67,6 +67,16 @@ public class Material { ...@@ -67,6 +67,16 @@ public class Material {
*/ */
private Long CkeckLeadTime; private Long CkeckLeadTime;
/**
* 最小生产量
*/
private BigDecimal minProduction;
/**
* 最大生产量
*/
private BigDecimal maxProduction;
@Override @Override
public String toString() { public String toString() {
return "Material{" + return "Material{" +
......
...@@ -290,7 +290,7 @@ public class GeneticDecoder { ...@@ -290,7 +290,7 @@ public class GeneticDecoder {
return 1; return 1;
} }
private void CreateNewOpSequence(Chromosome chromosome) private void CreateNewOpSequence(Chromosome chromosome,boolean isJit)
{ {
//成品订单 //成品订单
...@@ -342,10 +342,16 @@ public class GeneticDecoder { ...@@ -342,10 +342,16 @@ public class GeneticDecoder {
if (entry == null) { if (entry == null) {
continue; continue;
} }
entry.setSchedulingMode(Entry.SchedulingMode.FORWARD.name()); if(isJit) {
entry.setSchedulingMode(Entry.SchedulingMode.BACKWARD.name());
}else {
entry.setSchedulingMode(Entry.SchedulingMode.FORWARD.name());
}
if(entry!=null&&entry.getDependentOnOrderIds().size()>0) if(entry!=null&&entry.getDependentOnOrderIds().size()>0)
{ {
if(isJit) {
finalSequence.add(num);
}
for (int order : entry.getDependentOnOrderIds()) { for (int order : entry.getDependentOnOrderIds()) {
// 依赖的半成品订单可能不在旧排序里,缺失时跳过,避免空指针。 // 依赖的半成品订单可能不在旧排序里,缺失时跳过,避免空指针。
...@@ -357,8 +363,9 @@ public class GeneticDecoder { ...@@ -357,8 +363,9 @@ public class GeneticDecoder {
InsertSimSequence(orderProcessCounter,num1,finalSequence,sfSequence,allOperations); InsertSimSequence(orderProcessCounter,num1,finalSequence,sfSequence,allOperations);
} }
} }
if(!isJit) {
finalSequence.add(num); finalSequence.add(num);
}
}else { }else {
finalSequence.add(num); finalSequence.add(num);
...@@ -503,7 +510,7 @@ public class GeneticDecoder { ...@@ -503,7 +510,7 @@ public class GeneticDecoder {
if(isnew==1) { if(isnew==1) {
long t2 = System.nanoTime(); long t2 = System.nanoTime();
CreateNewOpSequence(chromosome); CreateNewOpSequence(chromosome,isJit);
// CreateNewOpSequence 会重建半成品插入顺序,生成后再规整一次,避免重复调度同一订单。 // CreateNewOpSequence 会重建半成品插入顺序,生成后再规整一次,避免重复调度同一订单。
normalizeOperationSequencing(chromosome); normalizeOperationSequencing(chromosome);
// FileHelper.writeLogFile("[PERF] serialDecode CreateNewOpSequence 耗时=" + fmtMs(System.nanoTime() - t2)); // FileHelper.writeLogFile("[PERF] serialDecode CreateNewOpSequence 耗时=" + fmtMs(System.nanoTime() - t2));
...@@ -605,15 +612,24 @@ public class GeneticDecoder { ...@@ -605,15 +612,24 @@ public class GeneticDecoder {
} }
} }
for (Map.Entry<Integer, List<Entry>> entry : entrysBygroupId.entrySet()) { Set<Integer> semiFinishedOrderIds=new HashSet<>();
int groupId = entry.getKey(); if(isJit)
Entry firstOp = entry.getValue().get(0); {
if (Entry.SchedulingMode.BACKWARD.name().equals( // 半成品订单ID集合
firstOp.getSchedulingMode())) { semiFinishedOrderIds = chromosome.getOrders().stream()
orderSchedulingInfo.put(groupId, .filter(Order::isNewSfCreate).map(Order::getId).collect(Collectors.toSet());
new AbstractMap.SimpleEntry<>(true, 0));
}
} }
for (Map.Entry<Integer, List<Entry>> entry : entrysBygroupId.entrySet()) {
int groupId = entry.getKey();
Entry firstOp = entry.getValue().get(0);
if (Entry.SchedulingMode.BACKWARD.name().equals(
firstOp.getSchedulingMode())&&semiFinishedOrderIds.contains(groupId)) {
orderSchedulingInfo.put(groupId,
new AbstractMap.SimpleEntry<>(true, 0));
}
}
// Map<Long, String> machineState = chromosome.getMachines().stream() // Map<Long, String> machineState = chromosome.getMachines().stream()
...@@ -624,34 +640,83 @@ public class GeneticDecoder { ...@@ -624,34 +640,83 @@ public class GeneticDecoder {
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>(); Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>();
// 记录已经整单转正排的订单,避免倒排序列后续再次进入同一个 groupId。 // 记录已经整单转正排的订单,避免倒排序列后续再次进入同一个 groupId。
Set<Integer> forwardFallbackOrderIds = new HashSet<>(); Set<Integer> forwardFallbackOrderIds = new HashSet<>();
// 混合排程:半成品正排后需要重排的成品订单
Set<Integer> reForwardFinishedOrderIds = new HashSet<>();
// 延迟重排映射:半成品ID → 关联成品ID集合(等半成品全部排完后再处理)
Map<Integer, Set<Integer>> pendingReForwardMap = new HashMap<>();
Map<Integer, Order> orders = chromosome.getOrders().stream()
.collect(Collectors.toMap(
Order::getId,
// 2. Value映射:Material → Material
order -> order
));
int opCount = 0; int opCount = 0;
long slowOpThresholdNs = 500_000_000L; // 500ms long slowOpThresholdNs = 500_000_000L; // 500ms
for (int groupId : chromosome.getOperationSequencing()) { for (int groupId : chromosome.getOperationSequencing()) {
int scheduledCount = orderProcessCounter.get(groupId); int scheduledCount = orderProcessCounter.get(groupId);
if(groupId==7)
{
int i=0;
}
List<Entry> orderOps=new ArrayList<>(); List<Entry> orderOps=new ArrayList<>();
boolean orderIsJit=orderDueDate.get(groupId)>0; boolean orderIsJit=orderDueDate.get(groupId)>0;
AbstractMap.SimpleEntry<Boolean, Integer> schedInfo = orderSchedulingInfo.get(groupId); AbstractMap.SimpleEntry<Boolean, Integer> schedInfo = orderSchedulingInfo.get(groupId);
orderIsJit = schedInfo != null && schedInfo.getKey();
orderIsJit = schedInfo != null && schedInfo.getKey();
// 半成品倒排失败后,关联成品强制正排
if (reForwardFinishedOrderIds.contains(groupId)) {
orderIsJit = false;
schedInfo = new AbstractMap.SimpleEntry<>(false, 0);
}
int orderAnchor = schedInfo != null ? schedInfo.getValue() : 0; int orderAnchor = schedInfo != null ? schedInfo.getValue() : 0;
// 半成品订单首次处理时,延迟计算锚点:沿依赖链找到根成品工序并正推 // 半成品订单首次处理时,延迟计算锚点:沿依赖链找到根成品工序并正推
if (orderIsJit && orderAnchor == 0) { if (orderIsJit && orderAnchor == 0) {
orderAnchor =bom.computeSemiFinishedAnchor(this,groupId, entrysBygroupId,
opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById); if (semiFinishedOrderIds.contains(groupId)) {
if(orderAnchor<0) { Order order= orders.get(groupId);
orderIsJit=false; orderAnchor =bom.computeHybridSemiAnchor(this,groupId, entrysBygroupId,
orderSchedulingInfo.put(groupId, opMachineKeyMap, chromosome, scheduleIndexById,
new AbstractMap.SimpleEntry<>(false, -1)); machineTasksCache, machineIdMap, entryIndexById,
}else { reForwardFinishedOrderIds,_globalParam,order);
orderSchedulingInfo.put(groupId,
new AbstractMap.SimpleEntry<>(true, orderAnchor)); if (orderAnchor < 0) {
orderIsJit = false;
orderSchedulingInfo.put(groupId,
new AbstractMap.SimpleEntry<>(false, -1));
if (!reForwardFinishedOrderIds.isEmpty()) {
pendingReForwardMap.put(groupId,
new HashSet<>(reForwardFinishedOrderIds));
reForwardFinishedOrderIds.clear();
}
} else {
orderSchedulingInfo.put(groupId,
new AbstractMap.SimpleEntry<>(true, orderAnchor));
}
} else {
orderAnchor = bom.computeSemiFinishedAnchor(this, groupId, entrysBygroupId,
opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById);
if (orderAnchor < 0) {
orderIsJit = false;
orderSchedulingInfo.put(groupId,
new AbstractMap.SimpleEntry<>(false, -1));
} else {
orderSchedulingInfo.put(groupId,
new AbstractMap.SimpleEntry<>(true, orderAnchor));
}
} }
} }
...@@ -718,6 +783,23 @@ public class GeneticDecoder { ...@@ -718,6 +783,23 @@ public class GeneticDecoder {
orderProcessCounter.put(groupId, entrysBygroupId.get(groupId).size()); orderProcessCounter.put(groupId, entrysBygroupId.get(groupId).size());
orderLastEndTime.put(groupId, forwardEndTime); orderLastEndTime.put(groupId, forwardEndTime);
forwardFallbackOrderIds.add(groupId); forwardFallbackOrderIds.add(groupId);
if (semiFinishedOrderIds.contains(groupId)) {
Set<Integer> fallbackFinishedIds = new HashSet<>();
List<Integer> targetFinishedOpIds = currentOp.getTargetFinishedOperationId();
if (targetFinishedOpIds != null && !targetFinishedOpIds.isEmpty()) {
for (Integer targetOpId : targetFinishedOpIds) {
Entry finishedOp = entryIndexById.get(targetOpId);
if (finishedOp != null) {
fallbackFinishedIds.add(finishedOp.getGroupId());
}
}
}
reForwardFinishedOrders(groupId, fallbackFinishedIds,
chromosome, machineTasksCache, scheduleIndexById,
machineIdMap, entryIndexById, opMachineKeyMap,
entrysBygroupId, orderProcessCounter, orderLastEndTime,
forwardFallbackOrderIds, orderSchedulingInfo);
}
opCount += entrysBygroupId.get(groupId).size(); opCount += entrysBygroupId.get(groupId).size();
continue; continue;
} }
...@@ -728,6 +810,22 @@ public class GeneticDecoder { ...@@ -728,6 +810,22 @@ public class GeneticDecoder {
orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1); orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);
orderLastEndTime.put(groupId, actualEndTime); orderLastEndTime.put(groupId, actualEndTime);
if (semiFinishedOrderIds.contains(groupId) &&
orderProcessCounter.get(groupId) >= entrysBygroupId.get(groupId).size()) {
Set<Integer> pendingFinishedIds = pendingReForwardMap.remove(groupId);
if (pendingFinishedIds != null && !pendingFinishedIds.isEmpty()) {
int semiEndTime = orderLastEndTime.get(groupId);
FileHelper.writeLogFile("[ReForward] 半成品" + groupId
+ "全部排完(结束时间=" + semiEndTime + "),重新正排关联成品"
+ pendingFinishedIds);
reForwardFinishedOrders(groupId, pendingFinishedIds,
chromosome, machineTasksCache, scheduleIndexById,
machineIdMap, entryIndexById, opMachineKeyMap,
entrysBygroupId, orderProcessCounter, orderLastEndTime,
forwardFallbackOrderIds, orderSchedulingInfo);
}
}
} }
if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) { if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) {
chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t)); chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t));
...@@ -750,7 +848,7 @@ public class GeneticDecoder { ...@@ -750,7 +848,7 @@ public class GeneticDecoder {
int isnew= generateGlobalOpList(chromosome); int isnew= generateGlobalOpList(chromosome);
if(isnew==1) { if(isnew==1) {
CreateNewOpSequence(chromosome); CreateNewOpSequence(chromosome, _globalParam.isJit());
// CreateNewOpSequence 会重建半成品插入顺序,生成后再规整一次,避免重复调度同一订单。 // CreateNewOpSequence 会重建半成品插入顺序,生成后再规整一次,避免重复调度同一订单。
normalizeOperationSequencing(chromosome); normalizeOperationSequencing(chromosome);
} }
...@@ -1427,7 +1525,7 @@ public class GeneticDecoder { ...@@ -1427,7 +1525,7 @@ public class GeneticDecoder {
// 下面开始生成正式的 geneDetails。 // 下面开始生成正式的 geneDetails。
if (_globalParam.is_smoothChangeOver()) { if (_globalParam.is_smoothChangeOver()) {
if (isJit && islockMachineTime) { if (isJit && islockMachineTime&&machineTasks!=null&&machineTasks.size()>0) {
// JIT 倒排 + 换型:同时校验前置换型、当前加工、后置换型能否插入相邻任务窗口。 // JIT 倒排 + 换型:同时校验前置换型、当前加工、后置换型能否插入相邻任务窗口。
BackwardChangeoverHelper.JitBackwardScheduleResult backwardResult = BackwardChangeoverHelper.JitBackwardScheduleResult backwardResult =
backwardChangeoverHelper.scheduleJitBackwardWithChangeover(machine, operation, earliestStartTime, backwardChangeoverHelper.scheduleJitBackwardWithChangeover(machine, operation, earliestStartTime,
...@@ -1504,11 +1602,8 @@ public class GeneticDecoder { ...@@ -1504,11 +1602,8 @@ public class GeneticDecoder {
.orElse(0); .orElse(0);
if (startTime < 0) { if (startTime < 0) {
if(islockMachineTime) if (isJit && islockMachineTime) {
{ return OperationScheduleResult.forwardFallback();
// FileHelper.writeLogFile(" 半成品222222 " + operation.getGroupId() + " - " + operation.getSequence() + ",开始时间: " + startTime + ",结束时间: " + 0 + ",处理时间: " + processingTime + ", 后处理: " + teardownTime +
// ", 前处理: " + preTime + ", 换型: " + setupTime + ", 数量: " + operation.getQuantity() + ", 设备: " + machine.getId() + ", 是否可中断: " + operation.getIsInterrupt());
} }
return OperationScheduleResult.success(null); return OperationScheduleResult.success(null);
...@@ -3117,5 +3212,41 @@ if(geneDetails!=null&&geneDetails.size()>0) ...@@ -3117,5 +3212,41 @@ if(geneDetails!=null&&geneDetails.size()>0)
orders.removeIf(t ->newoorderids.contains(t.getId())); orders.removeIf(t ->newoorderids.contains(t.getId()));
} }
} }
private void reForwardFinishedOrders(int semiOrderId,
Set<Integer> reForwardFinishedOrderIds,
Chromosome chromosome,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Integer, GAScheduleResult> scheduleIndexById,
Map<Long, Machine> machineIdMap,
Map<Integer, Entry> entryIndexById,
Map<String, OpMachine> opMachineKeyMap,
Map<Integer, List<Entry>> entrysBygroupId,
Map<Integer, Integer> orderProcessCounter,
Map<Integer, Integer> orderLastEndTime,
Set<Integer> forwardFallbackOrderIds,
Map<Integer, AbstractMap.SimpleEntry<Boolean, Integer>> orderSchedulingInfo) {
for (int finishedId : reForwardFinishedOrderIds) {
int scheduledCount = orderProcessCounter.getOrDefault(finishedId, 0);
if (scheduledCount == 0) {
continue;
}
clearOrderSchedulingForForwardFallback(chromosome, finishedId,
machineTasksCache, scheduleIndexById);
int forwardEndTime = scheduleOrderForwardFallback(finishedId,
chromosome, machineIdMap, machineTasksCache,
entryIndexById, scheduleIndexById, opMachineKeyMap);
orderProcessCounter.put(finishedId,
entrysBygroupId.get(finishedId).size());
orderLastEndTime.put(finishedId, forwardEndTime);
forwardFallbackOrderIds.add(finishedId);
orderSchedulingInfo.put(finishedId,
new AbstractMap.SimpleEntry<>(false, 0));
FileHelper.writeLogFile("[ReForward] 半成品" + semiOrderId
+ "倒排早于基准时间,成品" + finishedId + "重新正排,结束时间=" + forwardEndTime);
}
reForwardFinishedOrderIds.clear();
}
} }
...@@ -385,4 +385,113 @@ if(isJit) ...@@ -385,4 +385,113 @@ if(isJit)
return Math.max(estimatedStartTime, rawTime); return Math.max(estimatedStartTime, rawTime);
} }
/**
* 半成品锚点计算(JIT倒排模式:成品先于半成品,直接取成品已排的开始时间)
* 返回 -1 触发正排+标记成品重排,>=0 作为半成品倒排锚点(半成品最晚完成时间)
*/
public int computeHybridSemiAnchor(GeneticDecoder decoder,int semiOrderId,
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,
Set<Integer> reForwardFinishedOrderIds,GlobalParam _globalParam,Order order) {
List<Entry> sfOps = entrysBygroupId.get(semiOrderId);
if (sfOps == null || sfOps.isEmpty()) return 0;
Entry firstSfOp = sfOps.stream().min(Comparator.comparing(Entry::getSequence)).orElse(null);
if (firstSfOp == null) return 0;
List<Integer> targetFinishedOpIds = firstSfOp.getTargetFinishedOperationId();
if (targetFinishedOpIds == null || targetFinishedOpIds.isEmpty()) {
return 0;
}
// 找关联的成品订单
int finishedOrderId = -1;
Entry targetFinishedOp = null;
for (Integer targetOpId : targetFinishedOpIds) {
Entry op = entryIndexById.get(targetOpId);
if (op != null) {
targetFinishedOp = op;
finishedOrderId = op.getGroupId();
break;
}
}
if (finishedOrderId <= 0) return 0;
List<Entry> finishedOps = entrysBygroupId.get(finishedOrderId).stream()
.sorted(Comparator.comparing(Entry::getSequence))
.collect(Collectors.toList());
if (finishedOps.isEmpty()) return 0;
// JIT倒排模式成品已排完,直接从scheduleIndexById取成品第一道工序的开始时间
Entry finishedFirstOp = finishedOps.get(0);
GAScheduleResult finishedFirstResult = scheduleIndexById.get(finishedFirstOp.getId());
if (finishedFirstResult == null) {
// 成品还没排(不应该发生在JIT模式),降级为原有逻辑
return computeSemiFinishedAnchor(decoder, semiOrderId, entrysBygroupId,
opMachineKeyMap, chromosome, scheduleIndexById, machineTasksCache,
machineIdMap, entryIndexById);
}
String schedulingMode = finishedFirstOp.getSchedulingMode();
if (Entry.SchedulingMode.BACKWARD.name().equals(schedulingMode)) {
// 成品倒排成功 → 半成品倒排:锚点 = 成品开始时间 - 缓冲
int semiLatestEndTime = finishedFirstResult.getStartTime();
int semiTotalTime = 0;
for (Entry op : sfOps) {
String key = semiOrderId + "_" + op.getSequence();
OpMachine opt = opMachineKeyMap.get(key);
if (opt != null) semiTotalTime += calculateOperationProcessingTime(op, opt,_globalParam);
}
Material material= chromosome.getMaterials().get(order.getMaterialId());
int ckeckLeadTime=0;
if(material.getCkeckLeadTime()!=null)
{
ckeckLeadTime=(material.getCkeckLeadTime().intValue()*24*60*60);
}
semiTotalTime+=ckeckLeadTime;
if (semiLatestEndTime - semiTotalTime < 0) {
FileHelper.writeLogFile("[HybridSemi] 半成品" + semiOrderId +
" 倒排开工<0,正排+成品" + finishedOrderId + "重排");
reForwardFinishedOrderIds.add(finishedOrderId);
return -1;
}
FileHelper.writeLogFile("[HybridSemi] 半成品" + semiOrderId +
" 锚点=" + semiLatestEndTime + " (成品" + finishedOrderId +
"开始=" + finishedFirstResult.getStartTime() + ")");
return semiLatestEndTime-ckeckLeadTime;
} else {
// 成品正排了 → 半成品也正排
FileHelper.writeLogFile("[HybridSemi] 成品" + finishedOrderId +
"已正排,半成品" + semiOrderId + "也正排");
reForwardFinishedOrderIds.add(finishedOrderId);
return -1;
}
}
private int calculateOperationProcessingTime(Entry op, OpMachine machineOption,GlobalParam _globalParam) {
int total = 0;
if (op.getConstTime() == 1)//常数时间
{
total = (int) Math.ceil(machineOption.getRuntime().doubleValue());
} else {
double t = machineOption.getRuntime().doubleValue() / machineOption.getSingleOut().doubleValue() * (op.getQuantity());
total = (int) Math.ceil(t);
}
if (op.getSetupTime() != null) total += op.getSetupTime().intValue();
total += op.getTeardownTime();
if ( !_globalParam.is_smoothSetup()) {
total += op.getPreTime();
}
return total;
}
} }
...@@ -85,7 +85,9 @@ public class HybridAlgorithm { ...@@ -85,7 +85,9 @@ public class HybridAlgorithm {
{ {
throw new RuntimeException("没有待排产工单"); throw new RuntimeException("没有待排产工单");
} }
if (_GlobalParam.isIsMultipleMachine()) {
allOperations = OperationSplitService.splitMultiMachineOperations(allOperations, _GlobalParam, machines, _entryRel);
}
// if(materials!=null&&materials.size()>0) { // if(materials!=null&&materials.size()>0) {
// //
// materialRequirementService.init(materials, orders, allOperations, _entryRel, machineScheduler, machines,_GlobalParam); // materialRequirementService.init(materials, orders, allOperations, _entryRel, machineScheduler, machines,_GlobalParam);
...@@ -433,6 +435,7 @@ public class HybridAlgorithm { ...@@ -433,6 +435,7 @@ public class HybridAlgorithm {
chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyTreeMap(materials, String.class, Material.class)); // 简单拷贝,实际可能需要深拷贝 chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyTreeMap(materials, String.class, Material.class)); // 简单拷贝,实际可能需要深拷贝
chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) ); // 简单拷贝,实际可能需要深拷贝 chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) ); // 简单拷贝,实际可能需要深拷贝
chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(globalOpList, GlobalOperationInfo.class) ); // 简单拷贝,实际可能需要深拷贝 chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(globalOpList, GlobalOperationInfo.class) ); // 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights); //chromosome.setObjectiveWeights(_objectiveWeights);
chromosome.setBaseTime(param.getBaseTime()); chromosome.setBaseTime(param.getBaseTime());
...@@ -490,8 +493,9 @@ public class HybridAlgorithm { ...@@ -490,8 +493,9 @@ public class HybridAlgorithm {
chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyTreeMap(materials, String.class, Material.class)); // 简单拷贝,实际可能需要深拷贝 chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyTreeMap(materials, String.class, Material.class)); // 简单拷贝,实际可能需要深拷贝
chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) ); // 简单拷贝,实际可能需要深拷贝 if (chromosome.getAllOperations() == null || chromosome.getAllOperations().isEmpty()) {
// chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(globalOpList, GlobalOperationInfo.class) ); // 简单拷贝,实际可能需要深拷贝 chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) );
} // chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(globalOpList, GlobalOperationInfo.class) ); // 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights); //chromosome.setObjectiveWeights(_objectiveWeights);
chromosome.setBaseTime(param.getBaseTime()); chromosome.setBaseTime(param.getBaseTime());
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝 // chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
......
...@@ -478,7 +478,10 @@ public class Initialization { ...@@ -478,7 +478,10 @@ public class Initialization {
.thenComparing(randomIds::get)); .thenComparing(randomIds::get));
} }
} }
if (_globalParam.isIsMultipleMachine()) {
sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
}
int globalOpId = 0; int globalOpId = 0;
// 为每个工序选择机器 // 为每个工序选择机器
...@@ -583,7 +586,10 @@ public class Initialization { ...@@ -583,7 +586,10 @@ public class Initialization {
.thenComparing(randomIds::get)); .thenComparing(randomIds::get));
} }
if (_globalParam.isIsMultipleMachine()) {
sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
}
int globalOpId = 0; int globalOpId = 0;
// 为每个工序选择机器 // 为每个工序选择机器
for (Entry op : sortedOps) { for (Entry op : sortedOps) {
...@@ -672,6 +678,10 @@ public class Initialization { ...@@ -672,6 +678,10 @@ public class Initialization {
.thenComparing(op -> op.getMachineOptions().get(0).getProcessingTime() * op.getQuantity()) .thenComparing(op -> op.getMachineOptions().get(0).getProcessingTime() * op.getQuantity())
.thenComparing(randomIds::get)); .thenComparing(randomIds::get));
if (_globalParam.isIsMultipleMachine()) {
sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
}
int globalOpId = 0; int globalOpId = 0;
for (Entry op : sortedOps) { for (Entry op : sortedOps) {
...@@ -817,7 +827,10 @@ public class Initialization { ...@@ -817,7 +827,10 @@ public class Initialization {
}) })
.thenComparing(randomIds::get)); .thenComparing(randomIds::get));
} }
if (_globalParam.isIsMultipleMachine()) {
sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
}
int globalOpId = 0; int globalOpId = 0;
for (Entry op : sortedOps) { for (Entry op : sortedOps) {
int groupId = op.getGroupId(); int groupId = op.getGroupId();
...@@ -907,7 +920,10 @@ public class Initialization { ...@@ -907,7 +920,10 @@ public class Initialization {
}) })
.thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "")
.thenComparing(randomIds::get)); .thenComparing(randomIds::get));
if (_globalParam.isIsMultipleMachine()) {
sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
}
int globalOpId = 0; int globalOpId = 0;
for (Entry op : sortedOps) { for (Entry op : sortedOps) {
int groupId = op.getGroupId(); int groupId = op.getGroupId();
...@@ -971,7 +987,10 @@ public class Initialization { ...@@ -971,7 +987,10 @@ public class Initialization {
.thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起,减少换型 .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起,减少换型
.thenComparing(randomIds::get)); .thenComparing(randomIds::get));
if (_globalParam.isIsMultipleMachine()) {
sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
}
int globalOpId = 0; int globalOpId = 0;
......
...@@ -540,13 +540,20 @@ public class MachineCalculator { ...@@ -540,13 +540,20 @@ public class MachineCalculator {
double e= (double)processingTime/slot.getEfficiency(); double e= (double)processingTime/slot.getEfficiency();
LocalDateTime endCandidate=null;
LocalDateTime endCandidate = startCandidate.plusSeconds((int)Math.ceil(e)); LocalDateTime startCandidate1 = null;
if(isJit)
{
endCandidate = endCandidate1;
startCandidate1=endCandidate.plusSeconds(-(int) Math.ceil(e));;
}else {
endCandidate = startCandidate.plusSeconds((int) Math.ceil(e));
startCandidate1=startCandidate;
}
ScheduleResultDetail time = new ScheduleResultDetail(); ScheduleResultDetail time = new ScheduleResultDetail();
time.setKey(slot.getKey()); time.setKey(slot.getKey());
time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, startCandidate)); time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, startCandidate1));
time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, endCandidate)); time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, endCandidate));
time.setOneTime(oneTime); time.setOneTime(oneTime);
time.setQuantity(quantity); time.setQuantity(quantity);
......
...@@ -1250,7 +1250,7 @@ if(demand==null) ...@@ -1250,7 +1250,7 @@ if(demand==null)
} }
} }
} }
FileHelper.writeLogFile("BOM:"+material.getCode()); // FileHelper.writeLogFile("BOM:"+material.getCode());
if (needed <= 0) { if (needed <= 0) {
orderMaterial.setYpQty(allneeded - needed); orderMaterial.setYpQty(allneeded - needed);
orderMaterial.setQjQty(needed); orderMaterial.setQjQty(needed);
...@@ -1285,11 +1285,11 @@ if(demand==null) ...@@ -1285,11 +1285,11 @@ if(demand==null)
for (RoutingSupportingReplace rsr : routingsupportingreplaces2) { for (RoutingSupportingReplace rsr : routingsupportingreplaces2) {
Material material1 = materials.get(rsr.getTargetmaterialid()); Material material1 = materials.get(rsr.getTargetmaterialid());
FileHelper.writeLogFile("RoutingSupportingReplace:"+material1.getCode()); // FileHelper.writeLogFile("RoutingSupportingReplace:"+material1.getCode());
if (material1 == null) { if (material1 == null) {
break; break;
} }
FileHelper.writeLogFile("RoutingSupportingReplace: "+(commitChanges?"1":"0")+" " +material1.getCode()+": "+useStock); // FileHelper.writeLogFile("RoutingSupportingReplace: "+(commitChanges?"1":"0")+" " +material1.getCode()+": "+useStock);
OrderMaterialRequirement orderMaterial1 = MaterialStock(material1, rsr.getTargetmaterialid(), orderMaterial.getOrderId(), orderMaterial.getChildOrderId(), operationId, allneeded, needed, earliestStartTime, commitChanges); OrderMaterialRequirement orderMaterial1 = MaterialStock(material1, rsr.getTargetmaterialid(), orderMaterial.getOrderId(), orderMaterial.getChildOrderId(), operationId, allneeded, needed, earliestStartTime, commitChanges);
if (orderMaterial1 != null) { if (orderMaterial1 != null) {
...@@ -1297,7 +1297,7 @@ if(demand==null) ...@@ -1297,7 +1297,7 @@ if(demand==null)
needed -= useStock; needed -= useStock;
FileHelper.writeLogFile("RoutingSupportingReplace: "+(commitChanges?"1":"0")+" " +material1.getCode()+": "+useStock); // FileHelper.writeLogFile("RoutingSupportingReplace: "+(commitChanges?"1":"0")+" " +material1.getCode()+": "+useStock);
orderMaterial.setUseStock(orderMaterial.getUseStock() + useStock); orderMaterial.setUseStock(orderMaterial.getUseStock() + useStock);
orderMaterial.getReplaceMaterial().add(orderMaterial1); orderMaterial.getReplaceMaterial().add(orderMaterial1);
if (needed <= 0) { if (needed <= 0) {
......
...@@ -2,6 +2,8 @@ package com.aps.service.Algorithm; ...@@ -2,6 +2,8 @@ package com.aps.service.Algorithm;
import com.aps.common.util.FileHelper; import com.aps.common.util.FileHelper;
import com.aps.common.util.ProductionDeepCopyUtil; import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.Algorithm.IDAndChildID.NodeInfo;
import com.aps.entity.Algorithm.OperationDependency; import com.aps.entity.Algorithm.OperationDependency;
import com.aps.entity.basic.Entry; import com.aps.entity.basic.Entry;
import com.aps.entity.basic.GlobalParam; import com.aps.entity.basic.GlobalParam;
...@@ -30,14 +32,20 @@ public class OperationSplitService { ...@@ -30,14 +32,20 @@ public class OperationSplitService {
/** /**
* 对工序列表进行多设备拆分(预处理入口,结合设备负载) * 对工序列表进行多设备拆分(预处理入口,结合设备负载)
* *
* 对齐 SpiltOperation 的处理顺序:
* 1. 先通过 IdGroupingWithDualSerial.addNode 更新 OperatRel,生成新的 GlobalSerial、GroupSerial、NewParentIds、NewChildIds
* 2. 再从 OperatRel 的 NodeInfo 生成 Entry,设置 NextOperationId 和 PrevOperationId
*
* @param allOperations 原始工序列表 * @param allOperations 原始工序列表
* @param globalParam 全局参数 * @param globalParam 全局参数
* @param machines 设备列表(用于计算各设备总预期负载) * @param machines 设备列表(用于计算各设备总预期负载)
* @param operatRel 工序关系列表(可变参数,拆分后会被原地更新)
* @return 拆分后的工序列表 * @return 拆分后的工序列表
*/ */
public static List<Entry> splitMultiMachineOperations(List<Entry> allOperations, public static List<Entry> splitMultiMachineOperations(List<Entry> allOperations,
GlobalParam globalParam, GlobalParam globalParam,
List<Machine> machines) { List<Machine> machines,
List<GroupResult> operatRel) {
if (allOperations == null || allOperations.isEmpty()) { if (allOperations == null || allOperations.isEmpty()) {
return allOperations; return allOperations;
} }
...@@ -55,50 +63,140 @@ public class OperationSplitService { ...@@ -55,50 +63,140 @@ public class OperationSplitService {
FileHelper.writeLogFile("[工序拆分] 开始多设备工序拆分(负载感知),原始工序数=" + allOperations.size()); FileHelper.writeLogFile("[工序拆分] 开始多设备工序拆分(负载感知),原始工序数=" + allOperations.size());
// 旧 Entry 索引(id → Entry)
Map<Integer, Entry> oldEntryMap = new LinkedHashMap<>();
for (Entry op : allOperations) {
oldEntryMap.put(op.getId(), op);
}
Map<Long, Double> machineTotalLoad = calcMachineTotalLoad(allOperations); Map<Long, Double> machineTotalLoad = calcMachineTotalLoad(allOperations);
int maxId = allOperations.stream().mapToInt(Entry::getId).max().orElse(0); // ===== Phase 1: 先更新 OperatRel(结构权威)=====
int nextId = maxId + 1; List<GroupResult> currentRel = (operatRel != null && !operatRel.isEmpty())
? new ArrayList<>(operatRel) : rebuildOperatRel(allOperations);
Map<String, SplitOpMeta> splitMetas = new LinkedHashMap<>();
Map<Integer, List<Integer>> splitMapping = new LinkedHashMap<>(); int totalSplitOps = 0;
List<Entry> result = new ArrayList<>(); int totalSplitCount = 0;
Map<Integer, List<Entry>> groupMap = new LinkedHashMap<>(); Set<Entry> splitOriginals = new LinkedHashSet<>();
for (Entry op : allOperations) { for (Entry op : allOperations) {
groupMap.computeIfAbsent(op.getGroupId(), k -> new ArrayList<>()).add(op); List<MachineOption> options = op.getMachineOptions();
if (options == null || options.size() <= 1) {
continue;
}
splitOriginals.add(op);
} }
int totalSplitCount = 0; for (Entry op : splitOriginals) {
int totalSplitOps = 0; List<MachineOption> options = op.getMachineOptions();
int groupIdx = op.getGroupId() - 1;
GroupResult gr = currentRel.get(groupIdx);
for (Map.Entry<Integer, List<Entry>> groupEntry : groupMap.entrySet()) { NodeInfo origNode = gr.getNodeInfoList().stream()
List<Entry> groupOps = groupEntry.getValue(); .filter(n -> n.getOriginalId().equals(op.getExecId()))
groupOps.sort(Comparator.comparingInt(Entry::getSequence)); .findFirst().orElse(null);
if (origNode == null) {
List<Entry> newGroupOps = new ArrayList<>(); continue;
for (Entry op : groupOps) {
List<MachineOption> options = op.getMachineOptions();
if (options != null && options.size() > 1) {
List<Entry> subOps = splitEntryByLoad(op, options, nextId, machineTotalLoad);
nextId += subOps.size();
newGroupOps.addAll(subOps);
splitMapping.put(op.getId(),
subOps.stream().map(Entry::getId).collect(Collectors.toList()));
totalSplitOps++;
totalSplitCount += subOps.size();
} else {
newGroupOps.add(op);
}
} }
for (int i = 0; i < newGroupOps.size(); i++) { List<Integer> parentIds = origNode.getNewParentIds() != null
newGroupOps.get(i).setSequence(i + 1); ? new ArrayList<>(origNode.getNewParentIds()) : new ArrayList<>();
List<Integer> childIds = origNode.getNewChildIds() != null
? new ArrayList<>(origNode.getNewChildIds()) : new ArrayList<>();
String mainId = UUID.randomUUID().toString().replace("-", "");
double[] qtys = calcQuantityDistribution(op, options, machineTotalLoad);
SplitOpMeta meta = new SplitOpMeta(mainId, op);
meta.subExecIds.add(op.getExecId());
meta.subQtys.add(qtys[0]);
meta.subMachineOptions.add(options.get(0));
for (int i = 1; i < options.size(); i++) {
String newExecId = UUID.randomUUID().toString().replace("-", "");
currentRel = IdGroupingWithDualSerial.addNode(
currentRel, groupIdx, newExecId, parentIds, childIds, op.getExecId());
meta.subExecIds.add(newExecId);
meta.subQtys.add(qtys[i]);
meta.subMachineOptions.add(options.get(i));
} }
result.addAll(newGroupOps); splitMetas.put(op.getExecId(), meta);
totalSplitOps++;
totalSplitCount += options.size();
} }
updateAllDependencies(result, splitMapping); // 写回 operatRel
if (operatRel != null) {
operatRel.clear();
operatRel.addAll(currentRel);
}
FileHelper.writeLogFile(String.format(
"[工序拆分] OperatRel已更新,添加了%d个新节点,共%d个分组",
totalSplitCount - splitOriginals.size(), currentRel.size()));
// ===== Phase 2: 从更新后的 OperatRel 生成 Entry =====
List<Entry> result = new ArrayList<>();
for (int gi = 0; gi < currentRel.size(); gi++) {
GroupResult gr = currentRel.get(gi);
int groupId = gi + 1;
for (NodeInfo node : gr.getNodeInfoList()) {
int globalSerial = node.getGlobalSerial();
String execId = node.getOriginalId();
Entry entry = oldEntryMap.get(globalSerial);
if (entry != null) {
entry.setId(globalSerial);
entry.setSequence(node.getGroupSerial());
entry.setGroupId(groupId);
setEntryDepsFromNodeInfo(entry, node);
SplitOpMeta meta = splitMetas.get(execId);
if (meta != null) {
entry.setMainId(meta.mainId);
entry.setSplitSourceId(meta.originalEntry.getId());
entry.setState(1);
entry.setNewCreate(false);
entry.setQuantity(meta.subQtys.get(0));
MachineOption mo = meta.subMachineOptions.get(0);
entry.setSelectMachineID(mo.getMachineId());
entry.setMachineOptions(Collections.singletonList(mo));
}
} else {
SplitOpMeta meta = findMetaForExecId(splitMetas, execId);
if (meta != null) {
int idx = meta.subExecIds.indexOf(execId);
if (idx > 0) {
Entry sub = ProductionDeepCopyUtil.deepCopy(meta.originalEntry, Entry.class);
sub.setId(globalSerial);
sub.setExecId(execId);
sub.setSequence(node.getGroupSerial());
sub.setGroupId(groupId);
setEntryDepsFromNodeInfo(sub, node);
sub.setMainId(meta.mainId);
sub.setSplitSourceId(meta.originalEntry.getId());
sub.setState(2);
sub.setNewCreate(true);
sub.setSelectMachineID(meta.subMachineOptions.get(idx).getMachineId());
sub.setMachineOptions(
Collections.singletonList(meta.subMachineOptions.get(idx)));
sub.setQuantity(meta.subQtys.get(idx));
entry = sub;
oldEntryMap.put(globalSerial, entry);
}
}
}
if (entry != null) {
result.add(entry);
}
}
}
FileHelper.writeLogFile(String.format( FileHelper.writeLogFile(String.format(
"[工序拆分] 拆分了%d道多设备工序 → 产生%d道子工序,最终总工序数=%d", "[工序拆分] 拆分了%d道多设备工序 → 产生%d道子工序,最终总工序数=%d",
...@@ -228,6 +326,7 @@ public class OperationSplitService { ...@@ -228,6 +326,7 @@ public class OperationSplitService {
int maxId = ops.stream().mapToInt(Entry::getId).max().orElse(0); int maxId = ops.stream().mapToInt(Entry::getId).max().orElse(0);
int nextId = maxId + 1; int nextId = maxId + 1;
Map<Integer, List<Integer>> splitMapping = new LinkedHashMap<>();
List<Entry> result = new ArrayList<>(); List<Entry> result = new ArrayList<>();
for (Map.Entry<Integer, List<Entry>> groupEntry : groupMap.entrySet()) { for (Map.Entry<Integer, List<Entry>> groupEntry : groupMap.entrySet()) {
List<Entry> expanded = new ArrayList<>(); List<Entry> expanded = new ArrayList<>();
...@@ -236,6 +335,8 @@ public class OperationSplitService { ...@@ -236,6 +335,8 @@ public class OperationSplitService {
if (op.getSplitSourceId() == null && options != null && options.size() > 1) { if (op.getSplitSourceId() == null && options != null && options.size() > 1) {
List<Entry> subOps = splitEntryRandomPartial(op, options, nextId, rnd); List<Entry> subOps = splitEntryRandomPartial(op, options, nextId, rnd);
nextId += subOps.size(); nextId += subOps.size();
splitMapping.put(op.getId(),
subOps.stream().map(Entry::getId).collect(Collectors.toList()));
expanded.addAll(subOps); expanded.addAll(subOps);
} else { } else {
expanded.add(op); expanded.add(op);
...@@ -246,6 +347,8 @@ public class OperationSplitService { ...@@ -246,6 +347,8 @@ public class OperationSplitService {
} }
result.addAll(expanded); result.addAll(expanded);
} }
updateAllDependencies(result, splitMapping);
return result; return result;
} }
...@@ -263,6 +366,90 @@ public class OperationSplitService { ...@@ -263,6 +366,90 @@ public class OperationSplitService {
return load; return load;
} }
private static void setEntryDepsFromNodeInfo(Entry entry, NodeInfo node) {
if (node.getNewParentIds() != null && !node.getNewParentIds().isEmpty()) {
List<OperationDependency> prevDeps = new ArrayList<>();
for (int parentId : node.getNewParentIds()) {
if (parentId > 0) {
OperationDependency dep = new OperationDependency();
dep.setPrevOperationId(parentId);
dep.setNextOperationId(entry.getId());
prevDeps.add(dep);
}
}
entry.setPrevEntryIds(prevDeps);
}
if (node.getNewChildIds() != null && !node.getNewChildIds().isEmpty()) {
List<OperationDependency> nextDeps = new ArrayList<>();
for (int childId : node.getNewChildIds()) {
if (childId > 0) {
OperationDependency dep = new OperationDependency();
dep.setPrevOperationId(entry.getId());
dep.setNextOperationId(childId);
nextDeps.add(dep);
}
}
entry.setNextEntryIds(nextDeps);
}
}
private static double[] calcQuantityDistribution(Entry original, List<MachineOption> options,
Map<Long, Double> loadMap) {
int n = options.size();
double[] weights = new double[n];
double totalWeight = 0;
for (int i = 0; i < n; i++) {
MachineOption mo = options.get(i);
if (loadMap != null) {
double load = loadMap.getOrDefault(mo.getMachineId(), 0.0);
weights[i] = 1.0 / Math.max(load + mo.getProcessingTime(), 0.001);
} else {
weights[i] = 1.0 / Math.max(mo.getProcessingTime(), 0.001);
}
totalWeight += weights[i];
}
double[] quantities = new double[n];
double remaining = original.getQuantity();
for (int i = 0; i < n; i++) {
double proportion = (i == n - 1) ? 1.0 : weights[i] / totalWeight;
double qty = Math.max(1, Math.round(original.getQuantity() * proportion * 100.0) / 100.0);
if (i == n - 1) {
qty = remaining;
}
qty = Math.min(qty, remaining);
remaining -= qty;
quantities[i] = qty;
}
return quantities;
}
private static SplitOpMeta findMetaForExecId(Map<String, SplitOpMeta> metas, String execId) {
for (SplitOpMeta meta : metas.values()) {
if (meta.subExecIds.contains(execId)) {
return meta;
}
}
return null;
}
private static class SplitOpMeta {
final String mainId;
final Entry originalEntry;
final List<String> subExecIds = new ArrayList<>();
final List<Double> subQtys = new ArrayList<>();
final List<MachineOption> subMachineOptions = new ArrayList<>();
SplitOpMeta(String mainId, Entry originalEntry) {
this.mainId = mainId;
this.originalEntry = originalEntry;
}
}
private static void fixDependencyReferences(List<OperationDependency> deps, private static void fixDependencyReferences(List<OperationDependency> deps,
int originalId, int newId, boolean isPrev) { int originalId, int newId, boolean isPrev) {
if (deps == null) return; if (deps == null) return;
...@@ -326,4 +513,58 @@ public class OperationSplitService { ...@@ -326,4 +513,58 @@ public class OperationSplitService {
FileHelper.writeLogFile(String.format( FileHelper.writeLogFile(String.format(
"[工序拆分] 更新了%d个拆分的依赖引用", splitMapping.size())); "[工序拆分] 更新了%d个拆分的依赖引用", splitMapping.size()));
} }
/**
* 从拆分后的 Entry 列表重建 OperatRel (GroupResult 列表)
* 对齐 IdGroupingWithDualSerial 的输出格式:
* originalId = execId, globalSerial = id, groupSerial = sequence
* newParentIds = 从 prevEntryIds 提取的 prevOperationId
* newChildIds = 从 nextEntryIds 提取的 nextOperationId
*/
public static List<GroupResult> rebuildOperatRel(List<Entry> allOperations) {
Map<Integer, List<Entry>> groupMap = new LinkedHashMap<>();
for (Entry op : allOperations) {
groupMap.computeIfAbsent(op.getGroupId(), k -> new ArrayList<>()).add(op);
}
List<GroupResult> results = new ArrayList<>();
for (Map.Entry<Integer, List<Entry>> groupEntry : groupMap.entrySet()) {
List<Entry> groupOps = groupEntry.getValue();
groupOps.sort(Comparator.comparingInt(Entry::getSequence));
List<NodeInfo> nodeInfoList = new ArrayList<>();
Map<String, Integer> originalToGlobalSerial = new HashMap<>();
for (Entry op : groupOps) {
List<Integer> parentIds = new ArrayList<>();
if (op.getPrevEntryIds() != null) {
for (OperationDependency dep : op.getPrevEntryIds()) {
if (dep.getPrevOperationId() > 0) {
parentIds.add(dep.getPrevOperationId());
}
}
}
List<Integer> childIds = new ArrayList<>();
if (op.getNextEntryIds() != null) {
for (OperationDependency dep : op.getNextEntryIds()) {
if (dep.getNextOperationId() > 0) {
childIds.add(dep.getNextOperationId());
}
}
}
String execId = op.getExecId() != null ? op.getExecId() : "";
int globalSerial = op.getId();
int groupSerial = op.getSequence();
originalToGlobalSerial.put(execId, globalSerial);
nodeInfoList.add(new NodeInfo(execId, globalSerial, groupSerial, parentIds, childIds));
}
results.add(new GroupResult(nodeInfoList, originalToGlobalSerial));
}
return results;
}
} }
\ No newline at end of file
...@@ -2069,6 +2069,12 @@ public class PlanResultService { ...@@ -2069,6 +2069,12 @@ public class PlanResultService {
.sorted(Comparator.comparingInt(GAScheduleResult::getOperationId)) .sorted(Comparator.comparingInt(GAScheduleResult::getOperationId))
.collect(Collectors.toList()); .collect(Collectors.toList());
Map<Integer, Order> orders = schedule.getOrders().stream()
.collect(Collectors.toMap(
Order::getId,
// 2. Value映射:Material → Material
order -> order
));
for (GAScheduleResult job : sortedJobs) { for (GAScheduleResult job : sortedJobs) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String TargetFinishedOperationIds=""; String TargetFinishedOperationIds="";
...@@ -2078,14 +2084,16 @@ public class PlanResultService { ...@@ -2078,14 +2084,16 @@ public class PlanResultService {
.map(String::valueOf) // 把每个Integer转成String .map(String::valueOf) // 把每个Integer转成String
.collect(Collectors.joining(",")); .collect(Collectors.joining(","));
} }
Order order=orders.get(job.getGroupId());
sb.append(String.format( sb.append(String.format(
"[%d-%d]:[%s-%s] Order %d,OrderID %s, Machine %d, Operation %d, Quantity %.1f, processingTime %.1f, 前处理 %d, 后处理 %d, 离散参数 %d, bomtime %s,TargetOperationId %s", "[%d-%d]:[%s-%s] Order %d,OrderID %s,OrderDueDate %s, Machine %d, Operation %d, Quantity %.1f, processingTime %.1f, 前处理 %d, 后处理 %d, 离散参数 %d, bomtime %s,TargetOperationId %s",
job.getStartTime(), job.getStartTime(),
job.getEndTime(), job.getEndTime(),
ConvertTime(job.getStartTime()), ConvertTime(job.getStartTime()),
ConvertTime(job.getEndTime()), ConvertTime(job.getEndTime()),
job.getGroupId(), job.getGroupId(),
job.getOrderId(), job.getOrderId(),
order.getDueDate().format(DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss")),
job.getMachineId(), job.getMachineId(),
job.getOperationId(), job.getOperationId(),
job.getQuantity(), job.getQuantity(),
...@@ -2469,6 +2477,9 @@ if(job.getGeneDetails()!=null) ...@@ -2469,6 +2477,9 @@ if(job.getGeneDetails()!=null)
material.setMaterialTypeName(m.getMaterialTypeName()); material.setMaterialTypeName(m.getMaterialTypeName());
material.setCode(m.getCode()); material.setCode(m.getCode());
material.setName(m.getName()); material.setName(m.getName());
material.setMaxProduction(m.getMaxProduction());
material.setMinProduction(m.getMinProduction());
// material.setCkeckLeadTime(m.getInspectDuration()); // material.setCkeckLeadTime(m.getInspectDuration());
// material.setPurchaseLeadTime(m.getPurchaseDuration()); // material.setPurchaseLeadTime(m.getPurchaseDuration());
......
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