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

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

parent 932c42d2
......@@ -15,7 +15,7 @@ public class ScheduleParams {
// 基础参数(自适应调整的基准值)
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 MAX_MAX_ITERATIONS = 100;
private static final float MIN_CROSSOVER_PROB = 0.6f;
......@@ -172,10 +172,14 @@ public class ScheduleParams {
// 1. 种群大小:50 ~ 500,随工序数线性增加
populationSize = (int) Math.max(MIN_POPULATION_SIZE,
Math.min(MAX_POPULATION_SIZE, MIN_POPULATION_SIZE + totalOps * populationSizeCoeff));
int maxthead= Runtime.getRuntime().availableProcessors() - 1;
populationSize= populationSize / maxthead*maxthead;
// 确保偶数(方便交叉)
if (populationSize % 2 != 0) {
populationSize += 1;
}
// if (populationSize % 2 != 0) {
// populationSize += 1;
// }
// 2. 最大迭代次数:50 ~ 200,随工序数线性减少
maxIterations = (int) Math.max(MIN_MAX_ITERATIONS,
......
......@@ -73,11 +73,11 @@ public class GlobalParam {
public GlobalParam() {
// 初始化默认目标值配置
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MAKESPAN, true, 1, 0.6));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_FLOW_TIME, false, 2, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MAKESPAN, true, 1, 0.3));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_FLOW_TIME, true, 2, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_SETUP_TIME, true, 2, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MACHINE_LOAD, false, 3, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_TARDINESS, true, 1, 0.3));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_MACHINE_LOAD, true, 1, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_TARDINESS, true, 1, 0.6));
objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel()));
}
......
package com.aps.entity.basic;
/**
* 作者:佟礼
* 时间:2026-04-09
*/
public class KpiTargetConfig {
}
......@@ -425,7 +425,7 @@ public class GeneticAlgorithm {
// chromosome.setResultOld(new CopyOnWriteArrayList<>());
// }
decoder.decodeChromosomeWithCache(chromosome);
decoder.decodeChromosomeWithCache(chromosome,false);
if (chromosome.getFitness() == 0) {
chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights));
}
......
......@@ -88,17 +88,17 @@ public class GeneticDecoder {
{
FileHelper.writeLogFile("解码---------------"+population.size() );
boolean ismore=false;
boolean ismore=true;
if(ismore) {
CompletableFuture.allOf(population.stream()
.map(chromosome -> CompletableFuture.runAsync(() -> decodeChromosomeWithCache(chromosome), decodeExecutor))
.map(chromosome -> CompletableFuture.runAsync(() -> decodeChromosomeWithCache(chromosome,false), decodeExecutor))
.toArray(CompletableFuture[]::new))
.join();
} else {
if (population != null && population.size() > 0) {
population.forEach(chromosome -> {
decodeChromosomeWithCache( chromosome);
decodeChromosomeWithCache( chromosome,false);
});
}
}
......@@ -176,7 +176,7 @@ public class GeneticDecoder {
// return chromosome;
// }
public Chromosome decodeChromosomeWithCache(Chromosome chromosome) {
public Chromosome decodeChromosomeWithCache(Chromosome chromosome,boolean isParallel) {
String cacheKey = createCacheKey(chromosome);
// FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey );
......@@ -214,7 +214,7 @@ public class GeneticDecoder {
return chromosome;
}
// 3. 缓存未命中:执行解码逻辑
decode(chromosome);
decode(chromosome,isParallel);
// 4. 将解码结果存入缓存(无锁,ConcurrentHashMap 线程安全)
decodingCache.putIfAbsent(cacheKey, chromosome);
......@@ -367,12 +367,11 @@ if(finishedOrder==null||finishedOrder.size()==0)
orderProcessCounter.put(orderid, scheduledCount);
}
public void decode(Chromosome chromosome) {
int operationCount = chromosome.getAllOperations().size();
int cpuCores = Runtime.getRuntime().availableProcessors();
public void decode(Chromosome chromosome,boolean isParallel) {
//
// // 根据工序数量和CPU核心数决定是否使用内部并行
if (operationCount > 5000 && cpuCores > 4) {
if (isParallel) {
// 使用设备并行处理
// FileHelper.writeLogFile("使用并行处理 _s");
parallelDecodeByMachine(chromosome);
......@@ -392,7 +391,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
public void serialDecode(Chromosome chromosome) {
List<OrderMaterialRequirement> orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
// List<OrderMaterialRequirement> orderMaterials = materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
chromosome.setScenarioID(sceneId);
if(_globalParam.isIsCheckSf()) {
int isnew= generateGlobalOpList(chromosome);
......
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.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
......@@ -21,6 +22,11 @@ public class HillClimbing {
private List<Entry> allOperations;
private List<Order> orders;
private List<Material> materials;
private List<GroupResult> _entryRel;
//按优先级分组工序
private Map<Double, List<Entry>> priorityGroups;
......@@ -30,10 +36,17 @@ public class HillClimbing {
// 从List转为Map op.getGroupId() + "_" + op.getSequence(); 做主键
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.orders = orders;
this.materials = materials;
_entryRel=entryRel;
fitnessCalculator=_fitnessCalculator;
// 按优先级分组工序
priorityGroups = groupOperationsByPriority();
......@@ -92,7 +105,7 @@ public class HillClimbing {
Chromosome machineChange = generateMachineChange(current, op.getMachineOptions(), maPos);
if (machineChange != null) {
decode(decoder, machineChange);
decode(decoder, machineChange,machines);
if (isBetter(machineChange, current)) {
current = machineChange;
if (isBetter(current, best)) {
......@@ -263,7 +276,7 @@ public class HillClimbing {
Chromosome machineChange = generateMachineChange(current, op.getMachineOptions(), maPos);
if (machineChange != null) {
decode(decoder, machineChange);
decode(decoder, machineChange,machines);
if (isBetter(machineChange, current)) {
current = machineChange;
if (isBetter(current, best)) {
......@@ -328,7 +341,7 @@ public class HillClimbing {
}
Chromosome newChromosome = swapAtDistance(current, opPos, -s * step);
decode(decoder, newChromosome);
decode(decoder, newChromosome,machines);
if (isBetter(newChromosome, current)) {
current = newChromosome;
......@@ -357,7 +370,7 @@ public class HillClimbing {
}
Chromosome newChromosome = swapAtDistance(current, opPos, s * step);
decode(decoder, newChromosome);
decode(decoder, newChromosome,machines);
if (isBetter(newChromosome, current)) {
current = newChromosome;
......@@ -411,21 +424,24 @@ public class HillClimbing {
}
/**
* 构建位置索引:groupId_sequence -> position
*/
private Map<String, Integer> buildPositionIndex(Chromosome chromosome) {
String fitness="";
private void writeKpi(Chromosome chromosome) {
String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel();
for (int i = 0; i < fitness1.length; i++) {
fitness+=fitness1[i]+",";
fitness += fitness1[i] + ",";
}
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<>();
List<Integer> os = chromosome.getOperationSequencing();
......@@ -546,114 +562,6 @@ public class HillClimbing {
}
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,11 +611,34 @@ public class HillClimbing {
/**
* 解码染色体
*/
private void decode(GeneticDecoder decoder, Chromosome chromosome) {
// chromosome.setResult(new java.util.concurrent.CopyOnWriteArrayList<>());
decoder.decodeChromosomeWithCache(chromosome);
private void decode(GeneticDecoder decoder, Chromosome chromosome , List<Machine> machines) {
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.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;
import com.aps.common.util.DateTimeUtil;
import com.aps.common.util.DeepCopyUtil;
import com.aps.common.util.FileHelper;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.*;
import com.aps.common.util.*;
import com.aps.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.*;
import com.aps.service.plan.MachineSchedulerService;
......@@ -59,7 +56,7 @@ public class HybridAlgorithm {
// 初始化算法实例
private TabuSearch _tabuSearch;
private TabuSearchWithSA _tabuSearchWithSA;
public HybridAlgorithm(GlobalParam globalParam,List<Machine> machines, List<Order> orders,
......@@ -109,17 +106,16 @@ int opcount=allOperations.size();
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List<GlobalOperationInfo> globalOpList = initialization.generateGlobalOpList();
// 初始化变邻域搜索
_vns = new VariableNeighborhoodSearch( allOperations, _fitnessCalculator );
_hillClimbing = new HillClimbing(allOperations);
_simulatedAnnealing = new SimulatedAnnealing( allOperations, _fitnessCalculator);
_tabuSearch = new TabuSearch(allOperations);
_tabuSearchWithSA = new TabuSearchWithSA(_GlobalParam, allOperations, globalOpList, _fitnessCalculator, _objectiveWeights);
_vns = new VariableNeighborhoodSearch( allOperations,orders,materials,_entryRel, _fitnessCalculator );
_hillClimbing = new HillClimbing(allOperations,orders,materials,_entryRel, _fitnessCalculator);
_simulatedAnnealing = new SimulatedAnnealing( allOperations,orders,materials,_entryRel, _fitnessCalculator);
_tabuSearch = new TabuSearch(allOperations,orders,materials,_entryRel, _fitnessCalculator);
FileHelper.writeLogFile("初始化种群-----------开始-------");
// 步骤1:使用构造启发式算法生成初始种群
FileHelper.writeLogFile("构造启发式初始化-----------开始-------");
List<Chromosome> population = initialization.generateHeuristicInitialPopulation(param, globalOpList);
List<Chromosome> population = initialization.generateHeuristicInitialPopulation(param);
FileHelper.writeLogFile("构造启发式初始化-----------结束-------");
......@@ -137,8 +133,8 @@ int opcount=allOperations.size();
FileHelper.writeLogFile("按Objectives去重-----------开始-------" + population.size());
population = chromosomeDistinctByObjectives(population);
FileHelper.writeLogFile("按Objectives去重-----------结束-------" + population.size());
// if(1==1)
// return getBestChromosome(population.get(0), param.getBaseTime(), starttime);
// 步骤2:对初始种群进行爬山法局部优化
if(opcount<20 ) {
......@@ -158,6 +154,8 @@ int opcount=allOperations.size();
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 ) {
FileHelper.writeLogFile("模拟退火+爬山法优化-----------开始-------");
......@@ -166,6 +164,16 @@ int opcount=allOperations.size();
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);
}
......@@ -213,27 +221,35 @@ int opcount=allOperations.size();
List<Chromosome> newPopulation = new ArrayList<>();
newPopulation.add(best);
int n=0;
while (newPopulation.size() < param.getPopulationSize()) {
// 选择父代
FileHelper.writeLogFile("交叉-----------开始-------"+n);
Chromosome parent1 = selected.get(rnd.nextInt(selected.size()));
Chromosome parent2 = selected.get(rnd.nextInt(selected.size()));
// 交叉
Chromosome child = parent1;
if (rnd.nextDouble() < param.getCrossoverProb()) {
// 假设PoxCrossover返回包含两个子染色体的数组
Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
child=children.getFirst();
child.setID(UUID.randomUUID().toString());
}
// 变异
if (rnd.nextDouble() < param.getMutationProb()) {
geneticOps.mutate(child, globalOpList);
}
// if (rnd.nextDouble() < param.getCrossoverProb()) {
// // 假设PoxCrossover返回包含两个子染色体的数组
// Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
// child=children.getFirst();
// initDataToChromosome(child,param, allOperations,globalOpList);
// 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);;
......@@ -291,18 +307,7 @@ int opcount=allOperations.size();
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)
{
if(population==null)
......@@ -380,31 +385,8 @@ int opcount=allOperations.size();
return false;
}
private List<Chromosome> chromosomeDistinct1(List<Chromosome> population)
{
if(population==null)
{
FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",0 ));
return population;
}
// 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) {
for (int i=0;i<fronts.size();i++)
{
......@@ -433,6 +415,40 @@ int opcount=allOperations.size();
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)
{
FileHelper.writeLogFile("解码---------------"+population.size() );
......@@ -479,7 +495,7 @@ int opcount=allOperations.size();
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝,实际可能需要深拷贝
// _sceneService.saveChromosomeToFile(chromosome, "12345679");
decoder.decodeChromosomeWithCache(chromosome);
decoder.decodeChromosomeWithCache(chromosome,false);
// if (chromosome.getFitness() == 0) {
// chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights));
// }
......
......@@ -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<>();
int populationSize = param.getPopulationSize();
this.baseTime=param.getBaseTime();
......
......@@ -1885,7 +1885,7 @@ if(targetOp.getSequence()>1) {
decoder.decode(chromosome);
decoder.decode(chromosome,false);
KpiCalculator kpiCalculator=new KpiCalculator(chromosome);
kpiCalculator.calculatekpi();
......
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.entity.Algorithm.*;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.GlobalParam;
import com.aps.entity.basic.Machine;
import com.aps.entity.basic.MachineOption;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.*;
import java.util.*;
import java.util.concurrent.*;
......@@ -18,19 +17,39 @@ import java.util.stream.Collectors;
public class SimulatedAnnealing {
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<Order> orders;
private List<Material> materials;
private List<GroupResult> _entryRel;
private FitnessCalculator fitnessCalculator;
private Map<String, Entry> entrys;
private Map<String, Entry> entrys;
private Map<Integer, Entry> entrybyids;
public SimulatedAnnealing( List<Entry> allOperations, FitnessCalculator fitnessCalculator) {
public SimulatedAnnealing( List<Entry> allOperations, List<Order> orders,
List<Material> materials,List<GroupResult> entryRel, FitnessCalculator _fitnessCalculator) {
this.allOperations = allOperations;
this.orders = orders;
this.materials = materials;
_entryRel=entryRel;
Map<Integer, Object> mp = buildEntryKey();
this.fitnessCalculator = fitnessCalculator;
this.fitnessCalculator = _fitnessCalculator;
entrys=(Map<String, Entry>)mp.get(1);
entrybyids=(Map<Integer, Entry>)mp.get(2);
......@@ -75,16 +94,17 @@ private Map<String, Entry> entrys;
* 流程:模拟退火全局探索(按概率接受劣解)→ 降温 → 温度低时爬山法局部求精 → 输出最优
*/
public Chromosome searchWithHillClimbing(Chromosome chromosome, VariableNeighborhoodSearch vns,GeneticDecoder decoder, List<Machine> machines) {
FileHelper.writeLogFile("模拟退火+爬山法 - 开始执行");
log("模拟退火+爬山法 - 开始执行",true);
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
writeKpi(best);
// 初始化解码
// 记录初始KPI用于计算改进率
double[] initialFitnessLevel = best.getFitnessLevel().clone();
double initialFitness = best.getFitness();
// FileHelper.writeLogFile("模拟退火+爬山法 - 初始化解码完成");
// log("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度
double temperature = 100.0;
......@@ -92,15 +112,22 @@ private Map<String, Entry> entrys;
double temperatureThreshold = 1.0;
int maxIterations = 300;
int noImproveCount = 0;
int maxNoImprove = 50;
int maxNoImprove = 30; // 降低最大无改进次数
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代=%d",
temperature, coolingRate, temperatureThreshold, maxIterations));
// 新增:改进率监控参数
int stagnantWindow = 15; // 观察窗口大小
int[] recentImprovements = new int[stagnantWindow]; // 记录最近窗口内的改进情况
double improvementRateThreshold = 0.05; // 改进率阈值(5%)
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;
// 1. 使用智能策略生成邻域解(找瓶颈工序/设备)
......@@ -120,46 +147,74 @@ private Map<String, Entry> entrys;
acceptCount++;
// 更新全局最优
if (isBetter(current, best)) {
best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class);
writeKpi(best);
improved = true;
improveCount++;
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);
}
}
if (!improved) {
noImproveCount++;
}
// 记录本次改进情况
if (totalIterations <= stagnantWindow) {
recentImprovements[totalIterations - 1] = improved ? 1 : 0;
}
// 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));
// 每30次迭代输出一次状态
if ((totalIterations) % 30 == 0) {
log(String.format("模拟退火+爬山法 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d, 总改进率=%.2f%%",
totalIterations, maxIterations, temperature, acceptCount, improveCount, noImproveCount,
totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
}
// 6. 提前停止条件:温度低于阈值 或 连续多次没改进
if (temperature < temperatureThreshold || noImproveCount >= maxNoImprove) {
String stopReason = temperature < temperatureThreshold ? "温度低于阈值" : "连续无改进达到上限";
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 提前停止:%s,迭代%d次,最终温度=%.4f",
stopReason, i + 1, temperature));
// 6. 提前停止条件
boolean shouldStop = false;
String stopReason = "";
FileHelper.writeLogFile("模拟退火+爬山法 - 切换到爬山法求精");
HillClimbing hillClimbing = new HillClimbing( allOperations);
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);
log("模拟退火+爬山法 - 切换到爬山法求精");
HillClimbing hillClimbing = new HillClimbing( allOperations,orders,materials,_entryRel,fitnessCalculator);
Chromosome refined = hillClimbing.search(best, decoder, machines);
FileHelper.writeLogFile("模拟退火+爬山法 - 爬山法求精完成");
log("模拟退火+爬山法 - 爬山法求精完成");
return refined;
}
}
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f",
maxIterations, best.getFitness()));
log(String.format("模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f",
maxIterations, best.getFitness()),true);
logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations);
// 7. 输出全局最优排产
return best;
......@@ -170,7 +225,7 @@ private Map<String, Entry> entrys;
* 流程:模拟退火全局探索(按概率接受劣解)→ 降温 → 输出最优
*/
public Chromosome search(Chromosome chromosome,TabuSearch tabusearch,VariableNeighborhoodSearch vns, GeneticDecoder decoder, List<Machine> machines) {
FileHelper.writeLogFile("模拟退火+爬山法 - 开始执行");
log("模拟退火 - 开始执行",true);
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
decode(decoder, current,machines);
......@@ -178,9 +233,11 @@ private Map<String, Entry> entrys;
writeKpi(best);
// 初始化解码
// 记录初始KPI用于计算改进率
double[] initialFitnessLevel = best.getFitnessLevel().clone();
double initialFitness = best.getFitness();
// FileHelper.writeLogFile("模拟退火+爬山法 - 初始化解码完成");
// log("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度
double temperature = 100.0;
......@@ -188,16 +245,24 @@ private Map<String, Entry> entrys;
double temperatureThreshold = 1.0;
int maxIterations = 300;
int noImproveCount = 0;
int maxNoImprove = 50;
int maxNoImprove = 20; // 降低最大无改进次数,更快提前结束
// 新增:改进率监控参数
int stagnantWindow = 10; // 观察窗口大小
int[] recentImprovements = new int[stagnantWindow]; // 记录最近窗口内的改进情况
double improvementRateThreshold = 0.001; // 改进率阈值
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 参数配置:温度=%.1f, 降温率=%.2f, 阈值=%.1f, 最大迭代=%d",
temperature, coolingRate, temperatureThreshold, maxIterations));
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);
......@@ -206,6 +271,11 @@ private Map<String, Entry> entrys;
// 跳过禁忌解(除非是最优解)
if (tabusearch.isTabu(neighbor.getGeneStr()) && !isBetter(current,best)) {
temperature *= coolingRate;
noImproveCount++;
// 记录本次无改进
if (totalIterations <= stagnantWindow) {
recentImprovements[totalIterations - 1] = 0;
}
continue;
}
......@@ -216,42 +286,124 @@ private Map<String, Entry> entrys;
boolean accepted = false;
if (energyDifference > 0 || rnd.nextDouble() < Math.exp(energyDifference / temperature)) {
current = neighbor;
accepted = true;
acceptCount++;
acceptCount++;
if (isBetter(current, best)) {
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()));
// 记录改进详情
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;
// 每50次迭代输出一次状态
if ((i + 1) % 50 == 0) {
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 迭代%d/%d:温度=%.4f, 接受数=%d, 改进数=%d, 无改进连续=%d",
i + 1, maxIterations, temperature, acceptCount, improveCount, noImproveCount));
// 每次迭代都输出状态
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;
}
}
FileHelper.writeLogFile(String.format("模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f",
maxIterations, best.getFitness()));
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) {
String fitness = "";
......@@ -261,7 +413,7 @@ private Map<String, Entry> entrys;
fitness += fitness1[i] + ",";
}
FileHelper.writeLogFile(String.format("爬山法 - kpi:%s", fitness));
log(String.format("模拟退火 - kpi:%s", fitness),true);
}
......@@ -333,6 +485,9 @@ private Map<String, Entry> entrys;
return index0;
}
/**
* 解码染色体
*/
/**
* 解码染色体
*/
......@@ -341,11 +496,29 @@ private Map<String, Entry> entrys;
// 假设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多层次比较)
......
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.entity.Algorithm.*;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.GlobalParam;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.*;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 禁忌搜索算法
*/
public class TabuSearch {
private List<Entry> allOperations;
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<String> tabuList;
private int tabuListSize = 50;
public TabuSearch(List<Entry> allOperations) {
private List<Machine> cachedMachines;
private List<Order> cachedOrders;
private List<GroupResult> cachedEntryRel;
private List<Material> cachedMaterials;
private List<Entry> cachedAllOperations;
// 渴望准则:记录最优解的 fitness
private double[] bestFitness;
public TabuSearch(List<Entry> allOperations, List<Order> orders,
List<Material> materials,List<GroupResult> entryRel, FitnessCalculator _fitnessCalculator) {
this.tabuList = new ArrayList<>();
// 工序越多,禁忌表越长(适配1000+工序)
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, VariableNeighborhoodSearch vns,
GeneticDecoder decoder, List<Machine> machines) {
log("禁忌搜索 - 开始执行",true);
Chromosome current = 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 improveCount = 0;
int noImprovementCount = 0;
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;
log(String.format("禁忌搜索 - 参数:最大迭代=%d, 最大无改进=%d", maxIterations, maxNoImprovement));
for (int i = 0; i < maxIterations; i++) {
iterations++;
// 使用 VNS 生成邻域解(成功率排序后的策略)
Chromosome neighbor = vns.generateNeighbor(current);
if (neighbor == null) {
log("禁忌搜索 - 生成邻居失败,跳过");
noImprovementCount++;
// 记录无改进
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:禁忌且没有比最优解好,不接受
boolean improvedThisIteration = false;
if (accept) {
// 接受这个邻居
current = ProductionDeepCopyUtil.deepCopy(neighbor, Chromosome.class);
// 更新最优解
if (isBetterThanBest) {
best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class);
this.bestFitness = best.getFitnessLevel().clone();
writeKpi(best);
noImprovementCount = 0;
improveCount++;
improvedThisIteration = true;
logTabuImprovement(best, initialFitnessLevel, initialFitness, iterations);
log(String.format("禁忌搜索 - 找到更好解,迭代=%d", iterations),true);
} else if (isBetterThanCurrent) {
// 比当前解好但没有比最优解好
noImprovementCount = 0;
improvedThisIteration = true;
} else {
// 没有改进
noImprovementCount++;
}
} else {
// 不接受,无改进计数+1
noImprovementCount++;
}
// 记录本次改进情况
if (iterations <= stagnantWindow) {
recentImprovements[iterations - 1] = improvedThisIteration ? 1 : 0;
}
// 每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 = "";
if (noImprovementCount >= maxNoImprovement) {
shouldStop = true;
stopReason = String.format("连续%d次无改进", maxNoImprovement);
} else if (iterations >= 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", stopReason));
logTabuFinalSummary(best, initialFitnessLevel, initialFitness, iterations, improveCount);
break;
}
}
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] + ",";
}
log(String.format("变邻域搜索 - kpi:%s", fitness),true);
}
/**
* 记录禁忌搜索改进详情
*/
private void logTabuImprovement(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 logTabuFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness,
int totalIterations, int improveCount) {
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());
}
/**
* 检查解是否在禁忌表中
*/
......@@ -42,23 +281,50 @@ public class TabuSearch {
}
/**
* 添加解到禁忌表
* 添加解到禁忌表(FIFO策略)
*/
public void addToTabuList(String GeneStr) {
tabuList.add(GeneStr);
public void addToTabuList(String geneStr) {
tabuList.add(geneStr);
if (tabuList.size() > tabuListSize) {
// 移除最早加入的禁忌解(FIFO策略)
Iterator<String> iterator = tabuList.iterator();
iterator.next();
iterator.remove();
// 移除最早加入的禁忌解
tabuList.remove(0);
}
}
private void decode(GeneticDecoder decoder, Chromosome chromosome , List<Machine> machines) {
chromosome.setResult(new CopyOnWriteArrayList<>());
// 缓存 Machine 列表(第一次调用时缓存)
if (cachedMachines == null) {
cachedMachines = ProductionDeepCopyUtil.deepCopyList(machines, Machine.class);
}
// 使用缓存的列表,避免重复深拷贝
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(cachedMachines, Machine.class));
chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedOrders), Order.class));
chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedEntryRel), GroupResult.class));
chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyList(cachedMaterials, Material.class));
chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedAllOperations), Entry.class));
// 加载锁定工单到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) {
return fitnessCalculator.isBetter(c1,c2);
}
......
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
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.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.*;
import java.util.*;
......@@ -16,23 +19,184 @@ import java.util.stream.Collectors;
public class VariableNeighborhoodSearch {
private final Random rnd = new Random();
private void log(String message) {
log(message, true);
}
private void log(String message, boolean enableLogging) {
if (enableLogging) {
FileHelper.writeLogFile(message);
}
}
private List<Entry> allOperations;
private FitnessCalculator fitnessCalculator;
private List<Order> orders;
private List<Material> materials;
private List<GroupResult> _entryRel;
private Map<String, Entry> entrys;
private Map<Integer, Entry> entrybyids;
public VariableNeighborhoodSearch( List<Entry> allOperations, FitnessCalculator fitnessCalculator) {
// 预检查:是否有工序有多个机器选项
private boolean hasMultipleMachineOptions = false;
// 策略成功率统计
private int[] strategySuccessCount = new int[4];
private int[] strategyTotalCount = new int[4];
// 强制策略轮换:跟踪最后使用的策略
private int lastUsedStrategy = -1;
private int consecutiveSameStrategyCount = 0;
private static final int MAX_CONSECUTIVE_SAME_STRATEGY = 3; // 最多连续使用同一个策略3次
// 缓存的深拷贝列表,用于解码优化
private List<Machine> cachedMachines;
private List<Order> cachedOrders;
private List<GroupResult> cachedEntryRel;
private List<Material> cachedMaterials;
private List<Entry> cachedAllOperations;
// 邻域结构成功率统计(用于 search() 方法)
private static class NeighborhoodWithStats {
NeighborhoodStructure structure;
int successCount;
int totalCount;
NeighborhoodWithStats(NeighborhoodStructure structure) {
this.structure = structure;
this.successCount = 0;
this.totalCount = 0;
}
double getSuccessRate() {
return totalCount > 0 ? (double) successCount / totalCount : 0.5;
}
}
private List<NeighborhoodWithStats> neighborhoodsWithStats;
private int maxNoImproveRounds = 1;
public void setMaxNoImproveRounds(int maxNoImproveRounds) {
this.maxNoImproveRounds = maxNoImproveRounds;
}
public VariableNeighborhoodSearch( List<Entry> allOperations, List<Order> orders,
List<Material> materials,List<GroupResult> entryRel, FitnessCalculator fitnessCalculator) {
this(allOperations, orders, materials, entryRel, fitnessCalculator, 3);
}
public VariableNeighborhoodSearch( List<Entry> allOperations, List<Order> orders,
List<Material> materials,List<GroupResult> entryRel,
FitnessCalculator fitnessCalculator, int maxNoImproveRounds) {
this.maxNoImproveRounds = maxNoImproveRounds;
this.allOperations = allOperations;
this.orders = orders;
this.materials = materials;
_entryRel=entryRel;
this.fitnessCalculator = fitnessCalculator;
Map<Integer, Object> mp = buildEntryKey();
entrys=(Map<String, Entry>)mp.get(1);
entrybyids=(Map<Integer, Entry>)mp.get(2);
// 预检查:是否有工序有多个机器选项
for (Entry entry : allOperations) {
if (entry.getMachineOptions() != null && entry.getMachineOptions().size() > 1) {
hasMultipleMachineOptions = true;
break;
}
}
// 预缓存解码需要的深拷贝列表,避免重复拷贝
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);
// 初始化邻域结构统计
neighborhoodsWithStats = new ArrayList<>();
List<NeighborhoodStructure> initialNeighborhoods = defineNeighborhoodsInternal();
for (NeighborhoodStructure ns : initialNeighborhoods) {
neighborhoodsWithStats.add(new NeighborhoodWithStats(ns));
}
//log("VariableNeighborhoodSearch初始化: hasMultipleMachineOptions=" + hasMultipleMachineOptions);
}
/**
* 内部方法:定义邻域结构(不排序)
*/
private List<NeighborhoodStructure> defineNeighborhoodsInternal() {
List<NeighborhoodStructure> neighborhoods = new ArrayList<>();
//瓶颈工序机器选择变异
neighborhoods.add(new NeighborhoodStructure("SmartBottleneckChange", this::ChangeMachineForBottleneckOpWrapper));
//瓶颈工序在相同设备上移动
neighborhoods.add(new NeighborhoodStructure("moveBottleneckSameMachine", this::moveBottleneckSameMachineWrapper));
//瓶颈工序往前移动
neighborhoods.add(new NeighborhoodStructure("MoveBottleneckForward", this::moveBottleneckForwardWrapper));
//非瓶颈工序往后移动
neighborhoods.add(new NeighborhoodStructure("MoveNonBottleneckBackward", this::moveNonBottleneckBackwardWrapper));
//// 交换相同设备的两个工序
neighborhoods.add(new NeighborhoodStructure("SwapSameMachine", this::generateSameMachineSwapNeighbor));
// 交换两个工序的顺序
neighborhoods.add(new NeighborhoodStructure("Swap", this::generateSwapNeighborWrapper));
// 反转一个工序子序列
neighborhoods.add(new NeighborhoodStructure("Reverse", this::generateReverseNeighborWrapper));
// 插入一个工序到另一个位置
neighborhoods.add(new NeighborhoodStructure("Insert", this::generateInsertNeighborWrapper));
// 机器选择变异
neighborhoods.add(new NeighborhoodStructure("MachineChange", this::generateMachineChangeNeighbor));
return neighborhoods;
}
/**
* 定义邻域结构(按成功率排序)
*/
private List<NeighborhoodStructure> defineNeighborhoods() {
// 按成功率排序
List<NeighborhoodWithStats> sorted = new ArrayList<>(neighborhoodsWithStats);
sorted.sort((a, b) -> Double.compare(b.getSuccessRate(), a.getSuccessRate()));
// 提取 NeighborhoodStructure
List<NeighborhoodStructure> result = new ArrayList<>();
// for (NeighborhoodWithStats ns : sorted) {
// result.add(ns.structure);
// }
int maxNeighborhoods = Math.min(7, sorted.size());
for (int i = 0; i < maxNeighborhoods; i++) {
result.add(sorted.get(i).structure);
}
return result;
}
/**
* 记录邻域结构使用结果
*/
private void recordNeighborhoodResult(NeighborhoodStructure structure, boolean success) {
for (NeighborhoodWithStats ns : neighborhoodsWithStats) {
if (ns.structure.equals(structure)) {
ns.totalCount++;
if (success) {
ns.successCount++;
}
break;
}
}
}
/**
......@@ -53,58 +217,173 @@ public class VariableNeighborhoodSearch {
* 对单个个体进行变邻域搜索
*/
public Chromosome search(Chromosome chromosome, GeneticDecoder decoder, List<Machine> machines) {
log("变邻域搜索 - 开始执行",true);
// 深拷贝当前染色体
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
writeKpi(best);
// 定义邻域结构
List<NeighborhoodStructure> neighborhoods = defineNeighborhoods();
// 记录初始KPI用于跟踪改进
double[] initialFitnessLevel = best.getFitnessLevel().clone();
double initialFitness = best.getFitness();
// 提前结束参数
int noImproveRoundCount = 0; // 无改进轮数计数
int totalRounds = 0; // 总轮数
int totalImprovements = 0; // 总改进次数
int k = 0;
while (k < neighborhoods.size()) {
// 随机选择一个邻域结构
// 按成功率排序获取邻域结构(先获取一次)
List<NeighborhoodStructure> neighborhoods = defineNeighborhoods();
while (noImproveRoundCount < maxNoImproveRounds) {
totalRounds++;
log("变邻域搜索 - 轮次" + totalRounds + ", K===" + k);
NeighborhoodStructure neighborhood = neighborhoods.get(k);
// 找到对应的统计对象
NeighborhoodWithStats neighborhoodWithStats = null;
for (NeighborhoodWithStats ns : neighborhoodsWithStats) {
if (ns.structure.equals(neighborhood)) {
neighborhoodWithStats = ns;
break;
}
}
// 生成邻域解
Chromosome neighbor = generateNeighbor(current);
Chromosome neighbor = generateNeighbor(current, neighborhood);
if(neighbor == null) {
log("变邻域搜索 - null");
if (neighborhoodWithStats != null) {
recordNeighborhoodResult(neighborhood, false);
}
k++;
// 检查是否完成一轮
if (k >= neighborhoods.size()) {
noImproveRoundCount++;
log(String.format("变邻域搜索 - 本轮无改进,连续无改进轮数: %d/%d",
noImproveRoundCount, maxNoImproveRounds));
k = 0; // 重置k,开始新一轮
}
continue;
}
// 局部搜索
Chromosome localBest = localSearch(neighbor, decoder,null);
Chromosome localBest = localSearch(neighbor, decoder, machines);
// 邻域移动
if (isBetter(localBest, best)) {
best = localBest;
boolean success = isBetter(localBest, best);
if (success) {
best = ProductionDeepCopyUtil.deepCopy(localBest, Chromosome.class);
writeKpi(best);
current = localBest;
k = 0; // 重置邻域索引
noImproveRoundCount = 0; // 重置无改进计数
totalImprovements++;
logVNSImprovement(best, initialFitnessLevel, initialFitness, totalRounds, neighborhood.name);
log(String.format("变邻域搜索 - 邻域成功: %s", neighborhood.name),true);
} else {
k++; // 尝试下一个邻域
// 检查是否完成一轮
if (k >= neighborhoods.size()) {
noImproveRoundCount++;
log(String.format("变邻域搜索 - 本轮无改进,连续无改进轮数: %d/%d",
noImproveRoundCount, maxNoImproveRounds));
k = 0; // 重置k,开始新一轮
}
}
// 记录结果
if (neighborhoodWithStats != null) {
recordNeighborhoodResult(neighborhood, success);
}
// 检查提前结束条件
if (noImproveRoundCount >= maxNoImproveRounds) {
log(String.format("变邻域搜索 - 提前结束:连续%d轮无改进", maxNoImproveRounds));
logVNSFinalSummary(best, initialFitnessLevel, initialFitness, totalRounds, totalImprovements);
break;
}
}
if (noImproveRoundCount < maxNoImproveRounds) {
logVNSFinalSummary(best, initialFitnessLevel, initialFitness, totalRounds, totalImprovements);
}
return best;
}
/**
* 定义邻域结构
* 记录变邻域搜索改进详情
*/
private List<NeighborhoodStructure> defineNeighborhoods() {
List<NeighborhoodStructure> neighborhoods = new ArrayList<>();
private void logVNSImprovement(Chromosome best, double[] initialFitnessLevel, double initialFitness,
int round, String neighborhoodName) {
StringBuilder sb = new StringBuilder("变邻域搜索 - 改进详情: 轮次" + round + ", 邻域=" + neighborhoodName + ", ");
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));
}
// 邻域1:交换两个工序的顺序
neighborhoods.add(new NeighborhoodStructure("Swap", this::swapNeighborhood));
double totalImprovement = best.getFitness() - initialFitness;
sb.append(String.format("总Fitness: %.4f→%.4f(+%.4f)", initialFitness, best.getFitness(), totalImprovement));
log(sb.toString(),true);
}
// 邻域2:反转一个工序子序列
neighborhoods.add(new NeighborhoodStructure("Reverse", this::reverseNeighborhood));
/**
* 记录变邻域搜索最终总结
*/
private void logVNSFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness,
int totalRounds, int totalImprovements) {
StringBuilder sb = new StringBuilder("变邻域搜索 - 最终总结: ");
double[] currentFitness = best.getFitnessLevel();
// 邻域3:插入一个工序到另一个位置
neighborhoods.add(new NeighborhoodStructure("Insert", this::insertNeighborhood));
sb.append(String.format("总轮次%d次, 成功改进%d次, 改进率%.2f%%. ",
totalRounds, totalImprovements, totalRounds > 0 ? (double)totalImprovements / totalRounds * 100 : 0));
// 邻域4:机器选择变异
neighborhoods.add(new NeighborhoodStructure("MachineChange", this::machineChangeNeighborhood));
// 记录各邻域结构的成功率
sb.append("邻域成功率: ");
for (NeighborhoodWithStats ns : neighborhoodsWithStats) {
double rate = ns.getSuccessRate();
sb.append(String.format("[%s: %d/%d(%.1f%%)] ",
ns.structure.name, ns.successCount, ns.totalCount, rate * 100));
}
sb.append("\n");
return neighborhoods;
// 记录KPI改进
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) {
String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel();
for (int i = 0; i < fitness1.length; i++) {
fitness += fitness1[i] + ",";
}
log(String.format("变邻域搜索 - kpi:%s", fitness),true);
}
/**
* 定义邻域结构
*/
private Chromosome generateNeighbor(Chromosome chromosome, NeighborhoodStructure neighborhood) {
return neighborhood.apply(chromosome);
}
/**
* 生成邻域解 - 智能策略:优先处理瓶颈工序/设备
* 策略:
......@@ -115,45 +394,574 @@ public class VariableNeighborhoodSearch {
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<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex =(Map<Integer, Entry>)obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>)obj.get(2);
Map<String, Integer> MachinePositionIndex = buildEntryMachinePositionIndex(chromosome);
// 1. 找出瓶颈设备
Long bottleneckMachineId = findBottleneckMachine(chromosome);
if (results == null || results.isEmpty()) {
log("generateNeighbor: results为空,使用随机邻域");
return generateRandomNeighbor(chromosome,positionToEntryIndex,positionByPriority);
}
// 1. 找出瓶颈设备和关键工序
Map<String, Object> bottleneckAnalysis = findBottleneckMachineWithDetails(chromosome);
Long bottleneckMachineId = (Long) bottleneckAnalysis.get("bottleneckMachineId");
List<GAScheduleResult> criticalOps = (List<GAScheduleResult>) bottleneckAnalysis.get("criticalOps");
logBottleneckAnalysis(bottleneckAnalysis);
if (bottleneckMachineId != null && criticalOps != null && !criticalOps.isEmpty()) {
if (rnd.nextDouble() < 0.8) { // 增加使用智能策略的概率
// 构建策略顺序,考虑成功率
List<Integer> strategyOrder = buildStrategyOrder();
log(String.format("瓶颈设备-策略顺序=%s, 关键工序数=%d", strategyOrder, criticalOps.size()));
Chromosome result = null;
for (int attempt = 0; attempt < strategyOrder.size(); attempt++) {
int strategyIndex = strategyOrder.get(attempt);
// 如果没有多个机器选项,跳过策略1
if (strategyIndex == 0 && !hasMultipleMachineOptions) {
log(String.format("跳过%d/4: 策略1-无多机器选项", attempt + 1));
continue;
}
strategyTotalCount[strategyIndex]++;
if(strategyIndex == 0) {
log(String.format("尝试%d/4: 策略1-关键工序换设备", attempt + 1));
result = tryChangeMachineForBottleneckOp(chromosome, criticalOps, MachinePositionIndex, positionToEntryIndex, positionByPriority);
} else if(strategyIndex == 1) {
log(String.format("尝试%d/4: 策略2-关键工序往前移动", attempt + 1));
result = tryMoveBottleneckOpForward(chromosome, criticalOps, positionIndex, positionByPriority,positionToEntryIndex,MachinePositionIndex,false);
} else if(strategyIndex == 2) {
log(String.format("尝试%d/4: 策略3-相同设备工序交换", attempt + 1));
result = tryMoveBottleneckOpForward(chromosome, criticalOps, positionIndex, positionByPriority,positionToEntryIndex,MachinePositionIndex,true);
} else {
log(String.format("尝试%d/4: 策略4-非瓶颈工序往后移动", attempt + 1));
result = tryMoveNonBottleneckOpBackward(chromosome, bottleneckMachineId, positionIndex, positionByPriority, positionToEntryIndex);
}
if (result != null) {
strategySuccessCount[strategyIndex]++;
// 更新策略使用跟踪信息
if (strategyIndex == lastUsedStrategy) {
consecutiveSameStrategyCount++;
} else {
lastUsedStrategy = strategyIndex;
consecutiveSameStrategyCount = 1;
}
logStrategyStats();
log(String.format("策略成功,使用策略%d (连续%d次)", strategyIndex + 1, consecutiveSameStrategyCount));
return result;
}
log("当前策略失败,尝试下一个...");
}
log("所有瓶颈策略都失败,使用随机邻域");
}
} else {
log("没有找到瓶颈设备或关键工序");
}
log("使用随机邻域");
return generateRandomNeighbor(chromosome,positionToEntryIndex,positionByPriority);
}
/**
* 识别瓶颈设备及关键工序(更精准的分析)
* 优先选择订单数多的优先级组的工序
*/
private Map<String, Object> findBottleneckMachineWithDetails(Chromosome chromosome) {
Map<String, Object> result = new HashMap<>();
List<GAScheduleResult> allResults = chromosome.getResult();
Map<Long, Double> utilization = calculateMachineUtilization(chromosome);
Map<Long, List<GAScheduleResult>> machineOps = allResults != null ?
allResults.stream().collect(Collectors.groupingBy(GAScheduleResult::getMachineId)) :
new HashMap<>();
if (utilization.isEmpty()) {
result.put("bottleneckMachineId", null);
result.put("criticalOps", new ArrayList<GAScheduleResult>());
result.put("allResults", allResults);
return result;
}
// 找出利用率最高的设备
Long bottleneckMachineId = utilization.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse(null);
result.put("bottleneckMachineId", bottleneckMachineId);
result.put("utilization", utilization);
result.put("allResults", allResults);
// 找出关键工序:瓶颈设备上的工序 + 延迟订单的工序
List<GAScheduleResult> criticalOps = new ArrayList<>();
if (bottleneckMachineId != null) {
// 找出瓶颈设备上的工序
List<GAScheduleResult> bottleneckOps = findOpsOnBottleneckMachine(chromosome, bottleneckMachineId);
criticalOps.addAll(machineOps.getOrDefault(bottleneckMachineId, new ArrayList<>()));
}
if (!bottleneckOps.isEmpty()) {
// 70%概率优先处理瓶颈设备
if (rnd.nextDouble() < 0.7) {
int strategy = rnd.nextInt(10);
// 找出延迟的订单工序
List<GAScheduleResult> delayedOps = findDelayedOperations(chromosome);
criticalOps.addAll(delayedOps);
if(strategy<=3)
{
// 策略1:瓶颈设备上的工序换设备
return tryChangeMachineForBottleneckOp(chromosome, bottleneckOps, entrys, MachinePositionIndex);
// 去重
Set<Integer> seenOpIds = new HashSet<>();
List<GAScheduleResult> uniqueCriticalOps = new ArrayList<>();
for (GAScheduleResult op : criticalOps) {
if (!seenOpIds.contains(op.getOperationId())) {
seenOpIds.add(op.getOperationId());
uniqueCriticalOps.add(op);
}
}
// 优先选择订单数多的优先级组的工序
if (!uniqueCriticalOps.isEmpty()) {
// 构建优先级->订单数的映射
Map<Double, Set<Integer>> priorityToGroupIds = new HashMap<>();
for (GAScheduleResult op : uniqueCriticalOps) {
Entry entry = entrybyids.get(op.getOperationId());
if (entry != null) {
double priority = entry.getPriority();
priorityToGroupIds.computeIfAbsent(priority, k -> new HashSet<>()).add(op.getGroupId());
}
}
// 按订单数从多到少排序关键工序
uniqueCriticalOps.sort((op1, op2) -> {
Entry entry1 = entrybyids.get(op1.getOperationId());
Entry entry2 = entrybyids.get(op2.getOperationId());
if (entry1 == null || entry2 == null) {
return 0;
}
else if(strategy<=8) {
// 策略2:瓶颈设备上的工序往前移动
return tryMoveBottleneckOpForward(chromosome, bottleneckOps, positionIndex, positionToEntryIndex, entrys);
}else if(strategy<=10) {
// 策略3:非瓶颈设备上的工序往后移动
return tryMoveNonBottleneckOpBackward(chromosome, bottleneckMachineId, positionIndex, positionToEntryIndex, entrys);
int size1 = priorityToGroupIds.getOrDefault(entry1.getPriority(), new HashSet<>()).size();
int size2 = priorityToGroupIds.getOrDefault(entry2.getPriority(), new HashSet<>()).size();
// 订单数多的优先级排前面
int sizeCompare = Integer.compare(size2, size1);
if (sizeCompare != 0) {
return sizeCompare;
}
// 订单数相同时,按优先级排序
return Double.compare(entry2.getPriority(), entry1.getPriority());
});
}
result.put("criticalOps", uniqueCriticalOps);
result.put("delayedOps", delayedOps);
return result;
}
/**
* 找出延迟的工序
*/
private List<GAScheduleResult> findDelayedOperations(Chromosome chromosome) {
List<GAScheduleResult> delayedOps = new ArrayList<>();
List<GAScheduleResult> results = chromosome.getResult();
if (results == null || results.isEmpty()) {
return delayedOps;
}
// 按订单分组,计算订单完成时间
Map<Integer, Integer> orderCompletionTimes = new HashMap<>();
for (GAScheduleResult result : results) {
int groupId = result.getGroupId();
int endTime = result.getEndTime();
orderCompletionTimes.put(groupId, Math.max(orderCompletionTimes.getOrDefault(groupId, 0), endTime));
}
// 找出完成时间较晚的订单(超过平均完成时间的1.5倍)
if (!orderCompletionTimes.isEmpty()) {
double avgCompletionTime = orderCompletionTimes.values().stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0);
double threshold = avgCompletionTime * 1.5;
Set<Integer> delayedOrderIds = orderCompletionTimes.entrySet().stream()
.filter(e -> e.getValue() > threshold)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
// 收集这些延迟订单的工序
for (GAScheduleResult result : results) {
if (delayedOrderIds.contains(result.getGroupId())) {
delayedOps.add(result);
}
}
}
return delayedOps;
}
/**
* 瓶颈工序分析结果类
*/
private static class BottleneckOperationAnalysis {
GAScheduleResult operation;
double bottleneckScore; // 瓶颈评分(越高越可能是瓶颈)
int waitTime; // 工序等待时间(前一道工序结束到本工序开始)
int machineWaitTime; // 设备等待时间(设备上一道工序结束到本工序开始)
boolean onCriticalPath; // 是否在关键路径上
double delayContribution; // 延迟贡献度
BottleneckOperationAnalysis(GAScheduleResult op) {
this.operation = op;
this.bottleneckScore = 0;
this.waitTime = 0;
this.machineWaitTime = 0;
this.onCriticalPath = false;
this.delayContribution = 0;
}
}
/**
* 记录瓶颈分析详情(增强版)
*/
private void logBottleneckAnalysis(Map<String, Object> analysis) {
StringBuilder sb = new StringBuilder("变邻域搜索 - 瓶颈分析: ");
Long bottleneckMachineId = (Long) analysis.get("bottleneckMachineId");
List<GAScheduleResult> criticalOps = (List<GAScheduleResult>) analysis.get("criticalOps");
List<GAScheduleResult> delayedOps = (List<GAScheduleResult>) analysis.get("delayedOps");
Map<Long, Double> utilization = (Map<Long, Double>) analysis.get("utilization");
List<GAScheduleResult> allResults = (List<GAScheduleResult>) analysis.get("allResults");
sb.append(String.format("瓶颈设备ID=%d, ", bottleneckMachineId));
sb.append(String.format("关键工序数=%d, ", criticalOps != null ? criticalOps.size() : 0));
sb.append(String.format("延迟工序数=%d, ", delayedOps != null ? delayedOps.size() : 0));
if (utilization != null && !utilization.isEmpty()) {
sb.append("设备利用率: ");
utilization.entrySet().stream()
.sorted(Map.Entry.<Long, Double>comparingByValue().reversed())
.limit(5)
.forEach(e -> sb.append(String.format("[%d:%.1f%%] ", e.getKey(), e.getValue() * 100)));
}
log(sb.toString());
// 新增:精准瓶颈工序分析
if (allResults != null && !allResults.isEmpty()) {
List<BottleneckOperationAnalysis> bottleneckAnalyses = analyzeBottleneckOperations(allResults, bottleneckMachineId);
// 输出瓶颈工序TOP 5
log("变邻域搜索 - ===== 瓶颈工序TOP 5 (按瓶颈评分) =====");
for (int i = 0; i < Math.min(5, bottleneckAnalyses.size()); i++) {
BottleneckOperationAnalysis boa = bottleneckAnalyses.get(i);
GAScheduleResult op = boa.operation;
log(String.format(
" TOP%d: [工单%d-工序%d(设备%d)] | 评分=%.2f | 等待=%ds | 设备等待=%ds | 关键路径=%s | 延迟贡献=%.2f",
i + 1, op.getGroupId(), op.getOperationId(), op.getMachineId(),
boa.bottleneckScore, boa.waitTime, boa.machineWaitTime,
boa.onCriticalPath ? "是" : "否", boa.delayContribution
));
}
// 更新关键工序为识别出的瓶颈工序
if (criticalOps != null && !criticalOps.isEmpty() && !bottleneckAnalyses.isEmpty()) {
List<GAScheduleResult> topBottlenecks = bottleneckAnalyses.stream()
.limit(Math.min(10, bottleneckAnalyses.size()))
.map(boa -> boa.operation)
.collect(Collectors.toList());
analysis.put("criticalOps", topBottlenecks);
}
}
// 默认策略:随机邻域
return generateRandomNeighbor(chromosome, entrys);
// 记录原始关键工序详情(前5个)作为参考
if (criticalOps != null && !criticalOps.isEmpty()) {
StringBuilder criticalOpsSb = new StringBuilder("变邻域搜索 - 原始关键工序(前5个): ");
criticalOps.stream()
.limit(5)
.forEach(op -> criticalOpsSb.append(String.format("[工单%d-工序%d(设备%d)] ",
op.getGroupId(), op.getOperationId(), op.getMachineId())));
log(criticalOpsSb.toString());
}
}
/**
* 精准分析瓶颈工序
*/
private List<BottleneckOperationAnalysis> analyzeBottleneckOperations(List<GAScheduleResult> allResults, Long bottleneckMachineId) {
if (allResults == null || allResults.isEmpty()) {
return new ArrayList<>();
}
// 1. 按工单和工序顺序组织数据
Map<Integer, List<GAScheduleResult>> opsByGroup = allResults.stream()
.collect(Collectors.groupingBy(GAScheduleResult::getGroupId));
Map<Long, List<GAScheduleResult>> opsByMachine = allResults.stream()
.collect(Collectors.groupingBy(GAScheduleResult::getMachineId));
// 2. 计算每个订单的完成时间
Map<Integer, Integer> orderCompletionTime = new HashMap<>();
for (List<GAScheduleResult> ops : opsByGroup.values()) {
int maxEndTime = ops.stream()
.mapToInt(GAScheduleResult::getEndTime)
.max()
.orElse(0);
for (GAScheduleResult op : ops) {
orderCompletionTime.put(op.getGroupId(), maxEndTime);
}
}
// 3. 创建分析对象
List<BottleneckOperationAnalysis> analyses = new ArrayList<>();
Map<Integer, BottleneckOperationAnalysis> opIdToAnalysis = new HashMap<>();
for (GAScheduleResult op : allResults) {
BottleneckOperationAnalysis boa = new BottleneckOperationAnalysis(op);
analyses.add(boa);
opIdToAnalysis.put(op.getOperationId(), boa);
}
// 4. 计算工序等待时间(同一工单内,前一工序结束到本工序开始)
for (List<GAScheduleResult> ops : opsByGroup.values()) {
ops.sort(Comparator.comparingInt(GAScheduleResult::getStartTime));
for (int i = 1; i < ops.size(); i++) {
GAScheduleResult prevOp = ops.get(i - 1);
GAScheduleResult currOp = ops.get(i);
BottleneckOperationAnalysis boa = opIdToAnalysis.get(currOp.getOperationId());
if (boa != null) {
boa.waitTime = Math.max(0, currOp.getStartTime() - prevOp.getEndTime());
}
}
}
// 5. 计算设备等待时间(同一设备上,前一工序结束到本工序开始)
for (List<GAScheduleResult> ops : opsByMachine.values()) {
ops.sort(Comparator.comparingInt(GAScheduleResult::getStartTime));
for (int i = 1; i < ops.size(); i++) {
GAScheduleResult prevOp = ops.get(i - 1);
GAScheduleResult currOp = ops.get(i);
BottleneckOperationAnalysis boa = opIdToAnalysis.get(currOp.getOperationId());
if (boa != null) {
boa.machineWaitTime = Math.max(0, currOp.getStartTime() - prevOp.getEndTime());
}
}
}
// 6. 识别关键路径(从后往前推,没有松弛时间的工序)
int maxMakespan = allResults.stream()
.mapToInt(GAScheduleResult::getEndTime)
.max()
.orElse(0);
// 按结束时间倒序排列
List<GAScheduleResult> sortedByEndTime = new ArrayList<>(allResults);
sortedByEndTime.sort((a, b) -> Integer.compare(b.getEndTime(), a.getEndTime()));
// 找出在最大完工时间的工序作为关键路径起点
for (GAScheduleResult op : sortedByEndTime) {
if (op.getEndTime() == maxMakespan) {
BottleneckOperationAnalysis boa = opIdToAnalysis.get(op.getOperationId());
if (boa != null) {
boa.onCriticalPath = true;
}
}
}
// 7. 计算延迟贡献度(工序结束时间与订单完成时间的接近程度)
double avgCompletionTime = orderCompletionTime.values().stream()
.mapToInt(Integer::intValue)
.average()
.orElse(1);
for (BottleneckOperationAnalysis boa : analyses) {
GAScheduleResult op = boa.operation;
Integer orderEndTime = orderCompletionTime.get(op.getGroupId());
if (orderEndTime != null && orderEndTime > 0) {
// 工序越接近订单完成时间,延迟贡献度越高
boa.delayContribution = (double) op.getEndTime() / orderEndTime;
}
}
// 8. 计算综合瓶颈评分 - 修复版(防数据偏倚)
// 使用中位数和截断来避免极端值影响(如设备2341有2000多工序的情况)
List<Integer> waitTimes = analyses.stream().mapToInt(a -> a.waitTime).boxed().collect(Collectors.toList());
List<Integer> machineWaitTimes = analyses.stream().mapToInt(a -> a.machineWaitTime).boxed().collect(Collectors.toList());
Collections.sort(waitTimes);
Collections.sort(machineWaitTimes);
// 使用90分位数代替最大值,避免极端值影响
double p90WaitTime = Math.max(1, getPercentile(waitTimes, 0.90)); // 防止0导致NaN
double p90MachineWaitTime = Math.max(1, getPercentile(machineWaitTimes, 0.90)); // 防止0导致NaN
// 优先找出瓶颈设备上的工序
List<BottleneckOperationAnalysis> bottleneckMachineOps = new ArrayList<>();
if (bottleneckMachineId != null) {
for (BottleneckOperationAnalysis boa : analyses) {
if (boa.operation.getMachineId() == bottleneckMachineId) {
bottleneckMachineOps.add(boa);
}
}
}
// 统计各设备的工序数量,用于后续分析
Map<Long, Long> machineOpCount = analyses.stream()
.collect(Collectors.groupingBy(a -> a.operation.getMachineId(), Collectors.counting()));
for (BottleneckOperationAnalysis boa : analyses) {
double score = 0;
boolean isOnBottleneckMachine = (bottleneckMachineId != null && boa.operation.getMachineId() == bottleneckMachineId);
if (isOnBottleneckMachine) {
// 瓶颈设备上的工序:基础分极高,确保排在最前面
score += 10000; // 提高到10000,绝对保证排在前面
// 在瓶颈设备工序内部进行排序(使用截断值)
// 工序等待时间 (权重 30%)
double normalizedWaitTime = Math.min(boa.waitTime / p90WaitTime, 1.5);
score += normalizedWaitTime * 30;
// 设备等待时间 (权重 30%)
double normalizedMachineWaitTime = Math.min(boa.machineWaitTime / p90MachineWaitTime, 1.5);
score += normalizedMachineWaitTime * 30;
// 关键路径评分 (权重 25%)
if (boa.onCriticalPath) {
score += 25;
}
// 延迟贡献度评分 (权重 15%)
score += boa.delayContribution * 15;
} else {
// 非瓶颈设备上的工序:基础分低
score += 0;
// 使用截断值,避免极端值影响
double normalizedMachineWaitTime = Math.min(boa.machineWaitTime / p90MachineWaitTime, 1.5);
score += normalizedMachineWaitTime * 30;
double normalizedWaitTime = Math.min(boa.waitTime / p90WaitTime, 1.5);
score += normalizedWaitTime * 20;
// 关键路径评分 (权重 20%)
if (boa.onCriticalPath) {
score += 20;
}
// 延迟贡献度评分 (权重 10%)
score += boa.delayContribution * 10;
}
boa.bottleneckScore = score;
}
// 记录修复后的瓶颈工序信息
log(String.format("变邻域搜索 - 瓶颈设备ID=%d, 其上工序数=%d",
bottleneckMachineId, bottleneckMachineOps.size()));
// 输出各设备工序数量统计(前5个)
List<Map.Entry<Long, Long>> topMachinesByCount = machineOpCount.entrySet().stream()
.sorted((a, b) -> Long.compare(b.getValue(), a.getValue()))
.limit(5)
.collect(Collectors.toList());
StringBuilder machineCountStr = new StringBuilder("变邻域搜索 - 设备工序数(前5): ");
for (Map.Entry<Long, Long> entry : topMachinesByCount) {
machineCountStr.append(String.format("[%d:%d] ", entry.getKey(), entry.getValue()));
}
log(machineCountStr.toString());
// 9. 按瓶颈评分排序
analyses.sort((a, b) -> Double.compare(b.bottleneckScore, a.bottleneckScore));
return analyses;
}
/**
* 计算百分位数(用于防数据偏倚)
*/
private double getPercentile(List<Integer> sortedValues, double percentile) {
if (sortedValues.isEmpty()) {
return 1;
}
int index = (int) Math.ceil(percentile * sortedValues.size()) - 1;
index = Math.max(0, Math.min(index, sortedValues.size() - 1));
return sortedValues.get(index);
}
/**
* 构建策略顺序,基于成功率动态调整(优化版 + 强制轮换)
*/
private List<Integer> buildStrategyOrder() {
List<Integer> strategies = new ArrayList<>(Arrays.asList(0, 1, 2, 3));
// 强制策略轮换:如果某个策略被连续使用超过 MAX_CONSECUTIVE_SAME_STRATEGY 次,强制换一个
boolean needForceRotate = (lastUsedStrategy >= 0 && consecutiveSameStrategyCount >= MAX_CONSECUTIVE_SAME_STRATEGY);
if (needForceRotate) {
log(String.format("强制策略轮换:策略%d已连续使用%d次",
lastUsedStrategy, consecutiveSameStrategyCount));
}
// 按成功率排序,但加入随机扰动和探索机制
strategies.sort((a, b) -> {
double successRateA = strategyTotalCount[a] > 0 ?
(double) strategySuccessCount[a] / strategyTotalCount[a] : 0.3;
double successRateB = strategyTotalCount[b] > 0 ?
(double) strategySuccessCount[b] / strategyTotalCount[b] : 0.3;
// 强制轮换:给最后使用的策略降权
if (needForceRotate && a == lastUsedStrategy) {
successRateA -= 0.5; // 大幅降权
}
if (needForceRotate && b == lastUsedStrategy) {
successRateB -= 0.5;
}
// 给使用次数少的策略加分,鼓励探索
if (strategyTotalCount[a] < 5) {
successRateA += 0.3;
}
if (strategyTotalCount[b] < 5) {
successRateB += 0.3;
}
// 如果策略被尝试次数很多但成功率很低,给它额外加分鼓励探索
if (strategyTotalCount[a] > 10 && successRateA < 0.1) {
successRateA += 0.2;
}
if (strategyTotalCount[b] > 10 && successRateB < 0.1) {
successRateB += 0.2;
}
// 加入少量随机扰动,避免陷入局部最优
successRateA += rnd.nextDouble() * 0.15;
successRateB += rnd.nextDouble() * 0.15;
return Double.compare(successRateB, successRateA);
});
return strategies;
}
/**
* 记录策略统计信息
*/
private void logStrategyStats() {
StringBuilder sb = new StringBuilder("策略统计: ");
for (int i = 0; i < 4; i++) {
double rate = strategyTotalCount[i] > 0 ?
(double) strategySuccessCount[i] / strategyTotalCount[i] : 0.0;
sb.append(String.format("[%d]%d/%d(%.1f%%) ", i + 1,
strategySuccessCount[i], strategyTotalCount[i], rate * 100));
}
log(sb.toString());
}
/**
* 识别瓶颈设备(利用率最高的设备)
......@@ -218,8 +1026,7 @@ public class VariableNeighborhoodSearch {
/**
* 尝试给瓶颈设备上的工序换设备
*/
private Chromosome tryChangeMachineForBottleneckOp(Chromosome chromosome, List<GAScheduleResult> bottleneckOps, Map<String, Entry> entrys,Map<String, Integer> MachinePositionIndex) {
// 优先选择有多设备选项的工序
private Chromosome tryChangeMachineForBottleneckOp(Chromosome chromosome, List<GAScheduleResult> bottleneckOps,Map<String, Integer> MachinePositionIndex,Map<Integer, Entry> positionIndex,List<List<Integer>> positionByPriority) {
List<GAScheduleResult> candidates = bottleneckOps.stream()
.filter(op -> {
Entry entry = entrybyids.get(op.getOperationId());
......@@ -227,31 +1034,107 @@ public class VariableNeighborhoodSearch {
})
.collect(Collectors.toList());
log(String.format("tryChangeMachineForBottleneckOp: 候选工序数=%d (瓶颈工序总数=%d)", candidates.size(), bottleneckOps.size()));
if (candidates.isEmpty()) {
return generateRandomNeighbor(chromosome, entrys);
log("tryChangeMachineForBottleneckOp: 没有可换设备的候选工序");
return null;
}
// 优先选择订单数多的优先级的工序
// 构建优先级->订单数的映射
Map<Double, Set<Integer>> priorityToGroupIds = new HashMap<>();
for (GAScheduleResult op : candidates) {
Entry entry = entrybyids.get(op.getOperationId());
if (entry != null) {
double priority = entry.getPriority();
priorityToGroupIds.computeIfAbsent(priority, k -> new HashSet<>()).add(op.getGroupId());
}
}
// 从候选中随机选择一个工序,给它换设备
GAScheduleResult selectedOp = candidates.get(rnd.nextInt(candidates.size()));
// 按订单数从多到少排序候选工序
List<GAScheduleResult> sortedCandidates = new ArrayList<>(candidates);
sortedCandidates.sort((a, b) -> {
Entry entryA = entrybyids.get(a.getOperationId());
Entry entryB = entrybyids.get(b.getOperationId());
if (entryA == null || entryB == null) {
return 0;
}
int sizeA = priorityToGroupIds.getOrDefault(entryA.getPriority(), new HashSet<>()).size();
int sizeB = priorityToGroupIds.getOrDefault(entryB.getPriority(), new HashSet<>()).size();
// 订单数多的优先级排前面
int sizeCompare = Integer.compare(sizeB, sizeA);
if (sizeCompare != 0) {
return sizeCompare;
}
// 订单数相同时,按优先级排序
return Double.compare(entryB.getPriority(), entryA.getPriority());
});
// 70%概率选择前3个候选,30%概率随机选择
GAScheduleResult selectedOp;
if (sortedCandidates.size() <= 3) {
selectedOp = sortedCandidates.get(rnd.nextInt(sortedCandidates.size()));
} else {
if (rnd.nextDouble() < 0.7) {
selectedOp = sortedCandidates.get(rnd.nextInt(Math.min(3, sortedCandidates.size())));
} else {
selectedOp = sortedCandidates.get(3 + rnd.nextInt(sortedCandidates.size() - 3));
}
}
// 找到这个工序在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) {
log("tryChangeMachineForBottleneckOp: 成功找到工序,执行换设备");
return generateMachineChangeForSpecificOp(chromosome, entry.getMachineOptions(), maPos);
}
}
// 直接换设备
return generateMachineChangeNeighbor(chromosome);
log("tryChangeMachineForBottleneckOp: 找不到工序位置,尝试通用换设备");
Chromosome result = generateMachineChangeNeighbor(chromosome);
return result != null ? result : null;
}
private Chromosome ChangeMachineForBottleneckOpWrapper(Chromosome chromosome) {
List<GAScheduleResult> results = chromosome.getResult();
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex = (Map<Integer, Entry>) obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>) obj.get(2);
if (results == null || results.isEmpty()) {
return generateRandomNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
Map<String, Integer> machinePositionIndex = buildEntryMachinePositionIndex(chromosome);
Long bottleneckMachineId = findBottleneckMachine(chromosome);
if (bottleneckMachineId != null) {
List<GAScheduleResult> bottleneckOps = findOpsOnBottleneckMachine(chromosome, bottleneckMachineId);
if (!bottleneckOps.isEmpty()) {
Chromosome result = tryChangeMachineForBottleneckOp(chromosome, bottleneckOps, machinePositionIndex, positionToEntryIndex, positionByPriority);
if (result != null) {
return result;
}
}
}
return generateRandomNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
/**
* 给指定位置的工序换设备
*/
private Chromosome generateMachineChangeForSpecificOp(Chromosome chromosome, List<MachineOption> machineOptions, int idx) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome neighbor=copyChromosome(chromosome);// ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> ms = neighbor.getMachineSelection();
if (!ms.isEmpty() && idx >= 0 && idx < ms.size()) {
if (machineOptions.size() > 1) {
......@@ -273,65 +1156,143 @@ public class VariableNeighborhoodSearch {
return neighbor;
}
private Chromosome moveBottleneckForwardWrapper(Chromosome chromosome) {
List<GAScheduleResult> results = chromosome.getResult();
Map<String, Integer> positionIndex = buildPositionIndex(chromosome);
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex =(Map<Integer, Entry>)obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>)obj.get(2);
Map<String, Integer> MachinePositionIndex = buildEntryMachinePositionIndex(chromosome);
if (results == null || results.isEmpty()) {
return generateRandomNeighbor(chromosome,positionToEntryIndex,positionByPriority);
}
Long bottleneckMachineId = findBottleneckMachine(chromosome);
if (bottleneckMachineId != null) {
List<GAScheduleResult> bottleneckOps = findOpsOnBottleneckMachine(chromosome, bottleneckMachineId);
if (!bottleneckOps.isEmpty()) {
Chromosome result = tryMoveBottleneckOpForward(chromosome, bottleneckOps, positionIndex,positionByPriority,positionToEntryIndex,MachinePositionIndex,false);
if (result != null) {
return result;
}
}
}
return generateRandomNeighbor(chromosome,positionToEntryIndex,positionByPriority);
}
private Chromosome moveBottleneckSameMachineWrapper(Chromosome chromosome) {
List<GAScheduleResult> results = chromosome.getResult();
Map<String, Integer> positionIndex = buildPositionIndex(chromosome);
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex =(Map<Integer, Entry>)obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>)obj.get(2);
Map<String, Integer> MachinePositionIndex = buildEntryMachinePositionIndex(chromosome);
if (results == null || results.isEmpty()) {
return generateRandomNeighbor(chromosome,positionToEntryIndex,positionByPriority);
}
Long bottleneckMachineId = findBottleneckMachine(chromosome);
if (bottleneckMachineId != null) {
List<GAScheduleResult> bottleneckOps = findOpsOnBottleneckMachine(chromosome, bottleneckMachineId);
if (!bottleneckOps.isEmpty()) {
Chromosome result = tryMoveBottleneckOpForward(chromosome, bottleneckOps, positionIndex,positionByPriority,positionToEntryIndex,MachinePositionIndex,true);
if (result != null) {
return result;
}
}
}
return generateRandomNeighbor(chromosome,positionToEntryIndex,positionByPriority);
}
/**
* 尝试将瓶颈设备上的工序往前移动
*/
private Chromosome tryMoveBottleneckOpForward(Chromosome chromosome, List<GAScheduleResult> bottleneckOps,
Map<String, Integer> positionIndex,
Map<Integer, Entry> positionToEntryIndex,
Map<String, Entry> entrys) {
Map<String, Integer> positionkey,List<List<Integer>> positionByPriority,Map<Integer, Entry> positionIndex,Map<String, Integer> machinePositionIndex,boolean isSameMachine) {
log(String.format("tryMoveBottleneckOpForward: isSameMachine=%b", isSameMachine));
if (bottleneckOps.isEmpty()) {
return generateSwapNeighbor(chromosome, entrys);
log("tryMoveBottleneckOpForward: 瓶颈工序为空");
return null;
}
// 随机选择一个瓶颈工序
// 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);
// 先构建优先级->订单数的映射
Map<Double, Set<Integer>> priorityToGroupIds = new HashMap<>();
for (GAScheduleResult op : bottleneckOps) {
Entry entry = entrybyids.get(op.getOperationId());
if (entry != null) {
double priority = entry.getPriority();
priorityToGroupIds.computeIfAbsent(priority, k -> new HashSet<>()).add(op.getGroupId());
}
}
// 按优先级和订单完成时间排序:优先选择高优先级+延期订单的工序
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 sizeA = priorityToGroupIds.getOrDefault(entryA.getPriority(), new HashSet<>()).size();
int sizeB = priorityToGroupIds.getOrDefault(entryB.getPriority(), new HashSet<>()).size();
int sizeCompare = Integer.compare(sizeB, sizeA);
if (sizeCompare != 0) {
return sizeCompare;
}
// 订单数相同时,按优先级排序
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;
});
if (sortedBottleneckOps.isEmpty()) {
log("tryMoveBottleneckOpForward: 排序后为空");
return null;
}
GAScheduleResult selectedOp = sortedBottleneckOps.get(rnd.nextInt(Math.min(5, sortedBottleneckOps.size())));
Entry entry=entrybyids.get(selectedOp.getOperationId()) ;
Entry entry = entrybyids.get(selectedOp.getOperationId());
if (entry == null) {
log("tryMoveBottleneckOpForward: 找不到工序");
return null;
}
String key = entry.getGroupId() + "_" + entry.getSequence();
Integer opPos = positionIndex.get(key);
Integer opPos = positionkey.get(key);
if (opPos == null || opPos <= 0) {
return generateSwapNeighbor(chromosome, entrys);
log("tryMoveBottleneckOpForward: 找不到工序位置");
return null;
}
// 往前移动1-3步
// int steps = rnd.nextInt(3) + 1;
// return moveOperationForward(chromosome,positionToEntryIndex, opPos, steps);
// 使用插入方式往前移动(1-5步)
log(String.format("tryMoveBottleneckOpForward: 找到工序位置=%d", opPos));
if(isSameMachine) {
Chromosome result = generateSameMachineSwapNeighbor(chromosome,opPos,positionIndex,machinePositionIndex);
log("tryMoveBottleneckOpForward: 相同设备交换完成");
return result;
} else {
int steps = rnd.nextInt(5) + 1;
return insertOperationForward(chromosome, opPos, steps, entrys);
Chromosome result = insertOperationForward(chromosome, opPos, steps, entrys, positionIndex);
log(String.format("tryMoveBottleneckOpForward: 往前插入%d步完成", steps));
return result;
}
}
/**
* 计算每个订单的最后完成时间
......@@ -345,40 +1306,76 @@ public class VariableNeighborhoodSearch {
}
return orderEndTimes;
}
private Chromosome moveNonBottleneckBackwardWrapper(Chromosome chromosome) {
List<GAScheduleResult> results = chromosome.getResult();
Map<String, Integer> positionIndex = buildPositionIndex(chromosome);
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex =(Map<Integer, Entry>)obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>)obj.get(2);
if (results == null || results.isEmpty()) {
return generateRandomNeighbor(chromosome,positionToEntryIndex,positionByPriority);
}
Long bottleneckMachineId = findBottleneckMachine(chromosome);
if (bottleneckMachineId != null) {
Chromosome result = tryMoveNonBottleneckOpBackward(chromosome, bottleneckMachineId, positionIndex,positionByPriority, positionToEntryIndex);
if (result != null) {
return result;
}
}
return generateRandomNeighbor(chromosome,positionToEntryIndex,positionByPriority);
}
/**
* 尝试将非瓶颈设备上的工序往后移动(给瓶颈工序腾位置)
*/
private Chromosome tryMoveNonBottleneckOpBackward(Chromosome chromosome, Long bottleneckMachineId,
Map<String, Integer> positionIndex,
Map<Integer, Entry> positionToEntryIndex,
Map<String, Entry> entrys) {
Map<String, Integer> positionIndex,List<List<Integer>> positionByPriority,
Map<Integer, Entry> positionToEntryIndex
) {
log(String.format("tryMoveNonBottleneckOpBackward: 瓶颈设备ID=%d", bottleneckMachineId));
List<GAScheduleResult> results = chromosome.getResult();
if (results == null) {
return generateSwapNeighbor(chromosome, entrys);
log("tryMoveNonBottleneckOpBackward: results为空");
return null;
}
// 找出非瓶颈设备上的工序
List<GAScheduleResult> nonBottleneckOps = results.stream()
.filter(r -> r.getMachineId() != bottleneckMachineId)
.filter(r -> r.getMachineId()!=(bottleneckMachineId))
.collect(Collectors.toList());
log(String.format("tryMoveNonBottleneckOpBackward: 非瓶颈工序数=%d", nonBottleneckOps.size()));
if (nonBottleneckOps.isEmpty()) {
return generateSwapNeighbor(chromosome, entrys);
log("tryMoveNonBottleneckOpBackward: 没有非瓶颈工序");
return null;
}
// 随机选择一个非瓶颈工序
GAScheduleResult randomOp = nonBottleneckOps.get(rnd.nextInt(nonBottleneckOps.size()));
Entry entry=entrybyids.get(randomOp.getOperationId());
String key = entry.getGroupId()+"_"+entry.getSequence();
Entry entry = entrybyids.get(randomOp.getOperationId());
if (entry == null) {
log("tryMoveNonBottleneckOpBackward: 找不到工序");
return null;
}
String key = entry.getGroupId() + "_" + entry.getSequence();
Integer opPos = positionIndex.get(key);
if (opPos == null || opPos >= chromosome.getOperationSequencing().size() - 1) {
return generateSwapNeighbor(chromosome, entrys);
log("tryMoveNonBottleneckOpBackward: 工序位置无效");
return null;
}
// 往后移动1-3步
log(String.format("tryMoveNonBottleneckOpBackward: 找到工序位置=%d", opPos));
int steps = rnd.nextInt(3) + 1;
return moveOperationBackward(chromosome,positionToEntryIndex, opPos, steps);
Chromosome result = moveOperationBackward(chromosome, positionToEntryIndex, opPos, steps);
log(String.format("tryMoveNonBottleneckOpBackward: 往后移动%d步完成", steps));
return result;
}
/**
* 将工序往前移动
......@@ -418,7 +1415,7 @@ public class VariableNeighborhoodSearch {
* 将工序往后移动
*/
private Chromosome moveOperationBackward(Chromosome chromosome,Map<Integer, Entry> originalPositionIndex, int pos, int steps) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome neighbor=copyChromosome(chromosome);// ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (pos < 0 || pos >= os.size() - 1) {
......@@ -452,8 +1449,8 @@ public class VariableNeighborhoodSearch {
/**
* 将工序往前插入(不交换,直接插入到目标位置)
*/
private Chromosome insertOperationForward(Chromosome chromosome, int pos, int steps, Map<String, Entry> entrys) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
private Chromosome insertOperationForward(Chromosome chromosome, int pos, int steps, Map<String, Entry> entrys,Map<Integer, Entry> originalPositionIndex) {
Chromosome neighbor=copyChromosome(chromosome);// ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (pos <= 0 || pos >= os.size()) {
......@@ -461,7 +1458,7 @@ public class VariableNeighborhoodSearch {
}
// 获取要移动的工序(基于原始chromosome)
Map<Integer, Entry> originalPositionIndex = buildPositionToEntryIndex(chromosome, entrys);
// Map<Integer, Entry> originalPositionIndex = buildPositionToEntryIndex(chromosome);
Entry opToMove = originalPositionIndex.get(pos);
if (opToMove == null) {
return neighbor;
......@@ -495,42 +1492,81 @@ public class VariableNeighborhoodSearch {
/**
* 随机生成邻域解(兜底策略)
*/
private Chromosome generateRandomNeighbor(Chromosome chromosome, Map<String, Entry> entrys) {
int neighborType = rnd.nextInt(4);
private Chromosome generateRandomNeighbor(Chromosome chromosome,Map<Integer, Entry> positionIndex,List<List<Integer>> positionByPriority) {
int neighborType = rnd.nextInt(5);
log(String.format("随机生成邻域解-"+neighborType));
switch (neighborType) {
case 0:
return generateSwapNeighbor(chromosome, entrys);
return generateSwapNeighbor(chromosome,positionIndex,positionByPriority);
case 1:
return generateReverseNeighbor(chromosome, entrys);
return generateReverseNeighbor(chromosome,positionIndex,positionByPriority);
case 2:
return generateInsertNeighbor(chromosome, entrys);
return generateInsertNeighbor(chromosome,positionIndex,positionByPriority);
case 3:
return generateMachineChangeNeighbor(chromosome);
case 4:
return generateSameMachineSwapNeighbor(chromosome);
default:
return generateSwapNeighbor(chromosome, entrys);
return generateSwapNeighbor(chromosome,positionIndex,positionByPriority);
}
}
private Chromosome generateSwapNeighborWrapper(Chromosome chromosome) {
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex = (Map<Integer, Entry>) obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>) obj.get(2);
return generateSwapNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
private Chromosome copyChromosome(Chromosome chromosome)
{
Chromosome neighbor=new Chromosome();
neighbor.setID(UUID.randomUUID().toString());
neighbor.setOperationSequencing(chromosome.getOperationSequencing());
neighbor.setMachineSelection(chromosome.getMachineSelection());
neighbor.setScenarioID(chromosome.getScenarioID());
neighbor.setBaseTime(chromosome.getBaseTime());
neighbor.setFitnessLevel(chromosome.getFitnessLevel());
neighbor.setGlobalOpList(chromosome.getGlobalOpList());
return neighbor;
}
/**
* 生成交换邻域解 - 只在相同优先级的工序之间交换
*/
private Chromosome generateSwapNeighbor(Chromosome chromosome,Map<String, Entry> entrys) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
private Chromosome generateSwapNeighbor(Chromosome chromosome,Map<Integer, Entry> positionIndex,List<List<Integer>> positionByPriority) {
Chromosome neighbor=copyChromosome(chromosome);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
Map<Integer, Entry> positionIndex = buildPositionToEntryIndex(neighbor,entrys);
if (os.size() >= 2 && !positionByPriority.isEmpty()) {
int maxAttempts = 50;
for (int attempt = 0; attempt < maxAttempts; attempt++) {
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
// 优先选择前面的优先级组(订单数多的),使用加权随机
int priorityGroupIndex;
if (positionByPriority.size() <= 3) {
priorityGroupIndex = rnd.nextInt(positionByPriority.size());
} else {
// 70%概率选择前3个优先级组,30%概率选择其他
if (rnd.nextDouble() < 0.7) {
priorityGroupIndex = rnd.nextInt(Math.min(3, positionByPriority.size()));
} else {
priorityGroupIndex = 3 + rnd.nextInt(positionByPriority.size() - 3);
}
}
List<Integer> positionos = positionByPriority.get(priorityGroupIndex);
if (positionos.size() < 2) continue;
int idx1 = positionos.get(rnd.nextInt(positionos.size()));
int idx2 = positionos.get(rnd.nextInt(positionos.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) {
if (op1.getGroupId() != op2.getGroupId()) {
java.util.Collections.swap(os, idx1, idx2);
neighbor.setOperationSequencing(os);
break;
......@@ -540,20 +1576,49 @@ public class VariableNeighborhoodSearch {
}
return neighbor;
}
private Chromosome generateReverseNeighborWrapper(Chromosome chromosome) {
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex = (Map<Integer, Entry>) obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>) obj.get(2);
return generateReverseNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
/**
* 生成反转邻域解 - 只反转相同优先级的连续工序
*/
private Chromosome generateReverseNeighbor(Chromosome chromosome,Map<String, Entry> entrys) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
private Chromosome generateReverseNeighbor(Chromosome chromosome,Map<Integer, Entry> positionIndex,List<List<Integer>> positionByPriority) {
Chromosome neighbor = copyChromosome(chromosome); //ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
Map<Integer, Entry> positionIndex = buildPositionToEntryIndex(neighbor,entrys);
// Map<Integer, Entry> positionIndex = buildPositionToEntryIndex(neighbor);
int maxAttempts = 50;
for (int attempt = 0; attempt < maxAttempts; attempt++) {
int start = rnd.nextInt(os.size());
int end = rnd.nextInt(os.size());
// 优先选择前面的优先级组(订单数多的),使用加权随机
int priorityGroupIndex;
if (positionByPriority.size() <= 3) {
priorityGroupIndex = rnd.nextInt(positionByPriority.size());
} else {
// 70%概率选择前3个优先级组,30%概率选择其他
if (rnd.nextDouble() < 0.7) {
priorityGroupIndex = rnd.nextInt(Math.min(3, positionByPriority.size()));
} else {
priorityGroupIndex = 3 + rnd.nextInt(positionByPriority.size() - 3);
}
}
List<Integer> positionos = positionByPriority.get(priorityGroupIndex);
if (positionos.size() < 2) continue;
int startIdxInList = rnd.nextInt(positionos.size());
int endIdxInList = rnd.nextInt(positionos.size());
if (endIdxInList <= startIdxInList) continue;
int start = positionos.get(startIdxInList);
int end = positionos.get(endIdxInList);
if (end <= start) continue;
......@@ -561,17 +1626,17 @@ public class VariableNeighborhoodSearch {
if (startOp == null) continue;
double priority = startOp.getPriority();
boolean allSamePriority = true;
boolean allSameGroupId = 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;
if (op == null&&op.getGroupId()==startOp.getGroupId() ) {
allSameGroupId = false;
break;
}
}
if (allSamePriority) {
if (allSameGroupId) {
java.util.Collections.reverse(os.subList(start, end + 1));
neighbor.setOperationSequencing(os);
break;
......@@ -581,19 +1646,49 @@ public class VariableNeighborhoodSearch {
return neighbor;
}
private Chromosome generateInsertNeighborWrapper(Chromosome chromosome) {
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionToEntryIndex = (Map<Integer, Entry>) obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>) obj.get(2);
return generateInsertNeighbor(chromosome, positionToEntryIndex, positionByPriority);
}
/**
* 生成插入邻域解 - 只插入到相同优先级的位置
*/
private Chromosome generateInsertNeighbor(Chromosome chromosome,Map<String, Entry> entrys) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
private Chromosome generateInsertNeighbor(Chromosome chromosome,Map<Integer, Entry> positionIndex,List<List<Integer>> positionByPriority) {
Chromosome neighbor=copyChromosome(chromosome);// ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
if (os.size() >= 2) {
Map<Integer, Entry> positionIndex = buildPositionToEntryIndex(neighbor,entrys);
// Map<Integer, Entry> positionIndex = buildPositionToEntryIndex(neighbor);
int maxAttempts = 50;
for (int attempt = 0; attempt < maxAttempts; attempt++) {
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
// 优先选择前面的优先级组(订单数多的),使用加权随机
int priorityGroupIndex;
if (positionByPriority.size() <= 3) {
priorityGroupIndex = rnd.nextInt(positionByPriority.size());
} else {
// 70%概率选择前3个优先级组,30%概率选择其他
if (rnd.nextDouble() < 0.7) {
priorityGroupIndex = rnd.nextInt(Math.min(3, positionByPriority.size()));
} else {
priorityGroupIndex = 3 + rnd.nextInt(positionByPriority.size() - 3);
}
}
List<Integer> positionos = positionByPriority.get(priorityGroupIndex);
if (positionos.size() < 2) continue;
int idx1InList = rnd.nextInt(positionos.size());
int idx2InList = rnd.nextInt(positionos.size());
if (idx1InList == idx2InList) continue;
int idx1 = positionos.get(idx1InList);
int idx2 = positionos.get(idx2InList);
if (idx1 == idx2) continue;
......@@ -601,7 +1696,7 @@ public class VariableNeighborhoodSearch {
Entry op2 = positionIndex.get(idx2);
if (op1 != null && op2 != null) {
if (Math.abs(op1.getPriority() - op2.getPriority()) < 0.001) {
if (op1.getGroupId()!=op2.getGroupId()) {
int value = os.remove(idx1);
os.add(idx2, value);
neighbor.setOperationSequencing(os);
......@@ -617,7 +1712,7 @@ public class VariableNeighborhoodSearch {
* 生成机器选择邻域解 - 不受优先级限制
*/
private Chromosome generateMachineChangeNeighbor(Chromosome chromosome) {
Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome neighbor=copyChromosome(chromosome);// ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> ms = neighbor.getMachineSelection();
if (!ms.isEmpty()) {
int idx = rnd.nextInt(ms.size());
......@@ -643,12 +1738,132 @@ public class VariableNeighborhoodSearch {
return neighbor;
}
Chromosome generateSameMachineSwapNeighbor(Chromosome chromosome){
List<Integer> os = chromosome.getOperationSequencing();
Map<String, Integer> machinePositionIndex = buildEntryMachinePositionIndex(chromosome);
Map<Integer, Object> obj = buildPositionToEntryIndex(chromosome);
Map<Integer, Entry> positionIndex =(Map<Integer, Entry>)obj.get(1);
List<List<Integer>> positionByPriority = (List<List<Integer>>)obj.get(2);
return generateSameMachineSwapNeighbor(chromosome,rnd.nextInt(os.size()),positionIndex,machinePositionIndex);
}
private Chromosome generateSameMachineSwapNeighbor(Chromosome chromosome,int idx1,Map<Integer, Entry> positionIndex,Map<String, Integer> machinePositionIndex) {
Chromosome neighbor=copyChromosome(chromosome);// ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
List<Integer> os = neighbor.getOperationSequencing();
List<Integer> ms = neighbor.getMachineSelection();
if (os.size() >= 2 && ms.size() >= 2) {
List<Integer> positions = new ArrayList<>();
Entry op1 = positionIndex.get(idx1);
int maPos1 = machinePositionIndex.get(op1.getGroupId() + "_" + op1.getSequence());
int machineSeq1 = ms.get(maPos1);
MachineOption machineOption1 = op1.getMachineOptions().get(machineSeq1 - 1);
Long machineId1 = machineOption1.getMachineId();
for (int i = 0; i < os.size(); i++) {
Entry op = positionIndex.get(i);
if (op == null) continue;
int maPos = machinePositionIndex.get(op.getGroupId() + "_" + op.getSequence());
if (maPos < 0) continue;
int machineSeq = ms.get(maPos);
if (machineSeq < 1 || machineSeq > op.getMachineOptions().size()) continue;
MachineOption machineOption = op.getMachineOptions().get(machineSeq - 1);
Long machineId = machineOption.getMachineId();
if (machineId == null) continue;
if (machineId.equals(machineId1)&&Math.abs(op1.getPriority() - op.getPriority())==0&&op1.getGroupId()!=op.getGroupId()) {
positions.add(maPos);
}
}
if (positions.isEmpty()||positions.size() <=1) return neighbor;
int idx2 = positions.get(rnd.nextInt(positions.size()));
Collections.swap(os, idx1, idx2);
neighbor.setOperationSequencing(os);
}
return neighbor;
}
// private Chromosome generateSameMachineSwapNeighbor(Chromosome chromosome,int idx1,Map<Integer, Entry> positionIndex,Map<String, Integer> machinePositionIndex) {
//
// Chromosome neighbor = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
// List<Integer> os = neighbor.getOperationSequencing();
// List<Integer> ms = neighbor.getMachineSelection();
//
// if (os.size() >= 2 && ms.size() >= 2) {
//
// Map<Long, List<Integer>> machineToPositionsMap = new HashMap<>();
//
// for (int i = 0; i < os.size(); i++) {
// Entry op = positionIndex.get(i);
// if (op == null) continue;
//
// int maPos = machinePositionIndex.get(op.getGroupId() + "_" + op.getSequence());
// if (maPos < 0) continue;
//
// int machineSeq = ms.get(maPos);
// if (machineSeq < 1 || machineSeq > op.getMachineOptions().size()) continue;
//
// MachineOption machineOption = op.getMachineOptions().get(machineSeq - 1);
// Long machineId = machineOption.getMachineId();
// if (machineId == null) continue;
//
// machineToPositionsMap.computeIfAbsent(machineId, k -> new ArrayList<>()).add(i); }
//
// List<int[]> validPairs = new ArrayList<>();
//
// for (List<Integer> positions : machineToPositionsMap.values()) {
// if (positions.size() < 2) continue;
//
// for (int i = 0; i < positions.size(); i++) {
// for (int j = i + 1; j < positions.size(); j++) {
// int idx1 = positions.get(i);
// int idx2 = positions.get(j);
//
// Entry op1 = positionIndex.get(idx1);
// Entry op2 = positionIndex.get(idx2);
//
// if (op1 == null || op2 == null) continue;
// if (Math.abs(op1.getPriority() - op2.getPriority()) > 0.001) continue;
// if (op1.getGroupId()==(op2.getGroupId())) continue;
//
// validPairs.add(new int[]{idx1, idx2});
// }
// }
// }
//
// if (!validPairs.isEmpty()) {
// int[] pair = validPairs.get(rnd.nextInt(validPairs.size()));
// Collections.swap(os, pair[0], pair[1]);
// neighbor.setOperationSequencing(os);
// }
// }
// return neighbor;
// }
/**
* 局部搜索
*/
private Chromosome localSearch(Chromosome chromosome, GeneticDecoder decoder, ScheduleParams param) {
private Chromosome localSearch(Chromosome chromosome, GeneticDecoder decoder, List<Machine> machines) {
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
decode(decoder, best, machines);
//writeKpi(best);
// 预定义邻域结构,避免每次循环重复创建
List<NeighborhoodStructure> neighborhoods = defineNeighborhoods();
boolean improved = true;
while (improved) {
......@@ -656,15 +1871,25 @@ public class VariableNeighborhoodSearch {
// 生成所有可能的邻域解
List<Chromosome> neighbors = new ArrayList<>();
for (NeighborhoodStructure neighborhood : defineNeighborhoods()) {
neighbors.add(generateNeighbor(current));
for (NeighborhoodStructure neighborhood : neighborhoods) {
Chromosome neighbor = generateNeighbor(current, neighborhood);
if (neighbor != null) {
neighbors.add(neighbor);
}
}
if (neighbors.isEmpty()) {
break;
}
Batchdecode(decoder, neighbors, machines);
// 评估所有邻域解
for (Chromosome neighbor : neighbors) {
decode(decoder, neighbor, null);
if (isBetter(neighbor, best)) {
if (neighbor != null && isBetter(neighbor, best)) {
best = neighbor;
writeKpi(best);
current = neighbor;
improved = true;
}
......@@ -681,100 +1906,71 @@ public class VariableNeighborhoodSearch {
private void decode(GeneticDecoder decoder, Chromosome chromosome , List<Machine> machines) {
chromosome.setResult(new CopyOnWriteArrayList<>());
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines, Machine.class)); // 简单拷贝,实际可能需要深拷贝
decoder.decodeChromosomeWithCache(chromosome);
}
/**
* 比较两个染色体的优劣
*/
private boolean isBetter(Chromosome c1, Chromosome c2) {
return c1.getFitness() > c2.getFitness();
// 缓存 Machine 列表(第一次调用时缓存)
if (cachedMachines == null) {
cachedMachines = ProductionDeepCopyUtil.deepCopyList(machines, Machine.class);
}
/**
* 邻域1:交换两个工序的顺序
*/
private void swapNeighborhood(Chromosome chromosome) {
List<Integer> os = chromosome.getOperationSequencing();
if (os.size() < 2) return;
// 使用缓存的列表,避免重复深拷贝
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(cachedMachines, Machine.class));
chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedOrders), Order.class));
chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedEntryRel), GroupResult.class));
chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyList(cachedMaterials, Material.class));
chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedAllOperations), Entry.class));
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
while (idx2 == idx1) {
idx2 = rnd.nextInt(os.size());
// 加载锁定工单到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);
}
Collections.swap(os, idx1, idx2);
chromosome.setOperationSequencing(os);
private void Batchdecode(GeneticDecoder decoder, List<Chromosome> chromosomes , List<Machine> machines) {
// 缓存 Machine 列表(第一次调用时缓存)
if (cachedMachines == null) {
cachedMachines = ProductionDeepCopyUtil.deepCopyList(machines, Machine.class);
}
log(String.format("变邻域搜索 -复制对象S, 染色体数=" + chromosomes.size()));
/**
* 邻域2:反转一个工序子序列
*/
private void reverseNeighborhood(Chromosome chromosome) {
List<Integer> os = chromosome.getOperationSequencing();
if (os.size() < 2) return;
// 并行设置染色体字段
chromosomes.parallelStream().forEach(chromosome -> {
if (chromosome == null) return;
int start = rnd.nextInt(os.size());
int end = rnd.nextInt(os.size());
while (end <= start) {
end = rnd.nextInt(os.size());
}
chromosome.setResult(new CopyOnWriteArrayList<>());
Collections.reverse(os.subList(start, end + 1));
chromosome.setOperationSequencing(os);
// 使用缓存的列表,避免重复深拷贝
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(cachedMachines, Machine.class));
chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedOrders), Order.class));
chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedEntryRel), GroupResult.class));
chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyList(cachedMaterials, Material.class));
chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(cachedAllOperations), Entry.class));
// 加载锁定工单到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<>());
}
});
/**
* 邻域3:插入一个工序到另一个位置
*/
private void insertNeighborhood(Chromosome chromosome) {
List<Integer> os = chromosome.getOperationSequencing();
if (os.size() < 2) return;
log(String.format("变邻域搜索 -复制对象E"));
int idx1 = rnd.nextInt(os.size());
int idx2 = rnd.nextInt(os.size());
while (idx2 == idx1) {
idx2 = rnd.nextInt(os.size());
// 并行解码所有候选方案
decoder.Chromosomedecode(chromosomes);
}
int value = os.remove(idx1);
os.add(idx2, value);
chromosome.setOperationSequencing(os);
}
/**
* 邻域4:机器选择变异
* 比较两个染色体的优劣
*/
private void machineChangeNeighborhood(Chromosome chromosome) {
List<Integer> ms = chromosome.getMachineSelection();
if (ms.isEmpty()) return;
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);
}
private boolean isBetter(Chromosome c1, Chromosome c2) {
return fitnessCalculator.isBetter(c1,c2);
}
if (!availableMachines.isEmpty()) {
int newMachineSeq = availableMachines.get(rnd.nextInt(availableMachines.size()));
ms.set(idx, newMachineSeq);
chromosome.setMachineSelection(ms);
}
}
}
/**
* 构建位置索引:groupId_sequence -> position
*/
......@@ -791,6 +1987,8 @@ public class VariableNeighborhoodSearch {
String key = groupId + "_" + count;
index.put(key, i);
}
return index;
}
......@@ -816,8 +2014,15 @@ public class VariableNeighborhoodSearch {
/**
* 构建位置->Entry索引
*/
private Map<Integer, Entry> buildPositionToEntryIndex(Chromosome chromosome,Map<String, Entry> entrys) {
private Map<Integer, Object> buildPositionToEntryIndex(Chromosome chromosome) {
Map<Integer, Object> obj = new HashMap<>();
Map<Integer, Entry> index = new HashMap<>();
//将位置按照优先级分组
Map<Double, List<Integer>> indexByPriorityMap = new HashMap<>();
Map<Double, Set<Integer>> groupidByPriority = new HashMap<>();
List<Integer> os = chromosome.getOperationSequencing();
Map<Integer, Integer> orderProcessCounter = new HashMap<>();
......@@ -831,9 +2036,30 @@ public class VariableNeighborhoodSearch {
if (op != null) {
index.put(i, op);
double priority = op.getPriority();
indexByPriorityMap.computeIfAbsent(priority, k -> new ArrayList<>()).add(i);
groupidByPriority.computeIfAbsent(priority, k -> new HashSet()).add(op.getGroupId());
}
}
return index;
groupidByPriority.entrySet().removeIf(entry -> entry.getValue().size() == 1);
indexByPriorityMap.keySet().removeIf(key -> !groupidByPriority.containsKey(key));
List<Map.Entry<Double, List<Integer>>> sortedEntries = new ArrayList<>(indexByPriorityMap.entrySet());
sortedEntries.sort((e1, e2) -> {
int size1 = groupidByPriority.get(e1.getKey()).size();
int size2 = groupidByPriority.get(e2.getKey()).size();
return Integer.compare(size2, size1); // 降序:订单数多的排前面
});
List<List<Integer>> indexByPriority = new ArrayList<>();
for (Map.Entry<Double, List<Integer>> entry : sortedEntries) {
indexByPriority.add(entry.getValue());
}
obj.put(1,index);
obj.put(2,indexByPriority);
return obj;
}
/**
......@@ -860,7 +2086,7 @@ public class VariableNeighborhoodSearch {
* 邻域结构接口
*/
private interface NeighborhoodOperator {
void apply(Chromosome chromosome);
Chromosome apply(Chromosome chromosome);
}
/**
......@@ -875,8 +2101,8 @@ public class VariableNeighborhoodSearch {
this.operator = operator;
}
public void apply(Chromosome chromosome) {
operator.apply(chromosome);
public Chromosome apply(Chromosome chromosome) {
return operator.apply(chromosome);
}
}
}
\ No newline at end of file
......@@ -132,7 +132,7 @@ public class SceneService {
try {
ObjectMapper objectMapper = createObjectMapper();
SceneChromsome sceneChromsome=(SceneChromsome)redisUtils.get("SceneId."+sceneId);
SceneChromsome sceneChromsome=null;//(SceneChromsome)redisUtils.get("SceneId."+sceneId);
if(sceneChromsome==null)
{
sceneChromsome=new SceneChromsome();
......@@ -163,7 +163,7 @@ public class SceneService {
sceneChromsome.getSceneDetails().add(sceneDetail);
redisUtils.set("SceneId."+sceneId,sceneChromsome);
// redisUtils.set("SceneId."+sceneId,sceneChromsome);
File file = getChromosomeFile(sceneId,sceneChromsome.getVersion().toString());
......
......@@ -39,7 +39,8 @@ public class PlanResultServiceTest {
// TestSortService sortService=new TestSortService();
// sortService.test1();
// nsgaiiUtils.Test();
planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//2000
planResultService.execute2("08B1D87FE1B84ECDBAC2E546DDB6FB81");//2000
// planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//2000
// planResultService.execute2("C8B533BD8944405B9A2F8823C575C204");//500
// planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");//20
// 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