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

变领域优化

parent 78368160
...@@ -72,7 +72,7 @@ public class VariableNeighborhoodSearch { ...@@ -72,7 +72,7 @@ public class VariableNeighborhoodSearch {
private int currentLogLevel = LOG_LEVEL_INFO; private int currentLogLevel = LOG_LEVEL_INFO;
// 局部搜索优化 // 局部搜索优化
private static final int MAX_LOCAL_SEARCH_NEIGHBORS = 3; // 从5减少到2,大幅减少解码次数 private static final int MAX_LOCAL_SEARCH_NEIGHBORS = 2; // 从5减少到2,大幅减少解码次数
private void log(String message) { private void log(String message) {
log(message, LOG_LEVEL_INFO, false); log(message, LOG_LEVEL_INFO, false);
...@@ -229,6 +229,20 @@ public class VariableNeighborhoodSearch { ...@@ -229,6 +229,20 @@ public class VariableNeighborhoodSearch {
// 机器选择变异 // 机器选择变异
neighborhoods.add(new NeighborhoodStructure("MachineChange", this::generateMachineChangeNeighbor)); neighborhoods.add(new NeighborhoodStructure("MachineChange", this::generateMachineChangeNeighbor));
// ==================== 新增激进变邻域方法 ====================
// BlockMove - 移动工序块
neighborhoods.add(new NeighborhoodStructure("BlockMove", this::blockMoveWrapper));
// MultiOperationSwap - 一次交换多个工序
neighborhoods.add(new NeighborhoodStructure("MultiOperationSwap", this::multiOperationSwapWrapper));
// MultiMachineChange - 一次改变多个工序的机器选择
neighborhoods.add(new NeighborhoodStructure("MultiMachineChange", this::multiMachineChangeWrapper));
// HybridShake - 混合抖动:综合调整
neighborhoods.add(new NeighborhoodStructure("HybridShake", this::hybridShakeWrapper));
return neighborhoods; return neighborhoods;
} }
...@@ -1995,7 +2009,7 @@ public class VariableNeighborhoodSearch { ...@@ -1995,7 +2009,7 @@ public class VariableNeighborhoodSearch {
*/ */
private Chromosome localSearch(Chromosome chromosome, GeneticDecoder decoder, List<Machine> machines) { private Chromosome localSearch(Chromosome chromosome, GeneticDecoder decoder, List<Machine> machines) {
geneticOperations.DelOrder(chromosome); geneticOperations.DelOrder(chromosome);
Chromosome best = copyChromosome(chromosome); Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
decode(decoder, best, machines); decode(decoder, best, machines);
writeKpi(best); writeKpi(best);
// 预定义邻域结构,避免每次循环重复创建 // 预定义邻域结构,避免每次循环重复创建
...@@ -2073,7 +2087,7 @@ public class VariableNeighborhoodSearch { ...@@ -2073,7 +2087,7 @@ public class VariableNeighborhoodSearch {
log(String.format("变邻域搜索 -复制对象S, 染色体数=" + chromosomes.size())); log(String.format("变邻域搜索 -复制对象S, 染色体数=" + chromosomes.size()));
// 并行设置染色体字段 // 并行设置染色体字段
chromosomes.forEach(chromosome -> { chromosomes.parallelStream().forEach(chromosome -> {
if (chromosome == null) return; if (chromosome == null) return;
chromosome.setResult(new CopyOnWriteArrayList<>()); chromosome.setResult(new CopyOnWriteArrayList<>());
...@@ -2560,4 +2574,460 @@ public class VariableNeighborhoodSearch { ...@@ -2560,4 +2574,460 @@ public class VariableNeighborhoodSearch {
this.score = score; this.score = score;
} }
} }
// ==================== 激进变邻域方法 ====================
/**
* BlockMove - 移动工序块的变邻域方法包装器
*/
private Chromosome blockMoveWrapper(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 blockMove(chromosome, positionToEntryIndex, positionByPriority);
}
/**
* BlockMove - 移动一段连续的工序块到新位置
* 优先选择包含瓶颈工序的块,遵守优先级约束
*/
private Chromosome blockMove(Chromosome chromosome, Map<Integer, Entry> positionIndex, List<List<Integer>> positionByPriority) {
Chromosome neighbor = copyChromosome(chromosome);
List<Integer> os = neighbor.getOperationSequencing();
int n = os.size();
if (n < 5) return null; // 工序太少,无法进行块移动
// 获取瓶颈工序
Set<Integer> bottleneckOpIds = new HashSet<>();
try {
Map<String, Object> bottleneckAnalysis = findBottleneckMachineWithDetails(chromosome);
List<GAScheduleResult> criticalOps = (List<GAScheduleResult>) bottleneckAnalysis.get("criticalOps");
if (criticalOps != null) {
for (GAScheduleResult op : criticalOps) {
bottleneckOpIds.add(op.getOperationId());
}
}
} catch (Exception e) {
log("BlockMove: 获取瓶颈信息失败,使用正常模式");
}
// 找出包含瓶颈工序的位置
Set<Integer> bottleneckPositions = new HashSet<>();
for (Map.Entry<Integer, Entry> entry : positionIndex.entrySet()) {
if (bottleneckOpIds.contains(entry.getValue().getId())) {
bottleneckPositions.add(entry.getKey());
}
}
int maxAttempts = 20;
for (int attempt = 0; attempt < maxAttempts; attempt++) {
// 1. 选择块的起始位置 - 优先选择包含瓶颈工序的区域
int blockStart;
if (!bottleneckPositions.isEmpty() && rnd.nextDouble() < 0.7) {
// 70%概率从瓶颈工序附近选择
List<Integer> bottleneckPosList = new ArrayList<>(bottleneckPositions);
int bottleneckPos = bottleneckPosList.get(rnd.nextInt(bottleneckPosList.size()));
// 在瓶颈工序周围选择起始位置
int minStart = Math.max(0, bottleneckPos - 5);
int maxStart = Math.min(n - 4, bottleneckPos);
blockStart = minStart + rnd.nextInt(maxStart - minStart + 1);
} else {
// 否则从高优先级组中选择
if (!positionByPriority.isEmpty()) {
int priorityGroupIndex;
if (positionByPriority.size() <= 3) {
priorityGroupIndex = rnd.nextInt(positionByPriority.size());
} else {
if (rnd.nextDouble() < 0.7) {
priorityGroupIndex = rnd.nextInt(Math.min(3, positionByPriority.size()));
} else {
int otherCount = positionByPriority.size() - 3;
priorityGroupIndex = 3 + rnd.nextInt(otherCount);
}
}
List<Integer> positionos = positionByPriority.get(priorityGroupIndex);
if (!positionos.isEmpty()) {
blockStart = positionos.get(rnd.nextInt(positionos.size()));
blockStart = Math.max(0, Math.min(n - 4, blockStart));
} else {
blockStart = rnd.nextInt(n - 3);
}
} else {
blockStart = rnd.nextInt(n - 3);
}
}
// 2. 确定块大小:3-8个工序
int maxBlockSize = Math.min(8, n - blockStart);
int blockSize = rnd.nextInt(maxBlockSize - 2) + 3;
int blockEnd = blockStart + blockSize;
// 检查块中的工序是否都属于相似的优先级
boolean validBlock = true;
Double blockPriority = null;
int bottleneckCount = 0;
for (int i = blockStart; i < blockEnd && i < os.size(); i++) {
Entry entry = positionIndex.get(i);
if (entry != null) {
if (blockPriority == null) {
blockPriority = entry.getPriority();
} else if (Math.abs(entry.getPriority() - blockPriority) > 0.5) {
// 优先级差异太大,跳过这个块
validBlock = false;
break;
}
if (bottleneckOpIds.contains(entry.getId())) {
bottleneckCount++;
}
}
}
if (!validBlock) continue;
// 3. 选择新位置:不能在块内部,且尽量在同一优先级区域
List<Integer> possiblePositions = new ArrayList<>();
for (int pos = 0; pos < n - blockSize + 1; pos++) {
if (pos < blockStart - 1 || pos > blockEnd + 1) {
possiblePositions.add(pos);
}
}
if (possiblePositions.isEmpty()) continue;
// 优先选择同样是高优先级的位置
int newPosition;
if (!positionByPriority.isEmpty() && blockPriority != null) {
// 查找目标优先级组的位置
List<Integer> targetPositions = new ArrayList<>();
for (int pos : possiblePositions) {
Entry entry = positionIndex.get(pos);
if (entry != null && Math.abs(entry.getPriority() - blockPriority) <= 0.5) { targetPositions.add(pos);
}
}
if (!targetPositions.isEmpty() && rnd.nextDouble() < 0.7) {
newPosition = targetPositions.get(rnd.nextInt(targetPositions.size()));
} else {
newPosition = possiblePositions.get(rnd.nextInt(possiblePositions.size()));
}
} else {
newPosition = possiblePositions.get(rnd.nextInt(possiblePositions.size()));
}
log(String.format("BlockMove: 移动工序块 [%d,%d) -> %d, 块大小=%d, 瓶颈工序=%d/%d",
blockStart, blockEnd, newPosition, blockSize, bottleneckCount, blockSize));
// 4. 执行块移动
List<Integer> block = new ArrayList<>(os.subList(blockStart, blockEnd));
os.subList(blockStart, blockEnd).clear();
// 调整newPosition(因为移除块后索引变化了)
if (newPosition > blockStart) {
newPosition -= blockSize;
}
os.addAll(newPosition, block);
return neighbor;
}
return null;
}
/**
* MultiOperationSwap - 一次交换多个工序的包装器
*/
private Chromosome multiOperationSwapWrapper(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 multiOperationSwap(chromosome, positionToEntryIndex, positionByPriority);
}
/**
* MultiOperationSwap - 一次交换多对工序
* 优先选择瓶颈工序和关键路径工序,遵守优先级约束
*/
private Chromosome multiOperationSwap(Chromosome chromosome, Map<Integer, Entry> positionIndex, List<List<Integer>> positionByPriority) {
Chromosome neighbor = copyChromosome(chromosome);
List<Integer> os = neighbor.getOperationSequencing();
int n = os.size();
if (n < 4) return null; // 工序太少
// 获取瓶颈工序和关键路径工序
List<Integer> priorityPositions = new ArrayList<>();
Set<Integer> bottleneckOpIds = new HashSet<>();
try {
Map<String, Object> bottleneckAnalysis = findBottleneckMachineWithDetails(chromosome);
List<GAScheduleResult> criticalOps = (List<GAScheduleResult>) bottleneckAnalysis.get("criticalOps");
if (criticalOps != null) {
for (GAScheduleResult op : criticalOps) {
bottleneckOpIds.add(op.getOperationId());
}
}
// 构建瓶颈工序的位置索引
Map<String, Integer> posIndex = buildPositionIndex(chromosome);
for (Map.Entry<Integer, Entry> entry : positionIndex.entrySet()) {
if (bottleneckOpIds.contains(entry.getValue().getId())) {
priorityPositions.add(entry.getKey());
}
}
} catch (Exception e) {
log("MultiOperationSwap: 获取瓶颈信息失败,使用正常模式");
}
int swapPairs = rnd.nextInt(Math.min(3, n / 2)) + 1; // 1-3对交换
Set<Integer> usedPositions = new HashSet<>();
log(String.format("MultiOperationSwap: 准备执行 %d 对工序交换, 瓶颈工序数=%d", swapPairs, priorityPositions.size()));
for (int pair = 0; pair < swapPairs; pair++) {
int maxAttempts = 50;
boolean found = false;
for (int attempt = 0; attempt < maxAttempts && !found; attempt++) {
int pos1, pos2;
// 优先从瓶颈工序中选择,70%概率
if (!priorityPositions.isEmpty() && rnd.nextDouble() < 0.7) {
pos1 = priorityPositions.get(rnd.nextInt(priorityPositions.size()));
} else {
// 否则从优先级组中选择
if (positionByPriority.isEmpty()) {
pos1 = rnd.nextInt(n);
} else {
// 优先选择前面的优先级组
int priorityGroupIndex;
if (positionByPriority.size() <= 3) {
priorityGroupIndex = rnd.nextInt(positionByPriority.size());
} else {
if (rnd.nextDouble() < 0.7) {
priorityGroupIndex = rnd.nextInt(Math.min(3, positionByPriority.size()));
} else {
int otherCount = positionByPriority.size() - 3;
priorityGroupIndex = 3 + rnd.nextInt(otherCount);
}
}
List<Integer> positionos = positionByPriority.get(priorityGroupIndex);
if (positionos.isEmpty()) continue;
pos1 = positionos.get(rnd.nextInt(positionos.size()));
}
}
// 从同一个优先级组中选择pos2,确保优先级约束
Entry entry1 = positionIndex.get(pos1);
if (entry1 == null) continue;
List<Integer> possiblePos2 = new ArrayList<>();
// 查找同优先级的工序位置
for (List<Integer> priorityGroup : positionByPriority) {
if (priorityGroup.contains(pos1)) {
possiblePos2 = priorityGroup.stream()
.filter(p -> p != pos1 && !usedPositions.contains(p))
.collect(Collectors.toList());
break;
}
}
// 如果没有找到同优先级的,从瓶颈工序中找一个
if (possiblePos2.isEmpty() && !priorityPositions.isEmpty()) {
possiblePos2 = priorityPositions.stream()
.filter(p -> p != pos1 && !usedPositions.contains(p))
.collect(Collectors.toList());
}
// 如果还是没有,随机找一个(放宽约束)
if (possiblePos2.isEmpty()) {
for (int i = 0; i < n; i++) {
if (i != pos1 && !usedPositions.contains(i)) {
possiblePos2.add(i);
}
}
}
if (possiblePos2.isEmpty()) continue;
pos2 = possiblePos2.get(rnd.nextInt(possiblePos2.size()));
if (pos1 == pos2 || usedPositions.contains(pos1) || usedPositions.contains(pos2)) {
continue;
}
Entry entry2 = positionIndex.get(pos2);
if (entry1 == null || entry2 == null) continue;
// 执行交换
Integer temp = os.get(pos1);
os.set(pos1, os.get(pos2));
os.set(pos2, temp);
usedPositions.add(pos1);
usedPositions.add(pos2);
String bottleneckTag1 = bottleneckOpIds.contains(entry1.getId()) ? "[瓶颈]" : "";
String bottleneckTag2 = bottleneckOpIds.contains(entry2.getId()) ? "[瓶颈]" : "";
log(String.format(" 交换对 %d: pos=%d%s <-> pos=%d%s, 工单=%d<->%d",
pair + 1, pos1, bottleneckTag1, pos2, bottleneckTag2,
entry1.getGroupId(), entry2.getGroupId()));
found = true;
break;
}
}
if (usedPositions.size() >= 2) {
return neighbor;
}
return null;
}
/**
* MultiMachineChange - 一次改变多个工序的机器选择的包装器
*/
private Chromosome multiMachineChangeWrapper(Chromosome chromosome) {
return multiMachineChange(chromosome);
}
/**
* MultiMachineChange - 一次改变多个工序的机器选择
* 优先选择瓶颈工序和关键路径工序
*/
private Chromosome multiMachineChange(Chromosome chromosome) {
Chromosome neighbor = copyChromosome(chromosome);
List<GlobalOperationInfo> globalOps = neighbor.getGlobalOpList();
List<Integer> machineSelection = neighbor.getMachineSelection();
// 获取瓶颈工序
Set<Integer> bottleneckOpIds = new HashSet<>();
try {
Map<String, Object> bottleneckAnalysis = findBottleneckMachineWithDetails(chromosome);
List<GAScheduleResult> criticalOps = (List<GAScheduleResult>) bottleneckAnalysis.get("criticalOps");
if (criticalOps != null) {
for (GAScheduleResult op : criticalOps) {
bottleneckOpIds.add(op.getOperationId());
}
}
} catch (Exception e) {
log("MultiMachineChange: 获取瓶颈信息失败,使用正常模式");
}
// 收集有多个机器选项的工序,优先瓶颈工序
List<Integer> eligibleOps = new ArrayList<>();
List<Integer> bottleneckEligibleOps = new ArrayList<>();
for (int i = 0; i < globalOps.size(); i++) {
Entry entry = globalOps.get(i).getOp();
if (entry != null && entry.getMachineOptions() != null && entry.getMachineOptions().size() > 1) {
eligibleOps.add(i);
if (bottleneckOpIds.contains(entry.getId())) {
bottleneckEligibleOps.add(i);
}
}
}
if (eligibleOps.size() < 2) {
log("MultiMachineChange: 没有足够的多机器选项工序");
return null;
}
// 选择要改变的工序数量:2-5个
int changeCount = Math.min(rnd.nextInt(4) + 2, eligibleOps.size());
Set<Integer> selectedIndices = new HashSet<>();
log(String.format("MultiMachineChange: 准备改变 %d 个工序的机器选择, 瓶颈工序数=%d/%d",
changeCount, bottleneckEligibleOps.size(), eligibleOps.size()));
// 优先选择瓶颈工序,70%概率从瓶颈中选择
while (selectedIndices.size() < changeCount) {
int idx;
if (!bottleneckEligibleOps.isEmpty() && rnd.nextDouble() < 0.7) {
idx = bottleneckEligibleOps.get(rnd.nextInt(bottleneckEligibleOps.size()));
} else {
idx = eligibleOps.get(rnd.nextInt(eligibleOps.size()));
}
if (!selectedIndices.contains(idx)) {
selectedIndices.add(idx);
}
}
// 为每个选中的工序随机选择新机器
for (int idx : selectedIndices) {
Entry entry = globalOps.get(idx).getOp();
List<MachineOption> options = entry.getMachineOptions();
int currentSelection = machineSelection.get(idx);
// 随机选择一个不同于当前的机器
int newSelection;
if (options.size() == 2) {
newSelection = (currentSelection == 1) ? 0 : 1;
} else {
do {
newSelection = rnd.nextInt(options.size());
} while (newSelection == currentSelection);
}
machineSelection.set(idx, newSelection);
String bottleneckTag = bottleneckOpIds.contains(entry.getId()) ? "[瓶颈]" : "";
log(String.format(" 工序%d%s (工单%d): 机器选择 %d -> %d",
idx, bottleneckTag, entry.getGroupId(), currentSelection, newSelection));
}
return neighbor;
}
/**
* HybridShake - 混合抖动:同时进行位置和机器的综合调整
* 最激进的变邻域方法,用于彻底跳出局部最优
*/
private Chromosome hybridShakeWrapper(Chromosome chromosome) {
Chromosome neighbor = copyChromosome(chromosome);
log("HybridShake: 开始混合抖动调整");
// 50%概率进行块移动
if (rnd.nextDouble() < 0.5) {
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);
Chromosome blockResult = blockMove(neighbor, positionToEntryIndex, positionByPriority);
if (blockResult != null) {
neighbor = blockResult;
}
}
// 50%概率进行多机器改变
if (rnd.nextDouble() < 0.5) {
Chromosome machineResult = multiMachineChange(neighbor);
if (machineResult != null) {
neighbor = machineResult;
}
}
// 30%概率进行多工序交换
if (rnd.nextDouble() < 0.3) {
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);
Chromosome swapResult = multiOperationSwap(neighbor, positionToEntryIndex, positionByPriority);
if (swapResult != null) {
neighbor = swapResult;
}
}
log("HybridShake: 混合抖动完成");
return neighbor;
}
} }
\ No newline at end of file
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