Commit f2a1529b authored by Tong Li's avatar Tong Li

Merge remote-tracking branch 'origin/tl'

parents bb00017a f1998b61
...@@ -32,6 +32,11 @@ public class Chromosome { ...@@ -32,6 +32,11 @@ public class Chromosome {
/// </summary> /// </summary>
private List<Integer> machineSelection; private List<Integer> machineSelection;
// 缓存标记
private transient boolean machineStrDirty = true;
private transient boolean operationStrDirty = true;
private transient boolean geneStrDirty = true;
/// <summary> /// <summary>
/// 工序排序部分(工件/订单ID) /// 工序排序部分(工件/订单ID)
/// </summary> /// </summary>
...@@ -43,32 +48,53 @@ public class Chromosome { ...@@ -43,32 +48,53 @@ public class Chromosome {
private String geneStr; private String geneStr;
public String getGeneStr() { public String getGeneStr() {
geneStr=getMachineStr()+"_"+getOperationStr(); if (geneStrDirty || machineStrDirty || operationStrDirty) {
return geneStr; geneStr = getMachineStr() + "_" + getOperationStr();
geneStrDirty = false;
}
return geneStr;
} }
private Integer gsOrls=0; private Integer gsOrls=0;
public String getMachineStr() { public String getMachineStr() {
if (machineStrDirty) {
machineStr= Optional.ofNullable(machineSelection) machineStr = Optional.ofNullable(machineSelection)
.orElse(Collections.emptyList()) .orElse(Collections.emptyList())
.stream() .stream()
.map(String::valueOf) // Integer转String .map(String::valueOf)
.collect(Collectors.joining(",")); .collect(Collectors.joining(","));
return machineStr; machineStrDirty = false;
geneStrDirty = true;
}
return machineStr;
} }
public String getOperationStr() { public String getOperationStr() {
if (operationStrDirty) {
operationStr = Optional.ofNullable(operationSequencing)
.orElse(Collections.emptyList())
.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
operationStrDirty = false;
geneStrDirty = true;
}
return operationStr;
}
// 重写 setter 方法,在设置时标记为脏
public void setMachineSelection(List<Integer> machineSelection) {
this.machineSelection = machineSelection;
this.machineStrDirty = true;
this.geneStrDirty = true;
}
operationStr= Optional.ofNullable(operationSequencing) public void setOperationSequencing(List<Integer> operationSequencing) {
.orElse(Collections.emptyList()) this.operationSequencing = operationSequencing;
.stream() this.operationStrDirty = true;
.map(String::valueOf) // Integer转String this.geneStrDirty = true;
.collect(Collectors.joining(","));
return operationStr;
} }
...@@ -105,7 +131,7 @@ public class Chromosome { ...@@ -105,7 +131,7 @@ public class Chromosome {
private List<String> materialIds; private List<String> materialIds;
/* /*
* 最早完工时间(最小化) 最小化总加工时间 最小总换型时间 * 最早完工时间(最小化) 最小化总加工时间 最小总换型时间
*/ */
private double[] Objectives ; // 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay] private double[] Objectives ; // 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay]
private double[] MaxObjectives ; // private double[] MaxObjectives ; //
...@@ -113,8 +139,8 @@ public class Chromosome { ...@@ -113,8 +139,8 @@ public class Chromosome {
private int Rank; // 非支配排序等级(1最优) private int Rank; // 非支配排序等级(1最优)
private double CrowdingDistance =0; // 拥挤距离 越小越优 private double CrowdingDistance =0; // 拥挤距离 越小越优
/* /*
*(Objectives - min) / (max - min); *(Objectives - min) / (max - min);
*/ */
private double[] WeightedObjectives;//越靠近1越优 private double[] WeightedObjectives;//越靠近1越优
private double WeightedObjective =0; // 加权目标值(用于自定义权重) private double WeightedObjective =0; // 加权目标值(用于自定义权重)
......
...@@ -15,7 +15,7 @@ public class ScheduleParams { ...@@ -15,7 +15,7 @@ public class ScheduleParams {
// 基础参数(自适应调整的基准值) // 基础参数(自适应调整的基准值)
private static final int MIN_POPULATION_SIZE = 10; private static final int MIN_POPULATION_SIZE = 10;
private static final int MAX_POPULATION_SIZE = 50; private static final int MAX_POPULATION_SIZE = 20;
private static final int MIN_MAX_ITERATIONS = 50; private static final int MIN_MAX_ITERATIONS = 50;
private static final int MAX_MAX_ITERATIONS = 100; private static final int MAX_MAX_ITERATIONS = 100;
private static final float MIN_CROSSOVER_PROB = 0.6f; private static final float MIN_CROSSOVER_PROB = 0.6f;
...@@ -172,10 +172,14 @@ public class ScheduleParams { ...@@ -172,10 +172,14 @@ public class ScheduleParams {
// 1. 种群大小:50 ~ 500,随工序数线性增加 // 1. 种群大小:50 ~ 500,随工序数线性增加
populationSize = (int) Math.max(MIN_POPULATION_SIZE, populationSize = (int) Math.max(MIN_POPULATION_SIZE,
Math.min(MAX_POPULATION_SIZE, MIN_POPULATION_SIZE + totalOps * populationSizeCoeff)); Math.min(MAX_POPULATION_SIZE, MIN_POPULATION_SIZE + totalOps * populationSizeCoeff));
int maxthead= Runtime.getRuntime().availableProcessors() - 1;
populationSize= populationSize / maxthead*maxthead;
// 确保偶数(方便交叉) // 确保偶数(方便交叉)
if (populationSize % 2 != 0) { // if (populationSize % 2 != 0) {
populationSize += 1; // populationSize += 1;
} // }
// 2. 最大迭代次数:50 ~ 200,随工序数线性减少 // 2. 最大迭代次数:50 ~ 200,随工序数线性减少
maxIterations = (int) Math.max(MIN_MAX_ITERATIONS, maxIterations = (int) Math.max(MIN_MAX_ITERATIONS,
......
...@@ -73,11 +73,11 @@ public class GlobalParam { ...@@ -73,11 +73,11 @@ public class GlobalParam {
public GlobalParam() { public GlobalParam() {
// 初始化默认目标值配置 // 初始化默认目标值配置
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间 //完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MAKESPAN, true, 1, 0.6)); objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MAKESPAN, true, 1, 0.3));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_FLOW_TIME, false, 2, 0.1)); 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_SETUP_TIME, true, 2, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MACHINE_LOAD, false, 3, 0.1)); objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MACHINE_LOAD, true, 1, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_TARDINESS, true, 1, 0.3)); objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_TARDINESS, true, 1, 0.6));
objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel())); objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel()));
} }
......
package com.aps.entity.basic;
/**
* 作者:佟礼
* 时间:2026-04-09
*/
public class KpiTargetConfig {
}
...@@ -156,6 +156,11 @@ public class Order { ...@@ -156,6 +156,11 @@ public class Order {
* 是否新创建,默认值:false * 是否新创建,默认值:false
*/ */
private boolean newCreate = false; private boolean newCreate = false;
/**
* 是否新创建半成品,默认值:false
*/
private boolean newSfCreate = false;
/** /**
* 是否创建BOM,默认值:false * 是否创建BOM,默认值:false
......
...@@ -21,8 +21,10 @@ public class FitnessCalculator { ...@@ -21,8 +21,10 @@ public class FitnessCalculator {
ArrayList<Double> list = new ArrayList<>(); ArrayList<Double> list = new ArrayList<>();
double fitness=0; double fitness=0;
double total=0;
int i=0; int i=0;
int level=-1; int level=-1;
double[] weightedObjectives=new double[chromosome.getObjectives().length];
for (ObjectiveConfig config : param.getObjectiveConfigs()) { for (ObjectiveConfig config : param.getObjectiveConfigs()) {
if( config.isEnabled()) { if( config.isEnabled()) {
...@@ -65,7 +67,9 @@ public class FitnessCalculator { ...@@ -65,7 +67,9 @@ public class FitnessCalculator {
if (!param.isPureNSGAIIMode()) { if (!param.isPureNSGAIIMode()) {
val = val * config.getWeight(); val = val * config.getWeight();
} }
weightedObjectives[i]=val;
fitness += val; fitness += val;
total+=val;
i++; i++;
} }
} }
...@@ -87,6 +91,8 @@ public class FitnessCalculator { ...@@ -87,6 +91,8 @@ public class FitnessCalculator {
// fitness ≈ 0.01 // fitness ≈ 0.01
// 适应度值(越大越好) // 适应度值(越大越好)
chromosome.setFitness(total);
chromosome.setWeightedObjectives(weightedObjectives);
return list.stream().mapToDouble(Double::doubleValue).toArray(); return list.stream().mapToDouble(Double::doubleValue).toArray();
} }
...@@ -147,7 +153,7 @@ public class FitnessCalculator { ...@@ -147,7 +153,7 @@ public class FitnessCalculator {
// 2. 计算每个个体与平均值的平方差之和 // 2. 计算每个个体与平均值的平方差之和
float sumSqDiff = 0.0f; float sumSqDiff = 0.0f;
for (Chromosome chromosome : population) { for (Chromosome chromosome : population) {
double diff = chromosome.getWeightedObjective() - avgFitness; double diff = chromosome.getFitness() - avgFitness;
sumSqDiff += diff * diff; sumSqDiff += diff * diff;
} }
...@@ -155,6 +161,19 @@ public class FitnessCalculator { ...@@ -155,6 +161,19 @@ public class FitnessCalculator {
return (double) Math.sqrt(sumSqDiff / popSize); return (double) Math.sqrt(sumSqDiff / popSize);
} }
/**
* 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/
public boolean isBetter(Chromosome c1, Chromosome c2) {
for (int i = 0; i < c1.getFitnessLevel().length; i++) {
double[] Fitness1 = c1.getFitnessLevel();
double[] Fitness2 = c2.getFitnessLevel();
if (Fitness1[i] > Fitness2[i]) {
return true;
}
}
return false;
}
......
...@@ -425,7 +425,7 @@ public class GeneticAlgorithm { ...@@ -425,7 +425,7 @@ public class GeneticAlgorithm {
// chromosome.setResultOld(new CopyOnWriteArrayList<>()); // chromosome.setResultOld(new CopyOnWriteArrayList<>());
// } // }
decoder.decodeChromosomeWithCache(chromosome); decoder.decodeChromosomeWithCache(chromosome,false);
if (chromosome.getFitness() == 0) { if (chromosome.getFitness() == 0) {
chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights)); chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights));
} }
......
...@@ -35,13 +35,13 @@ import java.util.stream.IntStream; ...@@ -35,13 +35,13 @@ import java.util.stream.IntStream;
public class GeneticDecoder { 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 final ConcurrentHashMap<String, Chromosome> decodingCache = new ConcurrentHashMap<>();
// 缓存大小限制 // 缓存大小限制
private static final int MAX_CACHE_SIZE = 3000; private static final int MAX_CACHE_SIZE = 3000;
// 线程安全锁:避免多线程下缓存操作冲突(可选,若单线程可移除) // 线程安全锁:避免多线程下缓存操作冲突(可选,若单线程可移除)
// private final ReentrantLock cacheLock = new ReentrantLock(); // private final ReentrantLock cacheLock = new ReentrantLock();
private LocalDateTime baseTime; private LocalDateTime baseTime;
private final List<Machine> machines; private final List<Machine> machines;
private final MachineSchedulerService machineScheduler; private final MachineSchedulerService machineScheduler;
...@@ -70,10 +70,10 @@ public class GeneticDecoder { ...@@ -70,10 +70,10 @@ public class GeneticDecoder {
this.materials = materials; this.materials = materials;
this.machineScheduler = machineScheduler; this.machineScheduler = machineScheduler;
_globalParam=globalParam; _globalParam=globalParam;
machineCalculator=new MachineCalculator(baseTime,machines,machineScheduler); machineCalculator=new MachineCalculator(baseTime,machines,machineScheduler);
materialRequirementService=_materialRequirementService; materialRequirementService=_materialRequirementService;
sceneId=_sceneId; 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( private final ExecutorService decodeExecutor = new ThreadPoolExecutor(
...@@ -88,17 +88,17 @@ public class GeneticDecoder { ...@@ -88,17 +88,17 @@ public class GeneticDecoder {
{ {
FileHelper.writeLogFile("解码---------------"+population.size() ); FileHelper.writeLogFile("解码---------------"+population.size() );
boolean ismore=false; boolean ismore=true;
if(ismore) { if(ismore) {
CompletableFuture.allOf(population.stream() CompletableFuture.allOf(population.stream()
.map(chromosome -> CompletableFuture.runAsync(() -> decodeChromosomeWithCache(chromosome), decodeExecutor)) .map(chromosome -> CompletableFuture.runAsync(() -> decodeChromosomeWithCache(chromosome,false), decodeExecutor))
.toArray(CompletableFuture[]::new)) .toArray(CompletableFuture[]::new))
.join(); .join();
} else { } else {
if (population != null && population.size() > 0) { if (population != null && population.size() > 0) {
population.forEach(chromosome -> { population.forEach(chromosome -> {
decodeChromosomeWithCache( chromosome); decodeChromosomeWithCache( chromosome,false);
}); });
} }
} }
...@@ -176,7 +176,7 @@ public class GeneticDecoder { ...@@ -176,7 +176,7 @@ public class GeneticDecoder {
// return chromosome; // return chromosome;
// } // }
public Chromosome decodeChromosomeWithCache(Chromosome chromosome) { public Chromosome decodeChromosomeWithCache(Chromosome chromosome,boolean isParallel) {
String cacheKey = createCacheKey(chromosome); String cacheKey = createCacheKey(chromosome);
// FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey ); // FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey );
...@@ -214,7 +214,7 @@ public class GeneticDecoder { ...@@ -214,7 +214,7 @@ public class GeneticDecoder {
return chromosome; return chromosome;
} }
// 3. 缓存未命中:执行解码逻辑 // 3. 缓存未命中:执行解码逻辑
decode(chromosome); decode(chromosome,isParallel);
// 4. 将解码结果存入缓存(无锁,ConcurrentHashMap 线程安全) // 4. 将解码结果存入缓存(无锁,ConcurrentHashMap 线程安全)
decodingCache.putIfAbsent(cacheKey, chromosome); decodingCache.putIfAbsent(cacheKey, chromosome);
...@@ -266,7 +266,7 @@ public class GeneticDecoder { ...@@ -266,7 +266,7 @@ public class GeneticDecoder {
Initialization initialization=new Initialization(); Initialization initialization=new Initialization();
initialization.generateInitialSFPopulation(chromosome,globalOpList); initialization.generateInitialSFPopulation(chromosome,globalOpList);
chromosome.getGlobalOpList().addAll(globalOpList); chromosome.getGlobalOpList().addAll(globalOpList);
return 1; return 1;
} }
private void CreateNewOpSequence(Chromosome chromosome) private void CreateNewOpSequence(Chromosome chromosome)
...@@ -279,10 +279,10 @@ return 1; ...@@ -279,10 +279,10 @@ return 1;
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
if(finishedOrder==null||finishedOrder.size()==0) if(finishedOrder==null||finishedOrder.size()==0)
{ {
return; return;
} }
List<Integer> oldSequence=chromosome.getOperationSequencing(); List<Integer> oldSequence=chromosome.getOperationSequencing();
List<Integer> finalSequence = new ArrayList<>(); List<Integer> finalSequence = new ArrayList<>();
...@@ -359,7 +359,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -359,7 +359,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
} }
finalSequence.add(orderid); finalSequence.add(orderid);
}else { }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)); // int insertPos = Math.max(0, finalSequence.size() - rnd.nextInt(2));
finalSequence.add(insertPos,orderid); finalSequence.add(insertPos,orderid);
...@@ -367,17 +367,16 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -367,17 +367,16 @@ if(finishedOrder==null||finishedOrder.size()==0)
orderProcessCounter.put(orderid, scheduledCount); orderProcessCounter.put(orderid, scheduledCount);
} }
public void decode(Chromosome chromosome) { public void decode(Chromosome chromosome,boolean isParallel) {
int operationCount = chromosome.getAllOperations().size();
int cpuCores = Runtime.getRuntime().availableProcessors();
// //
// // 根据工序数量和CPU核心数决定是否使用内部并行 // // 根据工序数量和CPU核心数决定是否使用内部并行
if (operationCount > 5000 && cpuCores > 4) { if (isParallel) {
// 使用设备并行处理 // 使用设备并行处理
// FileHelper.writeLogFile("使用并行处理 _s"); // FileHelper.writeLogFile("使用并行处理 _s");
parallelDecodeByMachine(chromosome); parallelDecodeByMachine(chromosome);
// FileHelper.writeLogFile("使用并行处理 _e"); // FileHelper.writeLogFile("使用并行处理 _e");
} }
else { else {
// 使用串行处理 // 使用串行处理
// FileHelper.writeLogFile("使用串行处理 _s"); // FileHelper.writeLogFile("使用串行处理 _s");
...@@ -392,14 +391,14 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -392,14 +391,14 @@ if(finishedOrder==null||finishedOrder.size()==0)
public void serialDecode(Chromosome chromosome) { 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); chromosome.setScenarioID(sceneId);
if(_globalParam.isIsCheckSf()) { if(_globalParam.isIsCheckSf()) {
int isnew= generateGlobalOpList(chromosome); int isnew= generateGlobalOpList(chromosome);
if(isnew==1) { if(isnew==1) {
CreateNewOpSequence(chromosome); CreateNewOpSequence(chromosome);
} }
} }
List<GlobalOperationInfo> globalOpList=chromosome.getGlobalOpList(); List<GlobalOperationInfo> globalOpList=chromosome.getGlobalOpList();
...@@ -473,23 +472,24 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -473,23 +472,24 @@ if(finishedOrder==null||finishedOrder.size()==0)
Map<Integer, Integer> orderLastEndTime = new HashMap<>(); Map<Integer, Integer> orderLastEndTime = new HashMap<>();
Map<Integer, Entry> entryIndexById = new HashMap<>(); Map<Integer, Entry> entryIndexById = new HashMap<>();
Map<Integer, List<Entry>> entrysBygroupId = new HashMap<>(); Map<Integer, List<Entry>> entrysBygroupId = new HashMap<>();
Map<Integer, GAScheduleResult> scheduleIndexById = new ConcurrentHashMap<>();
for (Entry op : allOperations) { for (Entry op : allOperations) {
int groupId = op.getGroupId(); int groupId = op.getGroupId();
orderProcessCounter.putIfAbsent(groupId, 0); orderProcessCounter.putIfAbsent(groupId, 0);
orderLastEndTime.putIfAbsent(groupId, 0); orderLastEndTime.putIfAbsent(groupId, 0);
entryIndexById.put(op.getId(),op); entryIndexById.put(op.getId(),op);
entrysBygroupId.computeIfAbsent(groupId, k -> new ArrayList<>()).add(op); entrysBygroupId.computeIfAbsent(groupId, k -> new ArrayList<>()).add(op);
//scheduleIndexById.put(op.getId(),null);
} }
// Map<Long, String> machineState = chromosome.getMachines().stream() // Map<Long, String> machineState = chromosome.getMachines().stream()
// .collect(Collectors.toMap(Machine::getId, m -> "")); // .collect(Collectors.toMap(Machine::getId, m -> ""));
// List<Entry> allScheduledOps = new ArrayList<>(); // List<Entry> allScheduledOps = new ArrayList<>();
// 缓存机器任务 // 缓存机器任务
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>(); Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>();
for (Entry op : allOperations) {
}
for (int groupId : chromosome.getOperationSequencing()) { for (int groupId : chromosome.getOperationSequencing()) {
int scheduledCount = orderProcessCounter.get(groupId); int scheduledCount = orderProcessCounter.get(groupId);
List<Entry> orderOps = entrysBygroupId.get(groupId).stream() List<Entry> orderOps = entrysBygroupId.get(groupId).stream()
...@@ -541,26 +541,26 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -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; // int prevendtime=prevtime;
// prevtime = Math.max(prevtime, bomtime); // prevtime = Math.max(prevtime, bomtime);
// Machine machine = chromosome.getMachines().stream() // Machine machine = chromosome.getMachines().stream()
// .filter(m -> m.getId() == machineId) // .filter(m -> m.getId() == machineId)
// .findFirst() // .findFirst()
// .orElse(null); // .orElse(null);
// Machine machine = machineIdMap.get(machineId); // Machine machine = machineIdMap.get(machineId);
// int changeoverTime =0; //(lastDiscreteParameter.isEmpty() || // int changeoverTime =0; //(lastDiscreteParameter.isEmpty() ||
// lastDiscreteParameter.equals(currentOp.getDiscreteParameter())) ? 0 : 0; // lastDiscreteParameter.equals(currentOp.getDiscreteParameter())) ? 0 : 0;
int actualEndTime = processOperation(currentOp,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache); 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); orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);
orderLastEndTime.put(groupId, actualEndTime); orderLastEndTime.put(groupId, actualEndTime);
// machineState.put(machineId, currentOp.getDiscreteParameter()); // machineState.put(machineId, currentOp.getDiscreteParameter());
} }
if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) { if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) {
chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t)); chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t));
...@@ -570,131 +570,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -570,131 +570,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
calculateScheduleResult(chromosome); calculateScheduleResult(chromosome);
} }
public void parallelDecode(Chromosome chromosome) {
FileHelper.writeLogFile("构建工序依赖图 _s");
// 1. 构建工序依赖图
Map<Integer, List<Integer>> dependencyGraph = buildDependencyGraph(chromosome);
FileHelper.writeLogFile("拓扑排序 _s");
// 2. 拓扑排序
List<Integer> topologicalOrder = topologicalSort(dependencyGraph,chromosome);
FileHelper.writeLogFile("按设备分组 _s");
// 3. 按设备分组
Map<Long, List<Integer>> machineToOpsMap = new HashMap<>();
Map<Integer, Integer> opToGroupIdMap = new HashMap<>();
Map<Integer, Long> opToMachineMap = new HashMap<>();
List<GlobalOperationInfo> globalOpList=chromosome.getGlobalOpList();
// 步骤1:生成“工序→机器/加工时间”映射
List<OpMachine> opMachineMap = new ArrayList<>();
Map<String, OpMachine> opMachineKeyMap = new HashMap<>();
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>();
Map<Long, Machine> machineIdMap = chromosome.getMachines().stream()
.collect(Collectors.toMap(Machine::getId, m -> m));
// 构建工序ID索引:opId -> Entry(O(1)查找)
Map<Integer, Entry> opIdIndex = buildOpIdIndex(chromosome);
for (GlobalOperationInfo globalOp : globalOpList) {
int globalOpId = globalOp.getGlobalOpId();
Entry op = globalOp.getOp();
int groupId = globalOp.getGroupId();
int sequence = globalOp.getSequence();
// 从MachineSelection中获取当前工序的机器选择顺序号
int machineSeq = chromosome.getMachineSelection().get(globalOpId);
List<MachineOption> optionalMachines = op.getMachineOptions();
// 验证:机器顺序号必须在可选范围内
if (machineSeq < 1 || machineSeq > optionalMachines.size()) {
throw new IllegalStateException(String.format(
"全局工序%d(订单%d工序%d)的机器顺序号%d超出范围(1-%d)",
globalOpId, groupId, sequence, machineSeq, optionalMachines.size()));
}
// 获取选择的设备ID和加工时间
MachineOption selectedMachine = optionalMachines.get(machineSeq - 1);
OpMachine opMachine=new OpMachine();
opMachine.setGroupId(groupId);
opMachine.setSequence(sequence);
opMachine.setMachineId(selectedMachine.getMachineId());
opMachine.setProcessingTime(selectedMachine.getProcessingTime());
opMachine.setRuntime(selectedMachine.getRuntime());
opMachine.setSingleOut(selectedMachine.getSingleOut());
opMachineMap.add(opMachine);
String key = opMachine.getGroupId() + "_" + opMachine.getSequence();
opMachineKeyMap.put(key, opMachine);
}
FileHelper.writeLogFile("预处理工序信息 _s");
// 预处理工序信息
for (int opId : topologicalOrder) {
// Entry op = findOperationById(chromosome, opId);
Entry op = opIdIndex.get(opId);
if (op != null) {
// 假设已经为工序分配了设备
String opMachineKey = op.getGroupId() + "_" + op.getSequence();
OpMachine machineOption = opMachineKeyMap.get(opMachineKey);
if (machineOption != null) {
machineToOpsMap.computeIfAbsent(machineOption.getMachineId(), k -> new ArrayList<>()).add(opId);
opToGroupIdMap.put(opId, op.getGroupId());
opToMachineMap.put(opId, machineOption.getMachineId());
}
}
}
// 4. 并行处理
Map<Integer, CompletableFuture<Void>> opFutures = new HashMap<>();
Map<Long, CompletableFuture<Void>> machineFutures = new HashMap<>();
FileHelper.writeLogFile("并行处理 _s");
for (int opId : topologicalOrder) {
// 获取当前工序的依赖
// Entry op = findOperationById(chromosome, opId);
Entry op = opIdIndex.get(opId);
List<Integer> dependencies = dependencyGraph.getOrDefault(opId, Collections.emptyList());
// 等待所有依赖完成
List<CompletableFuture<Void>> dependencyFutures = dependencies.stream()
.map(opFutures::get)
.filter(Objects::nonNull)
.collect(Collectors.toList());
String opMachineKey = op.getGroupId() + "_" + op.getSequence();
OpMachine machineOption = opMachineKeyMap.get(opMachineKey);
Long machineId = machineOption.getMachineId();
double processTime = machineOption.getProcessingTime();
// 等待当前设备的上一个工序完成
CompletableFuture<Void> machineFuture = machineFutures.getOrDefault(machineId, CompletableFuture.completedFuture(null));
// 合并所有依赖
List<CompletableFuture<Void>> allDependencies = new ArrayList<>(dependencyFutures);
allDependencies.add(machineFuture);
// 创建当前工序的处理任务
CompletableFuture<Void> currentFuture = CompletableFuture.allOf(allDependencies.toArray(new CompletableFuture[0]))
.thenRunAsync(() -> {
// 处理当前工序
int actualEndTime = processOperation(op,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache);
});
// 保存当前工序的Future
opFutures.put(opId, currentFuture);
// 更新设备的Future
machineFutures.put(machineId, currentFuture);
}
// 等待所有工序完成
CompletableFuture.allOf(opFutures.values().toArray(new CompletableFuture[0])).join();
FileHelper.writeLogFile("calculateScheduleResult _s");
if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) {
chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t));
}
calculateScheduleResult(chromosome);
}
public void parallelDecodeByMachine(Chromosome chromosome) { public void parallelDecodeByMachine(Chromosome chromosome) {
// 1. 获取工序处理顺序 // 1. 获取工序处理顺序
List<Integer> operationSequencing = chromosome.getOperationSequencing(); List<Integer> operationSequencing = chromosome.getOperationSequencing();
...@@ -748,9 +624,15 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -748,9 +624,15 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 初始化订单处理计数器 // 初始化订单处理计数器
Map<Integer, Integer> orderProcessCounter = new HashMap<>(); Map<Integer, Integer> orderProcessCounter = new HashMap<>();
Map<Integer, Entry> entryIndexById = new HashMap<>();
Map<Integer, List<Entry>> entrysBygroupId = new HashMap<>();
Map<Integer, GAScheduleResult> scheduleIndexById= new ConcurrentHashMap<>();
for (Entry op : allOperations) { for (Entry op : allOperations) {
int groupId = op.getGroupId(); int groupId = op.getGroupId();
orderProcessCounter.putIfAbsent(groupId, 0); orderProcessCounter.putIfAbsent(groupId, 0);
entryIndexById.put(op.getId(),op);
entrysBygroupId.computeIfAbsent(groupId, k -> new ArrayList<>()).add(op);
} }
Map<Long, List<Entry>> machineToOpsMap = new HashMap<>(); Map<Long, List<Entry>> machineToOpsMap = new HashMap<>();
//按照 OperationSequencing 顺序生成 machineToOpsMap //按照 OperationSequencing 顺序生成 machineToOpsMap
...@@ -886,11 +768,11 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -886,11 +768,11 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 工序超过500的设备直接在主线程串行处理 // 工序超过500的设备直接在主线程串行处理
if (ops.size() > 500) { if (ops.size() > 500) {
// FileHelper.writeLogFile("设备 " + machineId + " 有 " + ops.size() + " 个工序,直接串行处理"); // FileHelper.writeLogFile("设备 " + machineId + " 有 " + ops.size() + " 个工序,直接串行处理");
processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock, opMachineKeyMap, machineIdMap, machineTasksCache); processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock, opMachineKeyMap, machineIdMap, machineTasksCache, entryIndexById,scheduleIndexById);
} else { } else {
// 工序少的设备创建线程处理 // 工序少的设备创建线程处理
Thread thread = new Thread(() -> { Thread thread = new Thread(() -> {
processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock, opMachineKeyMap, machineIdMap, machineTasksCache); processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock, opMachineKeyMap, machineIdMap, machineTasksCache, entryIndexById,scheduleIndexById);
}); });
thread.start(); thread.start();
threads.add(thread); threads.add(thread);
...@@ -920,7 +802,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -920,7 +802,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
*/ */
private void processMachineOps(Chromosome chromosome, Long machineId, List<Entry> ops, private void processMachineOps(Chromosome chromosome, Long machineId, List<Entry> ops,
Map<Integer, List<Integer>> dependencyGraph, Map<Integer, List<Integer>> dependencyGraph,
Map<Integer, Boolean> opCompleted, Object lock,Map<String, OpMachine> opMachineKeyMap,Map<Long, Machine> machineIdMap,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache) { Map<Integer, Boolean> opCompleted, Object lock,Map<String, OpMachine> opMachineKeyMap,Map<Long, Machine> machineIdMap,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {
//long machineStartTime = System.currentTimeMillis(); //long machineStartTime = System.currentTimeMillis();
for (int i = 0; i < ops.size(); i++) { for (int i = 0; i < ops.size(); i++) {
...@@ -955,17 +837,17 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -955,17 +837,17 @@ if(finishedOrder==null||finishedOrder.size()==0)
double processTime = machineOption.getProcessingTime(); double processTime = machineOption.getProcessingTime();
// 处理当前工序 // 处理当前工序
// long processStartTime = System.currentTimeMillis(); // long processStartTime = System.currentTimeMillis();
int actualEndTime = processOperation(op,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache); int actualEndTime = processOperation(op,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache, entryIndexById,scheduleIndexById);
// long processEndTime = System.currentTimeMillis(); // long processEndTime = System.currentTimeMillis();
// 标记工序完成 // 标记工序完成
synchronized (lock) { synchronized (lock) {
opCompleted.put(opId, true); opCompleted.put(opId, true);
} }
// long opEndTime = System.currentTimeMillis(); // long opEndTime = System.currentTimeMillis();
// if (i % 100 == 0 || i == ops.size() - 1) { // if (i % 100 == 0 || i == ops.size() - 1) {
// FileHelper.writeLogFile("设备 " + machineId + " 工序 " + i + "/" + ops.size() + // FileHelper.writeLogFile("设备 " + machineId + " 工序 " + i + "/" + ops.size() +
// " 完成,总耗时:" + (opEndTime - machineStartTime) + "ms,本工序耗时:" + (opEndTime - opStartTime) + "ms"); // " 完成,总耗时:" + (opEndTime - machineStartTime) + "ms,本工序耗时:" + (opEndTime - opStartTime) + "ms");
...@@ -1091,8 +973,8 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -1091,8 +973,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
return result; return result;
} }
/** /**
* 构建工序ID索引:opId -> Entry(O(1)查找) * 构建工序ID索引:opId -> Entry(O(1)查找)
*/ */
private Map<Integer, Entry> buildOpIdIndex(Chromosome chromosome) { private Map<Integer, Entry> buildOpIdIndex(Chromosome chromosome) {
Map<Integer, Entry> index = new HashMap<>(); Map<Integer, Entry> index = new HashMap<>();
for (Entry op : chromosome.getAllOperations()) { for (Entry op : chromosome.getAllOperations()) {
...@@ -1114,7 +996,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -1114,7 +996,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
private int processOperation(Entry currentOp,Long machineId,double processTime,OpMachine machineOption,Chromosome chromosome,Map<Long, Machine> machineIdMap,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache) private int processOperation(Entry currentOp,Long machineId,double processTime,OpMachine machineOption,Chromosome chromosome,Map<Long, Machine> machineIdMap,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById)
{ {
Machine targetMachine = machineIdMap.get(machineId); Machine targetMachine = machineIdMap.get(machineId);
...@@ -1123,7 +1005,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -1123,7 +1005,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
int teardownTime = currentOp.getTeardownTime(); int teardownTime = currentOp.getTeardownTime();
if (!currentOp.getPrevEntryIds().isEmpty()) { if (!currentOp.getPrevEntryIds().isEmpty()) {
// 处理多个前工序 // 处理多个前工序
prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine); prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine,entryIndexById, scheduleIndexById);
} }
int bomtime = getOperationBOMTime(currentOp,chromosome); int bomtime = getOperationBOMTime(currentOp,chromosome);
...@@ -1131,14 +1013,14 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -1131,14 +1013,14 @@ if(finishedOrder==null||finishedOrder.size()==0)
int prevendtime=prevtime; int prevendtime=prevtime;
prevtime = Math.max(prevtime, bomtime); prevtime = Math.max(prevtime, bomtime);
Machine machine = machineIdMap.get(machineId); Machine machine = machineIdMap.get(machineId);
int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,machineOption, chromosome,false,prevendtime,machineTasksCache); int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,machineOption, chromosome,false,prevendtime,machineTasksCache,entryIndexById, scheduleIndexById);
return actualEndTime; return actualEndTime;
} }
private int processWithSingleMachine(Entry operation, Machine machine, double processingTime, private int processWithSingleMachine(Entry operation, Machine machine, double processingTime,
int prevOperationEndTime,OpMachine machineOption, Chromosome chromosome,boolean calbom,int prevendtime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache) { int prevOperationEndTime,OpMachine machineOption, Chromosome chromosome,boolean calbom,int prevendtime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {
int processingTimeTotal=0; int processingTimeTotal=0;
int earliestStartTime = prevOperationEndTime; int earliestStartTime = prevOperationEndTime;
if(operation.getConstTime()==1)//常数时间 if(operation.getConstTime()==1)//常数时间
...@@ -1155,7 +1037,7 @@ return actualEndTime; ...@@ -1155,7 +1037,7 @@ return actualEndTime;
} }
if(machine==null||operation.getMachineOptions()==null) if(machine==null||operation.getMachineOptions()==null)
{ {
return 0; return 0;
} }
// MachineOption machineOption= operation.getMachineOptions().stream() // MachineOption machineOption= operation.getMachineOptions().stream()
...@@ -1181,7 +1063,7 @@ return actualEndTime; ...@@ -1181,7 +1063,7 @@ return actualEndTime;
//前处理,是否可以在相同任务前序未完工就开始设置时间, //前处理,是否可以在相同任务前序未完工就开始设置时间,
// 就是 最早开工时间是否+前处理时间,总的加工工时不考虑前处理 // 就是 最早开工时间是否+前处理时间,总的加工工时不考虑前处理
if (!_globalParam.is_smoothSetup()) { if (!_globalParam.is_smoothSetup()) {
// 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理 // 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理
earliestStartTime+=preTime; earliestStartTime+=preTime;
} }
GAScheduleResult existingResult = chromosome.getResultOld().stream().filter(r-> r.getOperationId() == operation.getId()).findFirst().orElse(null); GAScheduleResult existingResult = chromosome.getResultOld().stream().filter(r-> r.getOperationId() == operation.getId()).findFirst().orElse(null);
...@@ -1195,18 +1077,18 @@ return actualEndTime; ...@@ -1195,18 +1077,18 @@ return actualEndTime;
if (machineTasksCache.containsKey(machine.getId())) { if (machineTasksCache.containsKey(machine.getId())) {
machineTasks = machineTasksCache.get(machine.getId()); machineTasks = machineTasksCache.get(machine.getId());
} else { } else {
machineTasks = chromosome.getResult().stream() machineTasks = chromosome.getResult().stream()
.filter(t -> t.getMachineId() == machine.getId()) .filter(t -> t.getMachineId() == machine.getId())
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime)) .sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toCollection(CopyOnWriteArrayList::new)); .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
machineTasksCache.put(machine.getId(), machineTasks); machineTasksCache.put(machine.getId(), machineTasks);
} }
GAScheduleResult lastGeneOnMachine = null; GAScheduleResult lastGeneOnMachine = null;
if(machineTasks!=null&&machineTasks.size()>0) if(machineTasks!=null&&machineTasks.size()>0)
{ {
lastGeneOnMachine=machineTasks.get(machineTasks.size()-1); lastGeneOnMachine=machineTasks.get(machineTasks.size()-1);
} }
if(lastGeneOnMachine!=null&&_globalParam.is_smoothChangeOver()) if(lastGeneOnMachine!=null&&_globalParam.is_smoothChangeOver())
{ {
earliestStartTime = Math.max(earliestStartTime,lastGeneOnMachine.getEndTime()); earliestStartTime = Math.max(earliestStartTime,lastGeneOnMachine.getEndTime());
...@@ -1223,8 +1105,8 @@ return actualEndTime; ...@@ -1223,8 +1105,8 @@ return actualEndTime;
if (_globalParam.is_smoothChangeOver()) { if (_globalParam.is_smoothChangeOver()) {
Map<Integer, Object> reslte = calculateSetupTime(lastGeneOnMachine, operation, machine, earliestStartTime, processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), chromosome.getAllOperations()); Map<Integer, Object> reslte = calculateSetupTime(lastGeneOnMachine, operation, machine, earliestStartTime, processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), chromosome.getAllOperations());
// setupTime = (int) reslte.get(1);//换型时间 // setupTime = (int) reslte.get(1);//换型时间
// int setupStartTime = (int) reslte.get(2);//换型开始时间 // int setupStartTime = (int) reslte.get(2);//换型开始时间
//earliestStartTime=(int)reslte.get(3);//上个任务的结束时间 //earliestStartTime=(int)reslte.get(3);//上个任务的结束时间
earliestStartTime = (int) reslte.get(4);//最早开工时间 earliestStartTime = (int) reslte.get(4);//最早开工时间
} }
...@@ -1239,7 +1121,7 @@ return actualEndTime; ...@@ -1239,7 +1121,7 @@ return actualEndTime;
: earliestStartTime; : earliestStartTime;
} }
bomtime= EditOperationBOMTime(operation,chromosome,earliestStartTime,machineTasksCache); bomtime= EditOperationBOMTime(operation,chromosome,earliestStartTime,machineTasksCache, entryIndexById, scheduleIndexById);
if(bomtime>prevendtime&&bomtime<earliestStartTimeold) if(bomtime>prevendtime&&bomtime<earliestStartTimeold)
...@@ -1329,9 +1211,9 @@ return actualEndTime; ...@@ -1329,9 +1211,9 @@ return actualEndTime;
//开工时间需往后延 2小时 //开工时间需往后延 2小时
// 准备工时 加入到加工时间里 // 准备工时 加入到加工时间里
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间 // 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
GAScheduleResult result=new GAScheduleResult(); GAScheduleResult result=new GAScheduleResult();
...@@ -1368,17 +1250,17 @@ return actualEndTime; ...@@ -1368,17 +1250,17 @@ return actualEndTime;
processingTimeTotal1=(int) geneDetails.stream().filter(t->t.getUsedSegment()==null).mapToDouble(ScheduleResultDetail::getProcessingTime) // 替换为实际字段名 processingTimeTotal1=(int) geneDetails.stream().filter(t->t.getUsedSegment()==null).mapToDouble(ScheduleResultDetail::getProcessingTime) // 替换为实际字段名
.sum(); .sum();
List<TimeSegment> UsedSegments=geneDetails.stream(). List<TimeSegment> UsedSegments=geneDetails.stream().
filter(t->t.getUsedSegment()!=null) filter(t->t.getUsedSegment()!=null)
.map(ScheduleResultDetail::getUsedSegment).flatMap(List::stream) .map(ScheduleResultDetail::getUsedSegment).flatMap(List::stream)
// 收集为最终的 List // 收集为最终的 List
.collect(Collectors.toList()); .collect(Collectors.toList());
if(UsedSegments!=null&&UsedSegments.size()>0) if(UsedSegments!=null&&UsedSegments.size()>0)
{ {
processingTimeTotal1+=(int)UsedSegments.stream().mapToDouble(TimeSegment::getProcessingTime) // 替换为实际字段名 processingTimeTotal1+=(int)UsedSegments.stream().mapToDouble(TimeSegment::getProcessingTime) // 替换为实际字段名
.sum(); .sum();
} }
result.setProcessingTime(processingTimeTotal1); result.setProcessingTime(processingTimeTotal1);
...@@ -1386,15 +1268,15 @@ return actualEndTime; ...@@ -1386,15 +1268,15 @@ return actualEndTime;
// System.out.println("huanxingshijian="+result.getChangeOverTime()+"-------------------"+result.getOrderId()+"--------"+result.getExecId()+"---------"+prev.getOrderId()+"--------"+prev.getExecId()); // System.out.println("huanxingshijian="+result.getChangeOverTime()+"-------------------"+result.getOrderId()+"--------"+result.getExecId()+"---------"+prev.getOrderId()+"--------"+prev.getExecId());
chromosome.getResult().add(result); chromosome.getResult().add(result);
machine.setLastGene(result); machine.setLastGene(result);
// FileHelper.writeLogFile(" 结束 "+ConvertTime(startTime)+"--"+ConvertTime(endTime)+" "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime + // FileHelper.writeLogFile(" 结束 "+ConvertTime(startTime)+"--"+ConvertTime(endTime)+" "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
// ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt()); // ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt());
if (machineTasks != null) { if (machineTasks != null) {
machineTasks.add(result); machineTasks.add(result);
} }
scheduleIndexById.put(operation.getId(),result);
return endTime; return endTime;
} }
...@@ -1405,16 +1287,18 @@ return actualEndTime; ...@@ -1405,16 +1287,18 @@ return actualEndTime;
* @param chromosome * @param chromosome
* @return * @return
*/ */
private int CalPrevtime(int prevtime,Entry currentOp,Chromosome chromosome,double processTime,Machine machine) { private int CalPrevtime(int prevtime,Entry currentOp,Chromosome chromosome,double processTime,Machine machine,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {
List<OperationDependency> FsOperations = currentOp.getPrevEntryIds().stream() List<OperationDependency> FsOperations = currentOp.getPrevEntryIds().stream()
.filter(t -> t.getDependencyType() == DependencyType.FinishToStart) .filter(t -> t.getDependencyType() == DependencyType.FinishToStart)
.collect(Collectors.toList());//串行 .collect(Collectors.toList());//串行
if (FsOperations != null && FsOperations.size() > 0) { if (FsOperations != null && FsOperations.size() > 0) {
for (OperationDependency opid : FsOperations) { for (OperationDependency opid : FsOperations) {
List<GAScheduleResult> prevOperations = chromosome.getResult().stream() // List<GAScheduleResult> prevOperations = chromosome.getResult().stream()
.filter(t -> t.getGroupId() == currentOp.getGroupId() && t.getOperationId() == opid.getPrevOperationId()) // .filter(t -> t.getOperationId() == opid.getPrevOperationId())
.collect(Collectors.toList());//多台 // .collect(Collectors.toList());//
for (GAScheduleResult prevOp : prevOperations) { GAScheduleResult prevOp= scheduleIndexById.get(opid.getPrevOperationId());
// for (GAScheduleResult prevOp : prevOperations) {
if(prevOp!=null){
//加上后处理时间 //加上后处理时间
prevtime = Math.max(prevtime, prevOp.getEndTime() + currentOp.getTeardownTime()); prevtime = Math.max(prevtime, prevOp.getEndTime() + currentOp.getTeardownTime());
} }
...@@ -1431,31 +1315,36 @@ return actualEndTime; ...@@ -1431,31 +1315,36 @@ return actualEndTime;
for (int j=0;j<SSOperations.size();j++) for (int j=0;j<SSOperations.size();j++)
{ {
OperationDependency opid=SSOperations.get(j); OperationDependency opid=SSOperations.get(j);
List<GAScheduleResult> prevOperations = chromosome.getResult().stream() // List<GAScheduleResult> prevOperations = chromosome.getResult().stream()
.filter(t -> t.getGroupId() == currentOp.getGroupId() && t.getOperationId() == opid.getPrevOperationId()) // .filter(t -> t.getOperationId() == opid.getPrevOperationId())
.collect(Collectors.toList());//多台 // .collect(Collectors.toList());//多台
for (GAScheduleResult prevOp : prevOperations) { GAScheduleResult prevOp= scheduleIndexById.get(opid.getPrevOperationId());
// for (GAScheduleResult prevOp : prevOperations) {
if(prevOp!=null){
newScheduleResult.add(prevOp); newScheduleResult.add(prevOp);
newScheduleResultDetails.addAll(prevOp.getGeneDetails()); newScheduleResultDetails.addAll(prevOp.getGeneDetails());
} }
if(j==SSOperations.size()-1) 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); prevtime = Math.max(prevtime, prevtime1);
}else { }else {
Entry entry= chromosome.getAllOperations().stream() // Entry entry= chromosome.getAllOperations().stream()
.filter(t->t.getId()==opid.getPrevOperationId()) // .filter(t->t.getId()==opid.getPrevOperationId())
.findFirst().orElse(null); // .findFirst().orElse(null);
Entry entry=entryIndexById.get(opid.getPrevOperationId());
OperationDependency opid2=SSOperations.get(j+1); OperationDependency opid2=SSOperations.get(j+1);
Entry entry1= chromosome.getAllOperations().stream() // Entry entry1= chromosome.getAllOperations().stream()
.filter(t->t.getId()==opid2.getPrevOperationId()) // .filter(t->t.getId()==opid2.getPrevOperationId())
.findFirst().orElse(null); // .findFirst().orElse(null);
Entry entry1=entryIndexById.get(opid2.getPrevOperationId());
if(entry.getRoutingDetailId()!=entry1.getRoutingDetailId()) //不是同一前工序,效率不能合并 newScheduleResult 清空,如何是一个工序就合并计算
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); prevtime = Math.max(prevtime, prevtime1);
newScheduleResult.clear(); newScheduleResult.clear();
...@@ -1525,13 +1414,13 @@ return actualEndTime; ...@@ -1525,13 +1414,13 @@ return actualEndTime;
if (opboms != null && !opboms.isEmpty()) { if (opboms != null && !opboms.isEmpty()) {
// 计算RawTime // 计算RawTime
Optional<LocalDateTime> rawDateOpt = opboms.stream() Optional<LocalDateTime> rawDateOpt = opboms.stream()
.filter(t -> t.getMaterialTypeName().equals("MP")) .filter(t -> t.getMaterialTypeName().equals("MP"))
.map(OrderMaterialRequirement::getUseTime) .map(OrderMaterialRequirement::getUseTime)
.max(LocalDateTime::compareTo); .max(LocalDateTime::compareTo);
if (rawDateOpt.isPresent()) { if (rawDateOpt.isPresent()) {
rawTime = (int) Duration.between(baseTime, rawDateOpt.get()).getSeconds(); rawTime = (int) Duration.between(baseTime, rawDateOpt.get()).getSeconds();
} }
...@@ -1577,7 +1466,7 @@ return actualEndTime; ...@@ -1577,7 +1466,7 @@ return actualEndTime;
return Math.max(rawTime, sfTime); return Math.max(rawTime, sfTime);
} }
private int EditOperationBOMTime(Entry currentOp, Chromosome chromosome,int earliestStartTime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache) { private int EditOperationBOMTime(Entry currentOp, Chromosome chromosome,int earliestStartTime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {
List<OrderMaterialRequirement> opboms= currentOp.getMaterialRequirements(); List<OrderMaterialRequirement> opboms= currentOp.getMaterialRequirements();
...@@ -1585,13 +1474,13 @@ return actualEndTime; ...@@ -1585,13 +1474,13 @@ return actualEndTime;
{ {
return 0; return 0;
} }
LocalDateTime earliestStartTime1=baseTime.plusSeconds(earliestStartTime); LocalDateTime earliestStartTime1=baseTime.plusSeconds(earliestStartTime);
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache); materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById, baseTime);
return getOperationBOMTime(currentOp, chromosome); return getOperationBOMTime(currentOp, chromosome);
} }
public void EditorderOperation(Chromosome chromosome, int groupId,double needed,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache){ public void EditorderOperation(Chromosome chromosome, int groupId,double needed,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById){
List<Entry> orderOps = chromosome.getAllOperations().stream() List<Entry> orderOps = chromosome.getAllOperations().stream()
.filter(t -> t.getGroupId() == groupId) .filter(t -> t.getGroupId() == groupId)
.sorted(Comparator.comparing(Entry::getSequence)) .sorted(Comparator.comparing(Entry::getSequence))
...@@ -1635,7 +1524,7 @@ return getOperationBOMTime(currentOp, chromosome); ...@@ -1635,7 +1524,7 @@ return getOperationBOMTime(currentOp, chromosome);
int teardownTime = currentOp.getTeardownTime(); int teardownTime = currentOp.getTeardownTime();
if (!currentOp.getPrevEntryIds().isEmpty()) { if (!currentOp.getPrevEntryIds().isEmpty()) {
// 处理多个前工序 // 处理多个前工序
prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine); prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine, entryIndexById,scheduleIndexById);
} }
// 上个离散参数 // 上个离散参数
...@@ -1650,7 +1539,7 @@ return getOperationBOMTime(currentOp, chromosome); ...@@ -1650,7 +1539,7 @@ return getOperationBOMTime(currentOp, chromosome);
.findFirst() .findFirst()
.orElse(null); .orElse(null);
// 缓存机器任务 // 缓存机器任务
int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,opMachine, chromosome,true,prevendtime,machineTasksCache); int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,opMachine, chromosome,true,prevendtime,machineTasksCache, entryIndexById, scheduleIndexById);
} }
...@@ -1685,12 +1574,12 @@ return getOperationBOMTime(currentOp, chromosome); ...@@ -1685,12 +1574,12 @@ return getOperationBOMTime(currentOp, chromosome);
List<OrderMaterialRequirement> MaterialRequirements = currentOp.getMaterialRequirements().stream() List<OrderMaterialRequirement> MaterialRequirements = currentOp.getMaterialRequirements().stream()
.filter(t->!"MP".equals(t.getMaterialTypeName()) .filter(t->!"MP".equals(t.getMaterialTypeName())
&& t.getProductOrderID() != null && !t.getProductOrderID().isEmpty() && t.getProductOrderID() != null && !t.getProductOrderID().isEmpty()
) )
.collect(Collectors.toList()); .collect(Collectors.toList());
if(MaterialRequirements==null||MaterialRequirements.size()==0) if(MaterialRequirements==null||MaterialRequirements.size()==0)
{ {
continue; continue;
} }
for (OrderMaterialRequirement orderMaterial:MaterialRequirements) { for (OrderMaterialRequirement orderMaterial:MaterialRequirements) {
List<Integer> orderids= orderMaterial.getProductOrderID(); List<Integer> orderids= orderMaterial.getProductOrderID();
if(orderids!=null&&orderids.size()>0) { if(orderids!=null&&orderids.size()>0) {
...@@ -1730,7 +1619,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -1730,7 +1619,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
} }
List<OrderMaterialRequirement> orderMaterialRequirements= entry.getMaterialRequirements().stream().filter(t-> !"MP".equals(t.getMaterialTypeName()) List<OrderMaterialRequirement> orderMaterialRequirements= entry.getMaterialRequirements().stream().filter(t-> !"MP".equals(t.getMaterialTypeName())
&& t.getProductOrderID() != null && !t.getProductOrderID().isEmpty() && t.getProductOrderID() != null && !t.getProductOrderID().isEmpty()
).collect(Collectors.toList()); ).collect(Collectors.toList());
for (OrderMaterialRequirement mr:orderMaterialRequirements) { for (OrderMaterialRequirement mr:orderMaterialRequirements) {
List<Integer> orderids= mr.getProductOrderID(); List<Integer> orderids= mr.getProductOrderID();
if(orderids!=null&&orderids.size()>0) { if(orderids!=null&&orderids.size()>0) {
...@@ -1794,7 +1683,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -1794,7 +1683,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
* @return 可开工时间 * @return 可开工时间
*/ */
private int calculateNextOperationStartTime(List<GAScheduleResult> results,List<ScheduleResultDetail> details, int startindex, double time2) { 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(); .sum();
double time1 = 0.0; double time1 = 0.0;
...@@ -1816,7 +1705,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -1816,7 +1705,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
} }
if(results.size()>1) {//多前置工序 if(results.size()>1) {//多前置工序
calculateWithMoreMachine(details, leadCount); calculateWithMoreMachine(details, leadCount);
} }
// 单设备时使用原逻辑 // 单设备时使用原逻辑
return (int)calculateWithSingleMachine(details, leadCount, time1); return (int)calculateWithSingleMachine(details, leadCount, time1);
} }
...@@ -1873,10 +1762,10 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -1873,10 +1762,10 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
// //
// int minEndTimeForContinuity = prevEndTime - (int) ((qty - leadCount) * prevTimePerUnit); // int minEndTimeForContinuity = prevEndTime - (int) ((qty - leadCount) * prevTimePerUnit);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, minEndTimeForContinuity); // int adjustedStartTime = Math.max(productionTimeForLeadCount, minEndTimeForContinuity);
// int adjustedStartTime = Math.max(productionTimeForLeadCount, prevtime); // int adjustedStartTime = Math.max(productionTimeForLeadCount, prevtime);
// int totalProcessingTime = (int) (currentTimePerUnit * qty); // int totalProcessingTime = (int) (currentTimePerUnit * qty);
// int continuityAdjustedTime = ensureContinuousProduction(machine, adjustedStartTime, // int continuityAdjustedTime = ensureContinuousProduction(machine, adjustedStartTime,
// totalProcessingTime, currentOp); // totalProcessingTime, currentOp);
...@@ -1960,7 +1849,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -1960,7 +1849,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
} }
} }
alldetails.stream().sorted(Comparator.comparingInt(ScheduleResultDetail::getStartTime)); alldetails.stream().sorted(Comparator.comparingInt(ScheduleResultDetail::getStartTime));
int EndTime=0; int EndTime=0;
double accumulatedQty = 0.0; double accumulatedQty = 0.0;
for (ScheduleResultDetail detail : alldetails) { for (ScheduleResultDetail detail : alldetails) {
...@@ -1989,7 +1878,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -1989,7 +1878,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
return EndTime; return EndTime;
} }
/** /**
* 多设备并行时计算满足提前量的最早时间 * 多设备并行时计算满足提前量的最早时间
*/ */
private int calculateWithParallelMachines(List<ScheduleResultDetail> details, int leadCount, int time1) { private int calculateWithParallelMachines(List<ScheduleResultDetail> details, int leadCount, int time1) {
...@@ -2208,12 +2097,12 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2208,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 16:00 +10 -01 16:00 换型10:00 08:00
//01 18:00 +10 -02 08:00<0 换型 休息时间满足 //01 18:00 +10 -02 08:00<0 换型 休息时间满足
//01 18:00 +20 -02 08:00>0 //01 18:00 +20 -02 08:00>0
//01 18:00 +10 -02 00:00>0 //01 18:00 +10 -02 00:00>0
return reslte; return reslte;
}else { }else {
//开始时间加上设置时间重新算 //开始时间加上设置时间重新算
//如果是前提供任务是相同的则跳出 //如果是前提供任务是相同的则跳出
...@@ -2252,7 +2141,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2252,7 +2141,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
{ {
return reslte; return reslte;
} }
// LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS); // LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);
GAScheduleResult lastGeneOnMachine=machineTasks.get(machineTasks.size()-1); GAScheduleResult lastGeneOnMachine=machineTasks.get(machineTasks.size()-1);
...@@ -2266,7 +2155,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2266,7 +2155,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
if(AvailableTimeSegment!=null) { if(AvailableTimeSegment!=null) {
reslte.put(6,AvailableTimeSegment); 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; earliestStartTime= earliestStartTime>start ?earliestStartTime:start;
int earliestStartTime1=earliestStartTime; int earliestStartTime1=earliestStartTime;
...@@ -2307,14 +2196,14 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2307,14 +2196,14 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
} }
Entry prev= _allOperations.stream(). Entry prev= _allOperations.stream().
filter(t->t.getExecId().equals(ExecId)) filter(t->t.getExecId().equals(ExecId))
.findFirst().orElse(null); .findFirst().orElse(null);
int setupTime=0; int setupTime=0;
if(prev!=null) if(prev!=null)
{ {
//离散参数 //离散参数
// prev.getDiscreteParameter() // prev.getDiscreteParameter()
// setupTime = (prev.getProductId() != operation.getProductId()) // setupTime = (prev.getProductId() != operation.getProductId())
// ? (int) discreteParameterMatrixService.getDiscreteParameterMatrixValue(prev, operation) // ? (int) discreteParameterMatrixService.getDiscreteParameterMatrixValue(prev, operation)
...@@ -2336,7 +2225,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2336,7 +2225,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
} }
// setupTime=20*3600; // setupTime=20*3600;
operation.setChangeLineTime(setupTime); operation.setChangeLineTime(setupTime);
if(setupTime==0) if(setupTime==0)
{ {
...@@ -2355,20 +2244,20 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2355,20 +2244,20 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
{ {
cha=cha+1;//加1是工序开始加工时间 cha=cha+1;//加1是工序开始加工时间
reslte.put(2,lastGeneOnMachine.getEndTime());//换型开始时间 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 { else {
reslte.put(2,earliestStartTime-setupTime);//换型开始时间 reslte.put(2,earliestStartTime-setupTime);//换型开始时间
//如果空余时间足够 //如果空余时间足够
//可能会往前或后暂用设备时间 //可能会往前或后暂用设备时间
return reslte; return reslte;
} }
}else { }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);
} }
...@@ -2443,7 +2332,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2443,7 +2332,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
.filter(t -> orderIds.contains(t.getOrderId())) .filter(t -> orderIds.contains(t.getOrderId()))
.max(Comparator.comparing(Order::getDueDate)) .max(Comparator.comparing(Order::getDueDate))
.orElse(null); .orElse(null);
if (order.isNewCreate()) { if (order.isNewSfCreate()) {
continue; continue;
} }
LocalDateTime dueDateTime = order.getDueDate(); LocalDateTime dueDateTime = order.getDueDate();
...@@ -2549,13 +2438,13 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2549,13 +2438,13 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
return chromosome.getGeneStr(); return chromosome.getGeneStr();
// 拼接机器选择:用 "," 分隔(例:1,3,2,4) // 拼接机器选择:用 "," 分隔(例:1,3,2,4)
// String machineStr = chromosome.getMachineStr(); // String machineStr = chromosome.getMachineStr();
// 拼接工序排序:用 "|" 分隔(例:2|1|3|4) // 拼接工序排序:用 "|" 分隔(例: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 { ...@@ -25,6 +25,10 @@ public class GeneticOperations {
private static ScheduleParams param; private static ScheduleParams param;
public GeneticOperations() {
}
public GeneticOperations(GlobalParam globalParam,List<Entry> _allOperations,ScheduleParams _param) { public GeneticOperations(GlobalParam globalParam,List<Entry> _allOperations,ScheduleParams _param) {
_GlobalParam=globalParam; _GlobalParam=globalParam;
allOperations = _allOperations; allOperations = _allOperations;
...@@ -424,10 +428,12 @@ public class GeneticOperations { ...@@ -424,10 +428,12 @@ public class GeneticOperations {
public void DelOrder(Chromosome chromosome) { public void DelOrder(Chromosome chromosome) {
List<Entry> allOperations = chromosome.getAllOperations(); List<Entry> allOperations = chromosome.getAllOperations();
List<GlobalOperationInfo> globalOpList= chromosome.getGlobalOpList(); List<GlobalOperationInfo> globalOpList= chromosome.getGlobalOpList();
if(chromosome.getOrders()==null||chromosome.getOrders().size()==0)
return;
List<Order> orders = chromosome.getOrders(); List<Order> orders = chromosome.getOrders();
List<Integer> OperationSequencing= chromosome.getOperationSequencing(); List<Integer> OperationSequencing= chromosome.getOperationSequencing();
List<Integer> newoorderids= orders.stream() List<Integer> newoorderids= orders.stream()
.filter(t->t.isNewCreate()) .filter(t->t.isNewSfCreate())
.map(Order::getId) .map(Order::getId)
.sorted(Comparator.reverseOrder()) .sorted(Comparator.reverseOrder())
.collect(Collectors.toList()); .collect(Collectors.toList());
......
package com.aps.service.Algorithm; package com.aps.service.Algorithm;
import com.aps.common.util.FileHelper; import com.aps.common.util.FileHelper;
import com.aps.common.util.GlobalCacheUtil;
import com.aps.common.util.ProductionDeepCopyUtil; import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.*; import com.aps.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult; import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
...@@ -21,6 +22,11 @@ public class HillClimbing { ...@@ -21,6 +22,11 @@ public class HillClimbing {
private List<Entry> allOperations; private List<Entry> allOperations;
private List<Order> orders;
private List<Material> materials;
private List<GroupResult> _entryRel;
//按优先级分组工序 //按优先级分组工序
private Map<Double, List<Entry>> priorityGroups; private Map<Double, List<Entry>> priorityGroups;
...@@ -30,10 +36,17 @@ public class HillClimbing { ...@@ -30,10 +36,17 @@ public class HillClimbing {
// 从List转为Map op.getGroupId() + "_" + op.getSequence(); 做主键 // 从List转为Map op.getGroupId() + "_" + op.getSequence(); 做主键
private Map<String, Entry> entrys; private Map<String, Entry> entrys;
public HillClimbing(List<Entry> allOperations) { private FitnessCalculator fitnessCalculator;
public HillClimbing(List<Entry> allOperations, List<Order> orders,
List<Material> materials,List<GroupResult> entryRel, FitnessCalculator _fitnessCalculator) {
this.allOperations = allOperations; this.allOperations = allOperations;
this.orders = orders;
this.materials = materials;
_entryRel=entryRel;
fitnessCalculator=_fitnessCalculator;
// 按优先级分组工序 // 按优先级分组工序
priorityGroups = groupOperationsByPriority(); priorityGroups = groupOperationsByPriority();
...@@ -92,7 +105,7 @@ public class HillClimbing { ...@@ -92,7 +105,7 @@ public class HillClimbing {
Chromosome machineChange = generateMachineChange(current, op.getMachineOptions(), maPos); Chromosome machineChange = generateMachineChange(current, op.getMachineOptions(), maPos);
if (machineChange != null) { if (machineChange != null) {
decode(decoder, machineChange); decode(decoder, machineChange,machines);
if (isBetter(machineChange, current)) { if (isBetter(machineChange, current)) {
current = machineChange; current = machineChange;
if (isBetter(current, best)) { if (isBetter(current, best)) {
...@@ -263,7 +276,7 @@ public class HillClimbing { ...@@ -263,7 +276,7 @@ public class HillClimbing {
Chromosome machineChange = generateMachineChange(current, op.getMachineOptions(), maPos); Chromosome machineChange = generateMachineChange(current, op.getMachineOptions(), maPos);
if (machineChange != null) { if (machineChange != null) {
decode(decoder, machineChange); decode(decoder, machineChange,machines);
if (isBetter(machineChange, current)) { if (isBetter(machineChange, current)) {
current = machineChange; current = machineChange;
if (isBetter(current, best)) { if (isBetter(current, best)) {
...@@ -328,7 +341,7 @@ public class HillClimbing { ...@@ -328,7 +341,7 @@ public class HillClimbing {
} }
Chromosome newChromosome = swapAtDistance(current, opPos, -s * step); Chromosome newChromosome = swapAtDistance(current, opPos, -s * step);
decode(decoder, newChromosome); decode(decoder, newChromosome,machines);
if (isBetter(newChromosome, current)) { if (isBetter(newChromosome, current)) {
current = newChromosome; current = newChromosome;
...@@ -357,7 +370,7 @@ public class HillClimbing { ...@@ -357,7 +370,7 @@ public class HillClimbing {
} }
Chromosome newChromosome = swapAtDistance(current, opPos, s * step); Chromosome newChromosome = swapAtDistance(current, opPos, s * step);
decode(decoder, newChromosome); decode(decoder, newChromosome,machines);
if (isBetter(newChromosome, current)) { if (isBetter(newChromosome, current)) {
current = newChromosome; current = newChromosome;
...@@ -411,21 +424,24 @@ public class HillClimbing { ...@@ -411,21 +424,24 @@ public class HillClimbing {
} }
private void writeKpi(Chromosome chromosome) {
/** String fitness = "";
* 构建位置索引:groupId_sequence -> position
*/
private Map<String, Integer> buildPositionIndex(Chromosome chromosome) {
String fitness="";
double[] fitness1 = chromosome.getFitnessLevel(); double[] fitness1 = chromosome.getFitnessLevel();
for (int i = 0; i < fitness1.length; i++) { for (int i = 0; i < fitness1.length; i++) {
fitness+=fitness1[i]+","; fitness += fitness1[i] + ",";
} }
FileHelper.writeLogFile(String.format("爬山法 - kpi:%s", fitness)); FileHelper.writeLogFile(String.format("爬山法 - kpi:%s", fitness));
}
/**
* 构建位置索引:groupId_sequence -> position
*/
private Map<String, Integer> buildPositionIndex(Chromosome chromosome) {
writeKpi(chromosome);
Map<String, Integer> index = new HashMap<>(); Map<String, Integer> index = new HashMap<>();
List<Integer> os = chromosome.getOperationSequencing(); List<Integer> os = chromosome.getOperationSequencing();
...@@ -546,114 +562,6 @@ public class HillClimbing { ...@@ -546,114 +562,6 @@ public class HillClimbing {
} }
return neighbor; return neighbor;
} }
/**
* 生成邻域解
*/
private List<Chromosome> generateNeighbors(Chromosome chromosome) {
List<Chromosome> neighbors = new ArrayList<>();
// 生成交换邻域
neighbors.add(generateSwapNeighbor(chromosome));
// 生成反转邻域
neighbors.add(generateReverseNeighbor(chromosome));
// 生成插入邻域
neighbors.add(generateInsertNeighbor(chromosome));
// 生成机器选择邻域
neighbors.add(generateMachineChangeNeighbor(chromosome));
return neighbors;
}
/**
* 生成交换邻域解
*/
private Chromosome generateSwapNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
while (idx2 == idx1) {
idx2 = rnd.nextInt(os.size());
}
java.util.Collections.swap(os, idx1, idx2);
neighbor.setOperationSequencing(os);
}
return neighbor;
}
/**
* 生成反转邻域解
*/
private Chromosome generateReverseNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
int start = rnd.nextInt(os.size());
int end = rnd.nextInt(os.size());
while (end <= start) {
end = rnd.nextInt(os.size());
}
java.util.Collections.reverse(os.subList(start, end + 1));
neighbor.setOperationSequencing(os);
}
return neighbor;
}
/**
* 生成插入邻域解
*/
private Chromosome generateInsertNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
while (idx2 == idx1) {
idx2 = rnd.nextInt(os.size());
}
int value = os.remove(idx1);
os.add(idx2, value);
neighbor.setOperationSequencing(os);
}
return neighbor;
}
/**
* 生成机器选择邻域解
*/
private Chromosome generateMachineChangeNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> ms = neighbor.getMachineSelection();
List<GlobalOperationInfo> globalOpList=chromosome.getGlobalOpList();
if (!ms.isEmpty()) {
int idx = rnd.nextInt(ms.size());
GlobalOperationInfo globalOp = globalOpList.get(idx);
Entry op = globalOp.getOp();
if (op.getMachineOptions().size() > 1) {
int currentMachineSeq = ms.get(idx);
List<Integer> availableMachines = new ArrayList<>();
for (int i = 1; i <= op.getMachineOptions().size(); i++) {
if (i != currentMachineSeq) {
availableMachines.add(i);
}
}
if (!availableMachines.isEmpty()) {
int newMachineSeq = availableMachines.get(rnd.nextInt(availableMachines.size()));
ms.set(idx, newMachineSeq);
neighbor.setMachineSelection(ms);
}
}
}
return neighbor;
}
/** /**
* 生成机器选择邻域解 * 生成机器选择邻域解
*/ */
...@@ -703,12 +611,35 @@ public class HillClimbing { ...@@ -703,12 +611,35 @@ public class HillClimbing {
/** /**
* 解码染色体 * 解码染色体
*/ */
private void decode(GeneticDecoder decoder, Chromosome chromosome) { private void decode(GeneticDecoder decoder, Chromosome chromosome , List<Machine> machines) {
// chromosome.setResult(new java.util.concurrent.CopyOnWriteArrayList<>()); chromosome.setResult(new CopyOnWriteArrayList<>());
decoder.decodeChromosomeWithCache(chromosome);
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(orders), Order.class) ); // 简单拷贝,实际可能需要深拷贝
chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(_entryRel), GroupResult.class) ); // 简单拷贝,实际可能需要深拷贝
chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyList(materials,Material.class)); // 简单拷贝,实际可能需要深拷贝
chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) ); // 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights);
// chromosome.setBaseTime(param.getBaseTime());
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
// 加载锁定工单到ResultOld
List<GAScheduleResult> lockedOrders = GlobalCacheUtil.get("locked_orders_" + chromosome.getScenarioID());
if (lockedOrders != null && !lockedOrders.isEmpty()) {
chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(lockedOrders, GAScheduleResult.class));
FileHelper.writeLogFile("将 " + lockedOrders.size() + " 个锁定工单加载到初始种群中");
} else {
chromosome.setResultOld(new CopyOnWriteArrayList<>());
}
decoder.decodeChromosomeWithCache(chromosome,false);
} }
/** /**
* 比较两个染色体的优劣 * 比较两个染色体的优劣
*/ */
......
package com.aps.service.Algorithm; package com.aps.service.Algorithm;
import com.aps.common.util.DateTimeUtil; import com.aps.common.util.*;
import com.aps.common.util.DeepCopyUtil; import com.aps.entity.Algorithm.*;
import com.aps.common.util.FileHelper;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult; import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.*; import com.aps.entity.basic.*;
import com.aps.service.plan.MachineSchedulerService; import com.aps.service.plan.MachineSchedulerService;
...@@ -55,11 +52,11 @@ public class HybridAlgorithm { ...@@ -55,11 +52,11 @@ public class HybridAlgorithm {
// 初始化算法实例 // 初始化算法实例
private HillClimbing _hillClimbing; private HillClimbing _hillClimbing;
private SimulatedAnnealing _simulatedAnnealing; private SimulatedAnnealing _simulatedAnnealing;
private ParallelLocalSearch _parallelLocalSearch;
// 初始化算法实例 // 初始化算法实例
private TabuSearch _tabuSearch; private TabuSearch _tabuSearch;
private TabuSearchWithSA _tabuSearchWithSA;
public HybridAlgorithm(GlobalParam globalParam,List<Machine> machines, List<Order> orders, public HybridAlgorithm(GlobalParam globalParam,List<Machine> machines, List<Order> orders,
...@@ -109,18 +106,16 @@ int opcount=allOperations.size(); ...@@ -109,18 +106,16 @@ int opcount=allOperations.size();
// 预生成全局工序列表(所有初始化方法共享同一顺序) // 预生成全局工序列表(所有初始化方法共享同一顺序)
List<GlobalOperationInfo> globalOpList = initialization.generateGlobalOpList(); List<GlobalOperationInfo> globalOpList = initialization.generateGlobalOpList();
// 初始化变邻域搜索 // 初始化变邻域搜索
_vns = new VariableNeighborhoodSearch(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights); _vns = new VariableNeighborhoodSearch( allOperations,orders,materials,_entryRel, _fitnessCalculator );
_hillClimbing = new HillClimbing(allOperations); _hillClimbing = new HillClimbing(allOperations,orders,materials,_entryRel, _fitnessCalculator);
_simulatedAnnealing = new SimulatedAnnealing( allOperations); _simulatedAnnealing = new SimulatedAnnealing( allOperations,orders,materials,_entryRel, _fitnessCalculator);
_parallelLocalSearch = new ParallelLocalSearch(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights); _tabuSearch = new TabuSearch(allOperations,orders,materials,_entryRel, _fitnessCalculator);
_tabuSearch = new TabuSearch(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights);
_tabuSearchWithSA = new TabuSearchWithSA(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights);
FileHelper.writeLogFile("初始化种群-----------开始-------"); FileHelper.writeLogFile("初始化种群-----------开始-------");
// 步骤1:使用构造启发式算法生成初始种群 // 步骤1:使用构造启发式算法生成初始种群
FileHelper.writeLogFile("构造启发式初始化-----------开始-------"); FileHelper.writeLogFile("构造启发式初始化-----------开始-------");
List<Chromosome> population = initialization.generateHeuristicInitialPopulation(param, globalOpList); List<Chromosome> population = initialization.generateHeuristicInitialPopulation(param);
FileHelper.writeLogFile("构造启发式初始化-----------结束-------"); FileHelper.writeLogFile("构造启发式初始化-----------结束-------");
...@@ -138,15 +133,15 @@ int opcount=allOperations.size(); ...@@ -138,15 +133,15 @@ int opcount=allOperations.size();
FileHelper.writeLogFile("按Objectives去重-----------开始-------" + population.size()); FileHelper.writeLogFile("按Objectives去重-----------开始-------" + population.size());
population = chromosomeDistinctByObjectives(population); population = chromosomeDistinctByObjectives(population);
FileHelper.writeLogFile("按Objectives去重-----------结束-------" + population.size()); FileHelper.writeLogFile("按Objectives去重-----------结束-------" + population.size());
// if(1==1)
// return getBestChromosome(population.get(0), param.getBaseTime(), starttime);
// 步骤2:对初始种群进行爬山法局部优化 // 步骤2:对初始种群进行爬山法局部优化
if(opcount<20 ) { if(opcount<20 ) {
FileHelper.writeLogFile("爬山法局部优化-----------开始-------"); FileHelper.writeLogFile("爬山法局部优化-----------开始-------");
GeneticDecoder hillClimbingDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId); GeneticDecoder hillClimbingDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
Chromosome optimized = _hillClimbing.BatchSearchAll(population,machines, hillClimbingDecoder); Chromosome optimized = _hillClimbing.search(population.get(0), hillClimbingDecoder,machines);
FileHelper.writeLogFile("爬山法局部优化-----------结束-------"); FileHelper.writeLogFile("爬山法局部优化-----------结束-------");
return getBestChromosome(optimized, param.getBaseTime(), starttime); return getBestChromosome(optimized, param.getBaseTime(), starttime);
} }
...@@ -156,27 +151,37 @@ int opcount=allOperations.size(); ...@@ -156,27 +151,37 @@ int opcount=allOperations.size();
// 步骤2:对初始种群进行模拟退火+爬山法优化 // 步骤2:对初始种群进行模拟退火+爬山法优化
GeneticDecoder saDecoder1 = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId); GeneticDecoder saDecoder1 = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
GeneticDecoder vnsDecoder1 = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
GeneticDecoder tabuDecoder1 = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
if(opcount<800 ) { if(opcount<800 ) {
FileHelper.writeLogFile("模拟退火+爬山法优化-----------开始-------"); FileHelper.writeLogFile("模拟退火+爬山法优化-----------开始-------");
Chromosome saHcOptimized = _simulatedAnnealing.batchSearchGetMax(population, saDecoder1, machines); Chromosome saHcOptimized = _simulatedAnnealing.searchWithHillClimbing(population.get(0),_vns, saDecoder1, machines);
FileHelper.writeLogFile("模拟退火+爬山法优化-----------结束-------"); FileHelper.writeLogFile("模拟退火+爬山法优化-----------结束-------");
return getBestChromosome(saHcOptimized, param.getBaseTime(), starttime); return getBestChromosome(saHcOptimized, param.getBaseTime(), starttime);
} }
if(opcount>=800 ) {
Chromosome best=population.get(0);
best = _simulatedAnnealing.search(best, _tabuSearch, _vns, saDecoder1, machines);
best = _vns.search(best, vnsDecoder1, machines);
best = _tabuSearch.search(best, _vns, tabuDecoder1, machines);
return getBestChromosome(best, param.getBaseTime(), starttime);
}
List<List<Chromosome>> combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(population);
Chromosome best=ProductionDeepCopyUtil.deepCopy(population.get(0), Chromosome.class); // GetBest(combinedFronts,"初始");
int ordercount = globalOpList.stream() int ordercount = globalOpList.stream()
.mapToInt(GlobalOperationInfo::getGroupId) .mapToInt(GlobalOperationInfo::getGroupId)
.max() .max()
.orElse(0); .orElse(0);
Chromosome best=GetBest(combinedFronts,"初始");
// best=fronts.get(0).stream()
// .max(Comparator.comparingDouble(Chromosome::getFitness))
// .orElse(null);
double bestFitness=best.getFitness();
if(population.size()<param.getTournamentSize()) if(population.size()<param.getTournamentSize())
{ {
...@@ -185,7 +190,8 @@ int opcount=allOperations.size(); ...@@ -185,7 +190,8 @@ int opcount=allOperations.size();
} }
int Iteration=0; int noImproveCount = 0;
int maxNoImprove = 10;
// 步骤2:迭代进化 // 步骤2:迭代进化
FileHelper.writeLogFile("迭代进化-----------开始-------"+param.getMaxIterations()); FileHelper.writeLogFile("迭代进化-----------开始-------"+param.getMaxIterations());
for (int iter = 0; iter < param.getMaxIterations(); iter++) { for (int iter = 0; iter < param.getMaxIterations(); iter++) {
...@@ -193,6 +199,7 @@ int opcount=allOperations.size(); ...@@ -193,6 +199,7 @@ int opcount=allOperations.size();
FileHelper.writeLogFile("迭代进化------"+iter+"-----开始-------"); FileHelper.writeLogFile("迭代进化------"+iter+"-----开始-------");
// 计算种群适应度标准差,微调参数 // 计算种群适应度标准差,微调参数
double fitnessStd = _fitnessCalculator.calculateFitnessStd(population); double fitnessStd = _fitnessCalculator.calculateFitnessStd(population);
param.fineTuneParams(iter, fitnessStd); param.fineTuneParams(iter, fitnessStd);
...@@ -204,141 +211,62 @@ int opcount=allOperations.size(); ...@@ -204,141 +211,62 @@ int opcount=allOperations.size();
} }
FileHelper.writeLogFile("选择操作-----------开始-------"); FileHelper.writeLogFile("选择操作-----------开始-------");
// 选择前移除适应度为 0 或明显劣于当前最优解的个体,减少选择池规模:
double minValidFitness = bestFitness * 0.5; // 保留最优解50%以上的个体
List<Chromosome> validPopulation = population.stream()
.filter(c -> c.getFitness() >= minValidFitness)
.collect(Collectors.toList());
// 选择操作 // 选择操作
List<Chromosome> selected = geneticOps.tournamentSelection(validPopulation); List<Chromosome> selected = geneticOps.tournamentSelection(population);
FileHelper.writeLogFile("选择操作-----------结束-------"); FileHelper.writeLogFile("选择操作-----------结束-------");
// 变邻域搜索
FileHelper.writeLogFile("变邻域搜索-----------开始-------");
GeneticDecoder vnsDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
List<Chromosome> vnsImproved = _vns.search(selected, vnsDecoder, param);
selected.addAll(vnsImproved);
FileHelper.writeLogFile("变邻域搜索-----------结束-------");
// 模拟退火全局搜索
FileHelper.writeLogFile("模拟退火搜索-----------开始-------");
GeneticDecoder saDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
List<Chromosome> saImproved = new ArrayList<>();
for (Chromosome chromosome : selected) {
// Chromosome saOptimized = _simulatedAnnealing.search(chromosome, saDecoder, param);
// saImproved.add(saOptimized);
}
selected.addAll(saImproved);
FileHelper.writeLogFile("模拟退火搜索-----------结束-------");
// 多种局部搜索算法并行
FileHelper.writeLogFile("并行局部搜索-----------开始-------");
GeneticDecoder parallelDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
List<Chromosome> parallelImproved = new ArrayList<>();
for (Chromosome chromosome : selected) {
Chromosome parallelOptimized = _parallelLocalSearch.search(chromosome, parallelDecoder, param);
parallelImproved.add(parallelOptimized);
}
selected.addAll(parallelImproved);
FileHelper.writeLogFile("并行局部搜索-----------结束-------");
// 禁忌搜索+模拟退火
FileHelper.writeLogFile("禁忌搜索+模拟退火-----------开始-------");
GeneticDecoder tsDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
List<Chromosome> tsImproved = new ArrayList<>();
for (Chromosome chromosome : selected) {
Chromosome tsOptimized = _tabuSearchWithSA.search(chromosome, tsDecoder, param);
tsImproved.add(tsOptimized);
}
selected.addAll(tsImproved);
FileHelper.writeLogFile("禁忌搜索+模拟退火-----------结束-------");
// 交叉操作 // 交叉操作
FileHelper.writeLogFile("交叉操作-----------开始-------"); FileHelper.writeLogFile("交叉操作-----------开始-------");
List<Chromosome> nextPopulation = new ArrayList<>();
for (int i = 0; i < selected.size(); i += 2) {
if (i + 1 >= selected.size()) {
selected.get(i).setID(UUID.randomUUID().toString());
nextPopulation.add(selected.get(i));
break;
}
Chromosome parent1 = selected.get(i);
Chromosome parent2 = selected.get(i + 1);
if (rnd.nextDouble() < param.getCrossoverProb()) {
// 假设PoxCrossover返回包含两个子染色体的数组
Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
nextPopulation.add(children.getFirst());
nextPopulation.add(children.getSecond());
} else {
nextPopulation.add(parent1);
nextPopulation.add(parent2);
}
}
FileHelper.writeLogFile("交叉操作-----------结束-------");
FileHelper.writeLogFile("变异操作-----------开始-------");
// 变异操作
List<Chromosome> nextPopulation1 = new ArrayList<>();
for (Chromosome chromosome : nextPopulation) {
if (rnd.nextDouble() < param.getMutationProb()) {
Chromosome chromosome1= ProductionDeepCopyUtil.deepCopy(chromosome,Chromosome.class);
chromosome1.setID(UUID.randomUUID().toString());
geneticOps.mutate(chromosome1, globalOpList);
nextPopulation1.add(chromosome1);
}
}
nextPopulation.addAll(nextPopulation1);
FileHelper.writeLogFile("变异操作-----------结束-------");
FileHelper.writeLogFile("变异批量解码-----------开始-------");
Chromosomedecode(param,allOperations,globalOpList,nextPopulation);
FileHelper.writeLogFile("变异批量解码-----------结束-------");
// // 精英保留
// List<Chromosome> population1 = population.stream()
// .sorted((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()))
// .collect(Collectors.toList()); // 降序排序
//
//
// List<Chromosome> elites = population1.subList(0, param.getElitismCount());
List<Chromosome> newPopulation = new ArrayList<>(); List<Chromosome> newPopulation = new ArrayList<>();
//保留一定数量的上一代 newPopulation.add(best);
List<Chromosome> populationcopy = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize()/5); int n=0;
while (newPopulation.size() < param.getPopulationSize()) {
newPopulation.addAll(populationcopy); // 选择父代
newPopulation.addAll(nextPopulation); FileHelper.writeLogFile("交叉-----------开始-------"+n);
newPopulation= chromosomeDistinct1(newPopulation);
FileHelper.writeLogFile("非支配排序-----------开始-------"); Chromosome parent1 = selected.get(rnd.nextInt(selected.size()));
// 2.7 非支配排序 Chromosome parent2 = selected.get(rnd.nextInt(selected.size()));
combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(newPopulation); // 交叉
FileHelper.writeLogFile("非支配排序-----------结束-------"); Chromosome child = parent1;
// 2.8 选择下一代种群 // if (rnd.nextDouble() < param.getCrossoverProb()) {
population = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize()); // // 假设PoxCrossover返回包含两个子染色体的数组
// 更新种群 // Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
// population = newPopulation.stream() // child=children.getFirst();
// .limit(param.getPopulationSize() ) // initDataToChromosome(child,param, allOperations,globalOpList);
// .collect(Collectors.toList()); // child.setID(UUID.randomUUID().toString());
// }
// // 变异
// if (rnd.nextDouble() < param.getMutationProb()) {
// geneticOps.mutate(child, globalOpList);
// }
// 核心融合链(工业级标准顺序:GA生成子代 → SA跳坑 → VNS扩邻域 → TS精优化)
child = _simulatedAnnealing.search(child,_tabuSearch,_vns, saDecoder1, machines);
child = _vns.search(child, vnsDecoder1, machines);
child = _tabuSearch.search(child, _vns,tabuDecoder1, machines);
newPopulation.add(child);
FileHelper.writeLogFile("交叉-----------结束-------"+n);
}
population= chromosomeDistinctByObjectives(newPopulation);;
best= GetBest(combinedFronts,String.valueOf(iter)); if(_fitnessCalculator.isBetter(population.get(0),best))
if(bestFitness<best.getFitness())
{ {
bestFitness=best.getFitness(); best=ProductionDeepCopyUtil.deepCopy(population.get(0), Chromosome.class); // GetBest(combinedFronts,"初始");
Iteration=1;
noImproveCount=1;
}else { }else {
Iteration++; noImproveCount++;
if (Iteration > 5) { if (noImproveCount > 5) {
// 当连续 5 代无最优解提升时,降低交叉概率(如从 0.8 降至 0.5)、提高变异概率(如从 0.1 升至 0.2) // 当连续 5 代无最优解提升时,降低交叉概率(如从 0.8 降至 0.5)、提高变异概率(如从 0.1 升至 0.2)
param.fineTuneParams(); param.fineTuneParams();
} }
} }
if(Iteration>10) if(noImproveCount>maxNoImprove)
{ {
break; break;
} }
...@@ -379,18 +307,7 @@ int opcount=allOperations.size(); ...@@ -379,18 +307,7 @@ int opcount=allOperations.size();
return best; return best;
} }
private Chromosome GetBest(List<List<Chromosome>> fronts,String msg)
{
// WriteKpis(fronts,msg);
List<Chromosome> fChromosomes= fronts.get(0);
fChromosomes.sort((c1, c2) -> {
int rankCompare = Double.compare(c1.getCrowdingDistance(), c2.getCrowdingDistance());
return rankCompare != 0 ? rankCompare : Double.compare(c1.getFitness(), c2.getFitness());
});
Chromosome best=fChromosomes.get(0);
// WriteKpi(best,"最大");
return best;
}
private List<Chromosome> chromosomeDistinct(List<Chromosome> population) private List<Chromosome> chromosomeDistinct(List<Chromosome> population)
{ {
if(population==null) if(population==null)
...@@ -413,7 +330,7 @@ int opcount=allOperations.size(); ...@@ -413,7 +330,7 @@ int opcount=allOperations.size();
} }
/** /**
* 按Objectives去重,相同目标值的方案只保留一个(保留fitness最大的) * 按Objectives去重
*/ */
private List<Chromosome> chromosomeDistinctByObjectives(List<Chromosome> population) private List<Chromosome> chromosomeDistinctByObjectives(List<Chromosome> population)
{ {
...@@ -440,34 +357,36 @@ int opcount=allOperations.size(); ...@@ -440,34 +357,36 @@ int opcount=allOperations.size();
} }
} }
return new ArrayList<>(objectivesMap.values()); // 按 fitnessLevel 倒序排序(多层次比较)
} List<Chromosome> result = new ArrayList<>(objectivesMap.values());
result.sort((c1, c2) -> {
if (isBetter(c1, c2)) {
return -1; // c1 比 c2 好,c1 应该排在前面
} else if (isBetter(c2, c1)) {
return 1; // c2 比 c1 好,c2 应该排在前面
} else {
return 0; // 两者相等
}
});
private List<Chromosome> chromosomeDistinct1(List<Chromosome> population) return result;
{ }
if(population==null) /**
{ * 比较两个染色体的优劣(基于fitnessLevel多层次比较)
FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",0 )); */
return population; private boolean isBetter(Chromosome c1, Chromosome c2) {
for (int i = 0; i < c1.getFitnessLevel().length; i++) {
double[] Fitness1 = c1.getFitnessLevel();
double[] Fitness2 = c2.getFitnessLevel();
if (Fitness1[i] > Fitness2[i]) {
return true;
}
} }
return false;
}
// List<Chromosome> population1 = population.stream().filter(t->t.getGeneStr()==null).collect(Collectors.toList());
population = population.stream()
.collect(Collectors.toMap(
Chromosome::getGeneStr, // key:去重的字段(GeneStr)
u -> u, // value:Chromosome对象
(u1, u2) -> u1.getFitness() > u2.getFitness() ? u1 : u2 // 重复时保留第一个元素
))
.values() // 获取去重后的
.stream()
.collect(Collectors.toList());
return population;
}
private void WriteKpis(List<List<Chromosome>> fronts,String index) { private void WriteKpis(List<List<Chromosome>> fronts,String index) {
for (int i=0;i<fronts.size();i++) for (int i=0;i<fronts.size();i++)
{ {
...@@ -496,6 +415,40 @@ int opcount=allOperations.size(); ...@@ -496,6 +415,40 @@ int opcount=allOperations.size();
new ThreadPoolExecutor.CallerRunsPolicy() // 任务满了主线程执行,不丢失任务 new ThreadPoolExecutor.CallerRunsPolicy() // 任务满了主线程执行,不丢失任务
); );
private void initDataToChromosome(Chromosome chromosome,ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList) {
if (chromosome==null){
System.out.println("chromosome==null");
return;
}
chromosome.setResult(new CopyOnWriteArrayList<>());
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(orders), Order.class) ); // 简单拷贝,实际可能需要深拷贝
chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(_entryRel), GroupResult.class) ); // 简单拷贝,实际可能需要深拷贝
chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyList(materials,Material.class)); // 简单拷贝,实际可能需要深拷贝
chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) ); // 简单拷贝,实际可能需要深拷贝
chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(globalOpList, GlobalOperationInfo.class) ); // 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights);
chromosome.setBaseTime(param.getBaseTime());
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
// 加载锁定工单到ResultOld
List<GAScheduleResult> lockedOrders = GlobalCacheUtil.get("locked_orders_" + sceneId);
if (lockedOrders != null && !lockedOrders.isEmpty()) {
chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(lockedOrders, GAScheduleResult.class));
FileHelper.writeLogFile("将 " + lockedOrders.size() + " 个锁定工单加载到初始种群中");
} else {
chromosome.setResultOld(new CopyOnWriteArrayList<>());
}
}
private void Chromosomedecode(ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList,List<Chromosome> population) private void Chromosomedecode(ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList,List<Chromosome> population)
{ {
FileHelper.writeLogFile("解码---------------"+population.size() ); FileHelper.writeLogFile("解码---------------"+population.size() );
...@@ -542,7 +495,7 @@ int opcount=allOperations.size(); ...@@ -542,7 +495,7 @@ int opcount=allOperations.size();
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝 // chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679"); // _sceneService.saveChromosomeToFile(chromosome, "12345679");
decoder.decodeChromosomeWithCache(chromosome); decoder.decodeChromosomeWithCache(chromosome,false);
// if (chromosome.getFitness() == 0) { // if (chromosome.getFitness() == 0) {
// chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights)); // chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights));
// } // }
......
...@@ -343,7 +343,7 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders)); ...@@ -343,7 +343,7 @@ chromo.setOrders(new CopyOnWriteArrayList<>(orders));
/** /**
* 使用构造启发式算法生成初始种群 * 使用构造启发式算法生成初始种群
*/ */
public List<Chromosome> generateHeuristicInitialPopulation(ScheduleParams param, List<GlobalOperationInfo> globalOpList) { public List<Chromosome> generateHeuristicInitialPopulation(ScheduleParams param) {
List<Chromosome> population = new ArrayList<>(); List<Chromosome> population = new ArrayList<>();
int populationSize = param.getPopulationSize(); int populationSize = param.getPopulationSize();
this.baseTime=param.getBaseTime(); this.baseTime=param.getBaseTime();
......
...@@ -102,20 +102,20 @@ public class MaterialRequirementService { ...@@ -102,20 +102,20 @@ public class MaterialRequirementService {
.collect(Collectors.toList()); .collect(Collectors.toList());
List<RoutingHeader> routingHeaders=null; List<RoutingHeader> routingHeaders=null;
LambdaQueryWrapper<RoutingHeader> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<RoutingHeader> wrapper = new LambdaQueryWrapper<>();
wrapper.in(RoutingHeader::getId, routingIds); wrapper.in(RoutingHeader::getId, routingIds);
// .eq(RoutingHeader::getIsDeleted, 0) // .eq(RoutingHeader::getIsDeleted, 0)
// .eq(RoutingHeader::getApprovalStatus, 1); // .eq(RoutingHeader::getApprovalStatus, 1);
routingHeaders = routingHeaderMapper.selectList(wrapper); routingHeaders = routingHeaderMapper.selectList(wrapper);
List<Routingsupporting> routingsupportings=null; List<Routingsupporting> routingsupportings=null;
// 查询并缓存Routingsupporting // 查询并缓存Routingsupporting
LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>();
routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, routingIds) routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, routingIds)
.eq(Routingsupporting::getIsdeleted, 0); .eq(Routingsupporting::getIsdeleted, 0);
routingsupportings = routingsupportingMapper.selectList(routingsupportingwrapper); routingsupportings = routingsupportingMapper.selectList(routingsupportingwrapper);
// 查询并缓存RoutingSupportingReplace // 查询并缓存RoutingSupportingReplace
...@@ -126,10 +126,10 @@ public class MaterialRequirementService { ...@@ -126,10 +126,10 @@ public class MaterialRequirementService {
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>();
routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, routingsupportingids) routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, routingsupportingids)
.eq(RoutingSupportingReplace::getIsdeleted, 0); .eq(RoutingSupportingReplace::getIsdeleted, 0);
replaces = routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper); replaces = routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper);
} }
List<Material> useMaterials=new ArrayList<>(); List<Material> useMaterials=new ArrayList<>();
...@@ -145,7 +145,7 @@ public class MaterialRequirementService { ...@@ -145,7 +145,7 @@ public class MaterialRequirementService {
.collect(Collectors.toList()); .collect(Collectors.toList());
String orderId= order.getOrderId(); String orderId= order.getOrderId();
if(MaterialRequirements!=null) if(MaterialRequirements!=null)
{ {
...@@ -174,12 +174,12 @@ public class MaterialRequirementService { ...@@ -174,12 +174,12 @@ public class MaterialRequirementService {
} }
if(component.getSpentQty()==null) if(component.getSpentQty()==null)
{ {
throw new RuntimeException("配套数据有问题,需求数量为空,请检查数据,"+component.getMaterialNumber()); throw new RuntimeException("配套数据有问题,需求数量为空,请检查数据,"+component.getMaterialNumber());
} }
double allneeded = component.getSpentQty().doubleValue()/ component.getMainQty().doubleValue() * operation.getQuantity(); double allneeded = component.getSpentQty().doubleValue()/ component.getMainQty().doubleValue() * operation.getQuantity();
OrderMaterialRequirement orderMaterialRequirement = CreateMaterialRequirement(material, orderId, "", operation, 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()); orderMaterialRequirement.setBomId(component.getStrId());
if (!material.getMaterialTypeName().equals("MP") && isIsCheckSf) { if (!material.getMaterialTypeName().equals("MP") && isIsCheckSf) {
materialIds.add(materialId);//半成品ID materialIds.add(materialId);//半成品ID
...@@ -276,76 +276,76 @@ public class MaterialRequirementService { ...@@ -276,76 +276,76 @@ public class MaterialRequirementService {
LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>();
routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, routingIds) routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, routingIds)
.eq(Routingsupporting::getIsdeleted, 0); .eq(Routingsupporting::getIsdeleted, 0);
routingsupportings1 = routingsupportingMapper.selectList(routingsupportingwrapper); routingsupportings1 = routingsupportingMapper.selectList(routingsupportingwrapper);
if(routingsupportings1!=null&&routingsupportings1.size()>0) if(routingsupportings1!=null&&routingsupportings1.size()>0)
{ {
routingsupportings.addAll(routingsupportings1); routingsupportings.addAll(routingsupportings1);
List<String> routingsupportingids = routingsupportings1.stream() List<String> routingsupportingids = routingsupportings1.stream()
.map(Routingsupporting::getStrId) .map(Routingsupporting::getStrId)
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>();
routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, routingsupportingids) routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, routingsupportingids)
.eq(RoutingSupportingReplace::getIsdeleted, 0); .eq(RoutingSupportingReplace::getIsdeleted, 0);
routingsupportingreplaces1 = routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper); routingsupportingreplaces1 = routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper);
routingsupportingreplaces.addAll(routingsupportingreplaces1); routingsupportingreplaces.addAll(routingsupportingreplaces1);
List<String> materialIds=new ArrayList<>(); List<String> materialIds=new ArrayList<>();
for (Routingsupporting routingsupporting:routingsupportings1) { for (Routingsupporting routingsupporting:routingsupportings1) {
String materialID1= routingsupporting.getMaterialId(); 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)) {
Material material = _materials.stream() Material material = _materials.stream()
.filter(m -> m.getId().equals(materialID1)) .filter(m -> m.getId().equals(materialID1))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
if (material != null) { if (material != null) {
useMaterials.add(material); if(!useMaterialids.contains(materialID1)) {
useMaterialids.add(materialID1); useMaterials.add(material);
useMaterialids.add(materialID1);
}
if(!material.getMaterialTypeName().equals("MP")) {
materialIds.add(materialID1);
}
} }
} }
} for (RoutingSupportingReplace routingSupportingReplace:routingsupportingreplaces1) {
String materialID1= routingSupportingReplace.getMaterialid();
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)) { if(!useMaterialids.contains(materialID1)) {
useMaterials.add(m); Material material = _materials.stream()
useMaterialids.add(materialID1); .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) if(routingIds1!=null)
{ {
...@@ -392,7 +392,7 @@ public class MaterialRequirementService { ...@@ -392,7 +392,7 @@ public class MaterialRequirementService {
List<PlanResource> list =GetPlanResources(); List<PlanResource> list =GetPlanResources();
Map<Integer, PlanResource> planResourceByReferenceIdMap = list.stream() Map<Integer, PlanResource> planResourceByReferenceIdMap = list.stream()
.filter(pr -> pr.getReferenceId() != null) .filter(pr -> pr.getReferenceId() != null)
.collect(Collectors.toMap(PlanResource::getReferenceId, Function.identity())); .collect(Collectors.toMap(PlanResource::getReferenceId, Function.identity()));
...@@ -416,7 +416,7 @@ public class MaterialRequirementService { ...@@ -416,7 +416,7 @@ public class MaterialRequirementService {
List<Equipinfo> matchedEquipments = equipinfoByEquipTypeMap.get(machineId.intValue()); List<Equipinfo> matchedEquipments = equipinfoByEquipTypeMap.get(machineId.intValue());
if (matchedEquipments == null || matchedEquipments.isEmpty()) { 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 { ...@@ -477,7 +477,7 @@ public class MaterialRequirementService {
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
routingDiscreteParams = _routingDiscreteParamService.lambdaQuery() routingDiscreteParams = _routingDiscreteParamService.lambdaQuery()
.in(RoutingDiscreteParam::getRoutingDetailId, routingDetailIds) .in(RoutingDiscreteParam::getRoutingDetailId, routingDetailIds)
.eq(RoutingDiscreteParam::getIsDeleted, 0) .eq(RoutingDiscreteParam::getIsDeleted, 0)
.list(); .list();
...@@ -503,8 +503,6 @@ public class MaterialRequirementService { ...@@ -503,8 +503,6 @@ public class MaterialRequirementService {
* @return 所有物料需求列表 * @return 所有物料需求列表
*/ */
public List<OrderMaterialRequirement> buildMultiLevelRequirementNetwork(Chromosome chromosome,String sceneId, LocalDateTime _baseTime,GlobalParam _globalParam) { public List<OrderMaterialRequirement> buildMultiLevelRequirementNetwork(Chromosome chromosome,String sceneId, LocalDateTime _baseTime,GlobalParam _globalParam) {
baseTime=_baseTime;
globalParam=_globalParam;
List<OrderMaterialRequirement> allRequirements = new ArrayList<>(); List<OrderMaterialRequirement> allRequirements = new ArrayList<>();
List<Order> childorders = new ArrayList<>(); List<Order> childorders = new ArrayList<>();
List<Entry> _newEntrys = new ArrayList<>(); List<Entry> _newEntrys = new ArrayList<>();
...@@ -519,13 +517,13 @@ public class MaterialRequirementService { ...@@ -519,13 +517,13 @@ public class MaterialRequirementService {
.entrySet().stream() .entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> 0)); .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)); orders.forEach(t->clearFinishOrder(t));
for (Integer groupId : operationSequencing) 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()) { if (demand.getFinishOrderId() != null && !demand.getFinishOrderId().isEmpty()) {
continue; continue;
...@@ -546,7 +544,7 @@ public class MaterialRequirementService { ...@@ -546,7 +544,7 @@ public class MaterialRequirementService {
// 调用BuildOperationBOM方法(返回结果对象替代out参数) // 调用BuildOperationBOM方法(返回结果对象替代out参数)
BOMBuildResult operationResult = buildOperationSFBOM(operation.getOrderId(), "", BOMBuildResult operationResult = buildOperationSFBOM(operation.getOrderId(), "",
operation.getQuantity(), operation, 1,demand,sceneId,chromosome); operation.getQuantity(), operation, 1,demand,sceneId,chromosome,_baseTime,_globalParam);
// // 合并物料需求和子订单 // // 合并物料需求和子订单
if(operationResult!=null) { if(operationResult!=null) {
allRequirements.addAll(operationResult.getMaterialRequirements()); allRequirements.addAll(operationResult.getMaterialRequirements());
...@@ -567,13 +565,13 @@ public class MaterialRequirementService { ...@@ -567,13 +565,13 @@ public class MaterialRequirementService {
return allRequirements; return allRequirements;
} }
private void clearFinishOrder (Order order) private void clearFinishOrder (Order order)
{ {
if (order.getFinishOrderId() == null) { if (order.getFinishOrderId() == null) {
order.setFinishOrderId(new ArrayList<>()); order.setFinishOrderId(new ArrayList<>());
order.setTargetFinishedOperationId(new ArrayList<>()); order.setTargetFinishedOperationId(new ArrayList<>());
}
} }
}
/** /**
* 构建订单BOM * 构建订单BOM
...@@ -586,10 +584,10 @@ private void clearFinishOrder (Order order) ...@@ -586,10 +584,10 @@ private void clearFinishOrder (Order order)
* @return 包含物料需求列表和子订单列表的结果对象 * @return 包含物料需求列表和子订单列表的结果对象
*/ */
public BOMBuildResult buildOrderBOM(String sceneId,int parent, String materialID, String mainorderId, 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); forder.setCreateBom(true);
List<RoutingHeader> headers=GetRoutingHeader(sceneId); List<RoutingHeader> headers=GetRoutingHeader(sceneId);
RoutingHeader routingHeaders= headers.stream() RoutingHeader routingHeaders= headers.stream()
.filter(t->t.getId()==parent|| t.getMaterialId().equals(materialID)) .filter(t->t.getId()==parent|| t.getMaterialId().equals(materialID))
.findFirst() .findFirst()
...@@ -604,7 +602,7 @@ private void clearFinishOrder (Order order) ...@@ -604,7 +602,7 @@ private void clearFinishOrder (Order order)
List<Order> childorders2 = new ArrayList<>(); List<Order> childorders2 = new ArrayList<>();
List<Entry> _newEntrys = new ArrayList<>(); List<Entry> _newEntrys = new ArrayList<>();
List<Machine> _newMachines = new ArrayList<>(); List<Machine> _newMachines = new ArrayList<>();
// 遍历产品的工序,递归构建工序BOM // 遍历产品的工序,递归构建工序BOM
List<Entry> _allOperations= chromosome.getAllOperations(); List<Entry> _allOperations= chromosome.getAllOperations();
...@@ -615,7 +613,7 @@ private void clearFinishOrder (Order order) ...@@ -615,7 +613,7 @@ private void clearFinishOrder (Order order)
if (Operations != null) { if (Operations != null) {
for (Entry operation : Operations) { for (Entry operation : Operations) {
if(finishOpertionID!=0) if(finishOpertionID!=0)
{ {
...@@ -627,7 +625,7 @@ private void clearFinishOrder (Order order) ...@@ -627,7 +625,7 @@ private void clearFinishOrder (Order order)
} }
// 调用BuildOperationBOM方法(返回结果对象替代out参数) // 调用BuildOperationBOM方法(返回结果对象替代out参数)
BOMBuildResult operationResult = buildOperationBOM(mainorderId, childorderId, BOMBuildResult operationResult = buildOperationBOM(mainorderId, childorderId,
parentQuantity, operation, level,forder,sceneId,chromosome); parentQuantity, operation, level,forder,sceneId,chromosome, baseTime, globalParam);
// // 合并物料需求和子订单 // // 合并物料需求和子订单
if(operationResult!=null) { if(operationResult!=null) {
materialRequirements.addAll(operationResult.getMaterialRequirements()); materialRequirements.addAll(operationResult.getMaterialRequirements());
...@@ -650,7 +648,7 @@ private void clearFinishOrder (Order order) ...@@ -650,7 +648,7 @@ private void clearFinishOrder (Order order)
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数) * @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/ */
public BOMBuildResult buildOperationBOM(String orderId, String childorderId, double parentQuantity, 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<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
List<Order> _childorders = new ArrayList<>(); List<Order> _childorders = new ArrayList<>();
List<Entry> _newEntrys = new ArrayList<>(); List<Entry> _newEntrys = new ArrayList<>();
...@@ -678,8 +676,8 @@ private void clearFinishOrder (Order order) ...@@ -678,8 +676,8 @@ private void clearFinishOrder (Order order)
return null; return null;
} }
OrderMaterialRequirement orderMaterial= CreateMaterialRequirement(material,orderId,childorderId,operation,allneeded,component.getSpentQty().doubleValue(), component.getMainQty().doubleValue() , parentQuantity); OrderMaterialRequirement orderMaterial= CreateMaterialRequirement(material,orderId,childorderId,operation,allneeded,component.getSpentQty().doubleValue(), component.getMainQty().doubleValue() , parentQuantity, baseTime);
orderMaterial.setLevel(level); orderMaterial.setLevel(level);
orderMaterial.setBomId(component.getStrId()); orderMaterial.setBomId(component.getStrId());
materialRequirements.add(orderMaterial); materialRequirements.add(orderMaterial);
...@@ -713,8 +711,8 @@ private void clearFinishOrder (Order order) ...@@ -713,8 +711,8 @@ private void clearFinishOrder (Order order)
BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(), BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
orderId, order.getOrderId(), orderId, order.getOrderId(),
order.getQuantity(), l,order,operation.getId(),chromosome); order.getQuantity(), l,order,operation.getId(),chromosome, baseTime, globalParam);
// materialRequirements.addAll(childResult.getMaterialRequirements()); // materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders()); _childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys()); _newEntrys.addAll(childResult.getNewEntrys());
operation.getDependentOnOrderIds().add(order.getId()); operation.getDependentOnOrderIds().add(order.getId());
...@@ -743,7 +741,7 @@ private void clearFinishOrder (Order order) ...@@ -743,7 +741,7 @@ private void clearFinishOrder (Order order)
childorder.setQuantity((int) orderMaterial.getQjQty()); childorder.setQuantity((int) orderMaterial.getQjQty());
childorder.setFinishOrderId(new ArrayList<>()); childorder.setFinishOrderId(new ArrayList<>());
childorder.getFinishOrderId().add(forder.getId()); childorder.getFinishOrderId().add(forder.getId());
childorder.setNewCreate(true); childorder.setNewSfCreate(true);
childorder.setTargetFinishedOperationId(new ArrayList<>()); childorder.setTargetFinishedOperationId(new ArrayList<>());
childorder.getTargetFinishedOperationId().add(operation.getId()); childorder.getTargetFinishedOperationId().add(operation.getId());
childorder.setSerie(forder.getSerie()); childorder.setSerie(forder.getSerie());
...@@ -769,8 +767,8 @@ private void clearFinishOrder (Order order) ...@@ -769,8 +767,8 @@ private void clearFinishOrder (Order order)
int l = level + 1; int l = level + 1;
BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(), BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
orderId, childorder.getOrderId(), orderId, childorder.getOrderId(),
childorder.getQuantity(), l,childorder,0,chromosome); childorder.getQuantity(), l,childorder,0,chromosome, baseTime, globalParam);
// materialRequirements.addAll(childResult.getMaterialRequirements()); // materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders()); _childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys()); _newEntrys.addAll(childResult.getNewEntrys());
} }
...@@ -792,10 +790,10 @@ private void clearFinishOrder (Order order) ...@@ -792,10 +790,10 @@ private void clearFinishOrder (Order order)
RoutingHeader headers1= headers.stream() RoutingHeader headers1= headers.stream()
.filter(t->t.getMaterialId().equals(materialID)) .filter(t->t.getMaterialId().equals(materialID))
.findFirst().orElse(null); .findFirst().orElse(null);
if(headers1==null) if(headers1==null)
{ {
return null; return null;
} }
routingIds=headers1.getId().longValue(); routingIds=headers1.getId().longValue();
...@@ -811,8 +809,8 @@ if(headers1==null) ...@@ -811,8 +809,8 @@ if(headers1==null)
} }
List<RoutingDetailEquip> allroutingDetailEquips=GetRoutingDetailEquips(sceneId); List<RoutingDetailEquip> allroutingDetailEquips=GetRoutingDetailEquips(sceneId);
List<RoutingDetailEquip> routingDetailEquips= allroutingDetailEquips.stream() List<RoutingDetailEquip> routingDetailEquips= allroutingDetailEquips.stream()
.filter(t->t.getRoutingHeaderId().equals(headersid)) .filter(t->t.getRoutingHeaderId().equals(headersid))
.collect(Collectors.toList()); .collect(Collectors.toList());
...@@ -842,9 +840,9 @@ if(headers1==null) ...@@ -842,9 +840,9 @@ if(headers1==null)
List<RoutingDetailConnect> allroutingDetailconnections=GetRoutingDetailConnect(sceneId); List<RoutingDetailConnect> allroutingDetailconnections=GetRoutingDetailConnect(sceneId);
connections= allroutingDetailconnections.stream() connections= allroutingDetailconnections.stream()
.filter(t->t.getRoutingHeaderId().equals(headersid)) .filter(t->t.getRoutingHeaderId().equals(headersid))
.collect(Collectors.toList()); .collect(Collectors.toList());
List<ProdOrderProcess> ProdOrderProcesslist= connections.stream() List<ProdOrderProcess> ProdOrderProcesslist= connections.stream()
...@@ -921,7 +919,7 @@ if(headers1==null) ...@@ -921,7 +919,7 @@ if(headers1==null)
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数) * @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/ */
public BOMBuildResult buildOperationSFBOM(String orderId, String childorderId, double parentQuantity, 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<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
List<Order> _childorders = new ArrayList<>(); List<Order> _childorders = new ArrayList<>();
List<Entry> _newEntrys = new ArrayList<>(); List<Entry> _newEntrys = new ArrayList<>();
...@@ -949,99 +947,99 @@ if(headers1==null) ...@@ -949,99 +947,99 @@ if(headers1==null)
// 查找物料(流式处理替代First) // 查找物料(流式处理替代First)
if (!orderMaterial.getMaterialTypeName().equals("MP") ) { if (!orderMaterial.getMaterialTypeName().equals("MP") ) {
// 处理半成品/成品的现有订单 // 处理半成品/成品的现有订单
// 为什么要先找现有订单,绑定上,因为要把它排在成品工单前面,才能有时间 // 为什么要先找现有订单,绑定上,因为要把它排在成品工单前面,才能有时间
List<Order> orders2 = orders.stream() List<Order> orders2 = orders.stream()
.filter(t -> t.getMaterialId().equals(orderMaterial.getMaterialId()) && t.getSYQuantity() > 0) .filter(t -> t.getMaterialId().equals(orderMaterial.getMaterialId()) && t.getSYQuantity() > 0)
.sorted(Comparator.comparing(Order::getDueDate)) .sorted(Comparator.comparing(Order::getDueDate))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (!orders2.isEmpty()) { if (!orders2.isEmpty()) {
for (Order order : orders2) { for (Order order : orders2) {
if (order.getFinishOrderId() == null) { if (order.getFinishOrderId() == null) {
order.setFinishOrderId(new ArrayList<>()); order.setFinishOrderId(new ArrayList<>());
order.setTargetFinishedOperationId(new ArrayList<>()); order.setTargetFinishedOperationId(new ArrayList<>());
} }
order.getFinishOrderId().add(forder.getId()); order.getFinishOrderId().add(forder.getId());
order.getTargetFinishedOperationId().add(operation.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 (needed <= 0) { orderMaterial.getProductOrderID().add(order.getId());
break;
} 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());
} }
}
// 更新已配和缺件数量 if (needed <= 0) {
orderMaterial.setYpQty(allneeded - needed); break;
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;
} }
_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) ...@@ -1061,7 +1059,7 @@ if(headers1==null)
orderMaterial.setMaterialName(material.getName()); orderMaterial.setMaterialName(material.getName());
orderMaterial.setMaterialTypeName(material.getMaterialTypeName()); orderMaterial.setMaterialTypeName(material.getMaterialTypeName());
orderMaterial.setMaterialId(material.getId()); orderMaterial.setMaterialId(material.getId());
// orderMaterial.setCheckLeadTime(material.getCkeckLeadTime()); // orderMaterial.setCheckLeadTime(material.getCkeckLeadTime());
double useStock=0; double useStock=0;
// 扣减现有库存 // 扣减现有库存
List<Stock> stocks= material.getMaterialStocks().stream() List<Stock> stocks= material.getMaterialStocks().stream()
...@@ -1089,7 +1087,7 @@ if(headers1==null) ...@@ -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(); OrderMaterialRequirement orderMaterial = new OrderMaterialRequirement();
orderMaterial.setOrderId(orderId); orderMaterial.setOrderId(orderId);
...@@ -1140,14 +1138,14 @@ if(headers1==null) ...@@ -1140,14 +1138,14 @@ if(headers1==null)
* @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数) * @return 包含物料需求列表和子订单列表的结果对象(替代C#的out参数)
*/ */
public void EditOperationBOM(Entry operation,Chromosome chromosome,LocalDateTime earliestStartTime,GeneticDecoder coder,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache) { 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<>(); List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
String sceneId=chromosome.getScenarioID(); String sceneId=chromosome.getScenarioID();
Random rnd = new Random(); Random rnd = new Random();
List<OrderMaterialRequirement> MaterialRequirements= operation.getMaterialRequirements(); List<OrderMaterialRequirement> MaterialRequirements= operation.getMaterialRequirements();
MaterialRequirements = MaterialRequirements.stream() MaterialRequirements = MaterialRequirements.stream()
.sorted((a, b) -> { .sorted((a, b) -> {
// 定义判断条件:是否满足 非MP + 生产订单ID非空非空串 // 定义判断条件:是否满足 非MP + 生产订单ID非空非空串
boolean aMatch = !"MP".equals(a.getMaterialTypeName()) boolean aMatch = !"MP".equals(a.getMaterialTypeName())
...@@ -1228,12 +1226,12 @@ if(headers1==null) ...@@ -1228,12 +1226,12 @@ if(headers1==null)
if (orderMaterial1 != null) { if (orderMaterial1 != null) {
useStock = orderMaterial1.getUseStock(); useStock = orderMaterial1.getUseStock();
needed -= useStock; needed -= useStock;
orderMaterial.setUseStock(orderMaterial.getUseStock() + useStock); orderMaterial.setUseStock(orderMaterial.getUseStock() + useStock);
orderMaterial.getReplaceMaterial().add(orderMaterial1); orderMaterial.getReplaceMaterial().add(orderMaterial1);
if (needed <= 0) { if (needed <= 0) {
break; break;
} }
} }
} }
...@@ -1247,7 +1245,7 @@ if(headers1==null) ...@@ -1247,7 +1245,7 @@ if(headers1==null)
continue; continue;
} }
MaterialInTransit(material,"",orderMaterial,needed,earliestStartTime); MaterialInTransit(material,"",orderMaterial,needed,earliestStartTime, materials);
needed -= orderMaterial.getUseTransit(); needed -= orderMaterial.getUseTransit();
...@@ -1268,7 +1266,7 @@ if(headers1==null) ...@@ -1268,7 +1266,7 @@ if(headers1==null)
break; break;
} }
MaterialInTransit(material1,rsr.getMaterialid(),orderMaterial1,needed,earliestStartTime); MaterialInTransit(material1,rsr.getMaterialid(),orderMaterial1,needed,earliestStartTime, materials);
needed -= orderMaterial1.getUseTransit(); needed -= orderMaterial1.getUseTransit();
...@@ -1315,27 +1313,27 @@ if(headers1==null) ...@@ -1315,27 +1313,27 @@ if(headers1==null)
// 处理半成品/成品的现有订单 // 处理半成品/成品的现有订单
List<Integer> orderids= orderMaterial.getProductOrderID(); List<Integer> orderids= orderMaterial.getProductOrderID();
if(orderids!=null&&orderids.size()>0) { if(orderids!=null&&orderids.size()>0) {
for (Integer orderid : orderids) { for (Integer orderid : orderids) {
coder.ClearorderOperationResult(chromosome, orderid); coder.ClearorderOperationResult(chromosome, orderid);
coder.EditorderOperation(chromosome, orderid, needed,machineTasksCache); coder.EditorderOperation(chromosome, orderid, needed,machineTasksCache, entryIndexById, scheduleIndexById);
} }
}else { }else {
List<MaterialPurchase> materialPurchaseList=material.getMaterialPurchases(); List<MaterialPurchase> materialPurchaseList=material.getMaterialPurchases();
if(materialPurchaseList!=null&&materialPurchaseList.size()>0) { 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.setCheckLeadTime(result.getPurchaseCycle());
orderMaterial.setPurchaseTime(result.getInspectionCycle()); orderMaterial.setPurchaseTime(result.getInspectionCycle());
LocalDateTime purchaseEndTime = baseTime.plusDays(orderMaterial.getPurchaseTime() + orderMaterial.getCheckLeadTime()); LocalDateTime purchaseEndTime = baseTime.plusDays(orderMaterial.getPurchaseTime() + orderMaterial.getCheckLeadTime());
orderMaterial.setPurchaseEndTime(purchaseEndTime); orderMaterial.setPurchaseEndTime(purchaseEndTime);
} }
} }
} }
orderMaterial.getReplaceMaterial().removeIf(t->t.getUseStock()==0&&t.getUseTransit()==0); orderMaterial.getReplaceMaterial().removeIf(t->t.getUseStock()==0&&t.getUseTransit()==0);
} }
...@@ -1376,14 +1374,14 @@ if(headers1==null) ...@@ -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; double accumulated = 0;
LocalDateTime earliestTime = LocalDateTime.of(2000,1,1,0,0,0); LocalDateTime earliestTime = LocalDateTime.of(2000,1,1,0,0,0);
double useTransit = 0; double useTransit = 0;
if (material == null) { if (material == null) {
material = _materials.stream() material = materials.stream()
.filter(m -> m.getId().equals(materialId)) .filter(m -> m.getId().equals(materialId))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
......
...@@ -894,7 +894,7 @@ public class MaterialRequirementServicebf { ...@@ -894,7 +894,7 @@ public class MaterialRequirementServicebf {
childorder.setQuantity((int) orderMaterial.getQjQty()); childorder.setQuantity((int) orderMaterial.getQjQty());
childorder.setFinishOrderId(new ArrayList<>()); childorder.setFinishOrderId(new ArrayList<>());
childorder.getFinishOrderId().add(forder.getId()); childorder.getFinishOrderId().add(forder.getId());
childorder.setNewCreate(true); childorder.setNewSfCreate(true);
childorder.setTargetFinishedOperationId(new ArrayList<>()); childorder.setTargetFinishedOperationId(new ArrayList<>());
childorder.getTargetFinishedOperationId().add(operation.getId()); childorder.getTargetFinishedOperationId().add(operation.getId());
childorder.setSerie(forder.getSerie()); childorder.setSerie(forder.getSerie());
......
package com.aps.service.Algorithm;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.*;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.GlobalParam;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* 多种局部搜索算法并行
*/
public class ParallelLocalSearch {
private final ExecutorService executor;
private GlobalParam globalParam;
private List<Entry> allOperations;
private List<GlobalOperationInfo> globalOpList;
private FitnessCalculator fitnessCalculator;
private ObjectiveWeights objectiveWeights;
public ParallelLocalSearch(GlobalParam globalParam, List<Entry> allOperations, List<GlobalOperationInfo> globalOpList, FitnessCalculator fitnessCalculator, ObjectiveWeights objectiveWeights) {
this.globalParam = globalParam;
this.allOperations = allOperations;
this.globalOpList = globalOpList;
this.fitnessCalculator = fitnessCalculator;
this.objectiveWeights = objectiveWeights;
this.executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
}
/**
* 并行局部搜索
*/
public Chromosome search(Chromosome chromosome, GeneticDecoder decoder, ScheduleParams param) {
List<Callable<Chromosome>> tasks = new ArrayList<>();
// 添加爬山法任务
// tasks.add(() -> {
// HillClimbing hillClimbing = new HillClimbing(globalParam, allOperations, globalOpList, fitnessCalculator, objectiveWeights);
// return hillClimbing.search(chromosome, decoder, param);
// });
// 添加变邻域搜索任务
tasks.add(() -> {
VariableNeighborhoodSearch vns = new VariableNeighborhoodSearch(globalParam, allOperations, globalOpList, fitnessCalculator, objectiveWeights);
return vns.search(chromosome, decoder, param);
});
// 添加模拟退火任务
// tasks.add(() -> {
// SimulatedAnnealing sa = new SimulatedAnnealing(globalParam, allOperations, globalOpList, fitnessCalculator, objectiveWeights);
// return sa.search(chromosome, decoder, param);
// });
// 执行所有任务
List<Chromosome> results = new ArrayList<>();
try {
List<Future<Chromosome>> futures = executor.invokeAll(tasks);
for (Future<Chromosome> future : futures) {
results.add(future.get());
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 选择最优解
Chromosome best = chromosome;
for (Chromosome result : results) {
if (isBetter(result, best)) {
best = result;
}
}
return best;
}
/**
* 比较两个染色体的优劣
*/
private boolean isBetter(Chromosome c1, Chromosome c2) {
return c1.getFitness() > c2.getFitness();
}
/**
* 关闭线程池
*/
public void shutdown() {
executor.shutdown();
}
}
\ No newline at end of file
...@@ -1885,7 +1885,7 @@ if(targetOp.getSequence()>1) { ...@@ -1885,7 +1885,7 @@ if(targetOp.getSequence()>1) {
decoder.decode(chromosome); decoder.decode(chromosome,false);
KpiCalculator kpiCalculator=new KpiCalculator(chromosome); KpiCalculator kpiCalculator=new KpiCalculator(chromosome);
kpiCalculator.calculatekpi(); kpiCalculator.calculatekpi();
......
package com.aps.service.Algorithm; package com.aps.service.Algorithm;
import com.aps.common.util.FileHelper; import com.aps.common.util.FileHelper;
import com.aps.common.util.GlobalCacheUtil;
import com.aps.common.util.ProductionDeepCopyUtil; import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.*; import com.aps.entity.Algorithm.*;
import com.aps.entity.basic.Entry; import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.GlobalParam; import com.aps.entity.basic.*;
import com.aps.entity.basic.Machine;
import com.aps.entity.basic.MachineOption;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
...@@ -18,19 +17,41 @@ import java.util.stream.Collectors; ...@@ -18,19 +17,41 @@ import java.util.stream.Collectors;
public class SimulatedAnnealing { public class SimulatedAnnealing {
private final Random rnd = new Random(); private final Random rnd = new Random();
private void log(String message) {
log(message, false);
}
private void log(String message, boolean enableLogging) {
if (enableLogging) {
FileHelper.writeLogFile(message);
}
}
private List<Entry> allOperations; private List<Entry> allOperations;
private Map<String, Entry> entrys; private List<Order> orders;
private List<Material> materials;
private List<GroupResult> _entryRel;
private FitnessCalculator fitnessCalculator;
private Map<String, Entry> entrys;
private Map<Integer, Entry> entrybyids; private Map<Integer, Entry> entrybyids;
public SimulatedAnnealing( List<Entry> allOperations) { public SimulatedAnnealing( List<Entry> allOperations, List<Order> orders,
List<Material> materials,List<GroupResult> entryRel, FitnessCalculator _fitnessCalculator) {
this.allOperations = allOperations; this.allOperations = allOperations;
this.orders = orders;
this.materials = materials;
Map<Integer, Object> mp = buildEntryKey(); _entryRel=entryRel;
entrys=(Map<String, Entry>)mp.get(1); Map<Integer, Object> mp = buildEntryKey();
entrybyids=(Map<Integer, Entry>)mp.get(2); this.fitnessCalculator = _fitnessCalculator;
entrys=(Map<String, Entry>)mp.get(1);
entrybyids=(Map<Integer, Entry>)mp.get(2);
} }
private final ExecutorService decodeExecutor = new ThreadPoolExecutor( private final ExecutorService decodeExecutor = new ThreadPoolExecutor(
...@@ -40,7 +61,7 @@ private Map<String, Entry> entrys; ...@@ -40,7 +61,7 @@ private Map<String, Entry> entrys;
new ArrayBlockingQueue<>(200), // 有界队列,避免内存溢出 new ArrayBlockingQueue<>(200), // 有界队列,避免内存溢出
new ThreadPoolExecutor.CallerRunsPolicy() // 任务满了主线程执行,不丢失任务 new ThreadPoolExecutor.CallerRunsPolicy() // 任务满了主线程执行,不丢失任务
); );
public List<Chromosome> batchSearch(List<Chromosome> chromosomes, GeneticDecoder decoder, List<Machine> machines) { public List<Chromosome> batchSearch(List<Chromosome> chromosomes,VariableNeighborhoodSearch vns, GeneticDecoder decoder, List<Machine> machines) {
List<Chromosome> saHcOptimized=new ArrayList<>(); List<Chromosome> saHcOptimized=new ArrayList<>();
// CompletableFuture.allOf(chromosomes.stream() // CompletableFuture.allOf(chromosomes.stream()
// .map(chromosome -> CompletableFuture.runAsync(() -> { // .map(chromosome -> CompletableFuture.runAsync(() -> {
...@@ -50,15 +71,15 @@ private Map<String, Entry> entrys; ...@@ -50,15 +71,15 @@ private Map<String, Entry> entrys;
// .toArray(CompletableFuture[]::new)) // .toArray(CompletableFuture[]::new))
// .join(); // .join();
for (Chromosome chromosome:chromosomes) { for (Chromosome chromosome:chromosomes) {
Chromosome optimized = searchWithHillClimbing(chromosome, decoder, machines); Chromosome optimized = searchWithHillClimbing(chromosome,vns, decoder, machines);
saHcOptimized.add(optimized); saHcOptimized.add(optimized);
} }
return saHcOptimized; return saHcOptimized;
} }
public Chromosome batchSearchGetMax(List<Chromosome> chromosomes, GeneticDecoder decoder, List<Machine> machines) { public Chromosome batchSearchGetMax(List<Chromosome> chromosomes,VariableNeighborhoodSearch vns, GeneticDecoder decoder, List<Machine> machines) {
List<Chromosome> saHcOptimized=batchSearch(chromosomes,decoder,machines); List<Chromosome> saHcOptimized=batchSearch(chromosomes,vns,decoder,machines);
int bestidx= Getbest(saHcOptimized,null); int bestidx= Getbest(saHcOptimized,null);
if(bestidx>-1) { if(bestidx>-1) {
...@@ -72,17 +93,18 @@ private Map<String, Entry> entrys; ...@@ -72,17 +93,18 @@ private Map<String, Entry> entrys;
* 模拟退火搜索,当温度降低到一定程度后切换到爬山法 * 模拟退火搜索,当温度降低到一定程度后切换到爬山法
* 流程:模拟退火全局探索(按概率接受劣解)→ 降温 → 温度低时爬山法局部求精 → 输出最优 * 流程:模拟退火全局探索(按概率接受劣解)→ 降温 → 温度低时爬山法局部求精 → 输出最优
*/ */
public Chromosome searchWithHillClimbing(Chromosome chromosome, GeneticDecoder decoder, List<Machine> machines) { public Chromosome searchWithHillClimbing(Chromosome chromosome, VariableNeighborhoodSearch vns,GeneticDecoder decoder, List<Machine> machines) {
FileHelper.writeLogFile("模拟退火+爬山法 - 开始执行"); log("模拟退火+爬山法 - 开始执行",true);
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
writeKpi(best); writeKpi(best);
// 初始化解码
// 记录初始KPI用于计算改进率
double[] initialFitnessLevel = best.getFitnessLevel().clone();
double initialFitness = best.getFitness();
// FileHelper.writeLogFile("模拟退火+爬山法 - 初始化解码完成"); // log("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度 // 初始化温度
double temperature = 100.0; double temperature = 100.0;
...@@ -90,19 +112,26 @@ private Map<String, Entry> entrys; ...@@ -90,19 +112,26 @@ private Map<String, Entry> entrys;
double temperatureThreshold = 1.0; double temperatureThreshold = 1.0;
int maxIterations = 300; int maxIterations = 300;
int noImproveCount = 0; int noImproveCount = 0;
int maxNoImprove = 50; int maxNoImprove = 30; // 降低最大无改进次数
// 新增:改进率监控参数
int stagnantWindow = 15; // 观察窗口大小
int[] recentImprovements = new int[stagnantWindow]; // 记录最近窗口内的改进情况
double improvementRateThreshold = 0.05; // 改进率阈值(5%)
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代=%d", log(String.format("模拟退火+爬山法 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代=%d, 最大无改进=%d",
temperature, coolingRate, temperatureThreshold, maxIterations)); temperature, coolingRate, temperatureThreshold, maxIterations, maxNoImprove));
int acceptCount = 0; int acceptCount = 0;
int improveCount = 0; int improveCount = 0;
int totalIterations = 0;
for (int i = 0; i < maxIterations; i++) { for (int i = 0; i < maxIterations; i++) {
totalIterations = i + 1;
boolean improved = false; boolean improved = false;
// 1. 使用智能策略生成邻域解(找瓶颈工序/设备) // 1. 使用智能策略生成邻域解(找瓶颈工序/设备)
Chromosome neighbor = generateNeighbor(current); Chromosome neighbor = vns.generateNeighbor(current);
// 2. 解码 // 2. 解码
decode(decoder, neighbor,machines); decode(decoder, neighbor,machines);
...@@ -124,7 +153,10 @@ private Map<String, Entry> entrys; ...@@ -124,7 +153,10 @@ private Map<String, Entry> entrys;
improved = true; improved = true;
improveCount++; improveCount++;
noImproveCount = 0; noImproveCount = 0;
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 迭代%d:找到更优解,fitness=%.4f", i, best.getFitness()));
// 记录改进详情
logImprovementDetails(best, initialFitnessLevel, initialFitness, totalIterations);
log(String.format("模拟退火+爬山法 - 迭代%d:找到更优解,fitness=%.4f", totalIterations, best.getFitness()),true);
} }
} }
...@@ -132,36 +164,247 @@ private Map<String, Entry> entrys; ...@@ -132,36 +164,247 @@ private Map<String, Entry> entrys;
noImproveCount++; noImproveCount++;
} }
// 记录本次改进情况
if (totalIterations <= stagnantWindow) {
recentImprovements[totalIterations - 1] = improved ? 1 : 0;
}
// 5. 降温 // 5. 降温
temperature *= coolingRate; temperature *= coolingRate;
// 每50次迭代输出一次状态 // 每30次迭代输出一次状态
if ((i + 1) % 50 == 0) { if ((totalIterations) % 30 == 0) {
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d", log(String.format("模拟退火+爬山法 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d, 总改进率=%.2f%%",
i + 1, maxIterations, temperature, acceptCount, improveCount, noImproveCount)); totalIterations, maxIterations, temperature, acceptCount, improveCount, noImproveCount,
totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
}
// 6. 提前停止条件
boolean shouldStop = false;
String stopReason = "";
if (temperature < temperatureThreshold) {
shouldStop = true;
stopReason = "温度低于阈值";
} else if (noImproveCount >= maxNoImprove) {
shouldStop = true;
stopReason = String.format("连续无改进达到上限(%d次)", maxNoImprove);
} else if (totalIterations >= stagnantWindow) {
// 检查改进率是否过低
double recentImproveRate = calculateRecentImprovementRate(recentImprovements, stagnantWindow);
if (recentImproveRate < improvementRateThreshold) {
shouldStop = true;
stopReason = String.format("最近%d次迭代改进率过低(%.2f%%)", stagnantWindow, recentImproveRate * 100);
}
} }
// 6. 提前停止条件:温度低于阈值 或 连续多次没改进 if (shouldStop) {
if (temperature < temperatureThreshold || noImproveCount >= maxNoImprove) { log(String.format("模拟退火+爬山法 - 提前停止:%s,迭代%d次,最终温度=%.4f",
String stopReason = temperature < temperatureThreshold ? "温度低于阈值" : "连续无改进达到上限"; stopReason, totalIterations, temperature));
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 提前停止:%s,迭代%d次,最终温度=%.4f", logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations);
stopReason, i + 1, temperature));
FileHelper.writeLogFile("模拟退火+爬山法 - 切换到爬山法求精"); log("模拟退火+爬山法 - 切换到爬山法求精");
HillClimbing hillClimbing = new HillClimbing( allOperations); HillClimbing hillClimbing = new HillClimbing( allOperations,orders,materials,_entryRel,fitnessCalculator);
Chromosome refined = hillClimbing.search(best, decoder, machines); Chromosome refined = hillClimbing.search(best, decoder, machines);
FileHelper.writeLogFile("模拟退火+爬山法 - 爬山法求精完成"); log("模拟退火+爬山法 - 爬山法求精完成");
return refined; return refined;
} }
} }
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f", log(String.format("模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f",
maxIterations, best.getFitness())); maxIterations, best.getFitness()),true);
logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations);
// 7. 输出全局最优排产 // 7. 输出全局最优排产
return best; return best;
} }
/**
* 模拟退火搜索
* 流程:模拟退火全局探索(按概率接受劣解)→ 降温 → 输出最优
*/
public Chromosome search(Chromosome chromosome,TabuSearch tabusearch,VariableNeighborhoodSearch vns, GeneticDecoder decoder, List<Machine> machines) {
log("模拟退火 - 开始执行",true);
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
decode(decoder, current,machines);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
writeKpi(best);
// 初始化解码
// 记录初始KPI用于计算改进率
double[] initialFitnessLevel = best.getFitnessLevel().clone();
double initialFitness = best.getFitness();
// log("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度
double temperature = 100.0;
double coolingRate = 0.95;
double temperatureThreshold = 1.0;
int maxIterations = 300;
int noImproveCount = 0;
int maxNoImprove = 20; // 降低最大无改进次数,更快提前结束
// 新增:改进率监控参数
int stagnantWindow = 10; // 观察窗口大小
int[] recentImprovements = new int[stagnantWindow]; // 记录最近窗口内的改进情况
double improvementRateThreshold = 0.001; // 改进率阈值
log(String.format("模拟退火 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代=%d, 最大无改进=%d",
temperature, coolingRate, temperatureThreshold, maxIterations, maxNoImprove));
int acceptCount = 0;
int improveCount = 0;
int totalIterations = 0;
for (int i = 0; i < maxIterations; i++) {
totalIterations = i + 1;
boolean improved = false;
log(String.format("模拟退火 - 迭代%d:", totalIterations));
// 1. 使用智能策略生成邻域解(找瓶颈工序/设备)
Chromosome neighbor = vns.generateNeighbor(current);
// 2. 解码
decode(decoder, neighbor,machines);
// 跳过禁忌解(除非是最优解)
if (tabusearch.isTabu(neighbor.getGeneStr()) && !isBetter(current,best)) {
temperature *= coolingRate;
noImproveCount++;
// 记录本次无改进
if (totalIterations <= stagnantWindow) {
recentImprovements[totalIterations - 1] = 0;
}
continue;
}
// 3. 计算能量差
double energyDifference = calculateEnergyDifference(neighbor, current);
// 4. 按概率接受新解(模拟退火核心:有概率接受劣解)
boolean accepted = false;
if (energyDifference > 0 || rnd.nextDouble() < Math.exp(energyDifference / temperature)) {
current = neighbor;
acceptCount++;
if (isBetter(current, best)) {
best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class);
tabusearch.addToTabuList(best.getGeneStr());
writeKpi(best);
improved = true;
improveCount++;
noImproveCount = 0;
// 记录改进详情
logImprovementDetails(best, initialFitnessLevel, initialFitness, totalIterations);
log(String.format("模拟退火 - 迭代%d:找到更优解,fitness=%.4f", totalIterations, best.getFitness()));
}
}
if (!improved) {
noImproveCount++;
}
// 记录本次改进情况
if (totalIterations <= stagnantWindow) {
recentImprovements[totalIterations - 1] = improved ? 1 : 0;
}
// 5. 降温
temperature *= coolingRate;
// 每次迭代都输出状态
log(String.format("模拟退火 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d, 总改进率=%.2f%%",
totalIterations, maxIterations, temperature, acceptCount, improveCount, noImproveCount,
totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
// 6. 检查提前停止条件
boolean shouldStop = false;
String stopReason = "";
if (temperature < temperatureThreshold) {
shouldStop = true;
stopReason = "温度低于阈值";
} else if (noImproveCount >= maxNoImprove) {
shouldStop = true;
stopReason = String.format("连续无改进达到上限(%d次)", maxNoImprove);
} else if (totalIterations >= stagnantWindow) {
// 检查改进率是否过低
double recentImproveRate = calculateRecentImprovementRate(recentImprovements, stagnantWindow);
if (recentImproveRate < improvementRateThreshold) {
shouldStop = true;
stopReason = String.format("最近%d次迭代改进率过低(%.2f%%)", stagnantWindow, recentImproveRate * 100);
}
}
if (shouldStop) {
log(String.format("模拟退火 - 提前停止:%s,迭代%d次,最终温度=%.4f",
stopReason, totalIterations, temperature));
logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations);
return best;
}
}
log(String.format("模拟退火 - 完成所有%d次迭代,最终fitness=%.4f",
maxIterations, best.getFitness()),true);
logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations);
// 7. 输出全局最优排产
return best;
}
/**
* 记录改进详情
*/
private void logImprovementDetails(Chromosome best, double[] initialFitnessLevel, double initialFitness, int iteration) {
StringBuilder sb = new StringBuilder("模拟退火 - 改进详情: 迭代" + iteration + ", ");
double[] currentFitness = best.getFitnessLevel();
for (int i = 0; i < currentFitness.length; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(+%.4f) ", i+1, initialFitnessLevel[i], currentFitness[i], improvement));
}
double totalImprovement = best.getFitness() - initialFitness;
sb.append(String.format("总Fitness: %.4f→%.4f(+%.4f)", initialFitness, best.getFitness(), totalImprovement));
log(sb.toString());
}
/**
* 计算最近改进率
*/
private double calculateRecentImprovementRate(int[] recentImprovements, int windowSize) {
int improveCount = 0;
for (int i = 0; i < windowSize; i++) {
improveCount += recentImprovements[i];
}
return (double) improveCount / windowSize;
}
/**
* 记录最终总结
*/
private void logFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness, int improveCount, int totalIterations) {
StringBuilder sb = new StringBuilder("模拟退火 - 最终总结: ");
double[] currentFitness = best.getFitnessLevel();
sb.append(String.format("总迭代%d次, 成功改进%d次, 改进率%.2f%%. ",
totalIterations, improveCount, totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
for (int i = 0; i < currentFitness.length; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(%.2f%%) ", i+1, initialFitnessLevel[i], currentFitness[i],
initialFitnessLevel[i] > 0 ? improvement / initialFitnessLevel[i] * 100 : 0));
}
double totalImprovement = best.getFitness() - initialFitness;
sb.append(String.format("总Fitness: %.4f→%.4f(%.2f%%)", initialFitness, best.getFitness(),
initialFitness > 0 ? totalImprovement / initialFitness * 100 : 0));
log(sb.toString());
}
private void writeKpi(Chromosome chromosome) { private void writeKpi(Chromosome chromosome) {
String fitness = ""; String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel(); double[] fitness1 = chromosome.getFitnessLevel();
...@@ -170,7 +413,7 @@ private Map<String, Entry> entrys; ...@@ -170,7 +413,7 @@ private Map<String, Entry> entrys;
fitness += fitness1[i] + ","; fitness += fitness1[i] + ",";
} }
FileHelper.writeLogFile(String.format("爬山法 - kpi:%s", fitness)); log(String.format("模拟退火 - kpi:%s", fitness),true);
} }
...@@ -221,66 +464,7 @@ private Map<String, Entry> entrys; ...@@ -221,66 +464,7 @@ private Map<String, Entry> entrys;
return filteredGroups; return filteredGroups;
} }
/**
* 构建位置索引:groupId_sequence -> position
*/
private Map<String, Integer> buildPositionIndex(Chromosome chromosome) {
Map<String, Integer> index = new HashMap<>();
List<Integer> os = chromosome.getOperationSequencing();
Map<Integer, Integer> orderProcessCounter = new HashMap<>();
for (int i = 0; i < os.size(); i++) {
int groupId = os.get(i);
int count = orderProcessCounter.getOrDefault(groupId, 0) + 1;
orderProcessCounter.put(groupId, count);
String key = groupId + "_" + count;
index.put(key, i);
}
return index;
}
/**
* 构建位置索引:groupId_sequence -> Machines position
*/
private Map<String, Integer> buildEntryMachinePositionIndex(Chromosome chromosome) {
Map<String, Integer> index = new HashMap<>();
List<GlobalOperationInfo> globalOpList = chromosome.getGlobalOpList();
for (int i = 0; i < globalOpList.size(); i++) {
GlobalOperationInfo globalOp = globalOpList.get(i);
Entry op = globalOp.getOp();
int groupId = op.getGroupId();
int count = op.getSequence();
String key = groupId + "_" + count;
index.put(key, i);
}
return index;
}
/**
* 构建位置->Entry索引
*/
private Map<Integer, Entry> buildPositionToEntryIndex(Chromosome chromosome,Map<String, Entry> entrys) {
Map<Integer, Entry> index = new HashMap<>();
List<Integer> os = chromosome.getOperationSequencing();
Map<Integer, Integer> orderProcessCounter = new HashMap<>();
for (int i = 0; i < os.size(); i++) {
int groupId = os.get(i);
int count = orderProcessCounter.getOrDefault(groupId, 0) + 1;
orderProcessCounter.put(groupId, count);
String key = groupId + "_" + count;
Entry op = entrys.get(key);
if (op != null) {
index.put(i, op);
}
}
return index;
}
/** /**
* 构建Entry索引:op.getGroupId() + "_" + op.getSequence() -> Entry * 构建Entry索引:op.getGroupId() + "_" + op.getSequence() -> Entry
*/ */
...@@ -302,543 +486,8 @@ private Map<String, Entry> entrys; ...@@ -302,543 +486,8 @@ private Map<String, Entry> entrys;
} }
/** /**
* 生成邻域解 - 智能策略:优先处理瓶颈工序/设备 * 解码染色体
* 策略:
* 1. 优先处理瓶颈设备上的工序(换设备)
* 2. 瓶颈设备上的工序往前移动
* 3. 非瓶颈设备上的工序往后移动(给瓶颈工序腾位置)
*/
private Chromosome generateNeighbor(Chromosome chromosome) {
List<GAScheduleResult> results = chromosome.getResult();
if (results == null || results.isEmpty()) {
return generateRandomNeighbor(chromosome, entrys);
}
// 构建位置索引
Map<String, Integer> positionIndex = buildPositionIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex = buildPositionToEntryIndex(chromosome, entrys);
Map<String, Integer> MachinePositionIndex = buildEntryMachinePositionIndex(chromosome);
// 1. 找出瓶颈设备
Long bottleneckMachineId = findBottleneckMachine(chromosome);
if (bottleneckMachineId != null) {
// 找出瓶颈设备上的工序
List<GAScheduleResult> bottleneckOps = findOpsOnBottleneckMachine(chromosome, bottleneckMachineId);
if (!bottleneckOps.isEmpty()) {
// 70%概率优先处理瓶颈设备
if (rnd.nextDouble() < 0.7) {
int strategy = rnd.nextInt(10);
if(strategy<=3)
{
// 策略1:瓶颈设备上的工序换设备
return tryChangeMachineForBottleneckOp(chromosome, bottleneckOps, entrys, MachinePositionIndex);
}
else if(strategy<=8) {
// 策略2:瓶颈设备上的工序往前移动
return tryMoveBottleneckOpForward(chromosome, bottleneckOps, positionIndex, positionToEntryIndex, entrys);
}else if(strategy<=10) {
// 策略3:非瓶颈设备上的工序往后移动
return tryMoveNonBottleneckOpBackward(chromosome, bottleneckMachineId, positionIndex, positionToEntryIndex, entrys);
}
}
}
}
// 默认策略:随机邻域
return generateRandomNeighbor(chromosome, entrys);
}
/**
* 识别瓶颈设备(利用率最高的设备)
*/
private Long findBottleneckMachine(Chromosome chromosome) {
Map<Long, Double> utilization = calculateMachineUtilization(chromosome);
if (utilization.isEmpty()) {
return null;
}
return utilization.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse(null);
}
/**
* 查找在瓶颈设备上的工序
*/
private List<GAScheduleResult> findOpsOnBottleneckMachine(Chromosome chromosome, Long bottleneckMachineId) {
if (bottleneckMachineId == null) {
return new ArrayList<>();
}
return chromosome.getResult().stream()
.filter(r -> r.getMachineId() == bottleneckMachineId)
.collect(Collectors.toList());
}
/**
* 计算设备利用率
*/
private Map<Long, Double> calculateMachineUtilization(Chromosome chromosome) {
Map<Long, Double> utilization = new HashMap<>();
List<GAScheduleResult> results = chromosome.getResult();
if (results == null || results.isEmpty()) {
return utilization;
}
int maxEndTime = results.stream()
.mapToInt(GAScheduleResult::getEndTime)
.max()
.orElse(1);
Map<Long, List<GAScheduleResult>> machineResults = results.stream()
.collect(Collectors.groupingBy(GAScheduleResult::getMachineId));
for (Map.Entry<Long, List<GAScheduleResult>> entry : machineResults.entrySet()) {
long machineId = entry.getKey();
List<GAScheduleResult> machineOps = entry.getValue();
int totalProcessingTime = machineOps.stream()
.mapToInt(r -> r.getEndTime() - r.getStartTime())
.sum();
double util = (double) totalProcessingTime / maxEndTime;
utilization.put(machineId, util);
}
return utilization;
}
/**
* 尝试给瓶颈设备上的工序换设备
*/
private Chromosome tryChangeMachineForBottleneckOp(Chromosome chromosome, List<GAScheduleResult> bottleneckOps, Map<String, Entry> entrys,Map<String, Integer> MachinePositionIndex) {
// 优先选择有多设备选项的工序
List<GAScheduleResult> candidates = bottleneckOps.stream()
.filter(op -> {
Entry entry = entrybyids.get(op.getOperationId());
return entry != null && entry.getMachineOptions().size() > 1;
})
.collect(Collectors.toList());
if (candidates.isEmpty()) {
return generateRandomNeighbor(chromosome, entrys);
}
// 从候选中随机选择一个工序,给它换设备
GAScheduleResult selectedOp = candidates.get(rnd.nextInt(candidates.size()));
// 找到这个工序在globalOpList中的位置
int maPos = -1;
Entry entry= entrybyids.get(selectedOp.getOperationId());
if (entry != null && entry.getMachineOptions().size() > 1) {
maPos = MachinePositionIndex.get(entry.getGroupId() + "_" + entry.getSequence());
if (maPos >= 0) {
return generateMachineChangeForSpecificOp(chromosome, entry.getMachineOptions(), maPos);
}
}
// 直接换设备
return generateMachineChangeNeighbor(chromosome);
}
/**
* 给指定位置的工序换设备
*/
private Chromosome generateMachineChangeForSpecificOp(Chromosome chromosome, List<MachineOption> machineOptions, int idx) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> ms = neighbor.getMachineSelection();
if (!ms.isEmpty() && idx >= 0 && idx < ms.size()) {
if (machineOptions.size() > 1) {
int currentMachineSeq = ms.get(idx);
List<Integer> availableMachines = new ArrayList<>();
for (int i = 1; i <= machineOptions.size(); i++) {
if (i != currentMachineSeq) {
availableMachines.add(i);
}
}
if (!availableMachines.isEmpty()) {
int newMachineSeq = availableMachines.get(rnd.nextInt(availableMachines.size()));
ms.set(idx, newMachineSeq);
neighbor.setMachineSelection(ms);
}
}
}
return neighbor;
}
/**
* 尝试将瓶颈设备上的工序往前移动
*/
private Chromosome tryMoveBottleneckOpForward(Chromosome chromosome, List<GAScheduleResult> bottleneckOps,
Map<String, Integer> positionIndex,
Map<Integer, Entry> positionToEntryIndex,
Map<String, Entry> entrys) {
if (bottleneckOps.isEmpty()) {
return generateSwapNeighbor(chromosome, entrys);
}
// 随机选择一个瓶颈工序
// GAScheduleResult randomOp = bottleneckOps.get(rnd.nextInt(bottleneckOps.size()));
// 计算所有订单的完成时间
List<GAScheduleResult> allResults = chromosome.getResult();
Map<Integer, Integer> orderCompletionTimes = calculateOrderCompletionTimes(allResults);
// 找出最晚完成的订单(延期候选)
int latestCompletionTime = orderCompletionTimes.values().stream()
.mapToInt(Integer::intValue)
.max()
.orElse(0);
// 按优先级和订单完成时间排序:优先选择高优先级+延期订单的工序
List<GAScheduleResult> sortedBottleneckOps = new ArrayList<>(bottleneckOps);
sortedBottleneckOps.sort((a, b) -> {
Entry entryA = entrybyids.get(a.getOperationId());
Entry entryB = entrybyids.get(b.getOperationId());
if (entryA != null && entryB != null) {
// 首先比较优先级(高优先级在前)
int priorityCompare = Double.compare(entryB.getPriority(), entryA.getPriority());
if (priorityCompare != 0) {
return priorityCompare;
}
// 优先级相同,比较订单完成时间(晚完成的在前,即更可能延期)
int endTimeA = orderCompletionTimes.getOrDefault(a.getGroupId(), 0);
int endTimeB = orderCompletionTimes.getOrDefault(b.getGroupId(), 0);
return Integer.compare(endTimeB, endTimeA);
}
return 0;
});
GAScheduleResult selectedOp = sortedBottleneckOps.get(rnd.nextInt(Math.min(5, sortedBottleneckOps.size())));
Entry entry=entrybyids.get(selectedOp.getOperationId()) ;
String key = entry.getGroupId() + "_" + entry.getSequence();
Integer opPos = positionIndex.get(key);
if (opPos == null || opPos <= 0) {
return generateSwapNeighbor(chromosome, entrys);
}
// 往前移动1-3步
// int steps = rnd.nextInt(3) + 1;
// return moveOperationForward(chromosome,positionToEntryIndex, opPos, steps);
// 使用插入方式往前移动(1-5步)
int steps = rnd.nextInt(5) + 1;
return insertOperationForward(chromosome, opPos, steps, entrys);
}
/**
* 计算每个订单的最后完成时间
*/
private Map<Integer, Integer> calculateOrderCompletionTimes(List<GAScheduleResult> allResults) {
Map<Integer, Integer> orderEndTimes = new HashMap<>();
for (GAScheduleResult result : allResults) {
int groupId = result.getGroupId();
int endTime = result.getEndTime();
orderEndTimes.put(groupId, Math.max(orderEndTimes.getOrDefault(groupId, 0), endTime));
}
return orderEndTimes;
}
/**
* 尝试将非瓶颈设备上的工序往后移动(给瓶颈工序腾位置)
*/
private Chromosome tryMoveNonBottleneckOpBackward(Chromosome chromosome, Long bottleneckMachineId,
Map<String, Integer> positionIndex,
Map<Integer, Entry> positionToEntryIndex,
Map<String, Entry> entrys) {
List<GAScheduleResult> results = chromosome.getResult();
if (results == null) {
return generateSwapNeighbor(chromosome, entrys);
}
// 找出非瓶颈设备上的工序
List<GAScheduleResult> nonBottleneckOps = results.stream()
.filter(r -> r.getMachineId() != bottleneckMachineId)
.collect(Collectors.toList());
if (nonBottleneckOps.isEmpty()) {
return generateSwapNeighbor(chromosome, entrys);
}
// 随机选择一个非瓶颈工序
GAScheduleResult randomOp = nonBottleneckOps.get(rnd.nextInt(nonBottleneckOps.size()));
Entry entry=entrybyids.get(randomOp.getOperationId());
String key = entry.getGroupId()+"_"+entry.getSequence();
Integer opPos = positionIndex.get(key);
if (opPos == null || opPos >= chromosome.getOperationSequencing().size() - 1) {
return generateSwapNeighbor(chromosome, entrys);
}
// 往后移动1-3步
int steps = rnd.nextInt(3) + 1;
return moveOperationBackward(chromosome,positionToEntryIndex, opPos, steps);
}
/**
* 将工序往前移动
*/
private Chromosome moveOperationForward(Chromosome chromosome, Map<Integer, Entry> originalPositionIndex,int pos, int steps) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (pos <= 0 || pos >= os.size()) {
return neighbor;
}
// 获取要移动的工序和目标位置的工序(基于原始chromosome)
Entry opToMove = originalPositionIndex.get(pos);
if (opToMove == null) {
return neighbor;
}
int targetPos = Math.max(0, pos - steps);
Entry targetOp = originalPositionIndex.get(targetPos);
// 检查是否可以交换
if (targetOp != null && opToMove.getGroupId() == targetOp.getGroupId()) {
return neighbor;
}
if (targetOp != null && Math.abs(targetOp.getPriority() - opToMove.getPriority()) > 0.001) {
return neighbor;
}
// 直接交换到目标位置
java.util.Collections.swap(os, pos, targetPos);
neighbor.setOperationSequencing(os);
return neighbor;
}
/**
* 将工序往后移动
*/
private Chromosome moveOperationBackward(Chromosome chromosome,Map<Integer, Entry> originalPositionIndex, int pos, int steps) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (pos < 0 || pos >= os.size() - 1) {
return neighbor;
}
// 获取要移动的工序和目标位置的工序(基于原始chromosome)
Entry opToMove = originalPositionIndex.get(pos);
if (opToMove == null) {
return neighbor;
}
int targetPos = Math.min(os.size() - 1, pos + steps);
Entry targetOp = originalPositionIndex.get(targetPos);
// 检查是否可以交换
if (targetOp != null && opToMove.getGroupId() == targetOp.getGroupId()) {
return neighbor;
}
if (targetOp != null && Math.abs(targetOp.getPriority() - opToMove.getPriority()) > 0.001) {
return neighbor;
}
// 直接交换到目标位置
java.util.Collections.swap(os, pos, targetPos);
neighbor.setOperationSequencing(os);
return neighbor;
}
/**
* 将工序往前插入(不交换,直接插入到目标位置)
*/
private Chromosome insertOperationForward(Chromosome chromosome, int pos, int steps, Map<String, Entry> entrys) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (pos <= 0 || pos >= os.size()) {
return neighbor;
}
// 获取要移动的工序(基于原始chromosome)
Map<Integer, Entry> originalPositionIndex = buildPositionToEntryIndex(chromosome, entrys);
Entry opToMove = originalPositionIndex.get(pos);
if (opToMove == null) {
return neighbor;
}
// 找到最远可以插入的位置(不打破优先级)
int targetPos = Math.max(0, pos - steps);
int finalTargetPos = pos;
for (int i = pos - 1; i >= targetPos; i--) {
Entry leftOp = originalPositionIndex.get(i);
if (leftOp != null && opToMove.getGroupId() == leftOp.getGroupId()) {
break;
}
if (leftOp != null && Math.abs(leftOp.getPriority() - opToMove.getPriority()) > 0.001) {
break;
}
finalTargetPos = i;
}
if (finalTargetPos == pos) {
return neighbor;
}
// 执行插入:移除原位置,插入到目标位置
int value = os.remove(pos);
os.add(finalTargetPos, value);
neighbor.setOperationSequencing(os);
return neighbor;
}
/**
* 随机生成邻域解(兜底策略)
*/
private Chromosome generateRandomNeighbor(Chromosome chromosome, Map<String, Entry> entrys) {
int neighborType = rnd.nextInt(4);
switch (neighborType) {
case 0:
return generateSwapNeighbor(chromosome, entrys);
case 1:
return generateReverseNeighbor(chromosome, entrys);
case 2:
return generateInsertNeighbor(chromosome, entrys);
case 3:
return generateMachineChangeNeighbor(chromosome);
default:
return generateSwapNeighbor(chromosome, entrys);
}
}
/**
* 生成交换邻域解 - 只在相同优先级的工序之间交换
*/
private Chromosome generateSwapNeighbor(Chromosome chromosome,Map<String, Entry> entrys) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
Map<Integer, Entry> positionIndex = buildPositionToEntryIndex(neighbor,entrys);
int maxAttempts = 50;
for (int attempt = 0; attempt < maxAttempts; attempt++) {
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
if (idx1 == idx2) continue;
Entry op1 = positionIndex.get(idx1);
Entry op2 = positionIndex.get(idx2);
if (op1 != null && op2 != null) {
if (Math.abs(op1.getPriority() - op2.getPriority()) < 0.001) {
java.util.Collections.swap(os, idx1, idx2);
neighbor.setOperationSequencing(os);
break;
}
}
}
}
return neighbor;
}
/**
* 生成反转邻域解 - 只反转相同优先级的连续工序
*/
private Chromosome generateReverseNeighbor(Chromosome chromosome,Map<String, Entry> entrys) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
Map<Integer, Entry> positionIndex = buildPositionToEntryIndex(neighbor,entrys);
int maxAttempts = 50;
for (int attempt = 0; attempt < maxAttempts; attempt++) {
int start = rnd.nextInt(os.size());
int end = rnd.nextInt(os.size());
if (end <= start) continue;
Entry startOp = positionIndex.get(start);
if (startOp == null) continue;
double priority = startOp.getPriority();
boolean allSamePriority = true;
for (int i = start; i <= end; i++) {
Entry op = positionIndex.get(i);
if (op == null || Math.abs(op.getPriority() - priority) > 0.001) {
allSamePriority = false;
break;
}
}
if (allSamePriority) {
java.util.Collections.reverse(os.subList(start, end + 1));
neighbor.setOperationSequencing(os);
break;
}
}
}
return neighbor;
}
/**
* 生成插入邻域解 - 只插入到相同优先级的位置
*/
private Chromosome generateInsertNeighbor(Chromosome chromosome,Map<String, Entry> entrys) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
Map<Integer, Entry> positionIndex = buildPositionToEntryIndex(neighbor,entrys);
int maxAttempts = 50;
for (int attempt = 0; attempt < maxAttempts; attempt++) {
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
if (idx1 == idx2) continue;
Entry op1 = positionIndex.get(idx1);
Entry op2 = positionIndex.get(idx2);
if (op1 != null && op2 != null) {
if (Math.abs(op1.getPriority() - op2.getPriority()) < 0.001) {
int value = os.remove(idx1);
os.add(idx2, value);
neighbor.setOperationSequencing(os);
break;
}
}
}
}
return neighbor;
}
/**
* 生成机器选择邻域解 - 不受优先级限制
*/ */
private Chromosome generateMachineChangeNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> ms = neighbor.getMachineSelection();
if (!ms.isEmpty()) {
int idx = rnd.nextInt(ms.size());
GlobalOperationInfo globalOp = chromosome.getGlobalOpList().get(idx);
Entry op = globalOp.getOp();
if (op.getMachineOptions().size() > 1) {
int currentMachineSeq = ms.get(idx);
List<Integer> availableMachines = new ArrayList<>();
for (int i = 1; i <= op.getMachineOptions().size(); i++) {
if (i != currentMachineSeq) {
availableMachines.add(i);
}
}
if (!availableMachines.isEmpty()) {
int newMachineSeq = availableMachines.get(rnd.nextInt(availableMachines.size()));
ms.set(idx, newMachineSeq);
neighbor.setMachineSelection(ms);
}
}
}
return neighbor;
}
/** /**
* 解码染色体 * 解码染色体
*/ */
...@@ -847,24 +496,35 @@ private Map<String, Entry> entrys; ...@@ -847,24 +496,35 @@ private Map<String, Entry> entrys;
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射 // 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines, Machine.class)); // 简单拷贝,实际可能需要深拷贝 chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(orders), Order.class) ); // 简单拷贝,实际可能需要深拷贝
chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(_entryRel), GroupResult.class) ); // 简单拷贝,实际可能需要深拷贝
chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyList(materials,Material.class)); // 简单拷贝,实际可能需要深拷贝
decoder.decodeChromosomeWithCache(chromosome); chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) ); // 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights);
// chromosome.setBaseTime(param.getBaseTime());
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
// 加载锁定工单到ResultOld
List<GAScheduleResult> lockedOrders = GlobalCacheUtil.get("locked_orders_" + chromosome.getScenarioID());
if (lockedOrders != null && !lockedOrders.isEmpty()) {
chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(lockedOrders, GAScheduleResult.class));
log("将 " + lockedOrders.size() + " 个锁定工单加载到初始种群中");
} else {
chromosome.setResultOld(new CopyOnWriteArrayList<>());
}
decoder.decodeChromosomeWithCache(chromosome,true);
} }
/** /**
* 比较两个染色体的优劣(基于fitnessLevel多层次比较) * 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/ */
private boolean isBetter(Chromosome c1, Chromosome c2) { private boolean isBetter(Chromosome c1, Chromosome c2) {
for (int i = 0; i < c1.getFitnessLevel().length; i++) { return fitnessCalculator.isBetter(c1,c2);
double[] Fitness1 = c1.getFitnessLevel();
double[] Fitness2 = c2.getFitnessLevel();
if (Fitness1[i] > Fitness2[i]) {
return true;
}
}
return false;
} }
private int Getbest(List<Chromosome> candidates,Chromosome best) { private int Getbest(List<Chromosome> candidates,Chromosome best) {
// 找出最佳候选方案 // 找出最佳候选方案
......
package com.aps.service.Algorithm; package com.aps.service.Algorithm;
import com.aps.common.util.FileHelper;
import com.aps.common.util.GlobalCacheUtil;
import com.aps.common.util.ProductionDeepCopyUtil; import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.*; import com.aps.entity.Algorithm.*;
import com.aps.entity.basic.Entry; import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.GlobalParam; import com.aps.entity.basic.*;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/** /**
* 禁忌搜索算法 * 禁忌搜索算法
*/ */
public class TabuSearch { public class TabuSearch {
private final Random rnd = new Random();
private GlobalParam globalParam;
private List<Entry> allOperations;
private List<GlobalOperationInfo> globalOpList;
private FitnessCalculator fitnessCalculator;
private ObjectiveWeights objectiveWeights;
private void log(String message) {
log(message, false);
}
private void log(String message, boolean enableLogging) {
if (enableLogging) {
FileHelper.writeLogFile(message);
}
}
private FitnessCalculator fitnessCalculator;
// 禁忌表 // 禁忌表
private List<Chromosome> tabuList; private List<String> tabuList;
private int tabuListSize = 50; private int tabuListSize = 50;
public TabuSearch(GlobalParam globalParam, List<Entry> allOperations, List<GlobalOperationInfo> globalOpList, FitnessCalculator fitnessCalculator, ObjectiveWeights objectiveWeights) { private List<Machine> cachedMachines;
this.globalParam = globalParam; private List<Order> cachedOrders;
this.allOperations = allOperations; private List<GroupResult> cachedEntryRel;
this.globalOpList = globalOpList; private List<Material> cachedMaterials;
this.fitnessCalculator = fitnessCalculator; private List<Entry> cachedAllOperations;
this.objectiveWeights = objectiveWeights; // 渴望准则:记录最优解的 fitness
private double[] bestFitness;
public TabuSearch(List<Entry> allOperations, List<Order> orders,
List<Material> materials,List<GroupResult> entryRel, FitnessCalculator _fitnessCalculator) {
this.tabuList = new ArrayList<>(); this.tabuList = new ArrayList<>();
// 工序越多,禁忌表越长(适配1000+工序) // 工序越多,禁忌表越长(适配1000+工序)
this.tabuListSize = Math.min(50, allOperations.size() / 30); this.tabuListSize = Math.min(50, allOperations.size() / 30);
fitnessCalculator=_fitnessCalculator;
// 预缓存解码需要的深拷贝列表,避免重复拷贝
cachedAllOperations = ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class);
cachedOrders = ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(orders), Order.class);
cachedEntryRel = ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(entryRel), GroupResult.class);
cachedMaterials = ProductionDeepCopyUtil.deepCopyList(materials, Material.class);
} }
/** /**
* 禁忌搜索 * 禁忌搜索(优化版)
*/ */
public Chromosome search(Chromosome chromosome, GeneticDecoder decoder, ScheduleParams param) { public Chromosome search(Chromosome chromosome, VariableNeighborhoodSearch vns,
GeneticDecoder decoder, List<Machine> machines) {
log("禁忌搜索 - 开始执行",true);
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
this.bestFitness = best.getFitnessLevel().clone();
writeKpi(best);
// 记录初始KPI用于计算改进率
double[] initialFitnessLevel = best.getFitnessLevel().clone();
double initialFitness = best.getFitness();
int iterations = 0; int iterations = 0;
int maxIterations = 1000; int improveCount = 0;
int noImprovementCount = 0; int noImprovementCount = 0;
int maxNoImprovement = 100; int maxNoImprovement = 15; // 降低到15次无改进则停止
int maxIterations = Math.min(cachedAllOperations.size(), 80); // 降低到最多80次
// 改进率监控
int stagnantWindow = 10;
int[] recentImprovements = new int[stagnantWindow];
double improvementRateThreshold = 0.1; // 10%改进率阈值
// 多样性参数
int diversificationInterval = 20; // 每20次迭代尝试一次多样化
int lastDiversificationIteration = 0;
while (iterations < maxIterations && noImprovementCount < maxNoImprovement) { log(String.format("禁忌搜索 - 参数:最大迭代=%d, 最大无改进=%d", maxIterations, maxNoImprovement));
// 生成邻域解
List<Chromosome> neighbors = generateNeighbors(current);
// 过滤禁忌解 for (int i = 0; i < maxIterations; i++) {
List<Chromosome> validNeighbors = filterTabuSolutions(neighbors); iterations++;
// 评估所有邻域解 // 使用 VNS 生成邻域解(成功率排序后的策略)
Chromosome bestNeighbor = null; Chromosome neighbor = vns.generateNeighbor(current);
double bestNeighborFitness = Double.NEGATIVE_INFINITY;
for (Chromosome neighbor : validNeighbors) { if (neighbor == null) {
decode(decoder, neighbor, param); log("禁忌搜索 - 生成邻居失败,跳过");
if (neighbor.getFitness() > bestNeighborFitness) { noImprovementCount++;
bestNeighborFitness = neighbor.getFitness(); // 记录无改进
bestNeighbor = neighbor; if (iterations <= stagnantWindow) {
recentImprovements[iterations - 1] = 0;
} }
continue;
}
// 先检查禁忌(不需要解码!只需要 machineSelection 和 operationSequencing)
String neighborGeneStr = neighbor.getGeneStr();
String currentGeneStr = current.getGeneStr();
boolean isTabu = isTabu(neighborGeneStr);
// 方案 1:快速跳过和 current 一样的解(不用解码!)
if (neighborGeneStr.equals(currentGeneStr)) {
// 和当前解一样,跳过,不用解码
addToTabuList(neighborGeneStr);
noImprovementCount++;
if (iterations <= stagnantWindow) {
recentImprovements[iterations - 1] = 0;
}
continue;
}
// 添加到禁忌表(无论是否接受都先记下来)
addToTabuList(neighborGeneStr);
boolean accept = false;
boolean isBetterThanBest = false;
boolean isBetterThanCurrent = false;
// 解码(需要比较 fitness)
decode(decoder, neighbor, machines);
isBetterThanBest = isBetter(neighbor, best);
isBetterThanCurrent = isBetter(neighbor, current);
// 判断是否接受这个邻居
if (!isTabu) {
// 非禁忌,接受
accept = true;
} else if (isBetterThanBest) {
// 禁忌但比最优解好(渴望准则),接受
log("禁忌搜索 - 触发渴望准则,接受禁忌解");
accept = true;
} }
// else:禁忌且没有比最优解好,不接受
if (bestNeighbor != null) { boolean improvedThisIteration = false;
// 更新当前解
current = bestNeighbor;
// 更新禁忌表 if (accept) {
addToTabuList(current); // 接受这个邻居
current = ProductionDeepCopyUtil.deepCopy(neighbor, Chromosome.class);
// 更新最优解 // 更新最优解
if (isBetter(current, best)) { if (isBetterThanBest) {
best = current; best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class);
this.bestFitness = best.getFitnessLevel().clone();
writeKpi(best);
noImprovementCount = 0; noImprovementCount = 0;
improveCount++;
improvedThisIteration = true;
logTabuImprovement(best, initialFitnessLevel, initialFitness, iterations);
log(String.format("禁忌搜索 - 找到更好解,迭代=%d", iterations),true);
} else if (isBetterThanCurrent) {
// 比当前解好但没有比最优解好
noImprovementCount = 0;
improvedThisIteration = true;
} else { } else {
// 没有改进
noImprovementCount++; noImprovementCount++;
} }
} else {
// 不接受,无改进计数+1
noImprovementCount++;
} }
iterations++; // 记录本次改进情况
} if (iterations <= stagnantWindow) {
recentImprovements[iterations - 1] = improvedThisIteration ? 1 : 0;
}
return best; // 每10次迭代输出一次状态
} if (iterations % 10 == 0) {
log(String.format("禁忌搜索 - 迭代%d/%d, 改进数=%d, 无改进连续=%d, 改进率=%.2f%%",
iterations, maxIterations, improveCount, noImprovementCount,
iterations > 0 ? (double)improveCount / iterations * 100 : 0));
}
/** // 检查提前停止条件
* 生成邻域解 boolean shouldStop = false;
*/ String stopReason = "";
private List<Chromosome> generateNeighbors(Chromosome chromosome) {
List<Chromosome> neighbors = new ArrayList<>(); if (noImprovementCount >= maxNoImprovement) {
shouldStop = true;
// 生成多个邻域解 stopReason = String.format("连续%d次无改进", maxNoImprovement);
for (int i = 0; i < 10; i++) { } else if (iterations >= stagnantWindow) {
int neighborType = rnd.nextInt(4); double recentImproveRate = calculateRecentImprovementRate(recentImprovements, stagnantWindow);
switch (neighborType) { if (recentImproveRate < improvementRateThreshold) {
case 0: shouldStop = true;
neighbors.add(generateSwapNeighbor(chromosome)); stopReason = String.format("最近%d次迭代改进率过低(%.2f%%)", stagnantWindow, recentImproveRate * 100);
break; }
case 1: }
neighbors.add(generateReverseNeighbor(chromosome));
break; if (shouldStop) {
case 2: log(String.format("禁忌搜索 - 提前停止:%s", stopReason));
neighbors.add(generateInsertNeighbor(chromosome)); logTabuFinalSummary(best, initialFitnessLevel, initialFitness, iterations, improveCount);
break; break;
case 3:
neighbors.add(generateMachineChangeNeighbor(chromosome));
break;
} }
} }
return neighbors; logTabuFinalSummary(best, initialFitnessLevel, initialFitness, iterations, improveCount);
log(String.format("禁忌搜索 - 结束,总迭代=%d", iterations),true);
return best;
} }
private void writeKpi(Chromosome chromosome) {
String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel();
for (int i = 0; i < fitness1.length; i++) {
/** fitness += fitness1[i] + ",";
* 过滤禁忌解
*/
private List<Chromosome> filterTabuSolutions(List<Chromosome> neighbors) {
List<Chromosome> validNeighbors = new ArrayList<>();
for (Chromosome neighbor : neighbors) {
if (!isTabu(neighbor)) {
validNeighbors.add(neighbor);
}
} }
// 如果没有有效邻域解,返回所有邻域解 log(String.format("变邻域搜索 - kpi:%s", fitness),true);
if (validNeighbors.isEmpty()) {
return neighbors;
}
return validNeighbors;
} }
/** /**
* 检查解是否在禁忌表中 * 记录禁忌搜索改进详情
*/ */
private boolean isTabu(Chromosome chromosome) { private void logTabuImprovement(Chromosome best, double[] initialFitnessLevel, double initialFitness, int iteration) {
for (Chromosome tabuChromosome : tabuList) { StringBuilder sb = new StringBuilder("禁忌搜索 - 改进详情: 迭代" + iteration + ", ");
if (chromosome.getGeneStr().equals(tabuChromosome.getGeneStr())) { double[] currentFitness = best.getFitnessLevel();
return true;
} for (int i = 0; i < currentFitness.length; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(+%.4f) ", i+1, initialFitnessLevel[i], currentFitness[i], improvement));
} }
return false;
double totalImprovement = best.getFitness() - initialFitness;
sb.append(String.format("总Fitness: %.4f→%.4f(+%.4f)", initialFitness, best.getFitness(), totalImprovement));
log(sb.toString());
} }
/** /**
* 添加解到禁忌表 * 计算最近改进率
*/ */
private void addToTabuList(Chromosome chromosome) { private double calculateRecentImprovementRate(int[] recentImprovements, int windowSize) {
tabuList.add(chromosome); int improveCount = 0;
if (tabuList.size() > tabuListSize) { for (int i = 0; i < windowSize; i++) {
tabuList.remove(0); improveCount += recentImprovements[i];
} }
return (double) improveCount / windowSize;
} }
/** /**
* 生成交换邻域解 * 记录禁忌搜索最终总结
*/ */
private Chromosome generateSwapNeighbor(Chromosome chromosome) { private void logTabuFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness,
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); int totalIterations, int improveCount) {
List<Integer> os = neighbor.getOperationSequencing(); StringBuilder sb = new StringBuilder("禁忌搜索 - 最终总结: ");
if (os.size() >= 2) { double[] currentFitness = best.getFitnessLevel();
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size()); sb.append(String.format("总迭代%d次, 成功改进%d次, 改进率%.2f%%. ",
while (idx2 == idx1) { totalIterations, improveCount, totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
idx2 = rnd.nextInt(os.size());
} for (int i = 0; i < currentFitness.length; i++) {
Collections.swap(os, idx1, idx2); double improvement = currentFitness[i] - initialFitnessLevel[i];
neighbor.setOperationSequencing(os); sb.append(String.format("KPI%d: %.4f→%.4f(%.2f%%) ", i+1, initialFitnessLevel[i], currentFitness[i],
initialFitnessLevel[i] > 0 ? improvement / initialFitnessLevel[i] * 100 : 0));
} }
return neighbor;
}
double totalImprovement = best.getFitness() - initialFitness;
sb.append(String.format("总Fitness: %.4f→%.4f(%.2f%%)", initialFitness, best.getFitness(),
initialFitness > 0 ? totalImprovement / initialFitness * 100 : 0));
log(sb.toString());
}
/** /**
* 生成反转邻域解 * 检查解是否在禁忌表中
*/ */
private Chromosome generateReverseNeighbor(Chromosome chromosome) { public boolean isTabu(String GeneStr) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing(); return tabuList.contains(GeneStr);
if (os.size() >= 2) {
int start = rnd.nextInt(os.size());
int end = rnd.nextInt(os.size());
while (end <= start) {
end = rnd.nextInt(os.size());
}
Collections.reverse(os.subList(start, end + 1));
neighbor.setOperationSequencing(os);
}
return neighbor;
} }
/** /**
* 生成插入邻域解 * 添加解到禁忌表(FIFO策略)
*/ */
private Chromosome generateInsertNeighbor(Chromosome chromosome) { public void addToTabuList(String geneStr) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); tabuList.add(geneStr);
List<Integer> os = neighbor.getOperationSequencing(); if (tabuList.size() > tabuListSize) {
if (os.size() >= 2) { // 移除最早加入的禁忌解
int idx1 = rnd.nextInt(os.size()); tabuList.remove(0);
int idx2 = rnd.nextInt(os.size());
while (idx2 == idx1) {
idx2 = rnd.nextInt(os.size());
}
int value = os.remove(idx1);
os.add(idx2, value);
neighbor.setOperationSequencing(os);
} }
return neighbor;
} }
/**
* 生成机器选择邻域解
*/
private Chromosome generateMachineChangeNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> ms = neighbor.getMachineSelection();
if (!ms.isEmpty()) {
int idx = rnd.nextInt(ms.size());
GlobalOperationInfo globalOp = globalOpList.get(idx);
Entry op = globalOp.getOp();
if (op.getMachineOptions().size() > 1) {
int currentMachineSeq = ms.get(idx);
List<Integer> availableMachines = new ArrayList<>();
for (int i = 1; i <= op.getMachineOptions().size(); i++) {
if (i != currentMachineSeq) {
availableMachines.add(i);
}
}
if (!availableMachines.isEmpty()) { private void decode(GeneticDecoder decoder, Chromosome chromosome , List<Machine> machines) {
int newMachineSeq = availableMachines.get(rnd.nextInt(availableMachines.size())); chromosome.setResult(new CopyOnWriteArrayList<>());
ms.set(idx, newMachineSeq);
neighbor.setMachineSelection(ms); // 缓存 Machine 列表(第一次调用时缓存)
} if (cachedMachines == null) {
} cachedMachines = ProductionDeepCopyUtil.deepCopyList(machines, Machine.class);
} }
return neighbor;
}
/** // 使用缓存的列表,避免重复深拷贝
* 解码染色体 chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(cachedMachines, Machine.class));
*/ chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedOrders), Order.class));
private void decode(GeneticDecoder decoder, Chromosome chromosome, ScheduleParams param) { chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedEntryRel), GroupResult.class));
chromosome.setResult(new java.util.concurrent.CopyOnWriteArrayList<>()); chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyList(cachedMaterials, Material.class));
decoder.decodeChromosomeWithCache(chromosome); chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedAllOperations), Entry.class));
if (chromosome.getFitness() == 0) {
chromosome.setFitness(fitnessCalculator.calculateFitness(chromosome, objectiveWeights)); // 加载锁定工单到ResultOld
List<GAScheduleResult> lockedOrders = GlobalCacheUtil.get("locked_orders_" + chromosome.getScenarioID());
if (lockedOrders != null && !lockedOrders.isEmpty()) {
chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(lockedOrders, GAScheduleResult.class));
} else {
chromosome.setResultOld(new CopyOnWriteArrayList<>());
} }
decoder.decodeChromosomeWithCache(chromosome,true);
} }
/** /**
* 比较两个染色体的优劣 * 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/ */
private boolean isBetter(Chromosome c1, Chromosome c2) { private boolean isBetter(Chromosome c1, Chromosome c2) {
return c1.getFitness() > c2.getFitness(); return fitnessCalculator.isBetter(c1,c2);
} }
} }
\ No newline at end of file
package com.aps.service.Algorithm;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.*;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.GlobalParam;
import java.util.*;
/**
* 禁忌搜索+模拟退火混合算法
*/
public class TabuSearchWithSA {
private final Random rnd = new Random();
private GlobalParam globalParam;
private List<Entry> allOperations;
private List<GlobalOperationInfo> globalOpList;
private FitnessCalculator fitnessCalculator;
private ObjectiveWeights objectiveWeights;
// 禁忌表
private List<Chromosome> tabuList;
private int tabuListSize = 50;
public TabuSearchWithSA(GlobalParam globalParam, List<Entry> allOperations, List<GlobalOperationInfo> globalOpList, FitnessCalculator fitnessCalculator, ObjectiveWeights objectiveWeights) {
this.globalParam = globalParam;
this.allOperations = allOperations;
this.globalOpList = globalOpList;
this.fitnessCalculator = fitnessCalculator;
this.objectiveWeights = objectiveWeights;
this.tabuList = new ArrayList<>();
}
/**
* 禁忌搜索+模拟退火混合搜索
*/
public Chromosome search(Chromosome chromosome, GeneticDecoder decoder, ScheduleParams param) {
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
// 初始化温度
double temperature = 100.0;
double coolingRate = 0.95;
int iterations = 0;
int maxIterations = 1000;
int noImprovementCount = 0;
int maxNoImprovement = 100;
while (iterations < maxIterations && noImprovementCount < maxNoImprovement) {
// 生成邻域解
List<Chromosome> neighbors = generateNeighbors(current);
// 过滤禁忌解
List<Chromosome> validNeighbors = filterTabuSolutions(neighbors);
// 评估所有邻域解
Chromosome bestNeighbor = null;
double bestNeighborFitness = Double.NEGATIVE_INFINITY;
for (Chromosome neighbor : validNeighbors) {
decode(decoder, neighbor, param);
if (neighbor.getFitness() > bestNeighborFitness) {
bestNeighborFitness = neighbor.getFitness();
bestNeighbor = neighbor;
}
}
if (bestNeighbor != null) {
// 计算能量差
decode(decoder, current, param);
double energyDifference = bestNeighbor.getFitness() - current.getFitness();
// 结合模拟退火的概率接受机制
if (energyDifference > 0 || rnd.nextDouble() < Math.exp(energyDifference / temperature)) {
// 更新当前解
current = bestNeighbor;
// 更新禁忌表
addToTabuList(current);
// 更新最优解
if (isBetter(current, best)) {
best = current;
noImprovementCount = 0;
} else {
noImprovementCount++;
}
}
}
// 降温
temperature *= coolingRate;
iterations++;
}
return best;
}
/**
* 生成邻域解
*/
private List<Chromosome> generateNeighbors(Chromosome chromosome) {
List<Chromosome> neighbors = new ArrayList<>();
// 生成多个邻域解
for (int i = 0; i < 10; i++) {
int neighborType = rnd.nextInt(4);
switch (neighborType) {
case 0:
neighbors.add(generateSwapNeighbor(chromosome));
break;
case 1:
neighbors.add(generateReverseNeighbor(chromosome));
break;
case 2:
neighbors.add(generateInsertNeighbor(chromosome));
break;
case 3:
neighbors.add(generateMachineChangeNeighbor(chromosome));
break;
}
}
return neighbors;
}
/**
* 过滤禁忌解
*/
private List<Chromosome> filterTabuSolutions(List<Chromosome> neighbors) {
List<Chromosome> validNeighbors = new ArrayList<>();
for (Chromosome neighbor : neighbors) {
if (!isTabu(neighbor)) {
validNeighbors.add(neighbor);
}
}
// 如果没有有效邻域解,返回所有邻域解
if (validNeighbors.isEmpty()) {
return neighbors;
}
return validNeighbors;
}
/**
* 检查解是否在禁忌表中
*/
private boolean isTabu(Chromosome chromosome) {
for (Chromosome tabuChromosome : tabuList) {
if (chromosome.getGeneStr().equals(tabuChromosome.getGeneStr())) {
return true;
}
}
return false;
}
/**
* 添加解到禁忌表
*/
private void addToTabuList(Chromosome chromosome) {
tabuList.add(chromosome);
if (tabuList.size() > tabuListSize) {
tabuList.remove(0);
}
}
/**
* 生成交换邻域解
*/
private Chromosome generateSwapNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
while (idx2 == idx1) {
idx2 = rnd.nextInt(os.size());
}
Collections.swap(os, idx1, idx2);
neighbor.setOperationSequencing(os);
}
return neighbor;
}
/**
* 生成反转邻域解
*/
private Chromosome generateReverseNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
int start = rnd.nextInt(os.size());
int end = rnd.nextInt(os.size());
while (end <= start) {
end = rnd.nextInt(os.size());
}
Collections.reverse(os.subList(start, end + 1));
neighbor.setOperationSequencing(os);
}
return neighbor;
}
/**
* 生成插入邻域解
*/
private Chromosome generateInsertNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
while (idx2 == idx1) {
idx2 = rnd.nextInt(os.size());
}
int value = os.remove(idx1);
os.add(idx2, value);
neighbor.setOperationSequencing(os);
}
return neighbor;
}
/**
* 生成机器选择邻域解
*/
private Chromosome generateMachineChangeNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> ms = neighbor.getMachineSelection();
if (!ms.isEmpty()) {
int idx = rnd.nextInt(ms.size());
GlobalOperationInfo globalOp = globalOpList.get(idx);
Entry op = globalOp.getOp();
if (op.getMachineOptions().size() > 1) {
int currentMachineSeq = ms.get(idx);
List<Integer> availableMachines = new ArrayList<>();
for (int i = 1; i <= op.getMachineOptions().size(); i++) {
if (i != currentMachineSeq) {
availableMachines.add(i);
}
}
if (!availableMachines.isEmpty()) {
int newMachineSeq = availableMachines.get(rnd.nextInt(availableMachines.size()));
ms.set(idx, newMachineSeq);
neighbor.setMachineSelection(ms);
}
}
}
return neighbor;
}
/**
* 解码染色体
*/
private void decode(GeneticDecoder decoder, Chromosome chromosome, ScheduleParams param) {
chromosome.setResult(new java.util.concurrent.CopyOnWriteArrayList<>());
decoder.decodeChromosomeWithCache(chromosome);
if (chromosome.getFitness() == 0) {
chromosome.setFitness(fitnessCalculator.calculateFitness(chromosome, objectiveWeights));
}
}
/**
* 比较两个染色体的优劣
*/
private boolean isBetter(Chromosome c1, Chromosome c2) {
return c1.getFitness() > c2.getFitness();
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -222,7 +222,7 @@ public class PlanResultService { ...@@ -222,7 +222,7 @@ public class PlanResultService {
lockedOrderProcessorService.markLockedOrdersOccupiedTime(machines, timeConfig.getBaseTime()); lockedOrderProcessorService.markLockedOrdersOccupiedTime(machines, timeConfig.getBaseTime());
// 5. 执行调度算法 // 5. 执行调度算法
GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,Materials1,materialIds,machineScheduler,entryRel,materialRequirementService,_sceneService,SceneId); //new GeneticAlgorithm(products, machines, orders, machineScheduler); HybridAlgorithm scheduler =new HybridAlgorithm(globalParam,machines,orders,Materials1,materialIds,machineScheduler,entryRel,materialRequirementService,_sceneService,SceneId); //new GeneticAlgorithm(products, machines, orders, machineScheduler);
param.initAdaptiveParams(entrys.size()); param.initAdaptiveParams(entrys.size());
double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5 double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间 //完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
...@@ -238,7 +238,7 @@ public class PlanResultService { ...@@ -238,7 +238,7 @@ public class PlanResultService {
_sceneService.saveChromosomeToFile(chromosome, SceneId); _sceneService.saveChromosomeToFile(chromosome, SceneId);
WriteScheduleSummary(chromosome); // WriteScheduleSummary(chromosome);
return chromosome; return chromosome;
......
...@@ -132,7 +132,7 @@ public class SceneService { ...@@ -132,7 +132,7 @@ public class SceneService {
try { try {
ObjectMapper objectMapper = createObjectMapper(); ObjectMapper objectMapper = createObjectMapper();
SceneChromsome sceneChromsome=(SceneChromsome)redisUtils.get("SceneId."+sceneId); SceneChromsome sceneChromsome=null;//(SceneChromsome)redisUtils.get("SceneId."+sceneId);
if(sceneChromsome==null) if(sceneChromsome==null)
{ {
sceneChromsome=new SceneChromsome(); sceneChromsome=new SceneChromsome();
...@@ -163,7 +163,7 @@ public class SceneService { ...@@ -163,7 +163,7 @@ public class SceneService {
sceneChromsome.getSceneDetails().add(sceneDetail); sceneChromsome.getSceneDetails().add(sceneDetail);
redisUtils.set("SceneId."+sceneId,sceneChromsome); // redisUtils.set("SceneId."+sceneId,sceneChromsome);
File file = getChromosomeFile(sceneId,sceneChromsome.getVersion().toString()); File file = getChromosomeFile(sceneId,sceneChromsome.getVersion().toString());
......
...@@ -39,7 +39,8 @@ public class PlanResultServiceTest { ...@@ -39,7 +39,8 @@ public class PlanResultServiceTest {
// TestSortService sortService=new TestSortService(); // TestSortService sortService=new TestSortService();
// sortService.test1(); // sortService.test1();
// nsgaiiUtils.Test(); // nsgaiiUtils.Test();
planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//2000 planResultService.execute2("08B1D87FE1B84ECDBAC2E546DDB6FB81");//2000
// planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//2000
// planResultService.execute2("C8B533BD8944405B9A2F8823C575C204");//500 // planResultService.execute2("C8B533BD8944405B9A2F8823C575C204");//500
// planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");//20 // planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");//20
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D"); // planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
......
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