Commit f1998b61 authored by Tong Li's avatar Tong Li

变邻域+模拟退火+禁忌搜索

parent 8a7de711
......@@ -156,6 +156,11 @@ public class Order {
* 是否新创建,默认值:false
*/
private boolean newCreate = false;
/**
* 是否新创建半成品,默认值:false
*/
private boolean newSfCreate = false;
/**
* 是否创建BOM,默认值:false
......
......@@ -35,13 +35,13 @@ import java.util.stream.IntStream;
public class GeneticDecoder {
// private final Map<String, Chromosome> decodingCache = new HashMap<>();
// private final Map<String, Chromosome> decodingCache = new HashMap<>();
private final ConcurrentHashMap<String, Chromosome> decodingCache = new ConcurrentHashMap<>();
// 缓存大小限制
private static final int MAX_CACHE_SIZE = 3000;
// 线程安全锁:避免多线程下缓存操作冲突(可选,若单线程可移除)
// private final ReentrantLock cacheLock = new ReentrantLock();
// private final ReentrantLock cacheLock = new ReentrantLock();
private LocalDateTime baseTime;
private final List<Machine> machines;
private final MachineSchedulerService machineScheduler;
......@@ -70,10 +70,10 @@ public class GeneticDecoder {
this.materials = materials;
this.machineScheduler = machineScheduler;
_globalParam=globalParam;
machineCalculator=new MachineCalculator(baseTime,machines,machineScheduler);
machineCalculator=new MachineCalculator(baseTime,machines,machineScheduler);
materialRequirementService=_materialRequirementService;
sceneId=_sceneId;
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
}
private final ExecutorService decodeExecutor = new ThreadPoolExecutor(
......@@ -266,7 +266,7 @@ public class GeneticDecoder {
Initialization initialization=new Initialization();
initialization.generateInitialSFPopulation(chromosome,globalOpList);
chromosome.getGlobalOpList().addAll(globalOpList);
return 1;
return 1;
}
private void CreateNewOpSequence(Chromosome chromosome)
......@@ -279,10 +279,10 @@ return 1;
.distinct()
.collect(Collectors.toList());
if(finishedOrder==null||finishedOrder.size()==0)
{
return;
}
if(finishedOrder==null||finishedOrder.size()==0)
{
return;
}
List<Integer> oldSequence=chromosome.getOperationSequencing();
List<Integer> finalSequence = new ArrayList<>();
......@@ -359,7 +359,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
}
finalSequence.add(orderid);
}else {
int insertPos = Math.max(0, finalSequence.size());
int insertPos = Math.max(0, finalSequence.size());
// int insertPos = Math.max(0, finalSequence.size() - rnd.nextInt(2));
finalSequence.add(insertPos,orderid);
......@@ -373,10 +373,10 @@ if(finishedOrder==null||finishedOrder.size()==0)
// // 根据工序数量和CPU核心数决定是否使用内部并行
if (isParallel) {
// 使用设备并行处理
// FileHelper.writeLogFile("使用并行处理 _s");
// FileHelper.writeLogFile("使用并行处理 _s");
parallelDecodeByMachine(chromosome);
// FileHelper.writeLogFile("使用并行处理 _e");
}
// FileHelper.writeLogFile("使用并行处理 _e");
}
else {
// 使用串行处理
// FileHelper.writeLogFile("使用串行处理 _s");
......@@ -391,14 +391,14 @@ if(finishedOrder==null||finishedOrder.size()==0)
public void serialDecode(Chromosome chromosome) {
// List<OrderMaterialRequirement> orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
List<OrderMaterialRequirement> orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
chromosome.setScenarioID(sceneId);
if(_globalParam.isIsCheckSf()) {
int isnew= generateGlobalOpList(chromosome);
int isnew= generateGlobalOpList(chromosome);
if(isnew==1) {
CreateNewOpSequence(chromosome);
}
if(isnew==1) {
CreateNewOpSequence(chromosome);
}
}
List<GlobalOperationInfo> globalOpList=chromosome.getGlobalOpList();
......@@ -486,7 +486,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
// Map<Long, String> machineState = chromosome.getMachines().stream()
// .collect(Collectors.toMap(Machine::getId, m -> ""));
// List<Entry> allScheduledOps = new ArrayList<>();
// List<Entry> allScheduledOps = new ArrayList<>();
// 缓存机器任务
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>();
......@@ -541,26 +541,26 @@ if(finishedOrder==null||finishedOrder.size()==0)
// }
// 上个离散参数
// String lastDiscreteParameter = machineState.get(machineId);
// String lastDiscreteParameter = machineState.get(machineId);
// int bomtime = getOperationBOMTime(currentOp,chromosome);
// int bomtime = getOperationBOMTime(currentOp,chromosome);
// int prevendtime=prevtime;
// prevtime = Math.max(prevtime, bomtime);
// int prevendtime=prevtime;
// prevtime = Math.max(prevtime, bomtime);
// Machine machine = chromosome.getMachines().stream()
// .filter(m -> m.getId() == machineId)
// .findFirst()
// .orElse(null);
// Machine machine = machineIdMap.get(machineId);
// int changeoverTime =0; //(lastDiscreteParameter.isEmpty() ||
// lastDiscreteParameter.equals(currentOp.getDiscreteParameter())) ? 0 : 0;
// Machine machine = machineIdMap.get(machineId);
// int changeoverTime =0; //(lastDiscreteParameter.isEmpty() ||
// lastDiscreteParameter.equals(currentOp.getDiscreteParameter())) ? 0 : 0;
int actualEndTime = processOperation(currentOp,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache,entryIndexById,scheduleIndexById);
// int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,machineOption, chromosome,false,prevendtime,machineTasksCache);
// int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,machineOption, chromosome,false,prevendtime,machineTasksCache);
orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);
orderLastEndTime.put(groupId, actualEndTime);
// machineState.put(machineId, currentOp.getDiscreteParameter());
// machineState.put(machineId, currentOp.getDiscreteParameter());
}
if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) {
chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t));
......@@ -837,17 +837,17 @@ if(finishedOrder==null||finishedOrder.size()==0)
double processTime = machineOption.getProcessingTime();
// 处理当前工序
// long processStartTime = System.currentTimeMillis();
// long processStartTime = System.currentTimeMillis();
int actualEndTime = processOperation(op,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache, entryIndexById,scheduleIndexById);
// long processEndTime = System.currentTimeMillis();
// long processEndTime = System.currentTimeMillis();
// 标记工序完成
synchronized (lock) {
opCompleted.put(opId, true);
}
// long opEndTime = System.currentTimeMillis();
// long opEndTime = System.currentTimeMillis();
// if (i % 100 == 0 || i == ops.size() - 1) {
// FileHelper.writeLogFile("设备 " + machineId + " 工序 " + i + "/" + ops.size() +
// " 完成,总耗时:" + (opEndTime - machineStartTime) + "ms,本工序耗时:" + (opEndTime - opStartTime) + "ms");
......@@ -973,8 +973,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
return result;
}
/**
* 构建工序ID索引:opId -> Entry(O(1)查找)
*/
* 构建工序ID索引:opId -> Entry(O(1)查找)
*/
private Map<Integer, Entry> buildOpIdIndex(Chromosome chromosome) {
Map<Integer, Entry> index = new HashMap<>();
for (Entry op : chromosome.getAllOperations()) {
......@@ -1014,7 +1014,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
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;
return actualEndTime;
}
......@@ -1037,7 +1037,7 @@ return actualEndTime;
}
if(machine==null||operation.getMachineOptions()==null)
{
return 0;
return 0;
}
// MachineOption machineOption= operation.getMachineOptions().stream()
......@@ -1063,7 +1063,7 @@ return actualEndTime;
//前处理,是否可以在相同任务前序未完工就开始设置时间,
// 就是 最早开工时间是否+前处理时间,总的加工工时不考虑前处理
if (!_globalParam.is_smoothSetup()) {
// 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理
// 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理
earliestStartTime+=preTime;
}
GAScheduleResult existingResult = chromosome.getResultOld().stream().filter(r-> r.getOperationId() == operation.getId()).findFirst().orElse(null);
......@@ -1077,18 +1077,18 @@ return actualEndTime;
if (machineTasksCache.containsKey(machine.getId())) {
machineTasks = machineTasksCache.get(machine.getId());
} else {
machineTasks = chromosome.getResult().stream()
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);
}
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());
......@@ -1105,8 +1105,8 @@ return actualEndTime;
if (_globalParam.is_smoothChangeOver()) {
Map<Integer, Object> reslte = calculateSetupTime(lastGeneOnMachine, operation, machine, earliestStartTime, processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), chromosome.getAllOperations());
// setupTime = (int) reslte.get(1);//换型时间
// int setupStartTime = (int) reslte.get(2);//换型开始时间
// setupTime = (int) reslte.get(1);//换型时间
// int setupStartTime = (int) reslte.get(2);//换型开始时间
//earliestStartTime=(int)reslte.get(3);//上个任务的结束时间
earliestStartTime = (int) reslte.get(4);//最早开工时间
}
......@@ -1121,7 +1121,7 @@ return actualEndTime;
: earliestStartTime;
}
bomtime= EditOperationBOMTime(operation,chromosome,earliestStartTime,machineTasksCache, entryIndexById, scheduleIndexById);
bomtime= EditOperationBOMTime(operation,chromosome,earliestStartTime,machineTasksCache, entryIndexById, scheduleIndexById);
if(bomtime>prevendtime&&bomtime<earliestStartTimeold)
......@@ -1211,9 +1211,9 @@ return actualEndTime;
//开工时间需往后延 2小时
// 准备工时 加入到加工时间里
// 准备工时 加入到加工时间里
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
GAScheduleResult result=new GAScheduleResult();
......@@ -1250,17 +1250,17 @@ return actualEndTime;
processingTimeTotal1=(int) geneDetails.stream().filter(t->t.getUsedSegment()==null).mapToDouble(ScheduleResultDetail::getProcessingTime) // 替换为实际字段名
.sum();
List<TimeSegment> UsedSegments=geneDetails.stream().
List<TimeSegment> UsedSegments=geneDetails.stream().
filter(t->t.getUsedSegment()!=null)
.map(ScheduleResultDetail::getUsedSegment).flatMap(List::stream)
// 收集为最终的 List
.collect(Collectors.toList());
// 收集为最终的 List
.collect(Collectors.toList());
if(UsedSegments!=null&&UsedSegments.size()>0)
{
processingTimeTotal1+=(int)UsedSegments.stream().mapToDouble(TimeSegment::getProcessingTime) // 替换为实际字段名
.sum();
}
if(UsedSegments!=null&&UsedSegments.size()>0)
{
processingTimeTotal1+=(int)UsedSegments.stream().mapToDouble(TimeSegment::getProcessingTime) // 替换为实际字段名
.sum();
}
result.setProcessingTime(processingTimeTotal1);
......@@ -1268,15 +1268,15 @@ return actualEndTime;
// System.out.println("huanxingshijian="+result.getChangeOverTime()+"-------------------"+result.getOrderId()+"--------"+result.getExecId()+"---------"+prev.getOrderId()+"--------"+prev.getExecId());
chromosome.getResult().add(result);
machine.setLastGene(result);
chromosome.getResult().add(result);
machine.setLastGene(result);
// FileHelper.writeLogFile(" 结束 "+ConvertTime(startTime)+"--"+ConvertTime(endTime)+" "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
// ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt());
if (machineTasks != null) {
machineTasks.add(result);
}
scheduleIndexById.put(operation.getId(),result);
scheduleIndexById.put(operation.getId(),result);
return endTime;
}
......@@ -1297,7 +1297,7 @@ return actualEndTime;
// .filter(t -> t.getOperationId() == opid.getPrevOperationId())
// .collect(Collectors.toList());//
GAScheduleResult prevOp= scheduleIndexById.get(opid.getPrevOperationId());
// for (GAScheduleResult prevOp : prevOperations) {
// for (GAScheduleResult prevOp : prevOperations) {
if(prevOp!=null){
//加上后处理时间
prevtime = Math.max(prevtime, prevOp.getEndTime() + currentOp.getTeardownTime());
......@@ -1320,14 +1320,14 @@ return actualEndTime;
// .collect(Collectors.toList());//多台
GAScheduleResult prevOp= scheduleIndexById.get(opid.getPrevOperationId());
// for (GAScheduleResult prevOp : prevOperations) {
// for (GAScheduleResult prevOp : prevOperations) {
if(prevOp!=null){
newScheduleResult.add(prevOp);
newScheduleResultDetails.addAll(prevOp.getGeneDetails());
}
if(j==SSOperations.size()-1)
{
int prevtime1 = CalSSPrevtime(newScheduleResult,newScheduleResultDetails, prevtime, currentOp, chromosome, processTime, machine);
int prevtime1 = CalSSPrevtime(newScheduleResult,newScheduleResultDetails, prevtime, currentOp, chromosome, processTime, machine);
prevtime = Math.max(prevtime, prevtime1);
}else {
......@@ -1344,7 +1344,7 @@ return actualEndTime;
if(entry!=null&&entry1!=null&&entry.getRoutingDetailId()!=entry1.getRoutingDetailId())
{
int prevtime1 = CalSSPrevtime(newScheduleResult,newScheduleResultDetails, prevtime, currentOp, chromosome, processTime, machine);
int prevtime1 = CalSSPrevtime(newScheduleResult,newScheduleResultDetails, prevtime, currentOp, chromosome, processTime, machine);
prevtime = Math.max(prevtime, prevtime1);
newScheduleResult.clear();
......@@ -1414,13 +1414,13 @@ return actualEndTime;
if (opboms != null && !opboms.isEmpty()) {
// 计算RawTime
Optional<LocalDateTime> rawDateOpt = opboms.stream()
.filter(t -> t.getMaterialTypeName().equals("MP"))
.map(OrderMaterialRequirement::getUseTime)
.max(LocalDateTime::compareTo);
if (rawDateOpt.isPresent()) {
rawTime = (int) Duration.between(baseTime, rawDateOpt.get()).getSeconds();
}
Optional<LocalDateTime> rawDateOpt = opboms.stream()
.filter(t -> t.getMaterialTypeName().equals("MP"))
.map(OrderMaterialRequirement::getUseTime)
.max(LocalDateTime::compareTo);
if (rawDateOpt.isPresent()) {
rawTime = (int) Duration.between(baseTime, rawDateOpt.get()).getSeconds();
}
......@@ -1474,9 +1474,9 @@ return actualEndTime;
{
return 0;
}
LocalDateTime earliestStartTime1=baseTime.plusSeconds(earliestStartTime);
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById);
return getOperationBOMTime(currentOp, chromosome);
LocalDateTime earliestStartTime1=baseTime.plusSeconds(earliestStartTime);
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById, baseTime);
return getOperationBOMTime(currentOp, chromosome);
}
......@@ -1574,12 +1574,12 @@ return getOperationBOMTime(currentOp, chromosome);
List<OrderMaterialRequirement> MaterialRequirements = currentOp.getMaterialRequirements().stream()
.filter(t->!"MP".equals(t.getMaterialTypeName())
&& t.getProductOrderID() != null && !t.getProductOrderID().isEmpty()
)
)
.collect(Collectors.toList());
if(MaterialRequirements==null||MaterialRequirements.size()==0)
{
continue;
}
if(MaterialRequirements==null||MaterialRequirements.size()==0)
{
continue;
}
for (OrderMaterialRequirement orderMaterial:MaterialRequirements) {
List<Integer> orderids= orderMaterial.getProductOrderID();
if(orderids!=null&&orderids.size()>0) {
......@@ -1619,7 +1619,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
List<OrderMaterialRequirement> orderMaterialRequirements= entry.getMaterialRequirements().stream().filter(t-> !"MP".equals(t.getMaterialTypeName())
&& t.getProductOrderID() != null && !t.getProductOrderID().isEmpty()
).collect(Collectors.toList());
).collect(Collectors.toList());
for (OrderMaterialRequirement mr:orderMaterialRequirements) {
List<Integer> orderids= mr.getProductOrderID();
if(orderids!=null&&orderids.size()>0) {
......@@ -1683,7 +1683,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
* @return 可开工时间
*/
private int calculateNextOperationStartTime(List<GAScheduleResult> results,List<ScheduleResultDetail> details, int startindex, double time2) {
double qty= results.stream().mapToDouble(GAScheduleResult::getQuantity) // 替换为实际字段名
double qty= results.stream().mapToDouble(GAScheduleResult::getQuantity) // 替换为实际字段名
.sum();
double time1 = 0.0;
......@@ -1705,7 +1705,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
if(results.size()>1) {//多前置工序
calculateWithMoreMachine(details, leadCount);
}
}
// 单设备时使用原逻辑
return (int)calculateWithSingleMachine(details, leadCount, time1);
}
......@@ -1762,10 +1762,10 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
//
// int minEndTimeForContinuity = prevEndTime - (int) ((qty - leadCount) * prevTimePerUnit);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, minEndTimeForContinuity);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, prevtime);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, minEndTimeForContinuity);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, prevtime);
// int totalProcessingTime = (int) (currentTimePerUnit * qty);
// int totalProcessingTime = (int) (currentTimePerUnit * qty);
// int continuityAdjustedTime = ensureContinuousProduction(machine, adjustedStartTime,
// totalProcessingTime, currentOp);
......@@ -1849,7 +1849,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
}
alldetails.stream().sorted(Comparator.comparingInt(ScheduleResultDetail::getStartTime));
int EndTime=0;
int EndTime=0;
double accumulatedQty = 0.0;
for (ScheduleResultDetail detail : alldetails) {
......@@ -1878,7 +1878,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
return EndTime;
}
/**
/**
* 多设备并行时计算满足提前量的最早时间
*/
private int calculateWithParallelMachines(List<ScheduleResultDetail> details, int leadCount, int time1) {
......@@ -2097,12 +2097,12 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
//01 16:00 +20 -01 16:00 02 12:00 08:00 -18:00 01 16:18 02 08:00-12:00
//01 16:00 +20 -01 16:00 02 12:00 08:00 -18:00 01 16:18 02 08:00-12:00
//01 16:00 +10 -01 16:00 换型10:00 08:00
//01 18:00 +10 -02 08:00<0 换型 休息时间满足
//01 18:00 +20 -02 08:00>0
//01 18:00 +10 -02 00:00>0
return reslte;
return reslte;
}else {
//开始时间加上设置时间重新算
//如果是前提供任务是相同的则跳出
......@@ -2141,7 +2141,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
{
return reslte;
}
// LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);
// LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);
GAScheduleResult lastGeneOnMachine=machineTasks.get(machineTasks.size()-1);
......@@ -2155,7 +2155,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
if(AvailableTimeSegment!=null) {
reslte.put(6,AvailableTimeSegment);
int start= (int) ChronoUnit.SECONDS.between(baseTime, AvailableTimeSegment.get(0).getStart());
int start= (int) ChronoUnit.SECONDS.between(baseTime, AvailableTimeSegment.get(0).getStart());
earliestStartTime= earliestStartTime>start ?earliestStartTime:start;
int earliestStartTime1=earliestStartTime;
......@@ -2196,14 +2196,14 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
Entry prev= _allOperations.stream().
Entry prev= _allOperations.stream().
filter(t->t.getExecId().equals(ExecId))
.findFirst().orElse(null);
int setupTime=0;
if(prev!=null)
{
//离散参数
// prev.getDiscreteParameter()
// prev.getDiscreteParameter()
// setupTime = (prev.getProductId() != operation.getProductId())
// ? (int) discreteParameterMatrixService.getDiscreteParameterMatrixValue(prev, operation)
......@@ -2225,7 +2225,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
}
// setupTime=20*3600;
// setupTime=20*3600;
operation.setChangeLineTime(setupTime);
if(setupTime==0)
{
......@@ -2244,20 +2244,20 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
{
cha=cha+1;//加1是工序开始加工时间
reslte.put(2,lastGeneOnMachine.getEndTime());//换型开始时间
// reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime+cha,processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), ExecId,reslte);
// reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime+cha,processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), ExecId,reslte);
}
else {
reslte.put(2,earliestStartTime-setupTime);//换型开始时间
//如果空余时间足够
//可能会往前或后暂用设备时间
return reslte;
return reslte;
}
}else {
//开始时间加上设置时间重新算
//如果是前提供任务是相同的则跳出
// reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime,processingTimeTotal+setupTime, _globalParam.is_smoothChangeOverInWeek(),ExecId,reslte);
// reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime,processingTimeTotal+setupTime, _globalParam.is_smoothChangeOverInWeek(),ExecId,reslte);
}
......@@ -2332,7 +2332,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
.filter(t -> orderIds.contains(t.getOrderId()))
.max(Comparator.comparing(Order::getDueDate))
.orElse(null);
if (order.isNewCreate()) {
if (order.isNewSfCreate()) {
continue;
}
LocalDateTime dueDateTime = order.getDueDate();
......@@ -2438,13 +2438,13 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
return chromosome.getGeneStr();
// 拼接机器选择:用 "," 分隔(例:1,3,2,4)
// String machineStr = chromosome.getMachineStr();
// String machineStr = chromosome.getMachineStr();
// 拼接工序排序:用 "|" 分隔(例:2|1|3|4)
// String operationStr = chromosome.getOperationStr();
// String operationStr = chromosome.getOperationStr();
// 组合最终键(用 "_" 分隔两部分,避免冲突)
// return machineStr + "_" + operationStr;
// return machineStr + "_" + operationStr;
}
}
......@@ -25,6 +25,10 @@ public class GeneticOperations {
private static ScheduleParams param;
public GeneticOperations() {
}
public GeneticOperations(GlobalParam globalParam,List<Entry> _allOperations,ScheduleParams _param) {
_GlobalParam=globalParam;
allOperations = _allOperations;
......@@ -424,10 +428,12 @@ public class GeneticOperations {
public void DelOrder(Chromosome chromosome) {
List<Entry> allOperations = chromosome.getAllOperations();
List<GlobalOperationInfo> globalOpList= chromosome.getGlobalOpList();
if(chromosome.getOrders()==null||chromosome.getOrders().size()==0)
return;
List<Order> orders = chromosome.getOrders();
List<Integer> OperationSequencing= chromosome.getOperationSequencing();
List<Integer> newoorderids= orders.stream()
.filter(t->t.isNewCreate())
.filter(t->t.isNewSfCreate())
.map(Order::getId)
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
......
......@@ -102,20 +102,20 @@ public class MaterialRequirementService {
.collect(Collectors.toList());
List<RoutingHeader> routingHeaders=null;
LambdaQueryWrapper<RoutingHeader> wrapper = new LambdaQueryWrapper<>();
wrapper.in(RoutingHeader::getId, routingIds);
LambdaQueryWrapper<RoutingHeader> wrapper = new LambdaQueryWrapper<>();
wrapper.in(RoutingHeader::getId, routingIds);
// .eq(RoutingHeader::getIsDeleted, 0)
// .eq(RoutingHeader::getApprovalStatus, 1);
routingHeaders = routingHeaderMapper.selectList(wrapper);
routingHeaders = routingHeaderMapper.selectList(wrapper);
List<Routingsupporting> routingsupportings=null;
// 查询并缓存Routingsupporting
LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>();
routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, routingIds)
.eq(Routingsupporting::getIsdeleted, 0);
routingsupportings = routingsupportingMapper.selectList(routingsupportingwrapper);
LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>();
routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, routingIds)
.eq(Routingsupporting::getIsdeleted, 0);
routingsupportings = routingsupportingMapper.selectList(routingsupportingwrapper);
// 查询并缓存RoutingSupportingReplace
......@@ -126,10 +126,10 @@ public class MaterialRequirementService {
.distinct()
.collect(Collectors.toList());
LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>();
routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, routingsupportingids)
.eq(RoutingSupportingReplace::getIsdeleted, 0);
replaces = routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper);
LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>();
routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, routingsupportingids)
.eq(RoutingSupportingReplace::getIsdeleted, 0);
replaces = routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper);
}
List<Material> useMaterials=new ArrayList<>();
......@@ -145,7 +145,7 @@ public class MaterialRequirementService {
.collect(Collectors.toList());
String orderId= order.getOrderId();
String orderId= order.getOrderId();
if(MaterialRequirements!=null)
{
......@@ -174,12 +174,12 @@ public class MaterialRequirementService {
}
if(component.getSpentQty()==null)
{
throw new RuntimeException("配套数据有问题,需求数量为空,请检查数据,"+component.getMaterialNumber());
throw new RuntimeException("配套数据有问题,需求数量为空,请检查数据,"+component.getMaterialNumber());
}
double allneeded = component.getSpentQty().doubleValue()/ component.getMainQty().doubleValue() * operation.getQuantity();
OrderMaterialRequirement orderMaterialRequirement = CreateMaterialRequirement(material, orderId, "", operation,
allneeded,component.getSpentQty().doubleValue(), component.getMainQty().doubleValue(),operation.getQuantity());
allneeded,component.getSpentQty().doubleValue(), component.getMainQty().doubleValue(),operation.getQuantity(),baseTime);
orderMaterialRequirement.setBomId(component.getStrId());
if (!material.getMaterialTypeName().equals("MP") && isIsCheckSf) {
materialIds.add(materialId);//半成品ID
......@@ -276,76 +276,76 @@ public class MaterialRequirementService {
LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>();
routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, routingIds)
.eq(Routingsupporting::getIsdeleted, 0);
LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>();
routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, routingIds)
.eq(Routingsupporting::getIsdeleted, 0);
routingsupportings1 = routingsupportingMapper.selectList(routingsupportingwrapper);
if(routingsupportings1!=null&&routingsupportings1.size()>0)
{
routingsupportings1 = routingsupportingMapper.selectList(routingsupportingwrapper);
if(routingsupportings1!=null&&routingsupportings1.size()>0)
{
routingsupportings.addAll(routingsupportings1);
List<String> routingsupportingids = routingsupportings1.stream()
.map(Routingsupporting::getStrId)
.distinct()
.collect(Collectors.toList());
List<String> routingsupportingids = routingsupportings1.stream()
.map(Routingsupporting::getStrId)
.distinct()
.collect(Collectors.toList());
LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>();
routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, routingsupportingids)
.eq(RoutingSupportingReplace::getIsdeleted, 0);
LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>();
routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, routingsupportingids)
.eq(RoutingSupportingReplace::getIsdeleted, 0);
routingsupportingreplaces1 = routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper);
routingsupportingreplaces1 = routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper);
routingsupportingreplaces.addAll(routingsupportingreplaces1);
routingsupportingreplaces.addAll(routingsupportingreplaces1);
List<String> materialIds=new ArrayList<>();
for (Routingsupporting routingsupporting:routingsupportings1) {
String materialID1= routingsupporting.getMaterialId();
Material material = _materials.stream()
.filter(m -> m.getId().equals(materialID1))
.findFirst()
.orElse(null);
if (material != null) {
if(!useMaterialids.contains(materialID1)) {
useMaterials.add(material);
useMaterialids.add(materialID1);
}
if(!material.getMaterialTypeName().equals("MP")) {
materialIds.add(materialID1);
}
}
}
for (RoutingSupportingReplace routingSupportingReplace:routingsupportingreplaces1) {
String materialID1= routingSupportingReplace.getMaterialid();
if(!useMaterialids.contains(materialID1)) {
List<String> materialIds=new ArrayList<>();
for (Routingsupporting routingsupporting:routingsupportings1) {
String materialID1= routingsupporting.getMaterialId();
Material material = _materials.stream()
.filter(m -> m.getId().equals(materialID1))
.findFirst()
.orElse(null);
if (material != null) {
useMaterials.add(material);
useMaterialids.add(materialID1);
if(!useMaterialids.contains(materialID1)) {
useMaterials.add(material);
useMaterialids.add(materialID1);
}
if(!material.getMaterialTypeName().equals("MP")) {
materialIds.add(materialID1);
}
}
}
}
Map<Integer,Object> r1=preloadSfRoutingBomCache(materialIds, headers, routingsupportings, routingsupportingreplaces);
List<Long> routingIds2=(List<Long>) r1.get(1);
List<Material> useMaterials2=( List<Material>) r1.get(2);
if(routingIds2!=null)
{
routingIds.addAll(routingIds2);
}
if(useMaterials2!=null&&useMaterials2.size()>0) {
for (Material m:useMaterials2) {
String materialID1= m.getId();
for (RoutingSupportingReplace routingSupportingReplace:routingsupportingreplaces1) {
String materialID1= routingSupportingReplace.getMaterialid();
if(!useMaterialids.contains(materialID1)) {
useMaterials.add(m);
useMaterialids.add(materialID1);
Material material = _materials.stream()
.filter(m -> m.getId().equals(materialID1))
.findFirst()
.orElse(null);
if (material != null) {
useMaterials.add(material);
useMaterialids.add(materialID1);
}
}
}
Map<Integer,Object> r1=preloadSfRoutingBomCache(materialIds, headers, routingsupportings, routingsupportingreplaces);
List<Long> routingIds2=(List<Long>) r1.get(1);
List<Material> useMaterials2=( List<Material>) r1.get(2);
if(routingIds2!=null)
{
routingIds.addAll(routingIds2);
}
if(useMaterials2!=null&&useMaterials2.size()>0) {
for (Material m:useMaterials2) {
String materialID1= m.getId();
if(!useMaterialids.contains(materialID1)) {
useMaterials.add(m);
useMaterialids.add(materialID1);
}
}
}
}
}
}
if(routingIds1!=null)
{
......@@ -392,7 +392,7 @@ public class MaterialRequirementService {
List<PlanResource> list =GetPlanResources();
Map<Integer, PlanResource> planResourceByReferenceIdMap = list.stream()
Map<Integer, PlanResource> planResourceByReferenceIdMap = list.stream()
.filter(pr -> pr.getReferenceId() != null)
.collect(Collectors.toMap(PlanResource::getReferenceId, Function.identity()));
......@@ -416,7 +416,7 @@ public class MaterialRequirementService {
List<Equipinfo> matchedEquipments = equipinfoByEquipTypeMap.get(machineId.intValue());
if (matchedEquipments == null || matchedEquipments.isEmpty()) {
throw new RuntimeException(String.format("未找到machineId=%d对应的设备信息", machineId));
throw new RuntimeException(String.format("未找到machineId=%d对应的设备信息", machineId));
}
......@@ -477,7 +477,7 @@ public class MaterialRequirementService {
.distinct()
.collect(Collectors.toList());
routingDiscreteParams = _routingDiscreteParamService.lambdaQuery()
routingDiscreteParams = _routingDiscreteParamService.lambdaQuery()
.in(RoutingDiscreteParam::getRoutingDetailId, routingDetailIds)
.eq(RoutingDiscreteParam::getIsDeleted, 0)
.list();
......@@ -503,8 +503,6 @@ public class MaterialRequirementService {
* @return 所有物料需求列表
*/
public List<OrderMaterialRequirement> buildMultiLevelRequirementNetwork(Chromosome chromosome,String sceneId, LocalDateTime _baseTime,GlobalParam _globalParam) {
baseTime=_baseTime;
globalParam=_globalParam;
List<OrderMaterialRequirement> allRequirements = new ArrayList<>();
List<Order> childorders = new ArrayList<>();
List<Entry> _newEntrys = new ArrayList<>();
......@@ -519,13 +517,13 @@ public class MaterialRequirementService {
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> 0));
List<Integer> operationSequencing=chromosome.getOperationSequencing();
List<Integer> operationSequencing= new ArrayList<>(chromosome.getOperationSequencing());
orders.forEach(t->clearFinishOrder(t));
for (Integer groupId : operationSequencing)
{
Order demand=orders.stream().filter(t->t.getId()==groupId).findFirst().orElse(null);
Order demand=orders.stream().filter(t->t.getId()==groupId).findFirst().orElse(null);
if (demand.getFinishOrderId() != null && !demand.getFinishOrderId().isEmpty()) {
continue;
......@@ -546,7 +544,7 @@ public class MaterialRequirementService {
// 调用BuildOperationBOM方法(返回结果对象替代out参数)
BOMBuildResult operationResult = buildOperationSFBOM(operation.getOrderId(), "",
operation.getQuantity(), operation, 1,demand,sceneId,chromosome);
operation.getQuantity(), operation, 1,demand,sceneId,chromosome,_baseTime,_globalParam);
// // 合并物料需求和子订单
if(operationResult!=null) {
allRequirements.addAll(operationResult.getMaterialRequirements());
......@@ -567,13 +565,13 @@ public class MaterialRequirementService {
return allRequirements;
}
private void clearFinishOrder (Order order)
{
if (order.getFinishOrderId() == null) {
order.setFinishOrderId(new ArrayList<>());
order.setTargetFinishedOperationId(new ArrayList<>());
private void clearFinishOrder (Order order)
{
if (order.getFinishOrderId() == null) {
order.setFinishOrderId(new ArrayList<>());
order.setTargetFinishedOperationId(new ArrayList<>());
}
}
}
/**
* 构建订单BOM
......@@ -586,10 +584,10 @@ private void clearFinishOrder (Order order)
* @return 包含物料需求列表和子订单列表的结果对象
*/
public BOMBuildResult buildOrderBOM(String sceneId,int parent, String materialID, String mainorderId,
String childorderId, double parentQuantity, int level,Order forder,int finishOpertionID,Chromosome chromosome) {
String childorderId, double parentQuantity, int level,Order forder,int finishOpertionID,Chromosome chromosome, LocalDateTime baseTime, GlobalParam globalParam) {
forder.setCreateBom(true);
List<RoutingHeader> headers=GetRoutingHeader(sceneId);
List<RoutingHeader> headers=GetRoutingHeader(sceneId);
RoutingHeader routingHeaders= headers.stream()
.filter(t->t.getId()==parent|| t.getMaterialId().equals(materialID))
.findFirst()
......@@ -604,7 +602,7 @@ private void clearFinishOrder (Order order)
List<Order> childorders2 = new ArrayList<>();
List<Entry> _newEntrys = new ArrayList<>();
List<Machine> _newMachines = new ArrayList<>();
// 遍历产品的工序,递归构建工序BOM
// 遍历产品的工序,递归构建工序BOM
List<Entry> _allOperations= chromosome.getAllOperations();
......@@ -615,7 +613,7 @@ private void clearFinishOrder (Order order)
if (Operations != null) {
if (Operations != null) {
for (Entry operation : Operations) {
if(finishOpertionID!=0)
{
......@@ -627,7 +625,7 @@ private void clearFinishOrder (Order order)
}
// 调用BuildOperationBOM方法(返回结果对象替代out参数)
BOMBuildResult operationResult = buildOperationBOM(mainorderId, childorderId,
parentQuantity, operation, level,forder,sceneId,chromosome);
parentQuantity, operation, level,forder,sceneId,chromosome, baseTime, globalParam);
// // 合并物料需求和子订单
if(operationResult!=null) {
materialRequirements.addAll(operationResult.getMaterialRequirements());
......@@ -650,7 +648,7 @@ private void clearFinishOrder (Order order)
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/
public BOMBuildResult buildOperationBOM(String orderId, String childorderId, double parentQuantity,
Entry operation, int level,Order forder,String sceneId,Chromosome chromosome) {
Entry operation, int level,Order forder,String sceneId,Chromosome chromosome, LocalDateTime baseTime, GlobalParam globalParam) {
List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
List<Order> _childorders = new ArrayList<>();
List<Entry> _newEntrys = new ArrayList<>();
......@@ -678,8 +676,8 @@ private void clearFinishOrder (Order order)
return null;
}
OrderMaterialRequirement orderMaterial= CreateMaterialRequirement(material,orderId,childorderId,operation,allneeded,component.getSpentQty().doubleValue(), component.getMainQty().doubleValue() , parentQuantity);
orderMaterial.setLevel(level);
OrderMaterialRequirement orderMaterial= CreateMaterialRequirement(material,orderId,childorderId,operation,allneeded,component.getSpentQty().doubleValue(), component.getMainQty().doubleValue() , parentQuantity, baseTime);
orderMaterial.setLevel(level);
orderMaterial.setBomId(component.getStrId());
materialRequirements.add(orderMaterial);
......@@ -713,8 +711,8 @@ private void clearFinishOrder (Order order)
BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
orderId, order.getOrderId(),
order.getQuantity(), l,order,operation.getId(),chromosome);
// materialRequirements.addAll(childResult.getMaterialRequirements());
order.getQuantity(), l,order,operation.getId(),chromosome, baseTime, globalParam);
// materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys());
operation.getDependentOnOrderIds().add(order.getId());
......@@ -743,7 +741,7 @@ private void clearFinishOrder (Order order)
childorder.setQuantity((int) orderMaterial.getQjQty());
childorder.setFinishOrderId(new ArrayList<>());
childorder.getFinishOrderId().add(forder.getId());
childorder.setNewCreate(true);
childorder.setNewSfCreate(true);
childorder.setTargetFinishedOperationId(new ArrayList<>());
childorder.getTargetFinishedOperationId().add(operation.getId());
childorder.setSerie(forder.getSerie());
......@@ -769,8 +767,8 @@ private void clearFinishOrder (Order order)
int l = level + 1;
BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
orderId, childorder.getOrderId(),
childorder.getQuantity(), l,childorder,0,chromosome);
// materialRequirements.addAll(childResult.getMaterialRequirements());
childorder.getQuantity(), l,childorder,0,chromosome, baseTime, globalParam);
// materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys());
}
......@@ -792,10 +790,10 @@ private void clearFinishOrder (Order order)
RoutingHeader headers1= headers.stream()
.filter(t->t.getMaterialId().equals(materialID))
.findFirst().orElse(null);
if(headers1==null)
{
return null;
}
if(headers1==null)
{
return null;
}
routingIds=headers1.getId().longValue();
......@@ -811,8 +809,8 @@ if(headers1==null)
}
List<RoutingDetailEquip> allroutingDetailEquips=GetRoutingDetailEquips(sceneId);
List<RoutingDetailEquip> routingDetailEquips= allroutingDetailEquips.stream()
.filter(t->t.getRoutingHeaderId().equals(headersid))
.collect(Collectors.toList());
.filter(t->t.getRoutingHeaderId().equals(headersid))
.collect(Collectors.toList());
......@@ -842,9 +840,9 @@ if(headers1==null)
List<RoutingDetailConnect> allroutingDetailconnections=GetRoutingDetailConnect(sceneId);
connections= allroutingDetailconnections.stream()
.filter(t->t.getRoutingHeaderId().equals(headersid))
.collect(Collectors.toList());
connections= allroutingDetailconnections.stream()
.filter(t->t.getRoutingHeaderId().equals(headersid))
.collect(Collectors.toList());
List<ProdOrderProcess> ProdOrderProcesslist= connections.stream()
......@@ -921,7 +919,7 @@ if(headers1==null)
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/
public BOMBuildResult buildOperationSFBOM(String orderId, String childorderId, double parentQuantity,
Entry operation, int level,Order forder,String sceneId,Chromosome chromosome) {
Entry operation, int level,Order forder,String sceneId,Chromosome chromosome, LocalDateTime baseTime, GlobalParam globalParam) {
List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
List<Order> _childorders = new ArrayList<>();
List<Entry> _newEntrys = new ArrayList<>();
......@@ -949,99 +947,99 @@ if(headers1==null)
// 查找物料(流式处理替代First)
if (!orderMaterial.getMaterialTypeName().equals("MP") ) {
if (!orderMaterial.getMaterialTypeName().equals("MP") ) {
// 处理半成品/成品的现有订单
// 为什么要先找现有订单,绑定上,因为要把它排在成品工单前面,才能有时间
List<Order> orders2 = orders.stream()
.filter(t -> t.getMaterialId().equals(orderMaterial.getMaterialId()) && t.getSYQuantity() > 0)
.sorted(Comparator.comparing(Order::getDueDate))
.collect(Collectors.toList());
// 处理半成品/成品的现有订单
// 为什么要先找现有订单,绑定上,因为要把它排在成品工单前面,才能有时间
List<Order> orders2 = orders.stream()
.filter(t -> t.getMaterialId().equals(orderMaterial.getMaterialId()) && t.getSYQuantity() > 0)
.sorted(Comparator.comparing(Order::getDueDate))
.collect(Collectors.toList());
if (!orders2.isEmpty()) {
for (Order order : orders2) {
if (order.getFinishOrderId() == null) {
order.setFinishOrderId(new ArrayList<>());
order.setTargetFinishedOperationId(new ArrayList<>());
}
order.getFinishOrderId().add(forder.getId());
order.getTargetFinishedOperationId().add(operation.getId());
orderMaterial.getProductOrderID().add(order.getId());
double useq = Math.min(needed, order.getSYQuantity());
needed -= useq;
order.setSYQuantity(order.getSYQuantity() - useq);
//防止已经生成过一次
if (!order.isCreateBom()) {
// 递归构建BOM
int l = level + 1;
BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
orderId, order.getOrderId(),
order.getQuantity(), l,order,operation.getId(),chromosome);
materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys());
operation.getDependentOnOrderIds().add(order.getId());
}
if (!orders2.isEmpty()) {
for (Order order : orders2) {
if (order.getFinishOrderId() == null) {
order.setFinishOrderId(new ArrayList<>());
order.setTargetFinishedOperationId(new ArrayList<>());
}
order.getFinishOrderId().add(forder.getId());
order.getTargetFinishedOperationId().add(operation.getId());
if (needed <= 0) {
break;
}
orderMaterial.getProductOrderID().add(order.getId());
double useq = Math.min(needed, order.getSYQuantity());
needed -= useq;
order.setSYQuantity(order.getSYQuantity() - useq);
//防止已经生成过一次
if (!order.isCreateBom()) {
// 递归构建BOM
int l = level + 1;
BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
orderId, order.getOrderId(),
order.getQuantity(), l,order,operation.getId(),chromosome, baseTime, globalParam);
materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys());
operation.getDependentOnOrderIds().add(order.getId());
}
}
// 更新已配和缺件数量
orderMaterial.setYpQty(allneeded - needed);
orderMaterial.setQjQty(needed);
if (needed > 0&&globalParam.isIsCheckSf()) {
// 创建新的子订单
Order childorder = new Order();
String OrderId = UUID.randomUUID().toString().replace("-", "");
childorder.setOrderId(OrderId);
childorder.setMaterialId(orderMaterial.getMaterialId());
childorder.setMaterialCode(orderMaterial.getMaterialCode());
childorder.setMaterialName(orderMaterial.getMaterialTypeName());
childorder.setOrderCode("M_"+orderMaterial.getMaterialCode());
childorder.setQuantity((int) orderMaterial.getQjQty());
childorder.setFinishOrderId(new ArrayList<>());
childorder.getFinishOrderId().add(forder.getId());
childorder.setNewCreate(true);
childorder.setTargetFinishedOperationId(new ArrayList<>());
childorder.getTargetFinishedOperationId().add(operation.getId());
childorder.setSerie(forder.getSerie());
childorder.setStartDate(forder.getStartDate());
childorder.setDueDate(forder.getDueDate());
childorder.setPriority(forder.getPriority());
childorder.setActualPriority(forder.getActualPriority());
Map<Integer, Object> list= CreateChild(sceneId,childorder,orderMaterial.getMaterialId(), operation.getId(),chromosome);
if(list==null)
{
continue;
if (needed <= 0) {
break;
}
_childorders.add(childorder);
List<Entry> newentrys=(List<Entry>)list.get(1);
_newEntrys.addAll(newentrys);
orderMaterial.getProductOrderID().add(childorder.getId());
operation.getDependentOnOrderIds().add(childorder.getId());
// 递归构建BOM
int l = level + 1;
BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
orderId, childorder.getOrderId(),
childorder.getQuantity(), l,childorder,0,chromosome);
materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys());
}
}
// 更新已配和缺件数量
orderMaterial.setYpQty(allneeded - needed);
orderMaterial.setQjQty(needed);
if (needed > 0&&globalParam.isIsCheckSf()) {
// 创建新的子订单
Order childorder = new Order();
String OrderId = UUID.randomUUID().toString().replace("-", "");
childorder.setOrderId(OrderId);
childorder.setMaterialId(orderMaterial.getMaterialId());
childorder.setMaterialCode(orderMaterial.getMaterialCode());
childorder.setMaterialName(orderMaterial.getMaterialTypeName());
childorder.setOrderCode("M_"+orderMaterial.getMaterialCode());
childorder.setQuantity((int) orderMaterial.getQjQty());
childorder.setFinishOrderId(new ArrayList<>());
childorder.getFinishOrderId().add(forder.getId());
childorder.setNewSfCreate(true);
childorder.setTargetFinishedOperationId(new ArrayList<>());
childorder.getTargetFinishedOperationId().add(operation.getId());
childorder.setSerie(forder.getSerie());
childorder.setStartDate(forder.getStartDate());
childorder.setDueDate(forder.getDueDate());
childorder.setPriority(forder.getPriority());
childorder.setActualPriority(forder.getActualPriority());
Map<Integer, Object> list= CreateChild(sceneId,childorder,orderMaterial.getMaterialId(), operation.getId(),chromosome);
if(list==null)
{
continue;
}
_childorders.add(childorder);
List<Entry> newentrys=(List<Entry>)list.get(1);
_newEntrys.addAll(newentrys);
orderMaterial.getProductOrderID().add(childorder.getId());
operation.getDependentOnOrderIds().add(childorder.getId());
// 递归构建BOM
int l = level + 1;
BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
orderId, childorder.getOrderId(),
childorder.getQuantity(), l,childorder,0,chromosome, baseTime, globalParam);
materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys());
}
}
}
}
......@@ -1061,7 +1059,7 @@ if(headers1==null)
orderMaterial.setMaterialName(material.getName());
orderMaterial.setMaterialTypeName(material.getMaterialTypeName());
orderMaterial.setMaterialId(material.getId());
// orderMaterial.setCheckLeadTime(material.getCkeckLeadTime());
// orderMaterial.setCheckLeadTime(material.getCkeckLeadTime());
double useStock=0;
// 扣减现有库存
List<Stock> stocks= material.getMaterialStocks().stream()
......@@ -1089,7 +1087,7 @@ if(headers1==null)
}
private OrderMaterialRequirement CreateMaterialRequirement(Material material,String orderId, String childorderId, Entry operation,double need,double spentQty,double mainQty,double qty) {
private OrderMaterialRequirement CreateMaterialRequirement(Material material,String orderId, String childorderId, Entry operation,double need,double spentQty,double mainQty,double qty, LocalDateTime baseTime) {
OrderMaterialRequirement orderMaterial = new OrderMaterialRequirement();
orderMaterial.setOrderId(orderId);
......@@ -1140,14 +1138,14 @@ if(headers1==null)
* @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) {
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) {
List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
String sceneId=chromosome.getScenarioID();
Random rnd = new Random();
List<OrderMaterialRequirement> MaterialRequirements= operation.getMaterialRequirements();
MaterialRequirements = MaterialRequirements.stream()
MaterialRequirements = MaterialRequirements.stream()
.sorted((a, b) -> {
// 定义判断条件:是否满足 非MP + 生产订单ID非空非空串
boolean aMatch = !"MP".equals(a.getMaterialTypeName())
......@@ -1228,12 +1226,12 @@ if(headers1==null)
if (orderMaterial1 != null) {
useStock = orderMaterial1.getUseStock();
needed -= useStock;
orderMaterial.setUseStock(orderMaterial.getUseStock() + useStock);
orderMaterial.getReplaceMaterial().add(orderMaterial1);
if (needed <= 0) {
break;
}
needed -= useStock;
orderMaterial.setUseStock(orderMaterial.getUseStock() + useStock);
orderMaterial.getReplaceMaterial().add(orderMaterial1);
if (needed <= 0) {
break;
}
}
}
......@@ -1247,7 +1245,7 @@ if(headers1==null)
continue;
}
MaterialInTransit(material,"",orderMaterial,needed,earliestStartTime);
MaterialInTransit(material,"",orderMaterial,needed,earliestStartTime, materials);
needed -= orderMaterial.getUseTransit();
......@@ -1268,7 +1266,7 @@ if(headers1==null)
break;
}
MaterialInTransit(material1,rsr.getMaterialid(),orderMaterial1,needed,earliestStartTime);
MaterialInTransit(material1,rsr.getMaterialid(),orderMaterial1,needed,earliestStartTime, materials);
needed -= orderMaterial1.getUseTransit();
......@@ -1315,27 +1313,27 @@ if(headers1==null)
// 处理半成品/成品的现有订单
List<Integer> orderids= orderMaterial.getProductOrderID();
if(orderids!=null&&orderids.size()>0) {
if(orderids!=null&&orderids.size()>0) {
for (Integer orderid : orderids) {
coder.ClearorderOperationResult(chromosome, orderid);
coder.EditorderOperation(chromosome, orderid, needed,machineTasksCache, entryIndexById, scheduleIndexById);
}
for (Integer orderid : orderids) {
coder.ClearorderOperationResult(chromosome, orderid);
coder.EditorderOperation(chromosome, orderid, needed,machineTasksCache, entryIndexById, scheduleIndexById);
}
}else {
List<MaterialPurchase> materialPurchaseList=material.getMaterialPurchases();
if(materialPurchaseList!=null&&materialPurchaseList.size()>0) {
}else {
List<MaterialPurchase> materialPurchaseList=material.getMaterialPurchases();
if(materialPurchaseList!=null&&materialPurchaseList.size()>0) {
int randomSeq = rnd.nextInt(materialPurchaseList.size());
int randomSeq = rnd.nextInt(materialPurchaseList.size());
MaterialPurchase result = materialPurchaseList.get(randomSeq);
MaterialPurchase result = materialPurchaseList.get(randomSeq);
orderMaterial.setCheckLeadTime(result.getPurchaseCycle());
orderMaterial.setPurchaseTime(result.getInspectionCycle());
LocalDateTime purchaseEndTime = baseTime.plusDays(orderMaterial.getPurchaseTime() + orderMaterial.getCheckLeadTime());
orderMaterial.setPurchaseEndTime(purchaseEndTime);
}
}
orderMaterial.setCheckLeadTime(result.getPurchaseCycle());
orderMaterial.setPurchaseTime(result.getInspectionCycle());
LocalDateTime purchaseEndTime = baseTime.plusDays(orderMaterial.getPurchaseTime() + orderMaterial.getCheckLeadTime());
orderMaterial.setPurchaseEndTime(purchaseEndTime);
}
}
}
orderMaterial.getReplaceMaterial().removeIf(t->t.getUseStock()==0&&t.getUseTransit()==0);
}
......@@ -1376,14 +1374,14 @@ if(headers1==null)
private void MaterialInTransit(Material material,String materialId, OrderMaterialRequirement orderMaterial, double needed,LocalDateTime earliestStartTime ){
private void MaterialInTransit(Material material,String materialId, OrderMaterialRequirement orderMaterial, double needed,LocalDateTime earliestStartTime, List<Material> materials ){
// 处理在途物料
double accumulated = 0;
LocalDateTime earliestTime = LocalDateTime.of(2000,1,1,0,0,0);
double useTransit = 0;
if (material == null) {
material = _materials.stream()
material = materials.stream()
.filter(m -> m.getId().equals(materialId))
.findFirst()
.orElse(null);
......
......@@ -894,7 +894,7 @@ public class MaterialRequirementServicebf {
childorder.setQuantity((int) orderMaterial.getQjQty());
childorder.setFinishOrderId(new ArrayList<>());
childorder.getFinishOrderId().add(forder.getId());
childorder.setNewCreate(true);
childorder.setNewSfCreate(true);
childorder.setTargetFinishedOperationId(new ArrayList<>());
childorder.getTargetFinishedOperationId().add(operation.getId());
childorder.setSerie(forder.getSerie());
......
......@@ -19,12 +19,60 @@ import java.util.stream.Collectors;
public class VariableNeighborhoodSearch {
private final Random rnd = new Random();
// ==================== 常量定义 ====================
private static final int MAX_CONSECUTIVE_SAME_STRATEGY = 3;
private static final int MAX_NEIGHBORHOODS = 7;
private static final double HIGH_PRIORITY_GROUP_PROBABILITY = 0.7;
private static final int MAX_ATTEMPTS = 50;
private static final int NEIGHBOR_SELECTION_TOP_K = 3;
private static final int MOVE_STEPS_MIN = 1;
private static final int MOVE_STEPS_MAX = 5;
private static final int NON_BOTTLENECK_MOVE_STEPS_MAX = 3;
private static final int RANDOM_NEIGHBOR_TYPE_COUNT = 5;
private static final double INITIAL_SUCCESS_RATE = 0.3;
private static final double LOW_SUCCESS_RATE_THRESHOLD = 0.1;
private static final int LOW_SUCCESS_RATE_MIN_TRIALS = 10;
private static final double EXPLORATION_BONUS_FOR_LOW_USE = 0.3;
private static final double EXPLORATION_BONUS_FOR_LOW_SUCCESS = 0.2;
private static final double RANDOM_NOISE_FACTOR = 0.15;
private static final double FORCE_ROTATE_PENALTY = 0.5;
private static final double PERCENTILE_90 = 0.90;
private static final double BOTTLENECK_MACHINE_BASE_SCORE = 10000;
private static final double WAIT_TIME_WEIGHT = 30;
private static final double MACHINE_WAIT_TIME_WEIGHT = 30;
private static final double CRITICAL_PATH_WEIGHT_ON_BOTTLENECK = 25;
private static final double CRITICAL_PATH_WEIGHT_OFF_BOTTLENECK = 20;
private static final double DELAY_CONTRIBUTION_WEIGHT_ON_BOTTLENECK = 15;
private static final double DELAY_CONTRIBUTION_WEIGHT_OFF_BOTTLENECK = 10;
private static final double NORMALIZATION_CAP = 1.5;
private static final int TOP_BOTTLENECK_OPS_TO_RETURN = 10;
private static final int TOP_MACHINES_TO_LOG = 5;
private static final double PRIORITY_EPSILON = 0.001;
private static final int MIN_USE_COUNT_FOR_EXPLORATION_BONUS = 5;
// 日志级别
private static final int LOG_LEVEL_DEBUG = 0;
private static final int LOG_LEVEL_INFO = 1;
private static final int LOG_LEVEL_WARN = 2;
private int currentLogLevel = LOG_LEVEL_INFO;
// 局部搜索优化
private static final int MAX_LOCAL_SEARCH_NEIGHBORS = 5;
private void log(String message) {
log(message, true);
log(message, LOG_LEVEL_INFO, false);
}
private void log(String message, boolean enableLogging) {
if (enableLogging) {
log(message, LOG_LEVEL_INFO, enableLogging);
}
private void log(String message, int level) {
log(message, level, false);
}
private void log(String message, int level, boolean enableLogging) {
if (enableLogging && level >= currentLogLevel) {
FileHelper.writeLogFile(message);
}
}
......@@ -51,7 +99,6 @@ public class VariableNeighborhoodSearch {
// 强制策略轮换:跟踪最后使用的策略
private int lastUsedStrategy = -1;
private int consecutiveSameStrategyCount = 0;
private static final int MAX_CONSECUTIVE_SAME_STRATEGY = 3; // 最多连续使用同一个策略3次
// 缓存的深拷贝列表,用于解码优化
private List<Machine> cachedMachines;
......@@ -60,6 +107,8 @@ public class VariableNeighborhoodSearch {
private List<Material> cachedMaterials;
private List<Entry> cachedAllOperations;
private GeneticOperations geneticOperations;
// 邻域结构成功率统计(用于 search() 方法)
private static class NeighborhoodWithStats {
NeighborhoodStructure structure;
......@@ -87,7 +136,7 @@ public class VariableNeighborhoodSearch {
public VariableNeighborhoodSearch( List<Entry> allOperations, List<Order> orders,
List<Material> materials,List<GroupResult> entryRel, FitnessCalculator fitnessCalculator) {
this(allOperations, orders, materials, entryRel, fitnessCalculator, 3);
this(allOperations, orders, materials, entryRel, fitnessCalculator, 1);
}
public VariableNeighborhoodSearch( List<Entry> allOperations, List<Order> orders,
......@@ -126,7 +175,7 @@ public class VariableNeighborhoodSearch {
for (NeighborhoodStructure ns : initialNeighborhoods) {
neighborhoodsWithStats.add(new NeighborhoodWithStats(ns));
}
geneticOperations=new GeneticOperations();
//log("VariableNeighborhoodSearch初始化: hasMultipleMachineOptions=" + hasMultipleMachineOptions);
}
......@@ -147,6 +196,12 @@ public class VariableNeighborhoodSearch {
//非瓶颈工序往后移动
neighborhoods.add(new NeighborhoodStructure("MoveNonBottleneckBackward", this::moveNonBottleneckBackwardWrapper));
//瓶颈设备工序激进重排
neighborhoods.add(new NeighborhoodStructure("AggressiveBottleneckReorder", this::aggressiveBottleneckReorderWrapper));
//关键路径工序优化
neighborhoods.add(new NeighborhoodStructure("CriticalPathOptimize", this::criticalPathOptimizeWrapper));
//// 交换相同设备的两个工序
neighborhoods.add(new NeighborhoodStructure("SwapSameMachine", this::generateSameMachineSwapNeighbor));
......@@ -176,7 +231,7 @@ public class VariableNeighborhoodSearch {
// result.add(ns.structure);
// }
int maxNeighborhoods = Math.min(7, sorted.size());
int maxNeighborhoods = Math.min(MAX_NEIGHBORHOODS, sorted.size());
for (int i = 0; i < maxNeighborhoods; i++) {
result.add(sorted.get(i).structure);
}
......@@ -218,7 +273,7 @@ public class VariableNeighborhoodSearch {
*/
public Chromosome search(Chromosome chromosome, GeneticDecoder decoder, List<Machine> machines) {
log("变邻域搜索 - 开始执行",true);
geneticOperations.DelOrder(chromosome);
// 深拷贝当前染色体
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
......@@ -276,7 +331,7 @@ public class VariableNeighborhoodSearch {
// 邻域移动
boolean success = isBetter(localBest, best);
if (success) {
best = ProductionDeepCopyUtil.deepCopy(localBest, Chromosome.class);
best = localBest;
writeKpi(best);
current = localBest;
k = 0; // 重置邻域索引
......@@ -554,7 +609,7 @@ public class VariableNeighborhoodSearch {
}
// 订单数相同时,按优先级排序
return Double.compare(entry2.getPriority(), entry1.getPriority());
return Double.compare(entry1.getPriority(), entry2.getPriority());
});
}
......@@ -1072,7 +1127,7 @@ public class VariableNeighborhoodSearch {
}
// 订单数相同时,按优先级排序
return Double.compare(entryB.getPriority(), entryA.getPriority());
return Double.compare(entryA.getPriority(), entryB.getPriority());
});
// 70%概率选择前3个候选,30%概率随机选择
......@@ -1131,7 +1186,8 @@ public class VariableNeighborhoodSearch {
}
/**
* 给指定位置的工序换设备
* 给指定位置的工序换设备 - 考虑设备负载均衡优化
* 优先选择负载低的设备
*/
private Chromosome generateMachineChangeForSpecificOp(Chromosome chromosome, List<MachineOption> machineOptions, int idx) {
Chromosome neighbor=copyChromosome(chromosome);// ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
......@@ -1147,7 +1203,8 @@ public class VariableNeighborhoodSearch {
}
if (!availableMachines.isEmpty()) {
int newMachineSeq = availableMachines.get(rnd.nextInt(availableMachines.size()));
// 选择负载较低的设备(设备负载均衡优化)
int newMachineSeq = selectMachineByLoad(availableMachines, machineOptions, chromosome);
ms.set(idx, newMachineSeq);
neighbor.setMachineSelection(ms);
}
......@@ -1247,7 +1304,7 @@ public class VariableNeighborhoodSearch {
}
// 订单数相同时,按优先级排序
int priorityCompare = Double.compare(entryB.getPriority(), entryA.getPriority());
int priorityCompare = Double.compare(entryA.getPriority(), entryB.getPriority());
if (priorityCompare != 0) {
return priorityCompare;
}
......@@ -1381,6 +1438,7 @@ public class VariableNeighborhoodSearch {
* 将工序往前移动
*/
private Chromosome moveOperationForward(Chromosome chromosome, Map<Integer, Entry> originalPositionIndex,int pos, int steps) {
geneticOperations.DelOrder(chromosome);
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
......@@ -1522,14 +1580,15 @@ public class VariableNeighborhoodSearch {
private Chromosome copyChromosome(Chromosome chromosome)
{
geneticOperations.DelOrder(chromosome);
Chromosome neighbor=new Chromosome();
neighbor.setID(UUID.randomUUID().toString());
neighbor.setOperationSequencing(chromosome.getOperationSequencing());
neighbor.setMachineSelection(chromosome.getMachineSelection());
neighbor.setOperationSequencing(new ArrayList<>(chromosome.getOperationSequencing()));
neighbor.setMachineSelection(new ArrayList<>(chromosome.getMachineSelection()));
neighbor.setScenarioID(chromosome.getScenarioID());
neighbor.setBaseTime(chromosome.getBaseTime());
neighbor.setFitnessLevel(chromosome.getFitnessLevel());
neighbor.setGlobalOpList(chromosome.getGlobalOpList());
neighbor.setGlobalOpList(new ArrayList<>(chromosome.getGlobalOpList()));
return neighbor;
}
......@@ -1722,14 +1781,17 @@ public class VariableNeighborhoodSearch {
if (op.getMachineOptions().size() > 1) {
int currentMachineSeq = ms.get(idx);
List<Integer> availableMachines = new ArrayList<>();
List<MachineOption> machineOptions = new ArrayList<>();
for (int i = 1; i <= op.getMachineOptions().size(); i++) {
if (i != currentMachineSeq) {
availableMachines.add(i);
machineOptions.add(op.getMachineOptions().get(i));
}
}
if (!availableMachines.isEmpty()) {
int newMachineSeq = availableMachines.get(rnd.nextInt(availableMachines.size()));
// 选择负载较低的设备(设备负载均衡优化)
int newMachineSeq = selectMachineByLoad(availableMachines, machineOptions, chromosome);
ms.set(idx, newMachineSeq);
neighbor.setMachineSelection(ms);
}
......@@ -1858,10 +1920,11 @@ public class VariableNeighborhoodSearch {
* 局部搜索
*/
private Chromosome localSearch(Chromosome chromosome, GeneticDecoder decoder, List<Machine> machines) {
geneticOperations.DelOrder(chromosome);
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
decode(decoder, best, machines);
//writeKpi(best);
writeKpi(best);
// 预定义邻域结构,避免每次循环重复创建
List<NeighborhoodStructure> neighborhoods = defineNeighborhoods();
......@@ -1869,9 +1932,14 @@ public class VariableNeighborhoodSearch {
while (improved) {
improved = false;
// 生成所有可能的邻域解
// 生成邻域解(限制数量以提高性能)
List<Chromosome> neighbors = new ArrayList<>();
for (NeighborhoodStructure neighborhood : neighborhoods) {
if (neighbors.size() >= MAX_LOCAL_SEARCH_NEIGHBORS) {
break;
}
Chromosome neighbor = generateNeighbor(current, neighborhood);
if (neighbor != null) {
neighbors.add(neighbor);
......@@ -1884,7 +1952,7 @@ public class VariableNeighborhoodSearch {
Batchdecode(decoder, neighbors, machines);
// 评估所有邻域解
// 评估所有邻域解,找到第一个改进就停止(贪心策略)
for (Chromosome neighbor : neighbors) {
if (neighbor != null && isBetter(neighbor, best)) {
......@@ -1892,6 +1960,7 @@ public class VariableNeighborhoodSearch {
writeKpi(best);
current = neighbor;
improved = true;
break; // 找到一个改进就退出,提高效率
}
}
}
......@@ -2105,4 +2174,309 @@ public class VariableNeighborhoodSearch {
return operator.apply(chromosome);
}
}
/**
* 机器选项和负载信息的辅助类
*/
private static class MachineOptionWithUtilization {
int seq;
MachineOption option;
double utilization;
MachineOptionWithUtilization(int seq, MachineOption option, double utilization) {
this.seq = seq;
this.option = option;
this.utilization = utilization;
}
}
/**
* 选择负载较低的设备 - 设备负载均衡优化
* 优先选择负载低的设备
*/
private int selectMachineByLoad(List<Integer> availableMachineSeqs, List<MachineOption> machineOptions, Chromosome chromosome) {
// 计算当前各设备的负载(利用率)
Map<Long, Double> machineUtilization = calculateMachineUtilization(chromosome);
// 构建可用机器列表,按负载从低到高排序
List<MachineOptionWithUtilization> availableMachines = new ArrayList<>();
for (int seq : availableMachineSeqs) {
MachineOption option = machineOptions.get(seq - 1);
Long machineId = option.getMachineId();
double utilization = machineUtilization.getOrDefault(machineId, 0.0);
availableMachines.add(new MachineOptionWithUtilization(seq, option, utilization));
}
// 按利用率从低到高排序
availableMachines.sort(Comparator.comparingDouble(m -> m.utilization));
// 70%概率选择负载最低的设备,30%概率随机选择
if (rnd.nextDouble() < 0.7) {
return availableMachines.get(0).seq;
} else {
return availableMachines.get(rnd.nextInt(availableMachines.size())).seq;
}
}
/**
* 交换候选对象,包含位置和评分(用于准备时间优化)
*/
private static class SwapCandidate {
int position;
double score;
SwapCandidate(int position, double score) {
this.position = position;
this.score = score;
}
}
/**
* 瓶颈设备工序激进重排 - Wrapper方法
*/
private Chromosome aggressiveBottleneckReorderWrapper(Chromosome chromosome) {
List<GAScheduleResult> results = chromosome.getResult();
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex = (Map<Integer, Entry>) obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>) obj.get(2);
Map<String, Integer> machinePositionIndex = buildEntryMachinePositionIndex(chromosome);
if (results == null || results.isEmpty()) {
return generateRandomNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
Long bottleneckMachineId = findBottleneckMachine(chromosome);
if (bottleneckMachineId != null) {
Chromosome result = tryAggressiveBottleneckReorder(chromosome, bottleneckMachineId, positionToEntryIndex, machinePositionIndex);
if (result != null) {
return result;
}
}
return generateRandomNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
/**
* 瓶颈设备工序激进重排 - 更激进地调整瓶颈设备上的工序顺序
* 策略:将延迟订单的工序和高优先级工序尽可能往前移动
*/
private Chromosome tryAggressiveBottleneckReorder(Chromosome chromosome, Long bottleneckMachineId,
Map<Integer, Entry> positionIndex,
Map<String, Integer> machinePositionIndex) {
log("tryAggressiveBottleneckReorder: 开始激进重排瓶颈设备工序");
List<GAScheduleResult> allResults = chromosome.getResult();
if (allResults == null || allResults.isEmpty()) {
return null;
}
// 获取瓶颈设备上的所有工序
List<GAScheduleResult> bottleneckOps = allResults.stream()
.filter(r -> r.getMachineId()==(bottleneckMachineId))
.collect(Collectors.toList());
if (bottleneckOps.size() < 2) {
log("tryAggressiveBottleneckReorder: 瓶颈设备上工序太少,无法重排");
return null;
}
// 计算订单完成时间
Map<Integer, Integer> orderCompletionTimes = calculateOrderCompletionTimes(allResults);
// 找出延迟订单(结束时间 > 到期时间,假设Entry有dueDate字段,这里简化为结束时间较晚的订单)
Set<Integer> delayedOrderIds = new HashSet<>();
int avgCompletionTime = (int) orderCompletionTimes.values().stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0);
for (Map.Entry<Integer, Integer> entry : orderCompletionTimes.entrySet()) {
if (entry.getValue() > avgCompletionTime * 1.2) { // 超过平均完成时间20%视为延迟
delayedOrderIds.add(entry.getKey());
}
}
Chromosome neighbor = copyChromosome(chromosome);
List<Integer> os = neighbor.getOperationSequencing();
// 对瓶颈设备上的工序进行评分
List<OperationScore> scoredOps = new ArrayList<>();
for (GAScheduleResult op : bottleneckOps) {
Entry entry = entrybyids.get(op.getOperationId());
if (entry == null) continue;
double score = 0;
// 1. 延迟订单的工序加分
if (delayedOrderIds.contains(op.getGroupId())) {
score += 100;
}
// 2. 高优先级工序加分(注意:priority值越低优先级越高)
score += (10.0 / (entry.getPriority() + 0.1)) * 50; // 优先级值越低,得分越高
// 3. 结束时间晚的工序加分(优先移动)
score += (double) op.getEndTime() / 10000;
String key = entry.getGroupId() + "_" + entry.getSequence();
Integer pos = buildPositionIndex(chromosome).get(key);
if (pos != null) {
scoredOps.add(new OperationScore(pos, score));
}
}
if (scoredOps.size() < 2) {
return null;
}
// 按评分从高到低排序
scoredOps.sort((a, b) -> Double.compare(b.score, a.score));
// 选择评分最高的工序,尝试往前移动
OperationScore selectedOp = scoredOps.get(0);
int steps = rnd.nextInt(Math.min(10, selectedOp.position)) + 1; // 最多往前移动10步
log(String.format("tryAggressiveBottleneckReorder: 选择位置%d,往前移动%d步", selectedOp.position, steps));
return insertOperationForward(neighbor, selectedOp.position, steps, entrys, positionIndex);
}
/**
* 工序评分辅助类
*/
private static class OperationScore {
int position;
double score;
OperationScore(int position, double score) {
this.position = position;
this.score = score;
}
}
/**
* 关键路径工序优化 - Wrapper方法
*/
private Chromosome criticalPathOptimizeWrapper(Chromosome chromosome) {
List<GAScheduleResult> results = chromosome.getResult();
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex = (Map<Integer, Entry>) obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>) obj.get(2);
if (results == null || results.isEmpty()) {
return generateRandomNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
Long bottleneckMachineId = findBottleneckMachine(chromosome);
Chromosome result = tryCriticalPathOptimize(chromosome, bottleneckMachineId, positionToEntryIndex);
if (result != null) {
return result;
}
return generateRandomNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
/**
* 关键路径工序优化 - 专门针对关键路径上的工序进行优化
* 策略:
* 1. 找出关键路径上的工序
* 2. 优先尝试将关键路径工序往前移动
* 3. 尝试为关键路径工序换设备(如果有选择)
*/
private Chromosome tryCriticalPathOptimize(Chromosome chromosome, Long bottleneckMachineId,
Map<Integer, Entry> positionIndex) {
log("tryCriticalPathOptimize: 开始关键路径工序优化");
List<GAScheduleResult> allResults = chromosome.getResult();
if (allResults == null || allResults.isEmpty()) {
return null;
}
// 分析瓶颈工序,获取关键路径信息
List<BottleneckOperationAnalysis> analyses = analyzeBottleneckOperations(allResults, bottleneckMachineId);
// 找出关键路径上的工序
List<BottleneckOperationAnalysis> criticalPathOps = analyses.stream()
.filter(a -> a.onCriticalPath)
.collect(Collectors.toList());
if (criticalPathOps.isEmpty()) {
log("tryCriticalPathOptimize: 没有找到关键路径工序");
return null;
}
log(String.format("tryCriticalPathOptimize: 找到%d个关键路径工序", criticalPathOps.size()));
Chromosome neighbor = copyChromosome(chromosome);
List<Integer> os = neighbor.getOperationSequencing();
// 对关键路径工序进行评分
List<CriticalPathOpScore> scoredOps = new ArrayList<>();
for (BottleneckOperationAnalysis boa : criticalPathOps) {
GAScheduleResult op = boa.operation;
Entry entry = entrybyids.get(op.getOperationId());
if (entry == null) continue;
double score = 0;
// 1. 在瓶颈设备上的关键工序加分
if (bottleneckMachineId != null && op.getMachineId()==(bottleneckMachineId)) {
score += 100;
}
// 2. 等待时间长的工序加分
score += boa.waitTime / 100.0;
// 3. 机器等待时间长的工序加分
score += boa.machineWaitTime / 100.0;
// 4. 高优先级加分(注意:priority值越低优先级越高)
score += (10.0 / (entry.getPriority() + 0.1)) * 30; // 优先级值越低,得分越高
String key = entry.getGroupId() + "_" + entry.getSequence();
Integer pos = buildPositionIndex(chromosome).get(key);
if (pos != null) {
scoredOps.add(new CriticalPathOpScore(pos, entry, score));
}
}
if (scoredOps.isEmpty()) {
return null;
}
// 按评分从高到低排序
scoredOps.sort((a, b) -> Double.compare(b.score, a.score));
CriticalPathOpScore selected = scoredOps.get(0);
// 50%概率尝试往前移动,50%概率尝试换设备(如果有选择)
if (rnd.nextDouble() < 0.5 && selected.position > 0) {
// 尝试往前移动
int steps = rnd.nextInt(Math.min(5, selected.position)) + 1;
log(String.format("tryCriticalPathOptimize: 关键路径工序往前移动%d步", steps));
return insertOperationForward(neighbor, selected.position, steps, entrys, positionIndex);
} else if (selected.entry.getMachineOptions().size() > 1) {
// 尝试换设备
log("tryCriticalPathOptimize: 关键路径工序尝试换设备");
Map<String, Integer> machinePositionIndex = buildEntryMachinePositionIndex(chromosome);
int maPos = machinePositionIndex.get(selected.entry.getGroupId() + "_" + selected.entry.getSequence());
if (maPos >= 0) {
return generateMachineChangeForSpecificOp(neighbor, selected.entry.getMachineOptions(), maPos);
}
}
// 如果以上都失败,尝试简单的往前移动
if (selected.position > 0) {
int steps = rnd.nextInt(Math.min(3, selected.position)) + 1;
return insertOperationForward(neighbor, selected.position, steps, entrys, positionIndex);
}
return null;
}
/**
* 关键路径工序评分辅助类
*/
private static class CriticalPathOpScore {
int position;
Entry entry;
double score;
CriticalPathOpScore(int position, Entry entry, double score) {
this.position = position;
this.entry = entry;
this.score = score;
}
}
}
\ No newline at end of file
......@@ -238,7 +238,7 @@ public class PlanResultService {
_sceneService.saveChromosomeToFile(chromosome, SceneId);
WriteScheduleSummary(chromosome);
// WriteScheduleSummary(chromosome);
return chromosome;
......
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