Commit dd36e456 authored by Tong Li's avatar Tong Li

优化非分配排序

parent 4965288c
......@@ -110,12 +110,12 @@ public class GeneticAlgorithm {
FileHelper.writeLogFile("初始化批量解码-----------开始-------");
Chromosomedecode(param,allOperations,globalOpList,population);
FileHelper.writeLogFile("初始化批量解码-----------结束-------");
List<List<Chromosome>> fronts = _nsgaIIUtils.parallelFastNonDominatedSort(population);
List<List<Chromosome>> combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(population);
int ordercount = globalOpList.stream()
.mapToInt(GlobalOperationInfo::getGroupId)
.max()
.orElse(0);
Chromosome best=GetBest(fronts,"初始");
Chromosome best=GetBest(combinedFronts,"初始");
// best=fronts.get(0).stream()
// .max(Comparator.comparingDouble(Chromosome::getFitness))
......@@ -165,6 +165,7 @@ public class GeneticAlgorithm {
List<Chromosome> nextPopulation = new ArrayList<>();
for (int i = 0; i < selected.size(); i += 2) {
if (i + 1 >= selected.size()) {
selected.get(i).setID(UUID.randomUUID().toString());
nextPopulation.add(selected.get(i));
break;
}
......@@ -188,6 +189,7 @@ public class GeneticAlgorithm {
for (Chromosome chromosome : nextPopulation) {
if (rnd.nextDouble() < param.getMutationProb()) {
Chromosome chromosome1= ProductionDeepCopyUtil.deepCopy(chromosome,Chromosome.class);
chromosome1.setID(UUID.randomUUID().toString());
geneticOps.mutate(chromosome1, globalOpList);
nextPopulation1.add(chromosome1);
}
......@@ -209,12 +211,15 @@ public class GeneticAlgorithm {
// List<Chromosome> elites = population1.subList(0, param.getElitismCount());
List<Chromosome> newPopulation = new ArrayList<>();
newPopulation.addAll(population);
//保留一定数量的上一代
List<Chromosome> populationcopy = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize()/5);
newPopulation.addAll(populationcopy);
newPopulation.addAll(nextPopulation);
newPopulation= chromosomeDistinct1(newPopulation);
FileHelper.writeLogFile("非支配排序-----------开始-------");
// 2.7 非支配排序
List<List<Chromosome>> combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(newPopulation);
combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(newPopulation);
FileHelper.writeLogFile("非支配排序-----------结束-------");
// 2.8 选择下一代种群
population = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize());
......@@ -291,14 +296,9 @@ return population;
}
FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",population.size() ));
List<Chromosome> population1 = population.stream().filter(t->t.getGeneStr()==null).collect(Collectors.toList());
if(population1!=null&&population1.size()>0)
{
FileHelper.writeLogFile(String.format("排产-----------方案GeneStrnull数量---%d-------",population1.size() ));
}
population = population.stream()
.collect(Collectors.toMap(
Chromosome::getGeneStr, // key:去重的字段(GeneStr)
......@@ -308,7 +308,6 @@ if(population1!=null&&population1.size()>0)
.values() // 获取去重后的
.stream()
.collect(Collectors.toList());
FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",population.size() ));
return population;
}
......@@ -321,14 +320,9 @@ if(population1!=null&&population1.size()>0)
}
FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",population.size() ));
List<Chromosome> population1 = population.stream().filter(t->t.getGeneStr()==null).collect(Collectors.toList());
if(population1!=null&&population1.size()>0)
{
FileHelper.writeLogFile(String.format("排产-----------方案GeneStrnull数量---%d-------",population1.size() ));
}
population = population.stream()
.collect(Collectors.toMap(
Chromosome::getGeneStr, // key:去重的字段(GeneStr)
......@@ -338,7 +332,6 @@ if(population1!=null&&population1.size()>0)
.values() // 获取去重后的
.stream()
.collect(Collectors.toList());
FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",population.size() ));
return population;
}
......
......@@ -24,7 +24,7 @@ public class NSGAIIUtils {
public void init(ObjectiveWeights weights, int taskCount,boolean[] isMinimize) {
this.objectiveWeights = (weights != null) ? weights : new ObjectiveWeights();
this.taskCount = (taskCount > 0) ? taskCount : Runtime.getRuntime().availableProcessors();
this.taskCount = (taskCount > 0) ? taskCount : Runtime.getRuntime().availableProcessors()-1;
this.isMinimize=isMinimize;
}
......@@ -33,7 +33,7 @@ public class NSGAIIUtils {
*/
public void init(ObjectiveWeights weights, int taskCount) {
this.objectiveWeights = (weights != null) ? weights : new ObjectiveWeights();
this.taskCount = (taskCount > 0) ? taskCount : Runtime.getRuntime().availableProcessors();
this.taskCount = (taskCount > 0) ? taskCount : Runtime.getRuntime().availableProcessors()-1;
}
/**
......@@ -53,22 +53,171 @@ public class NSGAIIUtils {
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives(population);
if (popSize <= taskCount * 10) { // 小规模种群直接串行
if (popSize <= taskCount * 15) { // 小规模种群直接串行 7*15
fronts = fastNonDominatedSort(population);
} else {
int chunkCount = Math.min(taskCount, popSize);
// 步骤2:拆分种群为多个块,并行计算支配关系
List<List<Chromosome>> chunks = splitPopulation(population, chunkCount);
Map<Chromosome, List<Chromosome>> dominanceMatrix = new HashMap<>();
Map<Chromosome, Integer> dominatedCount = new HashMap<>();
for (Chromosome chromo : population) {
dominanceMatrix.put(chromo, new ArrayList<>());
dominatedCount.put(chromo, 0);
}
ExecutorService executor = Executors.newFixedThreadPool(chunkCount);
try {
List<Future<?>> futures = new ArrayList<>(); // 存储任务Future,确保全量等待
for (List<Chromosome> chunk : chunks) {
futures.add(executor.submit(() -> {
for (Chromosome p : chunk) {
for (Chromosome q : population) {
if (p == q) continue;
if (dominates(p, q)) {
synchronized (dominanceMatrix.get(p)) { // 细粒度锁
dominanceMatrix.get(p).add(q);
}
} else if (dominates(q, p)) {
synchronized (dominatedCount) {
dominatedCount.put(p, dominatedCount.get(p) + 1);
}
}
}
}
}));
}
// 核心修复2:等待所有任务完成,避免提前终止导致的计算不完整
for (Future<?> future : futures) {
try {
future.get(); // 等待单个任务完成,抛出异常则终止
} catch (ExecutionException e) {
throw new RuntimeException("并行计算支配关系失败", e.getCause());
}
}
executor.shutdown();
}catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("并行计算支配关系中断", e);
} finally {
if (!executor.isShutdown()) {
executor.shutdownNow(); // 确保线程池关闭
}
}
// 生成前沿
// 染色体 -> 数组下标的映射表
Map<Chromosome, Integer> chromosomeIndexMap = new HashMap<>(popSize);
int[] dominatedCounts = new int[popSize];
// 新增:支配矩阵数组化 - 每个p的下标,对应一个存储q下标的List
List<List<Integer>> dominanceMatrixArr = new ArrayList<>(popSize);
// ======== 修复空指针的核心行:循环popSize次,给每个索引塞一个空的ArrayList ========
for (int idx = 0; idx < popSize; idx++) {
dominanceMatrixArr.add(new ArrayList<>()); // 必须加这行,初始化每个位置的空列表
Chromosome c = population.get(idx);
chromosomeIndexMap.put(c, idx);
}
// 5. 填充映射表、被支配数数组、支配矩阵数组
for (int idx = 0; idx < popSize; idx++) {
Chromosome c = population.get(idx);
dominatedCounts[idx] = dominatedCount.get(c);
// 把HashMap的支配列表,转成q的下标列表,存入数组
List<Chromosome> qList = dominanceMatrix.get(c);
List<Integer> qIdxList = dominanceMatrixArr.get(idx); // 此时get(idx)绝对非空!
for (Chromosome q : qList) {
Integer qIdx = chromosomeIndexMap.get(q);
if(qIdx != null){ // 额外兜底:防止q是null导致的空指针
qIdxList.add(qIdx);
}
}
}
// ========== 初始化前沿列表,必须先添加F1(第一个前沿) ==========
List<Chromosome> firstFront = new ArrayList<>();
// 遍历种群,找到所有被支配数=0的个体 → 这就是F1,绝对不被任何个体支配的最优解
for (Chromosome chromosome : population) {
if (chromosome == null) continue;
int count = dominatedCount.getOrDefault(chromosome, 0);
if (count == 0) {
firstFront.add(chromosome);
}
}
fronts.add(firstFront);
boolean[] addedFlag = new boolean[popSize];
int i = 0;
while (i < fronts.size() && !fronts.get(i).isEmpty()) {
List<Chromosome> currentFront = fronts.get(i);
List<Chromosome> nextFront = new ArrayList<>();
Arrays.fill(addedFlag, false);
for (Chromosome p : currentFront) {
if (p == null) continue;
Integer pIdxObj = chromosomeIndexMap.get(p);
if (pIdxObj == null || pIdxObj >= popSize || pIdxObj < 0) continue;
int pIdx = pIdxObj;
// 拿到p能支配的所有q的下标,无空指针
List<Integer> qIdxList = dominanceMatrixArr.get(pIdx);
for (int qIdx : qIdxList) {
// 核心逻辑:被支配数-1
if (dominatedCounts[qIdx] <= 0) {
continue;
}
dominatedCounts[qIdx]--;
// 当被支配数=0时,加入下一个前沿,去重
if (dominatedCounts[qIdx] == 0 && !addedFlag[qIdx]) {
addedFlag[qIdx] = true;
nextFront.add(population.get(qIdx));
}
}
}
// 把下一个前沿加入列表,继续循环
if (!nextFront.isEmpty()) {
fronts.add(nextFront);
}
i++;
}
}
assignRankToSolutions(fronts);
return fronts;
}
public List<List<Chromosome>> parallelFastNonDominatedSort1(List<Chromosome> population) {
int popSize = population.size();
List<List<Chromosome>> fronts = new ArrayList<>();
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives(population);
if (popSize <= taskCount * 15) { // 小规模种群直接串行 7*15
fronts = fastNonDominatedSort(population);
} else {
int chunkCount = Math.min(taskCount, popSize);
// 步骤2:拆分种群为多个块,并行计算支配关系
List<List<Chromosome>> chunks = splitPopulation(population, taskCount);
List<List<Chromosome>> chunks = splitPopulation(population, chunkCount);
ConcurrentHashMap<Chromosome, ConcurrentLinkedQueue<Chromosome>> dominanceMatrix = new ConcurrentHashMap<>();
ConcurrentHashMap<Chromosome, AtomicInteger> dominatedCount = new ConcurrentHashMap<>();
// 初始化字典
for (Chromosome chromo : population) {
dominanceMatrix.putIfAbsent(chromo, new ConcurrentLinkedQueue<>());
dominatedCount.putIfAbsent(chromo, new AtomicInteger(0));
}
// 并行计算支配关系
chunks.parallelStream().forEach(chunk -> {
for (Chromosome p : chunk) {
......@@ -84,6 +233,8 @@ public class NSGAIIUtils {
}
});
// 步骤3:生成前沿
List<Chromosome> front1 = new ArrayList<>();
......@@ -114,11 +265,15 @@ public class NSGAIIUtils {
fronts.add(nextFront);
}
List<List<Chromosome>> fronts1= fastNonDominatedSort(population);
}
assignRankToSolutions(fronts);
return fronts;
}
/**
* 用Stream API为分层后的解批量赋值Rank
*/
......@@ -220,10 +375,21 @@ public class NSGAIIUtils {
// 计算每个目标的最大/最小值
double[] minValues = new double[kpisize];
double[] maxValues = new double[kpisize];
// for (int i = 0; i < kpisize; i++) {
// final int idx = i;
// minValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).min().orElse(0);
// maxValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).max().orElse(0);
// }
for (int i = 0; i < kpisize; i++) {
final int idx = i;
minValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).min().orElse(0);
maxValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).max().orElse(0);
minValues[i] = Double.MAX_VALUE;
maxValues[i] = Double.MIN_VALUE;
}
for (Chromosome chromo : population) {
double[] obj = chromo.getObjectives();
for (int i = 0; i < kpisize; i++) {
minValues[i] = Math.min(minValues[i], obj[i]);
maxValues[i] = Math.max(maxValues[i], obj[i]);
}
}
// 并行计算归一化和加权目标值
......@@ -337,7 +503,7 @@ public class NSGAIIUtils {
}
}
if(popSize>taskCount*10)
if(popSize>taskCount*15)
{
// 对每个目标维度并行计算距离
IntStream.range(0, popSize).parallel().forEach(m -> {
......
......@@ -39,7 +39,7 @@ public class PlanResultServiceTest {
// nsgaiiUtils.Test();
//planResultService.execute2("C5FB5EF2A7334A0A92F826F4937E1008");
// planResultService.execute2("726D4C1A712B4B1393175BD44B775B66");
planResultService.execute2("13CC1CF783CE40D7AE3264D09FAA6378");
planResultService.execute2("265F24B6DF3C40E4B17D193B0CC8AAF2");
// LocalDateTime t= LocalDateTime.of(2025, 11, 15, 6, 51, 11);
// List<Integer> opids=new ArrayList<>();BCA6FA43FFA444D3952CF8F6E1EA291B
// opids.add(1);
......
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