Commit 8dc6c378 authored by Tong Li's avatar Tong Li

MP

parent d16de264
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -830,7 +830,7 @@ public class MacroPlannerDataConverter {
.filter(e -> e.getEquipId() != null)
.map(e -> {
String unitId = "EQUIP_" + e.getEquipId();
double capCoeff = (e.getDuration() != null) ? e.getDuration().doubleValue() : 1.0;
double capCoeff = (e.getDuration() != null) ? e.getDuration().doubleValue()/3600/e.getOutputQuantity().doubleValue() : 1.0;
boolean lotSize = e.getOneBatchQuantity() != null
&& e.getOneBatchQuantity().compareTo(BigDecimal.ZERO) > 0;
double lotSizeVal = lotSize ? e.getOneBatchQuantity().doubleValue() : 0.0;
......
......@@ -205,7 +205,7 @@ public class TestDataBuilder {
// === 销售需求 (每个产品每周期都有外部需求) ===
// P1: 成品需求 50/周期
salesDemands.add(new SalesDemand(prodP1, spFG, p1, 50.0, 1.0));
salesDemands.add(new SalesDemand(prodP1, spFG, p1, 450.0, 1.0));
salesDemands.add(new SalesDemand(prodP1, spFG, p2, 60.0, 1.0));
salesDemands.add(new SalesDemand(prodP1, spFG, p3, 40.0, 1.0));
......
package com.aps.macroplanner.output.dto;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* 作者:佟礼
* 时间:2026-08-17
*/
/**
* 风险项 — 带等级的风险描述。
*
* <p>level 取值: "高" / "低"。</p>
*/
public class RiskItem {
private final String level;
private final String description;
@JsonCreator
public RiskItem(@JsonProperty("level") String level, @JsonProperty("description") String description) {
this.level = level;
this.description = description;
}
public String getLevel() { return level; }
public String getDescription() { return description; }
}
package com.aps.macroplanner.output.dto;
import java.util.ArrayList;
import java.util.List;
/**
* 销售需求满足结果 — 对应 Quintiq 中 LeafSalesDemandInPeriod 的回写数据。
*
......@@ -26,6 +29,11 @@ public class SalesDemandResult {
/** 优先级 */
private double priority;
/** 未完成原因分析 (仅当 unmetQty > 0 时有内容) */
private final List<String> unmetReasons = new ArrayList<>();
/** 风险分析 (即使满足也可能存在的供应链风险) */
private final List<RiskItem> risks = new ArrayList<>();
// ==================== Getters / Setters ====================
public String getSalesDemandId() { return salesDemandId; }
......@@ -60,4 +68,9 @@ public class SalesDemandResult {
public double getPriority() { return priority; }
public void setPriority(double v) { this.priority = v; }
public List<String> getUnmetReasons() { return unmetReasons; }
public List<RiskItem> getRisks() { return risks; }
}
\ No newline at end of file
......@@ -816,7 +816,7 @@ Map<Integer, Integer> targetGroupEnd=new HashMap<>();
: (schedInfo != null ? schedInfo.getValue() : 0);
OperationScheduleResult operationResult = processOperationSchedule(currentOp, machineId, processTime,
machineOption, chromosome, machineIdMap, machineTasksCache, entryIndexById,
machineOption, chromosome, machineIdMap,opMachineKeyMap, machineTasksCache, entryIndexById,
scheduleIndexById, dueDateForOp, 0,true, opIsJit);
if (operationResult.isForwardFallbackRequired()) {
......@@ -1237,7 +1237,7 @@ Map<Integer, Integer> targetGroupEnd=new HashMap<>();
int orderDueDate1=orderDueDate.get(op.getGroupId());
// 处理当前工序
// long processStartTime = System.currentTimeMillis();
int actualEndTime = processOperation(op,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache, entryIndexById,scheduleIndexById,orderDueDate1,true,false);
int actualEndTime = processOperation(op,machineId,processTime,machineOption,chromosome,machineIdMap,opMachineKeyMap,machineTasksCache, entryIndexById,scheduleIndexById,orderDueDate1,true,false);
// long processEndTime = System.currentTimeMillis();
......@@ -1434,7 +1434,7 @@ Map<Integer, Integer> targetGroupEnd=new HashMap<>();
OperationScheduleResult operationResult = processOperationSchedule(currentOp, machineOption.getMachineId(),
machineOption.getProcessingTime(), machineOption, chromosome, machineIdMap,
machineTasksCache, entryIndexById, scheduleIndexById, 0, operationStartTime,true, false);
opMachineKeyMap,machineTasksCache, entryIndexById, scheduleIndexById, 0, operationStartTime,true, false);
if (operationResult.isForwardFallbackRequired()) {
throw new IllegalStateException("正排兜底过程中不应再次触发正排兜底,groupId=" + groupId
+ ", operationId=" + currentOp.getId());
......@@ -1568,12 +1568,13 @@ Map<Integer, Integer> targetGroupEnd=new HashMap<>();
private int processOperation(Entry currentOp, Long machineId, double processTime,
OpMachine machineOption, Chromosome chromosome,
Map<Long, Machine> machineIdMap,
Map<String, OpMachine> opMachineKeyMap,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Integer, Entry> entryIndexById,
Map<Integer, GAScheduleResult> scheduleIndexById,
int orderDueDate, boolean islockMachineTime, boolean isJit) {
OperationScheduleResult result = processOperationSchedule(currentOp, machineId, processTime, machineOption,
chromosome, machineIdMap, machineTasksCache, entryIndexById, scheduleIndexById,
chromosome, machineIdMap,opMachineKeyMap, machineTasksCache, entryIndexById, scheduleIndexById,
orderDueDate,0, islockMachineTime, isJit);
return result.getEndTime();
}
......@@ -1581,6 +1582,7 @@ Map<Integer, Integer> targetGroupEnd=new HashMap<>();
private OperationScheduleResult processOperationSchedule(Entry currentOp, Long machineId, double processTime,
OpMachine machineOption, Chromosome chromosome,
Map<Long, Machine> machineIdMap,
Map<String, OpMachine> opMachineKeyMap,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Integer, Entry> entryIndexById,
Map<Integer, GAScheduleResult> scheduleIndexById,
......@@ -1600,6 +1602,9 @@ Map<Integer, Integer> targetGroupEnd=new HashMap<>();
prevtime = CalPrevtime(prevtime, currentOp, chromosome, processTime, targetMachine,
entryIndexById, scheduleIndexById);
}
// SS/FF 排产时预对齐:预查询后继设备可用,提前抬高前序开工/完工
prevtime = preAlignParallelSuccessors(currentOp, machineOption, prevtime, opMachineKeyMap,
chromosome, machineTasksCache, entryIndexById);
}
int prevendtime = prevtime;
......@@ -1611,11 +1616,12 @@ Map<Integer, Integer> targetGroupEnd=new HashMap<>();
public GAScheduleResult processOperationResult(Entry currentOp, Long machineId, double processTime,
OpMachine machineOption, Chromosome chromosome,
Map<Long, Machine> machineIdMap,
Map<String, OpMachine> opMachineKeyMap,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Integer, Entry> entryIndexById,
Map<Integer, GAScheduleResult> scheduleIndexById,
int orderDueDate, boolean islockMachineTime, boolean isJit) {
return processOperationSchedule(currentOp, machineId, processTime, machineOption, chromosome, machineIdMap,
return processOperationSchedule(currentOp, machineId, processTime, machineOption, chromosome, machineIdMap, opMachineKeyMap,
machineTasksCache, entryIndexById, scheduleIndexById, orderDueDate, 0,islockMachineTime, isJit)
.getScheduleResult();
}
......@@ -2462,6 +2468,58 @@ if(geneDetails!=null&&geneDetails.size()>0)
}
/**
* 排产时预对齐:正排中前序先排,这里预查询 SS/FF 后继所在设备的最早可用时间,
* 提前抬高前序的开工(SS)/完工(FF),使后继排程时能直接同时开工/结束,减少排完后的撤回重排。
*/
private int preAlignParallelSuccessors(Entry currentOp, OpMachine currentMachine, int prevtime,
Map<String, OpMachine> opMachineKeyMap,
Chromosome chromosome,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Integer, Entry> entryIndexById) {
if (opMachineKeyMap == null || currentOp.getNextEntryIds() == null || currentOp.getNextEntryIds().isEmpty()) {
return prevtime;
}
for (OperationDependency dep : currentOp.getNextEntryIds()) {
Entry succ = entryIndexById.get(dep.getNextOperationId());
if (succ == null) continue;
OpMachine succMachine = opMachineKeyMap.get(succ.getGroupId() + "_" + succ.getSequence());
if (succMachine == null) continue;
int succAvail = 0;
CopyOnWriteArrayList<GAScheduleResult> succTasks = getMachineTasks(succMachine.getMachineId(), chromosome, machineTasksCache);
GAScheduleResult lastTask = getLastMachineTask(succTasks);
if (lastTask != null) {
succAvail = lastTask.getEndTime();
}
if (dep.getDependencyType() == DependencyType.StartToStart) {
// 同时开始:前序开工不早于后继设备可用,使后继排程时能对齐开工
prevtime = Math.max(prevtime, succAvail);
} else if (dep.getDependencyType() == DependencyType.FinishToFinish) {
// 同时结束:前序完工对齐后继完工,反推前序开工
int curDuration = calcOpDuration(currentOp, currentMachine);
int succDuration = calcOpDuration(succ, succMachine);
prevtime = Math.max(prevtime, succAvail + succDuration - curDuration);
}
}
return prevtime;
}
/**
* 计算工序加工时长(不含准备工时),与 processWithSingleMachine 口径一致,用于 SS/FF 对齐反推。
*/
private int calcOpDuration(Entry op, OpMachine machineOption) {
if (op.getConstTime() == 1) {
return (int) Math.ceil(machineOption.getProcessingTime());
}
if (machineOption.getSingleOut() == null || machineOption.getSingleOut().doubleValue() == 0) {
return (int) Math.ceil(machineOption.getProcessingTime());
}
double t = machineOption.getRuntime().doubleValue() / machineOption.getSingleOut().doubleValue() * op.getQuantity();
return (int) Math.ceil(t);
}
/**
* 计算后序结束时间
* @param nexttime
......
......@@ -390,7 +390,7 @@ if(isJit)
GAScheduleResult result= decoder.processOperationResult( op, mId, mo.getProcessingTime(), mo, chromosome, machineIdMap, machineTasksCache, entryIndexById, scheduleIndexById, start, false, isJit);
GAScheduleResult result= decoder.processOperationResult( op, mId, mo.getProcessingTime(), mo, chromosome, machineIdMap, opMachineKeyMap,machineTasksCache, entryIndexById, scheduleIndexById, start, false, isJit);
// CopyOnWriteArrayList<ScheduleResultDetail> geneDetails = estimateCalendarAwareDuration(machine,op,machineTasks, start, rawDur,mo.getProcessingTime(),isJit);
......
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