Commit 8447ab72 authored by Tong Li's avatar Tong Li

遗传算法-NSGA-II

parent 2c399e24
...@@ -60,6 +60,11 @@ public class Chromosome { ...@@ -60,6 +60,11 @@ public class Chromosome {
private List<Order> orders; private List<Order> orders;
private List<Machine> InitMachines; private List<Machine> InitMachines;
private List<GroupResult> OperatRel; private List<GroupResult> OperatRel;
private double[] Objectives ; // 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay]
private int Rank; // 非支配排序等级(1最优)
private double CrowdingDistance =0; // 拥挤距离
private double WeightedObjective =0; // 加权目标值(用于自定义权重)
/// <summary> /// <summary>
/// 适应度值 /// 适应度值
/// </summary> /// </summary>
......
package com.aps.entity.Algorithm;
/**
* 作者:佟礼
* 时间:2025-12-09
* 多目标权重配置
*/
public class ObjectiveWeights {
/**
* 目标权重(默认值:[0.3, 0.2, 0.15, 0.2, 0.15])
* 对应:完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
*/
private double[] weights = new double[] { 0.3, 0.2, 0.15, 0.2, 0.15 };
/**
* NSGA-II模式:true=纯帕累托(无视权重),false=加权帕累托
*/
private boolean pureNSGAIIMode = true;
// Getter and Setter for weights
public double[] getWeights() {
return weights;
}
public void setWeights(double[] weights) {
this.weights = weights;
}
// Getter and Setter for pureNSGAIIMode
public boolean isPureNSGAIIMode() {
return pureNSGAIIMode;
}
public void setPureNSGAIIMode(boolean pureNSGAIIMode) {
this.pureNSGAIIMode = pureNSGAIIMode;
}
/**
* 归一化目标值(消除量纲影响)
*/
public double[] normalizeObjectives(double[] objectives, double[] minValues, double[] maxValues) {
double[] normalized = new double[objectives.length];
if(minValues==null||minValues.length==0)
{
for (int i = 0; i < objectives.length; i++) {
normalized[i]= 1/ (1 +(double) objectives[i]);
}
}else {
for (int i = 0; i < objectives.length; i++) {
if (maxValues[i] - minValues[i] == 0)
normalized[i] = 0;
else
normalized[i] = (objectives[i] - minValues[i]) / (maxValues[i] - minValues[i]);
}
}
return normalized;
}
/**
* 计算加权目标值
*/
public double calculateWeightedObjective(double[] normalizedObjectives) {
double sum = 0;
for (int i = 0; i < normalizedObjectives.length; i++)
sum += normalizedObjectives[i] * weights[i];
return sum;
}
/**
* 计算加权目标值
*/
public double calculateObjective(double[] normalizedObjectives) {
double sum = 0;
for (int i = 0; i < normalizedObjectives.length; i++)
sum += normalizedObjectives[i];
return sum;
}
}
...@@ -48,7 +48,7 @@ public class FitnessCalculator { ...@@ -48,7 +48,7 @@ public class FitnessCalculator {
// 2. 计算每个个体与平均值的平方差之和 // 2. 计算每个个体与平均值的平方差之和
float sumSqDiff = 0.0f; float sumSqDiff = 0.0f;
for (Chromosome chromosome : population) { for (Chromosome chromosome : population) {
double diff = chromosome.getFitness() - avgFitness; double diff = chromosome.getWeightedObjective() - avgFitness;
sumSqDiff += diff * diff; sumSqDiff += diff * diff;
} }
......
...@@ -2,11 +2,8 @@ package com.aps.service.Algorithm; ...@@ -2,11 +2,8 @@ package com.aps.service.Algorithm;
import com.aps.common.util.DeepCopyUtil; import com.aps.common.util.DeepCopyUtil;
import com.aps.common.util.ProductionDeepCopyUtil; import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.Chromosome; import com.aps.entity.Algorithm.*;
import com.aps.entity.Algorithm.GlobalOperationInfo;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult; import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.Algorithm.Pair;
import com.aps.entity.Algorithm.ScheduleParams;
import com.aps.entity.basic.*; import com.aps.entity.basic.*;
import com.aps.service.plan.MachineSchedulerService; import com.aps.service.plan.MachineSchedulerService;
...@@ -28,6 +25,10 @@ public class GeneticAlgorithm { ...@@ -28,6 +25,10 @@ public class GeneticAlgorithm {
FitnessCalculator _fitnessCalculator = new FitnessCalculator(); FitnessCalculator _fitnessCalculator = new FitnessCalculator();
private NSGAIIUtils _nsgaIIUtils = new NSGAIIUtils();
private ObjectiveWeights _objectiveWeights = new ObjectiveWeights();
public GeneticAlgorithm(GlobalParam globalParam,List<Machine> machines, List<Order> orders, public GeneticAlgorithm(GlobalParam globalParam,List<Machine> machines, List<Order> orders,
List<Material> materials, MachineSchedulerService machineScheduler,List<GroupResult> entryRel) { List<Material> materials, MachineSchedulerService machineScheduler,List<GroupResult> entryRel) {
this.machines = machines; this.machines = machines;
...@@ -37,7 +38,21 @@ public class GeneticAlgorithm { ...@@ -37,7 +38,21 @@ public class GeneticAlgorithm {
_GlobalParam=globalParam; _GlobalParam=globalParam;
_entryRel=entryRel; _entryRel=entryRel;
} }
public void Init(double[] customWeights, boolean pureNSGAIIMode) {
// 自定义权重配置
if (customWeights != null && customWeights.length == 5)
{
_objectiveWeights.setWeights(customWeights);
_objectiveWeights.setPureNSGAIIMode(pureNSGAIIMode);
}
_nsgaIIUtils.init(_objectiveWeights);
}
public Chromosome Run(ScheduleParams param, List<Entry> allOperations) { public Chromosome Run(ScheduleParams param, List<Entry> allOperations) {
System.out.println("开始"); System.out.println("开始");
Initialization initialization = new Initialization(_GlobalParam,allOperations); Initialization initialization = new Initialization(_GlobalParam,allOperations);
...@@ -51,15 +66,22 @@ public class GeneticAlgorithm { ...@@ -51,15 +66,22 @@ public class GeneticAlgorithm {
List<Chromosome> population = initialization.generateInitialPopulation(param, globalOpList); List<Chromosome> population = initialization.generateInitialPopulation(param, globalOpList);
Chromosomedecode(param,allOperations,globalOpList,population); Chromosomedecode(param,allOperations,globalOpList,population);
List<List<Chromosome>> fronts = _nsgaIIUtils.parallelFastNonDominatedSort(population);
int ordercount = globalOpList.stream() int ordercount = globalOpList.stream()
.mapToInt(GlobalOperationInfo::getGroupId) .mapToInt(GlobalOperationInfo::getGroupId)
.max() .max()
.orElse(0); .orElse(0);
Chromosome best=new Chromosome(); Chromosome best=new Chromosome();
best= population.stream()
.max(Comparator.comparingDouble(Chromosome::getFitness)) // best=fronts.get(0).stream()
// .max(Comparator.comparingDouble(Chromosome::getFitness))
// .orElse(null);
best = fronts.get(0).stream()
.sorted((c1, c2) -> Double.compare(c2.getWeightedObjective(), c1.getWeightedObjective()))
.findFirst()
.orElse(null); .orElse(null);
double bestFitness=0; double bestFitness=0;
int Iteration=0; int Iteration=0;
// 步骤2:迭代进化 // 步骤2:迭代进化
...@@ -108,31 +130,38 @@ public class GeneticAlgorithm { ...@@ -108,31 +130,38 @@ public class GeneticAlgorithm {
geneticOps.mutate(chromosome, globalOpList); geneticOps.mutate(chromosome, globalOpList);
} }
} }
Chromosomedecode(param,allOperations,globalOpList,nextPopulation);
// 精英保留 // // 精英保留
List<Chromosome> population1 = population.stream() // List<Chromosome> population1 = population.stream()
.sorted((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness())) // .sorted((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()))
.collect(Collectors.toList()); // 降序排序 // .collect(Collectors.toList()); // 降序排序
//
//
List<Chromosome> elites = population1.subList(0, param.getElitismCount()); // List<Chromosome> elites = population1.subList(0, param.getElitismCount());
List<Chromosome> newPopulation = new ArrayList<>(); List<Chromosome> newPopulation = new ArrayList<>();
newPopulation.addAll(elites); newPopulation.addAll(population);
newPopulation.addAll(nextPopulation); newPopulation.addAll(nextPopulation);
// 2.7 非支配排序
List<List<Chromosome>> combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(newPopulation);
// 2.8 选择下一代种群
population = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize());
// 更新种群 // 更新种群
population = newPopulation.stream() // population = newPopulation.stream()
.limit(param.getPopulationSize() ) // .limit(param.getPopulationSize() )
.collect(Collectors.toList()); // .collect(Collectors.toList());
Chromosomedecode(param,allOperations,globalOpList,population); fronts = _nsgaIIUtils.parallelFastNonDominatedSort(population);
best= population.stream() best = fronts.get(0).stream()
.max(Comparator.comparingDouble(Chromosome::getFitness)) .sorted((c1, c2) -> Double.compare(c2.getWeightedObjective(), c1.getWeightedObjective()))
.findFirst()
.orElse(null); .orElse(null);
if(bestFitness<best.getFitness()) if(bestFitness<best.getWeightedObjective())
{ {
bestFitness=best.getFitness(); bestFitness=best.getWeightedObjective();
}else { }else {
Iteration++; Iteration++;
...@@ -174,10 +203,12 @@ public class GeneticAlgorithm { ...@@ -174,10 +203,12 @@ public class GeneticAlgorithm {
chromosome.setGlobalOpList(globalOpList); // 简单拷贝,实际可能需要深拷贝 chromosome.setGlobalOpList(globalOpList); // 简单拷贝,实际可能需要深拷贝
Chromosome chromosomen = decoder.decodeChromosomeWithCache(chromosome); Chromosome chromosomen = decoder.decodeChromosomeWithCache(chromosome);
if (chromosomen.getFitness() == 0) { // if (chromosomen.getFitness() == 0) {
chromosomen.setFitness(_fitnessCalculator.calculateFitness(chromosomen)); // chromosomen.setFitness(_fitnessCalculator.calculateFitness(chromosomen));
} // }
}); });
} }
} }
......
...@@ -756,12 +756,12 @@ public class GeneticDecoder { ...@@ -756,12 +756,12 @@ public class GeneticDecoder {
chromosome.setMachineLoadStd(machineLoadBalance); chromosome.setMachineLoadStd(machineLoadBalance);
chromosome.setDelayTime(tardiness); chromosome.setDelayTime(tardiness);
// 加权求和作为适应度(权重可根据需求调整) double[] Objectives=new double[5];
// chromosome.setFitness(0.4 * (1.0 / (1 + makespan)) + Objectives[0] = makespan;
// 0.3 * (1.0 / (1 + tardiness)) + Objectives[1] = totalFlowTime;
// 0.1 * (1.0 / (1 + totalSetupTime)) + Objectives[2] = totalSetupTime;
// 0.1 * (1.0 / (1 + totalFlowTime)) + Objectives[3] = machineLoadBalance;
// 0.1 * machineLoadBalance); Objectives[4] = tardiness;
} }
private double calculateTotalFlowTime(Chromosome chromosome) { private double calculateTotalFlowTime(Chromosome chromosome) {
......
...@@ -47,12 +47,22 @@ public class GeneticOperations { ...@@ -47,12 +47,22 @@ public class GeneticOperations {
if (tournamentSize < candidates.size()) { if (tournamentSize < candidates.size()) {
candidates = candidates.subList(0, tournamentSize); candidates = candidates.subList(0, tournamentSize);
} }
// 步骤4: 从参与者中选择适应度最高的个体 // 步骤4: 从参与者中选择适应度最高的个体
// Chromosome best = candidates.stream()
// .max(Comparator.comparingDouble(Chromosome::getFitness))
// .orElseThrow(() -> new IllegalStateException("候选列表为空,无法选择最佳个体。"));
// // 复制个体(假设Chromosome有复制方法或通过构造函数复制)
Chromosome best = candidates.stream() Chromosome best = candidates.stream()
.max(Comparator.comparingDouble(Chromosome::getFitness)) // 第一步:按Rank升序排序(与OrderBy对应)
.orElseThrow(() -> new IllegalStateException("候选列表为空,无法选择最佳个体。")); .sorted(Comparator.comparingInt(Chromosome::getRank)
// 复制个体(假设Chromosome有复制方法或通过构造函数复制) // 第二步:按拥挤距离降序排序(与ThenByDescending对应)
.thenComparing(Comparator.comparingDouble(Chromosome::getCrowdingDistance).reversed()))
// 取第一个元素(与First()对应)
.findFirst()
// 处理空列表情况(避免NoSuchElementException)
.orElse(null);
selected.add(ProductionDeepCopyUtil.deepCopy(best)); selected.add(ProductionDeepCopyUtil.deepCopy(best));
} }
return selected; return selected;
......
package com.aps.service.Algorithm;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.ObjectiveWeights;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 增强版NSGA-II工具类(自定义权重+并行非支配排序)
*/
public class NSGAIIUtils {
private ObjectiveWeights objectiveWeights;
private int taskCount; // 并行任务数(默认=CPU核心数)
/**
* 初始化(设置权重和并行任务数)
*/
public void init(ObjectiveWeights weights, int taskCount) {
this.objectiveWeights = (weights != null) ? weights : new ObjectiveWeights();
this.taskCount = (taskCount > 0) ? taskCount : Runtime.getRuntime().availableProcessors();
}
/**
* 重载初始化方法(默认任务数)
*/
public void init(ObjectiveWeights weights) {
init(weights, 0);
}
/**
* 并行快速非支配排序(大规模种群提速50%+)
*/
public List<List<Chromosome>> parallelFastNonDominatedSort(List<Chromosome> population) {
int popSize = population.size();
if (popSize <= taskCount * 10) { // 小规模种群直接串行
return fastNonDominatedSort(population);
}
// 步骤1:预处理 - 计算归一化目标值和加权目标值
preprocessObjectives(population);
// 步骤2:拆分种群为多个块,并行计算支配关系
List<List<Chromosome>> chunks = splitPopulation(population, taskCount);
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) {
for (Chromosome q : population) {
if (p == q) continue;
if (dominates(p, q)) {
dominanceMatrix.get(p).add(q);
} else if (dominates(q, p)) {
dominatedCount.get(p).incrementAndGet();
}
}
}
});
// 步骤3:生成前沿
List<List<Chromosome>> fronts = new ArrayList<>();
List<Chromosome> front1 = new ArrayList<>();
for (Chromosome p : population) {
if (dominatedCount.get(p).get() == 0) {
p.setRank(1);
front1.add(p);
}
}
fronts.add(front1);
int i = 0;
while (fronts.get(i).size() > 0) {
List<Chromosome> nextFront = new ArrayList<>();
for (Chromosome p : fronts.get(i)) {
for (Chromosome q : dominanceMatrix.get(p)) {
AtomicInteger count = dominatedCount.get(q);
if (count.decrementAndGet() == 0) {
q.setRank(i + 2);
nextFront.add(q);
}
}
}
i++;
if (!nextFront.isEmpty()) {
fronts.add(nextFront);
}
}
return fronts;
}
/**
* 串行快速非支配排序(兼容小规模种群)
*/
public List<List<Chromosome>> fastNonDominatedSort(List<Chromosome> population) {
preprocessObjectives(population);
List<List<Chromosome>> fronts = new ArrayList<>();
Map<Chromosome, List<Chromosome>> S = new HashMap<>();
Map<Chromosome, Integer> n = new HashMap<>();
List<Chromosome> front1 = new ArrayList<>();
for (Chromosome p : population) {
S.put(p, new ArrayList<>());
n.put(p, 0);
for (Chromosome q : population) {
if (p == q) continue;
if (dominates(p, q)) {
S.get(p).add(q);
} else if (dominates(q, p)) {
n.put(p, n.get(p) + 1);
}
}
if (n.get(p) == 0) {
p.setRank(1);
front1.add(p);
}
}
fronts.add(front1);
int i = 0;
while (fronts.get(i).size() > 0) {
List<Chromosome> nextFront = new ArrayList<>();
for (Chromosome p : fronts.get(i)) {
for (Chromosome q : S.get(p)) {
n.put(q, n.get(q) - 1);
if (n.get(q) == 0) {
q.setRank(i + 2);
nextFront.add(q);
}
}
}
i++;
if (!nextFront.isEmpty()) {
fronts.add(nextFront);
}
}
return fronts;
}
/**
* 预处理目标值(归一化+加权)
*/
private void preprocessObjectives(List<Chromosome> population) {
// 计算每个目标的最大/最小值
double[] minValues = new double[5];
double[] maxValues = new double[5];
for (int i = 0; i < 5; 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);
}
// 并行计算归一化和加权目标值
population.parallelStream().forEach(chromo -> {
double[] normalized = objectiveWeights.normalizeObjectives(chromo.getObjectives(), minValues, maxValues);
if (objectiveWeights.isPureNSGAIIMode()) {
chromo.setWeightedObjective(objectiveWeights.calculateObjective(normalized));
}else {
chromo.setWeightedObjective(objectiveWeights.calculateWeightedObjective(normalized));
}
});
}
/**
* 拆分种群为多个块(用于并行计算)
*/
private List<List<Chromosome>> splitPopulation(List<Chromosome> population, int chunkCount) {
List<List<Chromosome>> chunks = new ArrayList<>();
int chunkSize = (int) Math.ceil((double) population.size() / chunkCount);
for (int i = 0; i < population.size(); i += chunkSize) {
int end = Math.min(i + chunkSize, population.size());
chunks.add(population.subList(i, end));
}
return chunks;
}
/**
* 判断p是否支配q(支持自定义权重)
*/
public boolean dominates(Chromosome p, Chromosome q) {
// 纯NSGA-II模式:标准帕累托支配
if (objectiveWeights.isPureNSGAIIMode()) {
boolean allBetterOrEqual = true;
boolean oneBetter = false;
double[] pObjectives = p.getObjectives();
double[] qObjectives = q.getObjectives();
for (int i = 0; i < pObjectives.length; i++) {
if (pObjectives[i] > qObjectives[i]) {
allBetterOrEqual = false;
break;
} else if (pObjectives[i] < qObjectives[i]) {
oneBetter = true;
}
}
return allBetterOrEqual && oneBetter;
}
// 加权NSGA-II模式:融合权重的支配关系
else {
// 方式1:加权目标值更小则支配(简单高效)
return p.getWeightedObjective() < q.getWeightedObjective();
// 方式2(可选):加权后的帕累托支配
// double pWeightedSum = 0, qWeightedSum = 0;
// for (int i = 0; i < p.getObjectives().length; i++) {
// pWeightedSum += p.getObjectives()[i] * objectiveWeights.getWeights()[i];
// qWeightedSum += q.getObjectives()[i] * objectiveWeights.getWeights()[i];
// }
// return pWeightedSum < qWeightedSum;
}
}
/**
* 并行计算拥挤距离
*/
public void parallelCalculateCrowdingDistance(List<Chromosome> front) {
if (front.isEmpty()) return;
int objCount = front.get(0).getObjectives().length;
int popSize = front.size();
// 初始化距离为0
front.parallelStream().forEach(chromo -> chromo.setCrowdingDistance(0.0));
// 对每个目标维度并行计算距离
IntStream.range(0, objCount).parallel().forEach(m -> {
// 按当前目标排序
List<Chromosome> sorted = front.stream()
.sorted(Comparator.comparingDouble(c -> c.getObjectives()[m]))
.collect(Collectors.toList());
// 边界个体距离设为无穷大
sorted.get(0).setCrowdingDistance(Double.POSITIVE_INFINITY);
sorted.get(popSize - 1).setCrowdingDistance(Double.POSITIVE_INFINITY);
double maxObj = sorted.get(popSize - 1).getObjectives()[m];
double minObj = sorted.get(0).getObjectives()[m];
if (maxObj - minObj == 0) return;
// 计算中间个体的拥挤距离
for (int i = 1; i < popSize - 1; i++) {
Chromosome chromo = sorted.get(i);
synchronized (chromo) { // 线程安全
double distance = chromo.getCrowdingDistance() +
(sorted.get(i + 1).getObjectives()[m] - sorted.get(i - 1).getObjectives()[m])
/ (maxObj - minObj);
chromo.setCrowdingDistance(distance);
}
}
});
}
/**
* 选择下一代种群(兼容并行计算)
*/
public List<Chromosome> selectNextPopulation(List<List<Chromosome>> fronts, int populationSize) {
List<Chromosome> nextPopulation = new ArrayList<>();
int currentSize = 0;
for (List<Chromosome> front : fronts) {
if (currentSize + front.size() <= populationSize) {
nextPopulation.addAll(front);
currentSize += front.size();
} else {
// 并行计算拥挤距离
parallelCalculateCrowdingDistance(front);
// 按拥挤距离排序,取前N个
List<Chromosome> sortedByDistance = front.stream()
.sorted((c1, c2) -> Double.compare(c2.getCrowdingDistance(), c1.getCrowdingDistance()))
.collect(Collectors.toList());
nextPopulation.addAll(sortedByDistance.subList(0, populationSize - currentSize));
currentSize = populationSize;
break;
}
}
return nextPopulation;
}
}
...@@ -23,6 +23,9 @@ import java.util.stream.IntStream; ...@@ -23,6 +23,9 @@ import java.util.stream.IntStream;
* 时间:2025-11-30 * 时间:2025-11-30
*/ */
public class ScheduleOperationService { public class ScheduleOperationService {
/** /**
* 移动工序方法 * 移动工序方法
* @param chromosome 染色体对象 * @param chromosome 染色体对象
...@@ -647,10 +650,20 @@ public class ScheduleOperationService { ...@@ -647,10 +650,20 @@ public class ScheduleOperationService {
decoder.decode(chromosome); decoder.decode(chromosome);
if(chromosome.getFitness()==0) { // if(chromosome.getWeightedObjective()==0) {
FitnessCalculator fitnessCalc = new FitnessCalculator(); //
chromosome.setFitness(fitnessCalc.calculateFitness(chromosome)); // double[] normalized = objectiveWeights.normalizeObjectives(chromosome.getObjectives(), null, null);
} // if (objectiveWeights.isPureNSGAIIMode()) {
// chromosome.setWeightedObjective(objectiveWeights.calculateObjective(normalized));
// } else {
// chromosome.setWeightedObjective(objectiveWeights.calculateWeightedObjective(normalized));
// }
// }
// if(chromosome.getFitness()==0) {
// FitnessCalculator fitnessCalc = new FitnessCalculator();
// chromosome.setFitness(fitnessCalc.calculateFitness(chromosome));
// }
} }
} }
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