Commit 932c42d2 authored by Tong Li's avatar Tong Li

混合算法

parent ad57430d
...@@ -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; // 加权目标值(用于自定义权重)
......
...@@ -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;
}
......
...@@ -392,7 +392,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -392,7 +392,7 @@ 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);
...@@ -474,7 +474,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -474,7 +474,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
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 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);
...@@ -627,7 +627,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -627,7 +627,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
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 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);
......
package com.aps.service.Algorithm; package com.aps.service.Algorithm;
import com.aps.common.util.DateTimeUtil; import com.aps.common.util.DateTimeUtil;
import com.aps.common.util.DeepCopyUtil; import com.aps.common.util.DeepCopyUtil;
import com.aps.common.util.FileHelper; import com.aps.common.util.FileHelper;
import com.aps.common.util.ProductionDeepCopyUtil; import com.aps.common.util.ProductionDeepCopyUtil;
...@@ -55,7 +55,7 @@ public class HybridAlgorithm { ...@@ -55,7 +55,7 @@ public class HybridAlgorithm {
// 初始化算法实例 // 初始化算法实例
private HillClimbing _hillClimbing; private HillClimbing _hillClimbing;
private SimulatedAnnealing _simulatedAnnealing; private SimulatedAnnealing _simulatedAnnealing;
private ParallelLocalSearch _parallelLocalSearch;
// 初始化算法实例 // 初始化算法实例
private TabuSearch _tabuSearch; private TabuSearch _tabuSearch;
...@@ -109,11 +109,10 @@ int opcount=allOperations.size(); ...@@ -109,11 +109,10 @@ 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, _fitnessCalculator );
_hillClimbing = new HillClimbing(allOperations); _hillClimbing = new HillClimbing(allOperations);
_simulatedAnnealing = new SimulatedAnnealing( allOperations); _simulatedAnnealing = new SimulatedAnnealing( allOperations, _fitnessCalculator);
_parallelLocalSearch = new ParallelLocalSearch(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights); _tabuSearch = new TabuSearch(allOperations);
_tabuSearch = new TabuSearch(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights);
_tabuSearchWithSA = new TabuSearchWithSA(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights); _tabuSearchWithSA = new TabuSearchWithSA(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights);
FileHelper.writeLogFile("初始化种群-----------开始-------"); FileHelper.writeLogFile("初始化种群-----------开始-------");
...@@ -146,7 +145,7 @@ int opcount=allOperations.size(); ...@@ -146,7 +145,7 @@ int opcount=allOperations.size();
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 +155,25 @@ int opcount=allOperations.size(); ...@@ -156,27 +155,25 @@ 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);
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);
} }
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 +182,8 @@ int opcount=allOperations.size(); ...@@ -185,7 +182,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 +191,7 @@ int opcount=allOperations.size(); ...@@ -193,6 +191,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 +203,54 @@ int opcount=allOperations.size(); ...@@ -204,141 +203,54 @@ 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<>(); List<Chromosome> newPopulation = new ArrayList<>();
for (int i = 0; i < selected.size(); i += 2) { newPopulation.add(best);
if (i + 1 >= selected.size()) { while (newPopulation.size() < param.getPopulationSize()) {
selected.get(i).setID(UUID.randomUUID().toString()); // 选择父代
nextPopulation.add(selected.get(i)); Chromosome parent1 = selected.get(rnd.nextInt(selected.size()));
break; Chromosome parent2 = selected.get(rnd.nextInt(selected.size()));
} // 交叉
Chromosome child = parent1;
Chromosome parent1 = selected.get(i);
Chromosome parent2 = selected.get(i + 1);
if (rnd.nextDouble() < param.getCrossoverProb()) { if (rnd.nextDouble() < param.getCrossoverProb()) {
// 假设PoxCrossover返回包含两个子染色体的数组 // 假设PoxCrossover返回包含两个子染色体的数组
Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount); Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
nextPopulation.add(children.getFirst()); child=children.getFirst();
nextPopulation.add(children.getSecond()); child.setID(UUID.randomUUID().toString());
} 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()) { if (rnd.nextDouble() < param.getMutationProb()) {
Chromosome chromosome1= ProductionDeepCopyUtil.deepCopy(chromosome,Chromosome.class); geneticOps.mutate(child, globalOpList);
chromosome1.setID(UUID.randomUUID().toString());
geneticOps.mutate(chromosome1, globalOpList);
nextPopulation1.add(chromosome1);
} }
} // 核心融合链(工业级标准顺序:GA生成子代 → SA跳坑 → VNS扩邻域 → TS精优化)
nextPopulation.addAll(nextPopulation1); child = _simulatedAnnealing.search(child,_tabuSearch,_vns, saDecoder1, machines);
FileHelper.writeLogFile("变异操作-----------结束-------"); child = _vns.search(child, vnsDecoder1, machines);
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> populationcopy = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize()/5);
newPopulation.addAll(populationcopy);
newPopulation.addAll(nextPopulation);
newPopulation= chromosomeDistinct1(newPopulation);
FileHelper.writeLogFile("非支配排序-----------开始-------");
// 2.7 非支配排序
combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(newPopulation);
FileHelper.writeLogFile("非支配排序-----------结束-------");
// 2.8 选择下一代种群
population = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize());
// 更新种群
// population = newPopulation.stream()
// .limit(param.getPopulationSize() )
// .collect(Collectors.toList());
newPopulation.add(child);
}
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;
} }
...@@ -413,7 +325,7 @@ int opcount=allOperations.size(); ...@@ -413,7 +325,7 @@ int opcount=allOperations.size();
} }
/** /**
* 按Objectives去重,相同目标值的方案只保留一个(保留fitness最大的) * 按Objectives去重
*/ */
private List<Chromosome> chromosomeDistinctByObjectives(List<Chromosome> population) private List<Chromosome> chromosomeDistinctByObjectives(List<Chromosome> population)
{ {
...@@ -440,7 +352,32 @@ int opcount=allOperations.size(); ...@@ -440,7 +352,32 @@ 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; // 两者相等
}
});
return result;
}
/**
* 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/
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;
} }
private List<Chromosome> chromosomeDistinct1(List<Chromosome> population) private List<Chromosome> chromosomeDistinct1(List<Chromosome> population)
......
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
...@@ -20,15 +20,17 @@ public class SimulatedAnnealing { ...@@ -20,15 +20,17 @@ public class SimulatedAnnealing {
private List<Entry> allOperations; private List<Entry> allOperations;
private FitnessCalculator fitnessCalculator;
private Map<String, Entry> entrys; 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, FitnessCalculator fitnessCalculator) {
this.allOperations = allOperations; this.allOperations = allOperations;
Map<Integer, Object> mp = buildEntryKey(); Map<Integer, Object> mp = buildEntryKey();
this.fitnessCalculator = fitnessCalculator;
entrys=(Map<String, Entry>)mp.get(1); entrys=(Map<String, Entry>)mp.get(1);
entrybyids=(Map<Integer, Entry>)mp.get(2); entrybyids=(Map<Integer, Entry>)mp.get(2);
...@@ -40,7 +42,7 @@ private Map<String, Entry> entrys; ...@@ -40,7 +42,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 +52,15 @@ private Map<String, Entry> entrys; ...@@ -50,15 +52,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,7 +74,7 @@ private Map<String, Entry> entrys; ...@@ -72,7 +74,7 @@ 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("模拟退火+爬山法 - 开始执行"); FileHelper.writeLogFile("模拟退火+爬山法 - 开始执行");
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
...@@ -102,7 +104,7 @@ private Map<String, Entry> entrys; ...@@ -102,7 +104,7 @@ private Map<String, Entry> entrys;
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);
...@@ -118,14 +120,14 @@ private Map<String, Entry> entrys; ...@@ -118,14 +120,14 @@ private Map<String, Entry> entrys;
acceptCount++; acceptCount++;
// 更新全局最优 // 更新全局最优
if (isBetter(current, best)) {
best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class); best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class);
writeKpi(best); writeKpi(best);
improved = true; improved = true;
improveCount++; improveCount++;
noImproveCount = 0; noImproveCount = 0;
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 迭代%d:找到更优解,fitness=%.4f", i, best.getFitness())); FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 迭代%d:找到更优解,fitness=%.4f", i, best.getFitness()));
}
} }
if (!improved) { if (!improved) {
...@@ -162,6 +164,95 @@ private Map<String, Entry> entrys; ...@@ -162,6 +164,95 @@ private Map<String, Entry> entrys;
// 7. 输出全局最优排产 // 7. 输出全局最优排产
return best; return best;
} }
/**
* 模拟退火搜索
* 流程:模拟退火全局探索(按概率接受劣解)→ 降温 → 输出最优
*/
public Chromosome search(Chromosome chromosome,TabuSearch tabusearch,VariableNeighborhoodSearch vns, GeneticDecoder decoder, List<Machine> machines) {
FileHelper.writeLogFile("模拟退火+爬山法 - 开始执行");
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
decode(decoder, current,machines);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
writeKpi(best);
// 初始化解码
// FileHelper.writeLogFile("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度
double temperature = 100.0;
double coolingRate = 0.95;
double temperatureThreshold = 1.0;
int maxIterations = 300;
int noImproveCount = 0;
int maxNoImprove = 50;
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代=%d",
temperature, coolingRate, temperatureThreshold, maxIterations));
int acceptCount = 0;
int improveCount = 0;
for (int i = 0; i < maxIterations; i++) {
boolean improved = false;
// 1. 使用智能策略生成邻域解(找瓶颈工序/设备)
Chromosome neighbor = vns.generateNeighbor(current);
// 2. 解码
decode(decoder, neighbor,machines);
// 跳过禁忌解(除非是最优解)
if (tabusearch.isTabu(neighbor.getGeneStr()) && !isBetter(current,best)) {
temperature *= coolingRate;
continue;
}
// 3. 计算能量差
double energyDifference = calculateEnergyDifference(neighbor, current);
// 4. 按概率接受新解(模拟退火核心:有概率接受劣解)
boolean accepted = false;
if (energyDifference > 0 || rnd.nextDouble() < Math.exp(energyDifference / temperature)) {
current = neighbor;
accepted = true;
acceptCount++;
best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class);
tabusearch.addToTabuList(best.getGeneStr());
writeKpi(best);
improved = true;
improveCount++;
noImproveCount = 0;
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 迭代%d:找到更优解,fitness=%.4f", i, best.getFitness()));
}
if (!improved) {
noImproveCount++;
}
// 5. 降温
temperature *= coolingRate;
// 每50次迭代输出一次状态
if ((i + 1) % 50 == 0) {
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d",
i + 1, maxIterations, temperature, acceptCount, improveCount, noImproveCount));
}
}
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f",
maxIterations, best.getFitness()));
// 7. 输出全局最优排产
return best;
}
private void writeKpi(Chromosome chromosome) { private void writeKpi(Chromosome chromosome) {
String fitness = ""; String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel(); double[] fitness1 = chromosome.getFitnessLevel();
...@@ -221,66 +312,7 @@ private Map<String, Entry> entrys; ...@@ -221,66 +312,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
*/ */
...@@ -301,544 +333,6 @@ private Map<String, Entry> entrys; ...@@ -301,544 +333,6 @@ private Map<String, Entry> entrys;
return index0; return index0;
} }
/**
* 生成邻域解 - 智能策略:优先处理瓶颈工序/设备
* 策略:
* 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;
}
/** /**
* 解码染色体 * 解码染色体
*/ */
...@@ -857,14 +351,7 @@ private Map<String, Entry> entrys; ...@@ -857,14 +351,7 @@ private Map<String, Entry> entrys;
* 比较两个染色体的优劣(基于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) {
// 找出最佳候选方案 // 找出最佳候选方案
......
...@@ -11,251 +11,59 @@ import java.util.*; ...@@ -11,251 +11,59 @@ import java.util.*;
* 禁忌搜索算法 * 禁忌搜索算法
*/ */
public class TabuSearch { public class TabuSearch {
private final Random rnd = new Random();
private GlobalParam globalParam;
private List<Entry> allOperations; private List<Entry> allOperations;
private List<GlobalOperationInfo> globalOpList;
private FitnessCalculator fitnessCalculator;
private ObjectiveWeights objectiveWeights;
// 禁忌表 // 禁忌表
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) { public TabuSearch(List<Entry> allOperations) {
this.globalParam = globalParam;
this.allOperations = allOperations;
this.globalOpList = globalOpList;
this.fitnessCalculator = fitnessCalculator;
this.objectiveWeights = objectiveWeights;
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);
} }
/**
* 禁忌搜索
*/
public Chromosome search(Chromosome chromosome, GeneticDecoder decoder, ScheduleParams param) {
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
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) {
// 更新当前解
current = bestNeighbor;
// 更新禁忌表
addToTabuList(current);
// 更新最优解
if (isBetter(current, best)) {
best = current;
noImprovementCount = 0;
} else {
noImprovementCount++;
}
}
iterations++;
}
return best;
}
/** /**
* 生成邻域解 * 检查解是否在禁忌表中
*/ */
private List<Chromosome> generateNeighbors(Chromosome chromosome) { public boolean isTabu(String GeneStr) {
List<Chromosome> neighbors = new ArrayList<>();
// 生成多个邻域解 return tabuList.contains(GeneStr);
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) { public void addToTabuList(String GeneStr) {
List<Chromosome> validNeighbors = new ArrayList<>(); tabuList.add(GeneStr);
if (tabuList.size() > tabuListSize) {
for (Chromosome neighbor : neighbors) { // 移除最早加入的禁忌解(FIFO策略)
if (!isTabu(neighbor)) { Iterator<String> iterator = tabuList.iterator();
validNeighbors.add(neighbor); iterator.next();
} iterator.remove();
} }
}
// 如果没有有效邻域解,返回所有邻域解
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
...@@ -6,6 +6,7 @@ import com.aps.entity.basic.*; ...@@ -6,6 +6,7 @@ import com.aps.entity.basic.*;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
/** /**
* 变邻域搜索算法 * 变邻域搜索算法
...@@ -14,28 +15,34 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -14,28 +15,34 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/ */
public class VariableNeighborhoodSearch { public class VariableNeighborhoodSearch {
private final Random rnd = new Random(); private final Random rnd = new Random();
private GlobalParam globalParam;
private List<Entry> allOperations; private List<Entry> allOperations;
private List<GlobalOperationInfo> globalOpList;
private FitnessCalculator fitnessCalculator; private FitnessCalculator fitnessCalculator;
private ObjectiveWeights objectiveWeights;
public VariableNeighborhoodSearch(GlobalParam globalParam, List<Entry> allOperations, List<GlobalOperationInfo> globalOpList, FitnessCalculator fitnessCalculator, ObjectiveWeights objectiveWeights) {
this.globalParam = globalParam; private Map<String, Entry> entrys;
private Map<Integer, Entry> entrybyids;
public VariableNeighborhoodSearch( List<Entry> allOperations, FitnessCalculator fitnessCalculator) {
this.allOperations = allOperations; this.allOperations = allOperations;
this.globalOpList = globalOpList;
this.fitnessCalculator = fitnessCalculator; this.fitnessCalculator = fitnessCalculator;
this.objectiveWeights = objectiveWeights; Map<Integer, Object> mp = buildEntryKey();
entrys=(Map<String, Entry>)mp.get(1);
entrybyids=(Map<Integer, Entry>)mp.get(2);
} }
/** /**
* 对种群中的每个个体进行变邻域搜索 * 对种群中的每个个体进行变邻域搜索
*/ */
public List<Chromosome> search(List<Chromosome> population, GeneticDecoder decoder, ScheduleParams param) { public List<Chromosome> search(List<Chromosome> population, GeneticDecoder decoder, List<Machine> machines) {
List<Chromosome> improvedPopulation = new ArrayList<>(); List<Chromosome> improvedPopulation = new ArrayList<>();
for (Chromosome chromosome : population) { for (Chromosome chromosome : population) {
Chromosome improvedChromosome = search(chromosome, decoder, param); Chromosome improvedChromosome = search(chromosome, decoder, machines);
improvedPopulation.add(improvedChromosome); improvedPopulation.add(improvedChromosome);
} }
...@@ -45,7 +52,7 @@ public class VariableNeighborhoodSearch { ...@@ -45,7 +52,7 @@ public class VariableNeighborhoodSearch {
/** /**
* 对单个个体进行变邻域搜索 * 对单个个体进行变邻域搜索
*/ */
public Chromosome search(Chromosome chromosome, GeneticDecoder decoder, ScheduleParams param) { public Chromosome search(Chromosome chromosome, GeneticDecoder decoder, List<Machine> machines) {
// 深拷贝当前染色体 // 深拷贝当前染色体
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);
...@@ -59,10 +66,10 @@ public class VariableNeighborhoodSearch { ...@@ -59,10 +66,10 @@ public class VariableNeighborhoodSearch {
NeighborhoodStructure neighborhood = neighborhoods.get(k); NeighborhoodStructure neighborhood = neighborhoods.get(k);
// 生成邻域解 // 生成邻域解
Chromosome neighbor = generateNeighbor(current, neighborhood); Chromosome neighbor = generateNeighbor(current);
// 局部搜索 // 局部搜索
Chromosome localBest = localSearch(neighbor, decoder, param); Chromosome localBest = localSearch(neighbor, decoder,null);
// 邻域移动 // 邻域移动
if (isBetter(localBest, best)) { if (isBetter(localBest, best)) {
...@@ -99,11 +106,540 @@ public class VariableNeighborhoodSearch { ...@@ -99,11 +106,540 @@ public class VariableNeighborhoodSearch {
} }
/** /**
* 生成邻域解 * 生成邻域解 - 智能策略:优先处理瓶颈工序/设备
* 策略:
* 1. 优先处理瓶颈设备上的工序(换设备)
* 2. 瓶颈设备上的工序往前移动
* 3. 非瓶颈设备上的工序往后移动(给瓶颈工序腾位置)
*/
public 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 generateNeighbor(Chromosome chromosome, NeighborhoodStructure neighborhood) { 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); Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
neighborhood.apply(neighbor); 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; return neighbor;
} }
...@@ -121,12 +657,12 @@ public class VariableNeighborhoodSearch { ...@@ -121,12 +657,12 @@ public class VariableNeighborhoodSearch {
// 生成所有可能的邻域解 // 生成所有可能的邻域解
List<Chromosome> neighbors = new ArrayList<>(); List<Chromosome> neighbors = new ArrayList<>();
for (NeighborhoodStructure neighborhood : defineNeighborhoods()) { for (NeighborhoodStructure neighborhood : defineNeighborhoods()) {
neighbors.add(generateNeighbor(current, neighborhood)); neighbors.add(generateNeighbor(current));
} }
// 评估所有邻域解 // 评估所有邻域解
for (Chromosome neighbor : neighbors) { for (Chromosome neighbor : neighbors) {
decode(decoder, neighbor, param); decode(decoder, neighbor, null);
if (isBetter(neighbor, best)) { if (isBetter(neighbor, best)) {
best = neighbor; best = neighbor;
current = neighbor; current = neighbor;
...@@ -138,15 +674,19 @@ public class VariableNeighborhoodSearch { ...@@ -138,15 +674,19 @@ public class VariableNeighborhoodSearch {
return best; return best;
} }
/** /**
* 解码染色体 * 解码染色体
*/ */
private void decode(GeneticDecoder decoder, Chromosome chromosome, ScheduleParams param) { private void decode(GeneticDecoder decoder, Chromosome chromosome , List<Machine> machines) {
chromosome.setResult(new CopyOnWriteArrayList<>()); chromosome.setResult(new CopyOnWriteArrayList<>());
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines, Machine.class)); // 简单拷贝,实际可能需要深拷贝
decoder.decodeChromosomeWithCache(chromosome); decoder.decodeChromosomeWithCache(chromosome);
if (chromosome.getFitness() == 0) {
chromosome.setFitness(fitnessCalculator.calculateFitness(chromosome, objectiveWeights));
}
} }
/** /**
...@@ -216,7 +756,7 @@ public class VariableNeighborhoodSearch { ...@@ -216,7 +756,7 @@ public class VariableNeighborhoodSearch {
if (ms.isEmpty()) return; if (ms.isEmpty()) return;
int idx = rnd.nextInt(ms.size()); int idx = rnd.nextInt(ms.size());
GlobalOperationInfo globalOp = globalOpList.get(idx); GlobalOperationInfo globalOp = chromosome.getGlobalOpList().get(idx);
Entry op = globalOp.getOp(); Entry op = globalOp.getOp();
if (op.getMachineOptions().size() > 1) { if (op.getMachineOptions().size() > 1) {
...@@ -235,6 +775,86 @@ public class VariableNeighborhoodSearch { ...@@ -235,6 +775,86 @@ public class VariableNeighborhoodSearch {
} }
} }
} }
/**
* 构建位置索引: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
*/
private Map<Integer, Object> buildEntryKey() {
Map<Integer, Object> index0 = new HashMap<>();
Map<String, Entry> index = new HashMap<>();
Map<Integer, Entry> index2 = new HashMap<>();
List<Entry> allOps = this.allOperations;
for (Entry op : allOps) {
String key = op.getGroupId() + "_" + op.getSequence();
index.put(key, op);
index2.put(op.getId(), op);
}
index0.put(1,index);
index0.put(2,index2);
return index0;
}
/** /**
* 邻域结构接口 * 邻域结构接口
......
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