物料配套

parent 40085732
......@@ -193,7 +193,7 @@ public class Chromosome {
/// 交付期延迟时间
/// </summary>
private double DelayTime;
private double SemiJitSlack;
private String ScenarioID;
......
......@@ -7,10 +7,10 @@ package com.aps.entity.Algorithm;
*/
public class ObjectiveWeights {
/**
* 目标权重(默认值:[0.3, 0.2, 0.15, 0.2, 0.15])
* 对应:完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
* 目标权重(默认值:[0.3, 0.2, 0.15, 0.2, 0.15, 0.01])
* 对应:完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间、半成品JIT
*/
private double[] weights = new double[] { 0.3, 0.2, 0.15, 0.2, 0.15 };
private double[] weights = new double[] { 0.3, 0.2, 0.15, 0.2, 0.15, 0.01 };
/**
* NSGA-II模式:true=纯帕累托(无视权重),false=加权帕累托
......
......@@ -160,4 +160,8 @@ private Long isInterrupt = 1l;
@Schema(description = "指定开始时间")
@JsonInclude(JsonInclude.Include.ALWAYS)
private LocalDateTime designatedStartTime;
private LocalDateTime jitPreferredStartTime;
private boolean jitTemporary = false;
}
......@@ -14,7 +14,6 @@ public class GlobalParam {
/// 是否可以打破优先级
/// </summary>
private boolean IsBreakPriority = false;
/// <summary>
/// 是否多台设备
/// </summary>
......@@ -51,6 +50,16 @@ public class GlobalParam {
*/
private boolean pureNSGAIIMode = true;
/**
* 半成品JIT缓冲时间(分钟)
*/
private int semiJitBufferMinutes = 0;
/**
* 物料/设备固定点求解最大迭代次数
*/
private int materialSolveMaxIterations = 8;
/// <summary>
......@@ -66,6 +75,7 @@ public class GlobalParam {
public static final String OBJECTIVE_SETUP_TIME = "setupTime"; // 总换型时间
public static final String OBJECTIVE_MACHINE_LOAD = "machineLoad"; // 机器负载均衡
public static final String OBJECTIVE_TARDINESS = "tardiness"; // 延迟时间
public static final String OBJECTIVE_SEMI_JIT = "semiJitSlack"; // 半成品提前完工惩罚
/// <summary>
/// 构造函数,初始化默认值
......@@ -73,15 +83,22 @@ public class GlobalParam {
public GlobalParam() {
// 初始化默认目标值配置
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MAKESPAN, true, 1, 0.3));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_FLOW_TIME, true, 2, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_SETUP_TIME, true, 2, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MACHINE_LOAD, true, 1, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_TARDINESS, true, 1, 0.6));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_MAKESPAN, 1, 0.3));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_FLOW_TIME, 2, 0.2));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_SETUP_TIME, 2, 0.15));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_MACHINE_LOAD, 1, 0.2));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_TARDINESS, 1, 0.15));
objectiveConfigs.add(createMinimizeObjectiveConfig(OBJECTIVE_SEMI_JIT, 2, 0.01));
objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel()));
}
private ObjectiveConfig createMinimizeObjectiveConfig(String name, int level, double weight) {
ObjectiveConfig config = new ObjectiveConfig(name, true, level, weight);
config.setMinimize(true);
return config;
}
/// <summary>
/// 获取目标值启用状态
/// </summary>
......
......@@ -58,6 +58,7 @@ public class GeneticDecoder {
private DiscreteParameterMatrixService discreteParameterMatrixService;
private String sceneId;
private boolean rebuildStructureForCurrentDecode = true;
......@@ -388,12 +389,24 @@ public class GeneticDecoder {
/**
* 染色体解码为调度方案
*/
public void decode(Chromosome chromosome, boolean isParallel, boolean rebuildStructure) {
boolean previousFlag = this.rebuildStructureForCurrentDecode;
this.rebuildStructureForCurrentDecode = rebuildStructure;
try {
decode(chromosome, isParallel);
} finally {
this.rebuildStructureForCurrentDecode = previousFlag;
}
}
public void serialDecode(Chromosome chromosome) {
List<OrderMaterialRequirement> orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
if (rebuildStructureForCurrentDecode) {
materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
}
chromosome.setScenarioID(sceneId);
if(_globalParam.isIsCheckSf()) {
if(rebuildStructureForCurrentDecode && _globalParam.isIsCheckSf()) {
int isnew= generateGlobalOpList(chromosome);
if(isnew==1) {
......@@ -403,6 +416,7 @@ public class GeneticDecoder {
List<GlobalOperationInfo> globalOpList=chromosome.getGlobalOpList();
List<Entry> allOperations=chromosome.getAllOperations();
allOperations.forEach(t -> t.setLatestCompletionTime(null));
......@@ -1008,10 +1022,7 @@ public class GeneticDecoder {
prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine,entryIndexById, scheduleIndexById);
}
int bomtime = getOperationBOMTime(currentOp,chromosome);
int prevendtime=prevtime;
prevtime = Math.max(prevtime, bomtime);
Machine machine = machineIdMap.get(machineId);
int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,machineOption, chromosome,false,prevendtime,machineTasksCache,entryIndexById, scheduleIndexById);
return actualEndTime;
......@@ -1066,41 +1077,92 @@ public class GeneticDecoder {
// 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理
earliestStartTime+=preTime;
}
GAScheduleResult existingResult = chromosome.getResultOld().stream().filter(r-> r.getOperationId() == operation.getId()).findFirst().orElse(null);
int operationId = operation.getId();
GAScheduleResult existingResult = chromosome.getResultOld().stream().filter(r-> r.getOperationId() == operationId).findFirst().orElse(null);
if(existingResult!=null)
{
earliestStartTime = Math.max(earliestStartTime,existingResult.getDesignatedStartTime());
}
int setupTime=0;
CopyOnWriteArrayList<GAScheduleResult> machineTasks;
if (machineTasksCache.containsKey(machine.getId())) {
machineTasks = machineTasksCache.get(machine.getId());
} else {
machineTasks = chromosome.getResult().stream()
.filter(t -> t.getMachineId() == machine.getId())
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
machineTasksCache.put(machine.getId(), machineTasks);
}
GAScheduleResult lastGeneOnMachine = null;
if(machineTasks!=null&&machineTasks.size()>0)
{
lastGeneOnMachine=machineTasks.get(machineTasks.size()-1);
}
if(lastGeneOnMachine!=null&&_globalParam.is_smoothChangeOver())
{
earliestStartTime = Math.max(earliestStartTime,lastGeneOnMachine.getEndTime());
if (operation.isJitTemporary() && operation.getJitPreferredStartTime() != null) {
int jitPreferredStartTime = (int) ChronoUnit.SECONDS.between(baseTime, operation.getJitPreferredStartTime());
earliestStartTime = Math.max(earliestStartTime, jitPreferredStartTime);
}
// _globalParam.set_smoothChangeOver(false);
CopyOnWriteArrayList<ScheduleResultDetail> geneDetails=new CopyOnWriteArrayList<>();
int setupTime=0;
long machineId = machine.getId();
boolean needMaterialCheck = (operation.getMaterialRequirements()!=null&&operation.getTargetFinishedOperationId()==null)||calbom;
boolean commitMaterialCheck = needMaterialCheck;
int baseEarliestStartTime = earliestStartTime;
int candidateStartTime = earliestStartTime;
int bomtime=0;
int maxSolveIterations = Math.max(1, _globalParam.getMaterialSolveMaxIterations());
boolean converged = !needMaterialCheck;
Entry scheduledOperation = operation;
Machine scheduledMachine = machine;
CopyOnWriteArrayList<GAScheduleResult> machineTasks = getMachineTasks(machineId, chromosome, machineTasksCache);
GAScheduleResult lastGeneOnMachine = getLastMachineTask(machineTasks);
MachineSchedulePreview machinePreview = null;
CopyOnWriteArrayList<ScheduleResultDetail> geneDetails=new CopyOnWriteArrayList<>();
if(needMaterialCheck) {
for (int iteration = 0; iteration < maxSolveIterations; iteration++) {
Entry refreshedOperation = entryIndexById.get(operationId);
if (refreshedOperation != null) {
scheduledOperation = refreshedOperation;
}
Machine refreshedMachine = getMachineById(chromosome, machineId);
if (refreshedMachine != null) {
scheduledMachine = refreshedMachine;
}
machineTasks = getMachineTasks(machineId, chromosome, machineTasksCache);
lastGeneOnMachine = getLastMachineTask(machineTasks);
if(lastGeneOnMachine!=null&&_globalParam.is_smoothChangeOver())
{
candidateStartTime = Math.max(candidateStartTime,lastGeneOnMachine.getEndTime());
}
machinePreview = buildMachinePreview(scheduledOperation, scheduledMachine, processingTime, processingTimeTotal,
candidateStartTime, lastGeneOnMachine, machineTasks, chromosome);
try {
bomtime = EditOperationBOMTime(scheduledOperation,chromosome,machinePreview.getStartTime(),machineTasksCache, entryIndexById, scheduleIndexById, false);
} finally {
Machine liveMachineAfterTrial = getMachineById(chromosome, machineId);
if (liveMachineAfterTrial != null) {
AddMachineAvailable(liveMachineAfterTrial, machinePreview.getGeneDetails());
} else {
AddMachineAvailable(scheduledMachine, machinePreview.getGeneDetails());
}
}
int nextCandidateStartTime = Math.max(baseEarliestStartTime, bomtime);
if (nextCandidateStartTime <= machinePreview.getStartTime()) {
converged = true;
candidateStartTime = nextCandidateStartTime;
break;
}
candidateStartTime = nextCandidateStartTime;
}
earliestStartTime = candidateStartTime;
Entry refreshedOperation = entryIndexById.get(operationId);
if (refreshedOperation != null) {
scheduledOperation = refreshedOperation;
operation = refreshedOperation;
}
Machine refreshedMachine = getMachineById(chromosome, machineId);
if (refreshedMachine != null) {
scheduledMachine = refreshedMachine;
machine = refreshedMachine;
}
machineTasks = getMachineTasks(machineId, chromosome, machineTasksCache);
lastGeneOnMachine = getLastMachineTask(machineTasks);
needMaterialCheck = false;
}
if((operation.getMaterialRequirements()!=null&&operation.getTargetFinishedOperationId()==null)||calbom) {
if(needMaterialCheck) {
int earliestStartTimeold=earliestStartTime;
if (_globalParam.is_smoothChangeOver()) {
......@@ -1121,13 +1183,10 @@ public class GeneticDecoder {
: earliestStartTime;
}
bomtime= EditOperationBOMTime(operation,chromosome,earliestStartTime,machineTasksCache, entryIndexById, scheduleIndexById);
bomtime= EditOperationBOMTime(operation,chromosome,earliestStartTime,machineTasksCache, entryIndexById, scheduleIndexById, false);
if(bomtime>prevendtime&&bomtime<earliestStartTimeold)
{
earliestStartTime=bomtime;
}
earliestStartTime = Math.max(earliestStartTime, bomtime);
}
......@@ -1214,6 +1273,20 @@ public class GeneticDecoder {
// 准备工时 加入到加工时间里
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
if (commitMaterialCheck) {
int committedBomTime = EditOperationBOMTime(operation,chromosome,startTime,machineTasksCache, entryIndexById, scheduleIndexById, true);
bomtime = Math.max(bomtime, committedBomTime);
if (committedBomTime > startTime) {
throw new IllegalStateException(String.format(
"工序固定点求解未收敛,operationId=%d, groupId=%d, startTime=%d, bomTime=%d, maxIterations=%d",
operation.getId(),
operation.getGroupId(),
startTime,
committedBomTime,
maxSolveIterations));
}
}
GAScheduleResult result=new GAScheduleResult();
......@@ -1228,7 +1301,9 @@ public class GeneticDecoder {
result.setProductId(operation.getProductId());
result.setProductName(operation.getProductName());
result.setProductCode(operation.getProductCode());
result.setTargetFinishedOperationId(operation.getTargetFinishedOperationId());
result.setTargetFinishedOperationId(operation.getTargetFinishedOperationId() == null
? null
: new ArrayList<>(operation.getTargetFinishedOperationId()));
result.setMachineId(machine.getId());
result.setStartTime(startTime);
result.setEndTime(endTime);
......@@ -1276,10 +1351,146 @@ public class GeneticDecoder {
if (machineTasks != null) {
machineTasks.add(result);
}
updateSemiJitTargets(operation, startTime, chromosome);
scheduleIndexById.put(operation.getId(),result);
return endTime;
}
private void updateSemiJitTargets(Entry parentOperation, int parentStartTime, Chromosome chromosome) {
if (parentOperation.getDependentOnOrderIds() == null || parentOperation.getDependentOnOrderIds().isEmpty()) {
return;
}
LocalDateTime targetTime = baseTime.plusSeconds(parentStartTime)
.minusMinutes(Math.max(0, _globalParam.getSemiJitBufferMinutes()));
if (targetTime.isBefore(baseTime)) {
targetTime = baseTime;
}
for (Integer childGroupId : parentOperation.getDependentOnOrderIds()) {
List<Entry> childOperations = chromosome.getAllOperations().stream()
.filter(t -> t.getGroupId() == childGroupId)
.collect(Collectors.toList());
if (childOperations.isEmpty()) {
continue;
}
int maxSequence = childOperations.stream().mapToInt(Entry::getSequence).max().orElse(Integer.MIN_VALUE);
for (Entry childOperation : childOperations) {
if (childOperation.getSequence() != maxSequence) {
continue;
}
if (childOperation.getLatestCompletionTime() == null || targetTime.isBefore(childOperation.getLatestCompletionTime())) {
childOperation.setLatestCompletionTime(targetTime);
}
if (childOperation.getTargetFinishedOperationId() == null) {
childOperation.setTargetFinishedOperationId(new ArrayList<>());
}
if (!childOperation.getTargetFinishedOperationId().contains(parentOperation.getId())) {
childOperation.getTargetFinishedOperationId().add(parentOperation.getId());
}
}
}
}
private MachineSchedulePreview buildMachinePreview(Entry operation, Machine machine, double processingTime, int processingTimeTotal,
int earliestStartTime, GAScheduleResult lastGeneOnMachine,
CopyOnWriteArrayList<GAScheduleResult> machineTasks, Chromosome chromosome) {
int setupTime = 0;
int previewStart = earliestStartTime;
int previewProcessingTotal = processingTimeTotal;
CopyOnWriteArrayList<ScheduleResultDetail> geneDetails;
if (_globalParam.is_smoothChangeOver()) {
Map<Integer,Object> reslte = calculateSetupTime(lastGeneOnMachine, operation, machine, previewStart, previewProcessingTotal, _globalParam.is_smoothChangeOverInWeek(),chromosome.getAllOperations());
setupTime=(int)reslte.get(1);
int setupStartTime=(int)reslte.get(2);
previewStart=(int)reslte.get(4);
previewProcessingTotal=(int)reslte.get(5);
if(setupTime==0)
{
geneDetails = machineCalculator.getNextAvailableTime(machine, previewStart, -1,
previewProcessingTotal, machineTasks, operation.getIsInterrupt()!=1, true,processingTime, operation.getQuantity(), true);
}else {
CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = (CopyOnWriteArrayList<TimeSegment>) reslte.get(6);
Map<Integer,Object> result = machineCalculator.CreateScheduleResult(machine, previewProcessingTotal, previewStart,
AvailableTimeSegment, processingTime, operation.getQuantity(), operation.getIsInterrupt() != 1, setupTime, _globalParam.is_smoothChangeOverInWeek(), setupStartTime);
setupTime=(int)result.get(1);
geneDetails=(CopyOnWriteArrayList<ScheduleResultDetail>) result.get(2);
}
}else {
geneDetails = machineCalculator.getNextAvailableTime(machine, previewStart, -1,
previewProcessingTotal, machineTasks, operation.getIsInterrupt()!=1, true,processingTime, operation.getQuantity(), true);
}
int startTime = geneDetails.stream()
.mapToInt(ScheduleResultDetail::getStartTime)
.min()
.orElse(0);
int endTime = geneDetails.stream()
.mapToInt(ScheduleResultDetail::getEndTime)
.max()
.orElse(0);
return new MachineSchedulePreview(startTime, endTime, setupTime, geneDetails);
}
private CopyOnWriteArrayList<GAScheduleResult> getMachineTasks(long machineId, Chromosome chromosome,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache) {
if (machineTasksCache.containsKey(machineId)) {
return machineTasksCache.get(machineId);
}
CopyOnWriteArrayList<GAScheduleResult> machineTasks = chromosome.getResult().stream()
.filter(t -> t.getMachineId() == machineId)
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
machineTasksCache.put(machineId, machineTasks);
return machineTasks;
}
private GAScheduleResult getLastMachineTask(CopyOnWriteArrayList<GAScheduleResult> machineTasks) {
if(machineTasks!=null&&machineTasks.size()>0)
{
return machineTasks.get(machineTasks.size()-1);
}
return null;
}
private Machine getMachineById(Chromosome chromosome, long machineId) {
return chromosome.getMachines().stream()
.filter(m -> m.getId() == machineId)
.findFirst()
.orElse(null);
}
private static class MachineSchedulePreview {
private final int startTime;
private final int endTime;
private final int setupTime;
private final CopyOnWriteArrayList<ScheduleResultDetail> geneDetails;
private MachineSchedulePreview(int startTime, int endTime, int setupTime, CopyOnWriteArrayList<ScheduleResultDetail> geneDetails) {
this.startTime = startTime;
this.endTime = endTime;
this.setupTime = setupTime;
this.geneDetails = geneDetails;
}
public int getStartTime() {
return startTime;
}
public int getEndTime() {
return endTime;
}
public int getSetupTime() {
return setupTime;
}
public CopyOnWriteArrayList<ScheduleResultDetail> getGeneDetails() {
return geneDetails;
}
}
/**
* 计算前序结束时间
* @param prevtime
......@@ -1415,8 +1626,9 @@ public class GeneticDecoder {
// 计算RawTime
Optional<LocalDateTime> rawDateOpt = opboms.stream()
.filter(t -> t.getMaterialTypeName().equals("MP"))
.filter(t -> "MP".equals(t.getMaterialTypeName()))
.map(OrderMaterialRequirement::getUseTime)
.filter(Objects::nonNull)
.max(LocalDateTime::compareTo);
if (rawDateOpt.isPresent()) {
rawTime = (int) Duration.between(baseTime, rawDateOpt.get()).getSeconds();
......@@ -1426,7 +1638,7 @@ public class GeneticDecoder {
// 计算SFTime
List<OrderMaterialRequirement> sfBoms = opboms.stream()
.filter(t -> !t.getMaterialTypeName().equals("MP")
.filter(t -> !"MP".equals(t.getMaterialTypeName())
&& t.getProductOrderID() != null && !t.getProductOrderID().isEmpty())
.collect(Collectors.toList());
......@@ -1455,8 +1667,9 @@ public class GeneticDecoder {
}
}
Optional<LocalDateTime> sfDateOpt = opboms.stream()
.filter(t -> !t.getMaterialTypeName().equals("MP")&&(t.getProductOrderID() == null || t.getProductOrderID().isEmpty()))
.filter(t -> !"MP".equals(t.getMaterialTypeName())&&(t.getProductOrderID() == null || t.getProductOrderID().isEmpty()))
.map(OrderMaterialRequirement::getUseTime)
.filter(Objects::nonNull)
.max(LocalDateTime::compareTo);
if (sfDateOpt.isPresent()) {
sfTime =Math.max(sfTime, (int) Duration.between(baseTime, sfDateOpt.get()).getSeconds());
......@@ -1467,17 +1680,73 @@ public class GeneticDecoder {
}
private int EditOperationBOMTime(Entry currentOp, Chromosome chromosome,int earliestStartTime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {
return EditOperationBOMTime(currentOp, chromosome, earliestStartTime, machineTasksCache, entryIndexById, scheduleIndexById, true);
}
private int EditOperationBOMTime(Entry currentOp, Chromosome chromosome,int earliestStartTime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById, boolean commitChanges) {
List<OrderMaterialRequirement> opboms= currentOp.getMaterialRequirements();
if(opboms==null)
{
return 0;
}
LocalDateTime earliestStartTime1=baseTime.plusSeconds(earliestStartTime);
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById, baseTime);
return getOperationBOMTime(currentOp, chromosome);
if(commitChanges) {
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById, baseTime, true);
return getOperationBOMTime(currentOp, chromosome);
}
TrialDecodeSnapshot snapshot = createTrialDecodeSnapshot(chromosome);
try {
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById, baseTime, true);
return getOperationBOMTime(currentOp, chromosome);
} finally {
restoreTrialDecodeSnapshot(snapshot, chromosome, machineTasksCache, entryIndexById, scheduleIndexById);
}
}
private TrialDecodeSnapshot createTrialDecodeSnapshot(Chromosome chromosome) {
TrialDecodeSnapshot snapshot = new TrialDecodeSnapshot();
snapshot.machines = ProductionDeepCopyUtil.deepCopyList(chromosome.getMachines(), Machine.class);
snapshot.orders = ProductionDeepCopyUtil.deepCopyList(chromosome.getOrders(), Order.class);
snapshot.materials = ProductionDeepCopyUtil.deepCopyList(chromosome.getMaterials(), Material.class);
snapshot.allOperations = ProductionDeepCopyUtil.deepCopyList(chromosome.getAllOperations(), Entry.class);
snapshot.results = ProductionDeepCopyUtil.deepCopyList(chromosome.getResult(), GAScheduleResult.class);
snapshot.reOrderIds = new ArrayList<>(chromosome.getReOrderids());
return snapshot;
}
private void restoreTrialDecodeSnapshot(TrialDecodeSnapshot snapshot, Chromosome chromosome,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Integer, Entry> entryIndexById,
Map<Integer, GAScheduleResult> scheduleIndexById) {
chromosome.setMachines(snapshot.machines);
chromosome.setOrders(snapshot.orders);
chromosome.setMaterials(snapshot.materials);
chromosome.setAllOperations(snapshot.allOperations);
chromosome.setResult(snapshot.results);
chromosome.setReOrderids(snapshot.reOrderIds);
machineTasksCache.clear();
entryIndexById.clear();
for (Entry entry : chromosome.getAllOperations()) {
entryIndexById.put(entry.getId(), entry);
}
scheduleIndexById.clear();
for (GAScheduleResult scheduleResult : chromosome.getResult()) {
scheduleIndexById.put(scheduleResult.getOperationId(), scheduleResult);
machineTasksCache.computeIfAbsent(scheduleResult.getMachineId(), key -> new CopyOnWriteArrayList<>()).add(scheduleResult);
}
}
private static class TrialDecodeSnapshot {
private List<Machine> machines;
private CopyOnWriteArrayList<Order> orders;
private List<Material> materials;
private CopyOnWriteArrayList<Entry> allOperations;
private CopyOnWriteArrayList<GAScheduleResult> results;
private List<Integer> reOrderIds;
}
public void EditorderOperation(Chromosome chromosome, int groupId,double needed,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById){
......@@ -1530,9 +1799,7 @@ public class GeneticDecoder {
// 上个离散参数
// String lastDiscreteParameter = machineState.get(machineId);
int bomtime = getOperationBOMTime(currentOp,chromosome);
int prevendtime=prevtime;
prevtime = Math.max(prevtime, bomtime);
Machine machine = chromosome.getMachines().stream()
.filter(m -> m.getId() == machineId)
......@@ -2301,7 +2568,7 @@ public class GeneticDecoder {
int i = 0;
for (ObjectiveConfig config : _globalParam.getObjectiveConfigs()) {
if (config.isEnabled()) {
if (config.getName() == GlobalParam.OBJECTIVE_MAKESPAN) {
if (GlobalParam.OBJECTIVE_MAKESPAN.equals(config.getName())) {
// 1. 最早完工时间(最小化)
double makespan = chromosome.getResult().stream()
.mapToInt(GAScheduleResult::getEndTime)
......@@ -2310,7 +2577,7 @@ public class GeneticDecoder {
Objectives[i] = makespan;
chromosome.setMakespan(makespan);
}
if (config.getName() == GlobalParam.OBJECTIVE_TARDINESS) {
if (GlobalParam.OBJECTIVE_TARDINESS.equals(config.getName())) {
// 2. 交付期满足情况(最小化延迟)
double tardiness = 0;
......@@ -2353,24 +2620,29 @@ public class GeneticDecoder {
Objectives[i] = tardiness;
chromosome.setDelayTime(tardiness);
}
if (config.getName() == GlobalParam.OBJECTIVE_SETUP_TIME) {
if (GlobalParam.OBJECTIVE_SETUP_TIME.equals(config.getName())) {
// 3. 最小总换型时间
double totalSetupTime = calculateTotalSetupTime(chromosome);
chromosome.setTotalChangeoverTime(totalSetupTime);
Objectives[i] = totalSetupTime;
}
if (config.getName() == GlobalParam.OBJECTIVE_FLOW_TIME) {
if (GlobalParam.OBJECTIVE_FLOW_TIME.equals(config.getName())) {
// 4. 最小化总流程时间 所有工序加工时间的总和
double totalFlowTime = calculateTotalFlowTime(chromosome);
chromosome.setTotalFlowTime(totalFlowTime);
Objectives[i] = totalFlowTime;
}
if (config.getName() == GlobalParam.OBJECTIVE_MACHINE_LOAD) {
if (GlobalParam.OBJECTIVE_MACHINE_LOAD.equals(config.getName())) {
// 5. 机器负载均衡
double machineLoadBalance = calculateMachineLoadBalance(chromosome);
chromosome.setMachineLoadStd(machineLoadBalance);
Objectives[i] = machineLoadBalance;
}
if (GlobalParam.OBJECTIVE_SEMI_JIT.equals(config.getName())) {
double semiJitSlack = calculateSemiJitSlack(chromosome);
chromosome.setSemiJitSlack(semiJitSlack);
Objectives[i] = semiJitSlack;
}
i++;
}
}
......@@ -2429,6 +2701,27 @@ public class GeneticDecoder {
// 标准差与平均值的比值衡量负载离散程度,值越小说明均衡度越高
return Math.sqrt(variance)/avgUtilization ;
}
private double calculateSemiJitSlack(Chromosome chromosome) {
Map<Integer, GAScheduleResult> resultByOperation = chromosome.getResult().stream()
.collect(Collectors.toMap(GAScheduleResult::getOperationId, t -> t, (left, right) -> left));
double semiJitSlack = 0;
for (Entry operation : chromosome.getAllOperations()) {
if (operation.getLatestCompletionTime() == null) {
continue;
}
GAScheduleResult result = resultByOperation.get(operation.getId());
if (result == null) {
continue;
}
LocalDateTime completionTime = baseTime.plusSeconds(result.getEndTime());
if (completionTime.isBefore(operation.getLatestCompletionTime())) {
semiJitSlack += ChronoUnit.MINUTES.between(completionTime, operation.getLatestCompletionTime());
}
}
return semiJitSlack;
}
/**
* 补全:创建缓存键(核心逻辑,需与原 C# CreateCacheKey 一致)
* 思路:将染色体的核心特征(机器选择+工序排序)拼接为字符串,确保相同染色体生成相同键
......
......@@ -133,6 +133,9 @@ int opcount=allOperations.size();
FileHelper.writeLogFile("按Objectives去重-----------开始-------" + population.size());
population = chromosomeDistinctByObjectives(population);
FileHelper.writeLogFile("按Objectives去重-----------结束-------" + population.size());
if (population == null || population.isEmpty()) {
throw new RuntimeException("初始种群为空,请检查 populationSize、种群初始化和解码结果");
}
// if(1==1)
// return getBestChromosome(population.get(0), param.getBaseTime(), starttime);
// 步骤2:对初始种群进行爬山法局部优化
......
......@@ -1046,7 +1046,7 @@ public class MaterialRequirementService {
return new BOMBuildResult(materialRequirements, _childorders,_newEntrys);
}
private OrderMaterialRequirement MaterialStock(Material material,String materialId,String orderId, String childorderId, Entry operation,double allneeded, double needed,LocalDateTime earliestStartTime ) {
private OrderMaterialRequirement MaterialStock(Material material,String materialId,String orderId, String childorderId, Entry operation,double allneeded, double needed,LocalDateTime earliestStartTime, boolean commitChanges ) {
OrderMaterialRequirement orderMaterial = new OrderMaterialRequirement();
orderMaterial.setOrderId(orderId);
......@@ -1054,16 +1054,16 @@ public class MaterialRequirementService {
orderMaterial.setChildOrderId(StringUtils.isBlank(childorderId) ? orderId : childorderId);
orderMaterial.setRequiredQuantity(allneeded);
orderMaterial.setQjQty(allneeded);
double availableNow = material.getCurrentStock();
orderMaterial.setMaterialCode(material.getCode());
orderMaterial.setMaterialName(material.getName());
orderMaterial.setMaterialTypeName(material.getMaterialTypeName());
orderMaterial.setMaterialId(material.getId());
// orderMaterial.setCheckLeadTime(material.getCkeckLeadTime());
double useStock=0;
// 扣减现有库存
List<Stock> stocks= material.getMaterialStocks().stream()
.filter(t->t.getExpiryDate().compareTo(earliestStartTime)>=0&&t.getAvailableInventory()>0)
.filter(t -> isStockValid(t, earliestStartTime) && t.getAvailableInventory() > 0)
.sorted(Comparator.comparing(Stock::getExpiryDate, Comparator.nullsLast(LocalDateTime::compareTo))
.thenComparing(Stock::getWarehousingDate, Comparator.nullsLast(LocalDateTime::compareTo)))
.collect(Collectors.toList());
if(stocks!=null)
{
......@@ -1071,7 +1071,9 @@ public class MaterialRequirementService {
double useStock1 = Math.min(needed,s.getAvailableInventory());
needed -=useStock1;
useStock+=useStock1;
s.setUsedInventory(s.getUsedInventory()+useStock1);
if(commitChanges) {
s.setUsedInventory(s.getUsedInventory()+useStock1);
}
if(needed==0)
{
break;
......@@ -1086,6 +1088,29 @@ public class MaterialRequirementService {
return orderMaterial;
}
private boolean isStockValid(Stock stock, LocalDateTime demandTime) {
return stock.getExpiryDate() == null || !stock.getExpiryDate().isBefore(demandTime);
}
private void resetRequirementCalc(OrderMaterialRequirement orderMaterial) {
orderMaterial.setUseStock(0);
orderMaterial.setUseTransit(0);
orderMaterial.setArrivalTime(null);
orderMaterial.setPurchaseStartTime(null);
orderMaterial.setPurchaseEndTime(null);
orderMaterial.setUseTime(null);
if (orderMaterial.getReplaceMaterial() != null && !orderMaterial.getReplaceMaterial().isEmpty()) {
for (OrderMaterialRequirement replace : orderMaterial.getReplaceMaterial()) {
replace.setUseStock(0);
replace.setUseTransit(0);
replace.setArrivalTime(null);
replace.setPurchaseStartTime(null);
replace.setPurchaseEndTime(null);
replace.setUseTime(null);
}
}
}
private OrderMaterialRequirement CreateMaterialRequirement(Material material,String orderId, String childorderId, Entry operation,double need,double spentQty,double mainQty,double qty, LocalDateTime baseTime) {
......@@ -1122,8 +1147,8 @@ public class MaterialRequirementService {
if (maxItem.isPresent()) {
MaterialPurchase result = maxItem.get();
orderMaterial.setCheckLeadTime(result.getPurchaseCycle());
orderMaterial.setPurchaseTime(result.getInspectionCycle());
orderMaterial.setPurchaseTime(result.getPurchaseCycle());
orderMaterial.setCheckLeadTime(result.getInspectionCycle());
}
}
orderMaterial.setUseTime(baseTime.plusDays(orderMaterial.getPurchaseTime()+orderMaterial.getCheckLeadTime()));
......@@ -1139,6 +1164,10 @@ public class MaterialRequirementService {
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/
public void EditOperationBOM(Entry operation,Chromosome chromosome,LocalDateTime earliestStartTime,GeneticDecoder coder,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById, LocalDateTime baseTime) {
EditOperationBOM(operation, chromosome, earliestStartTime, coder, machineTasksCache, entryIndexById, scheduleIndexById, baseTime, true);
}
public void EditOperationBOM(Entry operation,Chromosome chromosome,LocalDateTime earliestStartTime,GeneticDecoder coder,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById, LocalDateTime baseTime, boolean commitChanges) {
List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
String sceneId=chromosome.getScenarioID();
......@@ -1169,6 +1198,7 @@ public class MaterialRequirementService {
double allneeded = orderMaterial.getSpentQty()/ orderMaterial.getMainQty() * operation.getQuantity();
double needed = allneeded;
resetRequirementCalc(orderMaterial);
orderMaterial.setRequiredQuantity(needed);
orderMaterial.setQjQty(needed);
// 查找物料(流式处理替代First)
......@@ -1183,7 +1213,9 @@ public class MaterialRequirementService {
double useStock=0;
List<Stock> stocks= material.getMaterialStocks().stream()
.filter(t->t.getExpiryDate().compareTo(earliestStartTime)>=0&&t.getAvailableInventory()>0)
.filter(t -> isStockValid(t, earliestStartTime) && t.getAvailableInventory() > 0)
.sorted(Comparator.comparing(Stock::getExpiryDate, Comparator.nullsLast(LocalDateTime::compareTo))
.thenComparing(Stock::getWarehousingDate, Comparator.nullsLast(LocalDateTime::compareTo)))
.collect(Collectors.toList());
if(stocks!=null)
{
......@@ -1191,7 +1223,9 @@ public class MaterialRequirementService {
double useStock1 = Math.min(needed,s.getAvailableInventory());
needed -=useStock1;
useStock+=useStock1;
s.setUsedInventory(s.getUsedInventory()+useStock1);
if(commitChanges) {
s.setUsedInventory(s.getUsedInventory()+useStock1);
}
if(needed==0)
{
break;
......@@ -1202,7 +1236,9 @@ public class MaterialRequirementService {
if (needed <= 0) {
orderMaterial.setYpQty(allneeded - needed);
orderMaterial.setQjQty(needed);
remove.add(orderMaterial);
if(commitChanges) {
remove.add(orderMaterial);
}
continue;
}
List<RoutingSupportingReplace> routingsupportingreplaces= GetRoutingSupportingReplaces(sceneId);
......@@ -1222,7 +1258,7 @@ public class MaterialRequirementService {
if (material1 == null) {
break;
}
OrderMaterialRequirement orderMaterial1 = MaterialStock(material1, rsr.getTargetmaterialid(), orderMaterial.getOrderId(), orderMaterial.getChildOrderId(), operation, allneeded, needed, earliestStartTime);
OrderMaterialRequirement orderMaterial1 = MaterialStock(material1, rsr.getTargetmaterialid(), orderMaterial.getOrderId(), orderMaterial.getChildOrderId(), operation, allneeded, needed, earliestStartTime, commitChanges);
if (orderMaterial1 != null) {
useStock = orderMaterial1.getUseStock();
......@@ -1241,11 +1277,13 @@ public class MaterialRequirementService {
if (needed <= 0) {
orderMaterial.setYpQty(allneeded - needed);
orderMaterial.setQjQty(needed);
remove.add(orderMaterial);
if(commitChanges) {
remove.add(orderMaterial);
}
continue;
}
MaterialInTransit(material,"",orderMaterial,needed,earliestStartTime, materials);
MaterialInTransit(material,"",orderMaterial,needed,earliestStartTime, materials, commitChanges);
needed -= orderMaterial.getUseTransit();
......@@ -1266,7 +1304,7 @@ public class MaterialRequirementService {
break;
}
MaterialInTransit(material1,rsr.getMaterialid(),orderMaterial1,needed,earliestStartTime, materials);
MaterialInTransit(material1,rsr.getMaterialid(),orderMaterial1,needed,earliestStartTime, materials, commitChanges);
needed -= orderMaterial1.getUseTransit();
......@@ -1283,7 +1321,9 @@ public class MaterialRequirementService {
if (needed <= 0) {
orderMaterial.setYpQty(allneeded - needed);
orderMaterial.setQjQty(needed);
remove.add(orderMaterial);
if(commitChanges) {
remove.add(orderMaterial);
}
continue;
}
if (needed > 0) {
......@@ -1303,8 +1343,8 @@ public class MaterialRequirementService {
MaterialPurchase result = materialPurchaseList.get(randomSeq);
orderMaterial.setCheckLeadTime(result.getPurchaseCycle());
orderMaterial.setPurchaseTime(result.getInspectionCycle());
orderMaterial.setPurchaseTime(result.getPurchaseCycle());
orderMaterial.setCheckLeadTime(result.getInspectionCycle());
LocalDateTime purchaseEndTime = baseTime.plusDays(orderMaterial.getPurchaseTime() + orderMaterial.getCheckLeadTime());
orderMaterial.setPurchaseEndTime(purchaseEndTime);
}
......@@ -1315,9 +1355,11 @@ public class MaterialRequirementService {
List<Integer> orderids= orderMaterial.getProductOrderID();
if(orderids!=null&&orderids.size()>0) {
for (Integer orderid : orderids) {
coder.ClearorderOperationResult(chromosome, orderid);
coder.EditorderOperation(chromosome, orderid, needed,machineTasksCache, entryIndexById, scheduleIndexById);
if(commitChanges) {
for (Integer orderid : orderids) {
coder.ClearorderOperationResult(chromosome, orderid);
coder.EditorderOperation(chromosome, orderid, needed,machineTasksCache, entryIndexById, scheduleIndexById);
}
}
}else {
......@@ -1328,14 +1370,16 @@ public class MaterialRequirementService {
MaterialPurchase result = materialPurchaseList.get(randomSeq);
orderMaterial.setCheckLeadTime(result.getPurchaseCycle());
orderMaterial.setPurchaseTime(result.getInspectionCycle());
orderMaterial.setPurchaseTime(result.getPurchaseCycle());
orderMaterial.setCheckLeadTime(result.getInspectionCycle());
LocalDateTime purchaseEndTime = baseTime.plusDays(orderMaterial.getPurchaseTime() + orderMaterial.getCheckLeadTime());
orderMaterial.setPurchaseEndTime(purchaseEndTime);
}
}
}
orderMaterial.getReplaceMaterial().removeIf(t->t.getUseStock()==0&&t.getUseTransit()==0);
if(commitChanges) {
orderMaterial.getReplaceMaterial().removeIf(t->t.getUseStock()==0&&t.getUseTransit()==0);
}
}
// 计算预计可用时间
......@@ -1357,7 +1401,7 @@ public class MaterialRequirementService {
}
if (remove != null&&remove.size()>0) {
if (commitChanges && remove != null&&remove.size()>0) {
//删除先删排产结果,然后记录orderID,到排产方案里,最后一起删除
for (OrderMaterialRequirement mr:remove) {
List<Integer> orderids= mr.getProductOrderID();
......@@ -1374,11 +1418,10 @@ public class MaterialRequirementService {
private void MaterialInTransit(Material material,String materialId, OrderMaterialRequirement orderMaterial, double needed,LocalDateTime earliestStartTime, List<Material> materials ){
private void MaterialInTransit(Material material,String materialId, OrderMaterialRequirement orderMaterial, double needed,LocalDateTime earliestStartTime, List<Material> materials, boolean commitChanges ){
// 处理在途物料
double accumulated = 0;
LocalDateTime earliestTime = LocalDateTime.of(2000,1,1,0,0,0);
LocalDateTime earliestTime = null;
double useTransit = 0;
if (material == null) {
material = materials.stream()
......@@ -1390,18 +1433,24 @@ public class MaterialRequirementService {
}
}
// 按到货时间排序在途物料
Long CkeckLeadTime= material.getCkeckLeadTime();
List<MaterialSupply> sortedInTransit = material.getInTransit().stream()
.filter(t -> t.getQuantity() > 0&&t.getArrivalTime().compareTo(earliestStartTime)<=0 )
.sorted(Comparator.comparing(MaterialSupply::getArrivalTime).reversed())
.filter(t -> t.getQuantity() > 0)
.sorted(Comparator.comparing(MaterialSupply::getArrivalTime, Comparator.nullsLast(LocalDateTime::compareTo)))
.collect(Collectors.toList());
for (MaterialSupply supply : sortedInTransit) {
double useq = Math.min(needed, supply.getQuantity());
if (useq <= 0) {
continue;
}
useTransit += useq;
needed -= useq;
supply.setQuantity(supply.getQuantity() - useq);
earliestTime=earliestTime.compareTo(supply.getArrivalTime())>0?earliestTime:supply.getArrivalTime();
if(commitChanges) {
supply.setQuantity(supply.getQuantity() - useq);
}
if (earliestTime == null || (supply.getArrivalTime() != null && supply.getArrivalTime().isAfter(earliestTime))) {
earliestTime = supply.getArrivalTime();
}
if (needed <= 0) {
break;
}
......
......@@ -19,7 +19,7 @@ public class NSGAIIUtils {
private int taskCount; // 并行任务数(默认=CPU核心数)
private GlobalParam globalParam; // 全局参数配置
// true 越小越好
private boolean[] isMinimize = {true, true, true, true, true};
private boolean[] isMinimize = {true, true, true, true, true, true};
......@@ -627,7 +627,8 @@ public class NSGAIIUtils {
for (int i = 0; i < kpisize; i++) {
final int idx = i;
if(isMinimize[i])
boolean minimize = i >= isMinimize.length || isMinimize[i];
if(minimize)
{
idealPoint[i] = front.stream().mapToDouble(c -> c.getObjectives()[idx]).min().orElse(0);
......
package com.aps.service.Algorithm;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GAScheduleResult;
import com.aps.entity.Algorithm.OrderMaterialRequirement;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.GlobalParam;
import com.aps.entity.basic.Material;
import com.aps.entity.Stock;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 缂栬緫鍚庣殑缁熶竴 JIT 鍚庡鐞嗭細
* 鍏堜繚璇佸彲琛岋紝鍐嶆妸鍙楀奖鍝嶇殑鍗婃垚鍝佸皬鑼冨洿寰€鍚庢媺锛屽敖閲忚创杩戞柊鐨勭墿鏂欓渶姹傚伐搴忓紑宸ユ椂闂淬€?
*/
public class PostEditJitService {
public boolean applyPostEditJitBias(Chromosome chromosome, GlobalParam globalParam) {
clearTemporaryJitBias(chromosome);
if (chromosome == null
|| chromosome.getAllOperations() == null
|| chromosome.getAllOperations().isEmpty()
|| chromosome.getResult() == null
|| chromosome.getResult().isEmpty()) {
return false;
}
Map<Integer, GAScheduleResult> currentResults = chromosome.getResult().stream()
.collect(Collectors.toMap(GAScheduleResult::getOperationId, r -> r, (left, right) -> right));
Map<Integer, GAScheduleResult> previousResults = chromosome.getResultOld() == null
? Collections.emptyMap()
: chromosome.getResultOld().stream()
.collect(Collectors.toMap(GAScheduleResult::getOperationId, r -> r, (left, right) -> right));
Map<Integer, List<Entry>> operationsByGroup = chromosome.getAllOperations().stream()
.collect(Collectors.groupingBy(Entry::getGroupId));
Map<String, Material> materialsById = chromosome.getMaterials() == null
? Collections.emptyMap()
: chromosome.getMaterials().stream()
.collect(Collectors.toMap(Material::getId, m -> m, (left, right) -> left));
Map<Integer, Set<Integer>> childGroupsByParentOp = buildChildGroupIndex(chromosome.getAllOperations());
if (childGroupsByParentOp.isEmpty()) {
return false;
}
int bufferSeconds = Math.max(0, globalParam.getSemiJitBufferMinutes()) * 60;
Map<Integer, Integer> pendingParentStarts = new HashMap<>();
ArrayDeque<Integer> queue = new ArrayDeque<>();
for (Map.Entry<Integer, GAScheduleResult> entry : currentResults.entrySet()) {
int operationId = entry.getKey();
if (!isOperationChanged(entry.getValue(), previousResults.get(operationId))) {
continue;
}
if (!childGroupsByParentOp.containsKey(operationId) || childGroupsByParentOp.get(operationId).isEmpty()) {
continue;
}
pendingParentStarts.put(operationId, entry.getValue().getStartTime());
queue.offer(operationId);
}
if (queue.isEmpty()) {
return false;
}
boolean updated = false;
while (!queue.isEmpty()) {
Integer parentOperationId = queue.poll();
Integer parentStartTime = pendingParentStarts.get(parentOperationId);
if (parentStartTime == null) {
continue;
}
Set<Integer> childGroupIds = childGroupsByParentOp.get(parentOperationId);
if (childGroupIds == null || childGroupIds.isEmpty()) {
continue;
}
for (Integer childGroupId : childGroupIds) {
List<Entry> childOperations = operationsByGroup.get(childGroupId);
if (childOperations == null || childOperations.isEmpty()) {
continue;
}
int currentGroupStart = Integer.MAX_VALUE;
int currentGroupEnd = Integer.MIN_VALUE;
boolean allScheduled = true;
for (Entry childOperation : childOperations) {
GAScheduleResult childResult = currentResults.get(childOperation.getId());
if (childResult == null) {
allScheduled = false;
break;
}
currentGroupStart = Math.min(currentGroupStart, childResult.getStartTime());
currentGroupEnd = Math.max(currentGroupEnd, childResult.getEndTime());
}
if (!allScheduled || currentGroupEnd < currentGroupStart) {
continue;
}
Entry firstChildOperation = childOperations.stream()
.min(Comparator.comparingInt(Entry::getSequence))
.orElse(null);
if (firstChildOperation == null) {
continue;
}
GAScheduleResult firstChildResult = currentResults.get(firstChildOperation.getId());
if (firstChildResult != null
&& (firstChildResult.isIsLocked() || firstChildResult.getLockStartTime() == 1)) {
continue;
}
int groupSpan = currentGroupEnd - currentGroupStart;
int preferredStartTime = Math.max(0, parentStartTime - bufferSeconds - groupSpan);
int effectivePreferredStart = preferredStartTime;
Integer latestStockBackedStart = resolveLatestStockBackedGroupStart(
childOperations, currentResults, materialsById, chromosome.getBaseTime(), currentGroupStart);
if (latestStockBackedStart != null) {
effectivePreferredStart = Math.min(effectivePreferredStart, latestStockBackedStart);
}
if (firstChildOperation.isJitTemporary() && firstChildOperation.getJitPreferredStartTime() != null) {
int existingPreferredStart = (int) ChronoUnit.SECONDS.between(
chromosome.getBaseTime(), firstChildOperation.getJitPreferredStartTime());
effectivePreferredStart = Math.min(existingPreferredStart, preferredStartTime);
if (latestStockBackedStart != null) {
effectivePreferredStart = Math.min(effectivePreferredStart, latestStockBackedStart);
}
}
if (effectivePreferredStart <= currentGroupStart) {
continue;
}
firstChildOperation.setJitPreferredStartTime(chromosome.getBaseTime().plusSeconds(effectivePreferredStart));
firstChildOperation.setJitTemporary(true);
updated = true;
int groupShift = effectivePreferredStart - currentGroupStart;
if (groupShift <= 0) {
continue;
}
for (Entry childOperation : childOperations) {
if (!childGroupsByParentOp.containsKey(childOperation.getId())
|| childGroupsByParentOp.get(childOperation.getId()).isEmpty()) {
continue;
}
GAScheduleResult childResult = currentResults.get(childOperation.getId());
if (childResult == null) {
continue;
}
int shiftedParentStart = childResult.getStartTime() + groupShift;
Integer existingTarget = pendingParentStarts.get(childOperation.getId());
if (existingTarget == null || shiftedParentStart > existingTarget) {
pendingParentStarts.put(childOperation.getId(), shiftedParentStart);
queue.offer(childOperation.getId());
}
}
}
}
return updated;
}
public void clearTemporaryJitBias(Chromosome chromosome) {
if (chromosome == null || chromosome.getAllOperations() == null) {
return;
}
for (Entry operation : chromosome.getAllOperations()) {
operation.setJitPreferredStartTime(null);
operation.setJitTemporary(false);
}
}
private boolean isOperationChanged(GAScheduleResult current, GAScheduleResult previous) {
if (current == null) {
return false;
}
if (previous == null) {
return true;
}
return current.getStartTime() != previous.getStartTime()
|| current.getEndTime() != previous.getEndTime()
|| current.getMachineId() != previous.getMachineId();
}
private Integer resolveLatestStockBackedGroupStart(List<Entry> childOperations,
Map<Integer, GAScheduleResult> currentResults,
Map<String, Material> materialsById,
LocalDateTime baseTime,
int currentGroupStart) {
Integer latestGroupStart = null;
for (Entry childOperation : childOperations) {
GAScheduleResult childResult = currentResults.get(childOperation.getId());
if (childResult == null || childOperation.getMaterialRequirements() == null || childOperation.getMaterialRequirements().isEmpty()) {
continue;
}
int opOffset = childResult.getStartTime() - currentGroupStart;
for (OrderMaterialRequirement requirement : childOperation.getMaterialRequirements()) {
if (requirement == null || requirement.getUseStock() <= 0 || !"MP".equals(requirement.getMaterialTypeName())) {
continue;
}
Material material = materialsById.get(requirement.getMaterialId());
Integer latestOpStart = resolveLatestStockBackedOperationStart(material, requirement.getUseStock(), baseTime);
if (latestOpStart == null) {
continue;
}
int candidateGroupStart = latestOpStart - opOffset;
latestGroupStart = latestGroupStart == null
? candidateGroupStart
: Math.min(latestGroupStart, candidateGroupStart);
}
}
return latestGroupStart;
}
private Integer resolveLatestStockBackedOperationStart(Material material, double useStockQty, LocalDateTime baseTime) {
if (material == null || material.getMaterialStocks() == null || material.getMaterialStocks().isEmpty() || useStockQty <= 0) {
return null;
}
double remaining = useStockQty;
LocalDateTime earliestUsedExpiry = null;
List<Stock> stocks = material.getMaterialStocks().stream()
.filter(stock -> stock != null && stock.getTotal() - stock.getTotalLock() > 0)
.sorted(Comparator.comparing(Stock::getExpiryDate, Comparator.nullsLast(LocalDateTime::compareTo))
.thenComparing(Stock::getWarehousingDate, Comparator.nullsLast(LocalDateTime::compareTo)))
.collect(Collectors.toList());
for (Stock stock : stocks) {
double usableQty = stock.getTotal() - stock.getTotalLock();
if (usableQty <= 0) {
continue;
}
double consumeQty = Math.min(remaining, usableQty);
if (consumeQty <= 0) {
continue;
}
if (stock.getExpiryDate() != null) {
earliestUsedExpiry = earliestUsedExpiry == null || stock.getExpiryDate().isBefore(earliestUsedExpiry)
? stock.getExpiryDate()
: earliestUsedExpiry;
}
remaining -= consumeQty;
if (remaining <= 0) {
break;
}
}
if (earliestUsedExpiry == null) {
return null;
}
return (int) ChronoUnit.SECONDS.between(baseTime, earliestUsedExpiry);
}
private Map<Integer, Set<Integer>> buildChildGroupIndex(Collection<Entry> operations) {
Map<Integer, Set<Integer>> childGroupsByParentOp = new HashMap<>();
for (Entry operation : operations) {
if (operation.getDependentOnOrderIds() != null) {
for (Integer childGroupId : operation.getDependentOnOrderIds()) {
if (childGroupId != null) {
childGroupsByParentOp
.computeIfAbsent(operation.getId(), key -> new HashSet<>())
.add(childGroupId);
}
}
}
if (operation.getTargetFinishedOperationId() != null) {
for (Integer parentOperationId : operation.getTargetFinishedOperationId()) {
if (parentOperationId != null) {
childGroupsByParentOp
.computeIfAbsent(parentOperationId, key -> new HashSet<>())
.add(operation.getGroupId());
}
}
}
}
return childGroupsByParentOp.entrySet().stream()
.filter(entry -> entry.getValue() != null && !entry.getValue().isEmpty())
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().stream()
.filter(Objects::nonNull)
.collect(Collectors.toSet())));
}
}
......@@ -1851,42 +1851,23 @@ if(targetOp.getSequence()>1) {
*/
public void redecode(Chromosome chromosome,LocalDateTime baseTime, GlobalParam globalParam)
{
List<Material> UseMaterials= materialRequirementService.GetMaterials(chromosome.getScenarioID());
chromosome.setMaterials(new ArrayList<>());
if(UseMaterials==null) {
if (chromosome.getMaterialIds() != null && chromosome.getMaterialIds().size() > 0) {
List<Material> Materials = planResultService.InitMaterial();
UseMaterials = Materials.stream()
.filter(t -> chromosome.getMaterialIds()
.contains(t.getId())).collect(Collectors.toList());
chromosome.setMaterials(UseMaterials);
materialRequirementService.SetMaterials(chromosome.getScenarioID(),UseMaterials);
}
}else {
chromosome.setMaterials(UseMaterials);
}
DelOrder(chromosome);
MachineSchedulerService machineScheduler = new MachineSchedulerService(baseTime);
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(chromosome.getInitMachines(),Machine.class) );
GeneticDecoder decoder = new GeneticDecoder(globalParam,baseTime, chromosome.getMachines(),
chromosome.getOrders(), null, machineScheduler,materialRequirementService,chromosome.getScenarioID());
List<Material> baseMaterialsSnapshot = resolveDecodeMaterials(chromosome);
chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(chromosome.getResult(),GAScheduleResult.class));
chromosome.getResult().clear();
CopyOnWriteArrayList<GAScheduleResult> Resultlock= chromosome.getResult().stream()
.filter(o -> o.isIsLocked() == true)
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
chromosome.setResult(ProductionDeepCopyUtil.deepCopyList(Resultlock,GAScheduleResult.class));
GeneticDecoder decoder = prepareDecodePass(chromosome, baseTime, globalParam, baseMaterialsSnapshot, true);
decoder.decode(chromosome,false);
PostEditJitService postEditJitService = new PostEditJitService();
try {
if (postEditJitService.applyPostEditJitBias(chromosome, globalParam)) {
chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(chromosome.getResult(),GAScheduleResult.class));
decoder = prepareDecodePass(chromosome, baseTime, globalParam, baseMaterialsSnapshot, false);
decoder.decode(chromosome,false, false);
}
} finally {
postEditJitService.clearTemporaryJitBias(chromosome);
}
KpiCalculator kpiCalculator=new KpiCalculator(chromosome);
kpiCalculator.calculatekpi();
......@@ -1907,6 +1888,47 @@ if(targetOp.getSequence()>1) {
}
private GeneticDecoder prepareDecodePass(Chromosome chromosome, LocalDateTime baseTime, GlobalParam globalParam,
List<Material> baseMaterialsSnapshot, boolean removeGeneratedOrders) {
if (removeGeneratedOrders) {
DelOrder(chromosome);
}
if (chromosome.getOrders() != null) {
chromosome.getOrders().forEach(order -> order.setCreateBom(false));
}
resetDecodeMaterials(chromosome, baseMaterialsSnapshot);
MachineSchedulerService machineScheduler = new MachineSchedulerService(baseTime);
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(chromosome.getInitMachines(),Machine.class) );
chromosome.getResult().clear();
chromosome.setResult(new CopyOnWriteArrayList<>());
return new GeneticDecoder(globalParam,baseTime, chromosome.getMachines(),
chromosome.getOrders(), null, machineScheduler,materialRequirementService,chromosome.getScenarioID());
}
private List<Material> resolveDecodeMaterials(Chromosome chromosome) {
List<Material> useMaterials = materialRequirementService.GetMaterials(chromosome.getScenarioID());
if (useMaterials == null && chromosome.getMaterialIds() != null && chromosome.getMaterialIds().size() > 0) {
List<Material> materials = planResultService.InitMaterial();
useMaterials = materials.stream()
.filter(t -> chromosome.getMaterialIds().contains(t.getId()))
.collect(Collectors.toList());
}
if (useMaterials == null) {
useMaterials = new ArrayList<>();
}
return ProductionDeepCopyUtil.deepCopyList(useMaterials, Material.class);
}
private void resetDecodeMaterials(Chromosome chromosome, List<Material> baseMaterialsSnapshot) {
List<Material> materialsForDecode = ProductionDeepCopyUtil.deepCopyList(baseMaterialsSnapshot, Material.class);
chromosome.setMaterials(materialsForDecode);
materialRequirementService.SetMaterials(chromosome.getScenarioID(), materialsForDecode);
}
public void DelOrder(Chromosome chromosome) {
List<Entry> allOperations = chromosome.getAllOperations();
List<GlobalOperationInfo> globalOpList= chromosome.getGlobalOpList();
......@@ -1914,7 +1936,7 @@ if(targetOp.getSequence()>1) {
List<Integer> OperationSequencing= chromosome.getOperationSequencing();
List<GAScheduleResult> ScheduleResults = chromosome.getResult();
List<Integer> newoorderids= orders.stream()
.filter(t->t.isNewCreate())
.filter(t -> t.isNewCreate() || t.isNewSfCreate())
.map(Order::getId)
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
......
......@@ -1867,6 +1867,7 @@ public class PlanResultService {
FileHelper.writeLogFile(String.format("Setup Time: %f minutes", schedule.getTotalChangeoverTime()));
FileHelper.writeLogFile(String.format("Flow Time: %f minutes", schedule.getTotalFlowTime()));
FileHelper.writeLogFile(String.format("Machine Load Balance: %.2f%%", schedule.getMachineLoadStd() * 100));
FileHelper.writeLogFile(String.format("Semi JIT Slack: %f minutes", schedule.getSemiJitSlack()));
FileHelper.writeLogFile("-------------------------");
// 按订单分组写入
......
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