Commit f30098ce authored by Tong Li's avatar Tong Li

目标kpi可配置

parent e9d075e2
...@@ -2,6 +2,11 @@ package com.aps.entity.basic; ...@@ -2,6 +2,11 @@ package com.aps.entity.basic;
import lombok.Data; import lombok.Data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* 作者:佟礼 * 作者:佟礼
* 时间:2025-11-21 * 时间:2025-11-21
...@@ -43,4 +48,122 @@ public class GlobalParam { ...@@ -43,4 +48,122 @@ public class GlobalParam {
private boolean _smoothChangeOver = true; // 默认true,设置时间 是否考虑换型时间 private boolean _smoothChangeOver = true; // 默认true,设置时间 是否考虑换型时间
private boolean _smoothChangeOverInWeek = true; // 默认true,后台任务设置 休息时间是否换型 private boolean _smoothChangeOverInWeek = true; // 默认true,后台任务设置 休息时间是否换型
/**
* NSGA-II模式:true=纯帕累托(无视权重),false=加权帕累托
*/
private boolean pureNSGAIIMode = true;
/// <summary>
/// 目标值配置列表:包含目标值的名称、是否启用、层级和权重
/// </summary>
private List<ObjectiveConfig> objectiveConfigs = new ArrayList<>();
/// <summary>
/// 目标值名称常量
/// </summary>
public static final String OBJECTIVE_MAKESPAN = "makespan"; // 最早完工时间
public static final String OBJECTIVE_FLOW_TIME = "flowTime"; // 总流程时间
public static final String OBJECTIVE_SETUP_TIME = "setupTime"; // 总换型时间
public static final String OBJECTIVE_MACHINE_LOAD = "machineLoad"; // 机器负载均衡
public static final String OBJECTIVE_TARDINESS = "tardiness"; // 延迟时间
/// <summary>
/// 构造函数,初始化默认值
/// </summary>
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_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));
}
/// <summary>
/// 获取目标值启用状态
/// </summary>
public Map<String, Boolean> getObjectiveEnabled() {
Map<String, Boolean> enabledMap = new HashMap<>();
for (ObjectiveConfig config : objectiveConfigs) {
enabledMap.put(config.getName(), config.isEnabled());
}
return enabledMap;
}
/// <summary>
/// 获取目标值层级
/// </summary>
public Map<String, Integer> getObjectiveLevels() {
Map<String, Integer> levelsMap = new HashMap<>();
for (ObjectiveConfig config : objectiveConfigs) {
levelsMap.put(config.getName(), config.getLevel());
}
return levelsMap;
}
/// <summary>
/// 获取目标值顺序
/// </summary>
public List<String> getObjectiveOrder() {
List<String> orderList = new ArrayList<>();
for (ObjectiveConfig config : objectiveConfigs) {
orderList.add(config.getName());
}
return orderList;
}
/// <summary>
/// 获取目标值权重
/// </summary>
public Map<String, Double> getObjectiveWeights() {
Map<String, Double> weightsMap = new HashMap<>();
for (ObjectiveConfig config : objectiveConfigs) {
if(config.isEnabled()) {
weightsMap.put(config.getName(), config.getWeight());
}
}
return weightsMap;
}
/// <summary>
/// 根据名称获取目标值配置
/// </summary>
public ObjectiveConfig getObjectiveConfig(String name) {
for (ObjectiveConfig config : objectiveConfigs) {
if (config.getName().equals(name)) {
return config;
}
}
return null;
}
/// <summary>
/// 添加目标值配置
/// </summary>
public void addObjectiveConfig(ObjectiveConfig config) {
objectiveConfigs.add(config);
}
/// <summary>
/// 更新目标值配置
/// </summary>
public void updateObjectiveConfig(String name, ObjectiveConfig config) {
for (int i = 0; i < objectiveConfigs.size(); i++) {
if (objectiveConfigs.get(i).getName().equals(name)) {
objectiveConfigs.set(i, config);
return;
}
}
}
/// <summary>
/// 移除目标值配置
/// </summary>
public void removeObjectiveConfig(String name) {
objectiveConfigs.removeIf(config -> config.getName().equals(name));
}
} }
package com.aps.entity.basic;
import lombok.Data;
/**
* 目标值配置实体类
* 作者:佟礼
* 时间:2026-03-17
*/
@Data
public class ObjectiveConfig {
/**
* 目标值名称
*/
private String name;
/**
* 是否启用
*/
private boolean enabled;
/**
* 层级,层级越低优先级越高,1为最高
*/
private int level;
/**
* 权重
*/
private double weight;
/**
* 构造函数
*/
public ObjectiveConfig() {
}
/**
* 构造函数
*/
public ObjectiveConfig(String name, boolean enabled, int level, double weight) {
this.name = name;
this.enabled = enabled;
this.level = level;
this.weight = weight;
}
}
\ No newline at end of file
...@@ -65,14 +65,10 @@ public class GeneticAlgorithm { ...@@ -65,14 +65,10 @@ public class GeneticAlgorithm {
materialIds=_materialIds; materialIds=_materialIds;
} }
public void Init(double[] customWeights, boolean pureNSGAIIMode) { public void Init() {
// 自定义权重配置 // 自定义权重配置
if (customWeights != null && customWeights.length == 5)
{ _nsgaIIUtils.init(_GlobalParam);
_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) {
......
...@@ -1759,73 +1759,91 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -1759,73 +1759,91 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
private void calculateScheduleResult(Chromosome chromosome) { private void calculateScheduleResult(Chromosome chromosome) {
// 1. 最早完工时间(最小化) double[] Objectives=new double[_globalParam.getObjectiveWeights().size()];
double makespan = chromosome.getResult().stream()
.mapToInt(GAScheduleResult::getEndTime) int i=0;
.max() for (ObjectiveConfig config : _globalParam.getObjectiveConfigs()) {
.orElse(0); if( config.isEnabled())
{
// 2. 交付期满足情况(最小化延迟) if(config.getName()==GlobalParam.OBJECTIVE_MAKESPAN)
double tardiness = 0; {
// 1. 最早完工时间(最小化)
Map<Integer, List<GAScheduleResult>> orderGroups = chromosome.getResult().stream() double makespan = chromosome.getResult().stream()
.collect(Collectors.groupingBy(GAScheduleResult::getGroupId)); .mapToInt(GAScheduleResult::getEndTime)
.max()
for (Map.Entry<Integer, List<GAScheduleResult>> group : orderGroups.entrySet()) { .orElse(0);
int groupId = group.getKey(); Objectives[i]=makespan;
int orderCompletion = group.getValue().stream() chromosome.setMakespan(makespan);
.mapToInt(GAScheduleResult::getEndTime) }
.max() if(config.getName()==GlobalParam.OBJECTIVE_TARDINESS)
.orElse(0); {
List<String> orderIds = group.getValue().stream() // 2. 交付期满足情况(最小化延迟)
.map(GAScheduleResult::getOrderId) double tardiness = 0;
.distinct()
.sorted() Map<Integer, List<GAScheduleResult>> orderGroups = chromosome.getResult().stream()
.collect(Collectors.toList()); .collect(Collectors.groupingBy(GAScheduleResult::getGroupId));
Order order = chromosome.getOrders().stream()
.filter(t->orderIds.contains(t.getOrderId())) for (Map.Entry<Integer, List<GAScheduleResult>> group : orderGroups.entrySet()) {
.max(Comparator.comparing(Order::getDueDate)) int groupId = group.getKey();
.orElse(null); int orderCompletion = group.getValue().stream()
if(order.isNewCreate()) .mapToInt(GAScheduleResult::getEndTime)
{continue;} .max()
LocalDateTime dueDateTime=order.getDueDate(); .orElse(0);
List<String> orderIds = group.getValue().stream()
.map(GAScheduleResult::getOrderId)
.distinct()
LocalDateTime completionTime =baseTime.plusSeconds(orderCompletion); .sorted()
.collect(Collectors.toList());
Order order = chromosome.getOrders().stream()
if (completionTime.isAfter(dueDateTime)) { .filter(t->orderIds.contains(t.getOrderId()))
// 计算延迟小时数(修复时间计算) .max(Comparator.comparing(Order::getDueDate))
long hours = ChronoUnit.HOURS.between(dueDateTime, completionTime); .orElse(null);
long minutes = ChronoUnit.MINUTES.between(dueDateTime, completionTime) % 60; if(order.isNewCreate())
tardiness += hours*60 + (double) minutes ; {continue;}
} LocalDateTime dueDateTime=order.getDueDate();
LocalDateTime completionTime =baseTime.plusSeconds(orderCompletion);
if (completionTime.isAfter(dueDateTime)) {
// 计算延迟小时数(修复时间计算)
long hours = ChronoUnit.HOURS.between(dueDateTime, completionTime);
long minutes = ChronoUnit.MINUTES.between(dueDateTime, completionTime) % 60;
tardiness += hours*60 + (double) minutes ;
}
}
Objectives[i]=tardiness;
chromosome.setDelayTime(tardiness);
}
if(config.getName()==GlobalParam.OBJECTIVE_SETUP_TIME)
{
// 3. 最小总换型时间
double totalSetupTime = calculateTotalSetupTime(chromosome);
chromosome.setTotalChangeoverTime(totalSetupTime);
Objectives[i]=totalSetupTime;
}
if(config.getName()==GlobalParam.OBJECTIVE_FLOW_TIME)
{
// 4. 最小化总流程时间 所有工序加工时间的总和
double totalFlowTime = calculateTotalFlowTime(chromosome);
chromosome.setTotalFlowTime(totalFlowTime);
Objectives[i]=totalFlowTime;
}
if(config.getName()==GlobalParam.OBJECTIVE_MACHINE_LOAD)
{
// 5. 机器负载均衡
double machineLoadBalance = calculateMachineLoadBalance(chromosome);
chromosome.setMachineLoadStd(machineLoadBalance);
Objectives[i]=machineLoadBalance;
}
i++;
}
} }
// 3. 最小总换型时间
double totalSetupTime = calculateTotalSetupTime(chromosome);
// 4. 最小化总流程时间 所有工序加工时间的总和
double totalFlowTime = calculateTotalFlowTime(chromosome);
// 5. 机器负载均衡
double machineLoadBalance = calculateMachineLoadBalance(chromosome);
// 存储各目标值
chromosome.setMakespan(makespan);
chromosome.setTotalFlowTime(totalFlowTime);
chromosome.setTotalChangeoverTime(totalSetupTime);
chromosome.setMachineLoadStd(machineLoadBalance);
chromosome.setDelayTime(tardiness);
double[] Objectives=new double[5];
Objectives[0] = makespan;
Objectives[1] = totalFlowTime;
Objectives[2] = totalSetupTime;
Objectives[3] = machineLoadBalance;
Objectives[4] = tardiness;
chromosome.setObjectives(Objectives); chromosome.setObjectives(Objectives);
} }
......
...@@ -3,14 +3,12 @@ package com.aps.service.Algorithm; ...@@ -3,14 +3,12 @@ package com.aps.service.Algorithm;
import com.aps.common.util.FileHelper; import com.aps.common.util.FileHelper;
import com.aps.entity.Algorithm.Chromosome; import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.ObjectiveWeights; import com.aps.entity.Algorithm.ObjectiveWeights;
import com.aps.entity.basic.GlobalParam;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
/** /**
...@@ -19,31 +17,56 @@ import java.util.stream.IntStream; ...@@ -19,31 +17,56 @@ import java.util.stream.IntStream;
public class NSGAIIUtils { public class NSGAIIUtils {
private ObjectiveWeights objectiveWeights; private ObjectiveWeights objectiveWeights;
private int taskCount; // 并行任务数(默认=CPU核心数) private int taskCount; // 并行任务数(默认=CPU核心数)
private GlobalParam globalParam; // 全局参数配置
// true 越小越好 // true 越小越好
private boolean[] isMinimize = {true, true, true, true, true}; private boolean[] isMinimize = {true, true, true, true, true};
public void init(ObjectiveWeights weights, int taskCount,boolean[] isMinimize) {
this.objectiveWeights = (weights != null) ? weights : new ObjectiveWeights();
this.taskCount = (taskCount > 0) ? taskCount : Runtime.getRuntime().availableProcessors()-1;
this.isMinimize=isMinimize;
}
/** /**
* 初始化(设置权重和并行任务数) * 初始化(设置权重和并行任务数)
*/ */
public void init(ObjectiveWeights weights, int taskCount) { public void init(GlobalParam globalParam, int taskCount) {
this.objectiveWeights = (weights != null) ? weights : new ObjectiveWeights(); this.globalParam = globalParam;
this.objectiveWeights = (globalParam.getObjectiveWeights() != null) ? buildObjectiveWeightsFromGlobalParam() : new ObjectiveWeights();
this.taskCount = (taskCount > 0) ? taskCount : Runtime.getRuntime().availableProcessors()-1; this.taskCount = (taskCount > 0) ? taskCount : Runtime.getRuntime().availableProcessors()-1;
} }
/** /**
* 重载初始化方法(默认任务数) * 重载初始化方法(默认任务数)
*/ */
public void init(ObjectiveWeights weights) { public void init(GlobalParam globalParam) {
init(weights, 0); init(globalParam, 0);
} }
/**
* 从 globalParam 构建 ObjectiveWeights
*/
private ObjectiveWeights buildObjectiveWeightsFromGlobalParam() {
ObjectiveWeights weights = new ObjectiveWeights();
// 设置 pureNSGAIIMode
if (globalParam != null) {
weights.setPureNSGAIIMode(globalParam.isPureNSGAIIMode());
// 按照固定顺序构建权重数组
Map<String, Double> objectiveWeights = globalParam.getObjectiveWeights();
double[] weightsArray = new double[objectiveWeights.size()];
int i=0;
for (Double weight : objectiveWeights.values()) {
weightsArray[i]= weight;
i++;
}
weights.setWeights(weightsArray);
}
return weights;
}
/** /**
* 并行快速非支配排序(大规模种群提速50%+) * 并行快速非支配排序(大规模种群提速50%+)
...@@ -65,57 +88,75 @@ public class NSGAIIUtils { ...@@ -65,57 +88,75 @@ public class NSGAIIUtils {
// 步骤2:拆分种群为多个块,并行计算支配关系 // 步骤2:拆分种群为多个块,并行计算支配关系
List<List<Chromosome>> chunks = splitPopulation(population, chunkCount); List<List<Chromosome>> chunks = splitPopulation(population, chunkCount);
Map<Chromosome, List<Chromosome>> dominanceMatrix = new HashMap<>(); // Map<Chromosome, List<Chromosome>> dominanceMatrix = new HashMap<>();
Map<Chromosome, Integer> dominatedCount = new HashMap<>(); // Map<Chromosome, Integer> dominatedCount = new HashMap<>();
ConcurrentHashMap<Chromosome, ConcurrentLinkedQueue<Chromosome>> dominanceMatrix = new ConcurrentHashMap<>();
ConcurrentHashMap<Chromosome, AtomicInteger> dominatedCount = new ConcurrentHashMap<>();
for (Chromosome chromo : population) { for (Chromosome chromo : population) {
dominanceMatrix.put(chromo, new ArrayList<>()); // dominanceMatrix.put(chromo, new ArrayList<>());
dominatedCount.put(chromo, 0); // dominatedCount.put(chromo, 0);
dominanceMatrix.putIfAbsent(chromo, new ConcurrentLinkedQueue<>());
dominatedCount.putIfAbsent(chromo, new AtomicInteger(0));
} }
ExecutorService executor = Executors.newFixedThreadPool(chunkCount); // ExecutorService executor = Executors.newFixedThreadPool(chunkCount);
try { // try {
List<Future<?>> futures = new ArrayList<>(); // 存储任务Future,确保全量等待 // List<Future<?>> futures = new ArrayList<>(); // 存储任务Future,确保全量等待
for (List<Chromosome> chunk : chunks) { // for (List<Chromosome> chunk : chunks) {
futures.add(executor.submit(() -> { // futures.add(executor.submit(() -> {
for (Chromosome p : chunk) { // for (Chromosome p : chunk) {
for (Chromosome q : population) { // for (Chromosome q : population) {
if (p == q) continue; // if (p == q) continue;
if (dominates(p, q)) { // if (dominates(p, q)) {
synchronized (dominanceMatrix.get(p)) { // 细粒度锁 // synchronized (dominanceMatrix.get(p)) { // 细粒度锁
dominanceMatrix.get(p).add(q); // dominanceMatrix.get(p).add(q);
} // }
} else if (dominates(q, p)) { // } else if (dominates(q, p)) {
synchronized (dominatedCount) { // synchronized (dominatedCount) {
dominatedCount.put(p, dominatedCount.get(p) + 1); // 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(); // 确保线程池关闭
// }
// }
// 并行计算支配关系
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();
} }
}));
}
// 核心修复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(); // 确保线程池关闭
}
}
// 生成前沿 // 生成前沿
// 染色体 -> 数组下标的映射表 // 染色体 -> 数组下标的映射表
...@@ -124,6 +165,7 @@ public class NSGAIIUtils { ...@@ -124,6 +165,7 @@ public class NSGAIIUtils {
// 新增:支配矩阵数组化 - 每个p的下标,对应一个存储q下标的List // 新增:支配矩阵数组化 - 每个p的下标,对应一个存储q下标的List
List<List<Integer>> dominanceMatrixArr = new ArrayList<>(popSize); List<List<Integer>> dominanceMatrixArr = new ArrayList<>(popSize);
// ======== 修复空指针的核心行:循环popSize次,给每个索引塞一个空的ArrayList ======== // ======== 修复空指针的核心行:循环popSize次,给每个索引塞一个空的ArrayList ========
//初始化每个位置的空列表
for (int idx = 0; idx < popSize; idx++) { for (int idx = 0; idx < popSize; idx++) {
dominanceMatrixArr.add(new ArrayList<>()); // 必须加这行,初始化每个位置的空列表 dominanceMatrixArr.add(new ArrayList<>()); // 必须加这行,初始化每个位置的空列表
Chromosome c = population.get(idx); Chromosome c = population.get(idx);
...@@ -133,16 +175,28 @@ public class NSGAIIUtils { ...@@ -133,16 +175,28 @@ public class NSGAIIUtils {
for (int idx = 0; idx < popSize; idx++) { for (int idx = 0; idx < popSize; idx++) {
Chromosome c = population.get(idx); Chromosome c = population.get(idx);
dominatedCounts[idx] = dominatedCount.get(c); // dominatedCounts[idx] = dominatedCount.get(c);
// 把HashMap的支配列表,转成q的下标列表,存入数组 // // 把HashMap的支配列表,转成q的下标列表,存入数组
List<Chromosome> qList = dominanceMatrix.get(c); // List<Chromosome> qList = dominanceMatrix.get(c);
List<Integer> qIdxList = dominanceMatrixArr.get(idx); // 此时get(idx)绝对非空! // List<Integer> qIdxList = dominanceMatrixArr.get(idx); // 此时get(idx)绝对非空!
for (Chromosome q : qList) { // for (Chromosome q : qList) {
// Integer qIdx = chromosomeIndexMap.get(q);
// if(qIdx != null){ // 额外兜底:防止q是null导致的空指针
// qIdxList.add(qIdx);
// }
// }
dominatedCounts[idx] = dominatedCount.get(c).get();
// 把ConcurrentHashMap的支配队列,转成q的下标列表,存入数组
ConcurrentLinkedQueue<Chromosome> qQueue = dominanceMatrix.get(c);
List<Integer> qIdxList = dominanceMatrixArr.get(idx);
for (Chromosome q : qQueue) {
Integer qIdx = chromosomeIndexMap.get(q); Integer qIdx = chromosomeIndexMap.get(q);
if(qIdx != null){ // 额外兜底:防止q是null导致的空指针 if(qIdx != null){ // 额外兜底:防止q是null导致的空指针
qIdxList.add(qIdx); qIdxList.add(qIdx);
} }
} }
} }
// ========== 初始化前沿列表,必须先添加F1(第一个前沿) ========== // ========== 初始化前沿列表,必须先添加F1(第一个前沿) ==========
...@@ -150,7 +204,9 @@ public class NSGAIIUtils { ...@@ -150,7 +204,9 @@ public class NSGAIIUtils {
// 遍历种群,找到所有被支配数=0的个体 → 这就是F1,绝对不被任何个体支配的最优解 // 遍历种群,找到所有被支配数=0的个体 → 这就是F1,绝对不被任何个体支配的最优解
for (Chromosome chromosome : population) { for (Chromosome chromosome : population) {
if (chromosome == null) continue; if (chromosome == null) continue;
int count = dominatedCount.getOrDefault(chromosome, 0); // int count = dominatedCount.getOrDefault(chromosome, 0);
int count = dominatedCount.getOrDefault(chromosome, new AtomicInteger(0)).get();
if (count == 0) { if (count == 0) {
firstFront.add(chromosome); firstFront.add(chromosome);
} }
...@@ -375,22 +431,22 @@ public class NSGAIIUtils { ...@@ -375,22 +431,22 @@ public class NSGAIIUtils {
*/ */
private void preprocessObjectives(List<Chromosome> population) { private void preprocessObjectives(List<Chromosome> population) {
int kpisize = population.get(0).getObjectives().length; int kpiSize = population.get(0).getObjectives().length;
// 计算每个目标的最大/最小值 // 计算每个目标的最大/最小值
double[] minValues = new double[kpisize]; double[] minValues = new double[kpiSize];
double[] maxValues = new double[kpisize]; double[] maxValues = new double[kpiSize];
// for (int i = 0; i < kpisize; i++) { // for (int i = 0; i < kpisize; i++) {
// final int idx = i; // final int idx = i;
// minValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).min().orElse(0); // minValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).min().orElse(0);
// maxValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).max().orElse(0); // maxValues[i] = population.stream().mapToDouble(c -> c.getObjectives()[idx]).max().orElse(0);
// } // }
for (int i = 0; i < kpisize; i++) { for (int i = 0; i < kpiSize; i++) {
minValues[i] = Double.MAX_VALUE; minValues[i] = Double.MAX_VALUE;
maxValues[i] = Double.MIN_VALUE; maxValues[i] = Double.MIN_VALUE;
} }
for (Chromosome chromo : population) { for (Chromosome chromo : population) {
double[] obj = chromo.getObjectives(); double[] obj = chromo.getObjectives();
for (int i = 0; i < kpisize; i++) { for (int i = 0; i < kpiSize; i++) {
minValues[i] = Math.min(minValues[i], obj[i]); minValues[i] = Math.min(minValues[i], obj[i]);
maxValues[i] = Math.max(maxValues[i], obj[i]); maxValues[i] = Math.max(maxValues[i], obj[i]);
} }
...@@ -400,6 +456,7 @@ public class NSGAIIUtils { ...@@ -400,6 +456,7 @@ public class NSGAIIUtils {
population.parallelStream().forEach(chromo -> { population.parallelStream().forEach(chromo -> {
double[] normalized = objectiveWeights.normalizeObjectives(chromo.getObjectives(), minValues, maxValues,this.isMinimize); double[] normalized = objectiveWeights.normalizeObjectives(chromo.getObjectives(), minValues, maxValues,this.isMinimize);
chromo.setMaxObjectives(maxValues); chromo.setMaxObjectives(maxValues);
chromo.setMinObjectives(minValues); chromo.setMinObjectives(minValues);
chromo.setWeightedObjectives(normalized); chromo.setWeightedObjectives(normalized);
...@@ -434,6 +491,11 @@ public class NSGAIIUtils { ...@@ -434,6 +491,11 @@ public class NSGAIIUtils {
// 纯NSGA-II模式:标准帕累托支配 // 纯NSGA-II模式:标准帕累托支配
double[] pObjectives = p.getWeightedObjectives(); double[] pObjectives = p.getWeightedObjectives();
double[] qObjectives = q.getWeightedObjectives(); double[] qObjectives = q.getWeightedObjectives();
// 如果启用了目标层级,则使用层级排序
// if (globalParam != null && globalParam.getObjectiveLevels() != null) {
// return dominatesWithLevels(p, q, pObjectives, qObjectives);
// }
if (objectiveWeights.isPureNSGAIIMode()) { if (objectiveWeights.isPureNSGAIIMode()) {
boolean hasBetter = false; // 是否至少有一个目标更优 boolean hasBetter = false; // 是否至少有一个目标更优
boolean hasWorse = false; // 是否有任何一个目标更差 boolean hasWorse = false; // 是否有任何一个目标更差
...@@ -478,6 +540,74 @@ public class NSGAIIUtils { ...@@ -478,6 +540,74 @@ public class NSGAIIUtils {
return hasBetterScore && hasAtLeastOneNotWorse; return hasBetterScore && hasAtLeastOneNotWorse;
} }
} }
/**
* 基于目标层级的支配关系判断
*/
private boolean dominatesWithLevels(Chromosome p, Chromosome q, double[] pObjectives, double[] qObjectives) {
// 获取启用的目标及其层级
Map<String, Integer> objectiveLevels = globalParam.getObjectiveLevels();
List<String> objectiveOrder = globalParam.getObjectiveOrder();
List<String> enabledObjectives = new ArrayList<>();
Map<String, Integer> levelMap = new HashMap<>();
// 构建启用的目标列表和层级映射
int objIndex = 0;
for (String objectiveName : objectiveOrder) {
if (globalParam.getObjectiveEnabled().getOrDefault(objectiveName, true)) {
enabledObjectives.add(objectiveName);
levelMap.put(objectiveName, objectiveLevels.getOrDefault(objectiveName, 1));
objIndex++;
}
}
// 按层级从低到高排序,层级越低优先级越高
List<Integer> sortedLevels = new ArrayList<>(new HashSet<>(levelMap.values()));
sortedLevels.sort(Comparator.naturalOrder());
// 遍历每个层级
for (int level : sortedLevels) {
// 获取当前层级的所有目标名称
List<String> levelObjectives = new ArrayList<>();
for (Map.Entry<String, Integer> entry : levelMap.entrySet()) {
if (entry.getValue() == level) {
levelObjectives.add(entry.getKey());
}
}
// 比较当前层级的目标值
boolean hasBetter = false;
boolean hasWorse = false;
for (String objectiveName : levelObjectives) {
int objIdx = enabledObjectives.indexOf(objectiveName);
if (objIdx < 0 || objIdx >= pObjectives.length || objIdx >= qObjectives.length) {
continue;
}
double thisObj = pObjectives[objIdx];
double otherObj = qObjectives[objIdx];
// 目标越大越好:当前解 > 另一个解 → 更优
if (thisObj > otherObj) {
hasBetter = true;
}
// 当前解 < 另一个解 → 更差
else if (thisObj < otherObj) {
hasWorse = true;
}
}
// 如果当前层级有差异,则根据差异判断支配关系
if (hasBetter && !hasWorse) {
return true;
} else if (hasWorse) {
return false;
}
// 如果当前层级无差异,则继续比较下一层级
}
// 所有层级都无差异,不支配
return false;
}
/** /**
* 并行计算拥挤距离 * 并行计算拥挤距离
...@@ -547,6 +677,16 @@ public class NSGAIIUtils { ...@@ -547,6 +677,16 @@ public class NSGAIIUtils {
} }
return Math.sqrt(sum); // 开平方得到欧氏距离 return Math.sqrt(sum); // 开平方得到欧氏距离
} }
// 考虑使用标准化欧氏距离
private double calculateNormalizedEuclideanDistance(double[] objectives, double[] idealPoint, double[] maxValues, double[] minValues) {
double sum = 0.0;
for (int i = 0; i < objectives.length; i++) {
double range = maxValues[i] - minValues[i];
double normalizedDiff = range > 0 ? (objectives[i] - idealPoint[i]) / range : 0;
sum += normalizedDiff * normalizedDiff;
}
return Math.sqrt(sum);
}
/** /**
* 选择下一代种群(兼容并行计算) * 选择下一代种群(兼容并行计算)
...@@ -576,11 +716,11 @@ public class NSGAIIUtils { ...@@ -576,11 +716,11 @@ public class NSGAIIUtils {
public void Test() { public void Test() {
ObjectiveWeights weights = new ObjectiveWeights(); GlobalParam globalParam1 = new GlobalParam();
double[] weightvs = new double[] { 0.5, 0.5 };
weights.setWeights(weightvs);
weights.setPureNSGAIIMode(false); globalParam1.setPureNSGAIIMode(false);
init(weights); init(globalParam1);
List<Chromosome> chromosomeList = new ArrayList<>(); List<Chromosome> chromosomeList = new ArrayList<>();
Chromosome chromosome1 = new Chromosome(); Chromosome chromosome1 = new Chromosome();
chromosome1.setID("A"); chromosome1.setID("A");
......
...@@ -208,13 +208,14 @@ public class PlanResultService { ...@@ -208,13 +208,14 @@ public class PlanResultService {
.map(Material::getId) .map(Material::getId)
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
globalParam.setPureNSGAIIMode(false);
// 5. 执行调度算法 // 5. 执行调度算法
GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,Materials1,materialIds,machineScheduler,entryRel,materialRequirementService,_sceneService,SceneId); //new GeneticAlgorithm(products, machines, orders, machineScheduler); GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,Materials1,materialIds,machineScheduler,entryRel,materialRequirementService,_sceneService,SceneId); //new GeneticAlgorithm(products, machines, orders, machineScheduler);
param.initAdaptiveParams(entrys.size()); param.initAdaptiveParams(entrys.size());
double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5 double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间 //完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
scheduler.Init(customWeights,false); scheduler.Init();
// scheduler.Init(customWeights,false);
Chromosome chromosome =scheduler.Run(param,entrys); Chromosome chromosome =scheduler.Run(param,entrys);
KpiCalculator kpiCalculator=new KpiCalculator(chromosome); KpiCalculator kpiCalculator=new KpiCalculator(chromosome);
...@@ -770,7 +771,8 @@ public class PlanResultService { ...@@ -770,7 +771,8 @@ public class PlanResultService {
param.initAdaptiveParams(entrys.size()); param.initAdaptiveParams(entrys.size());
double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5 double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间 //完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
scheduler.Init(customWeights,false); // scheduler.Init(customWeights,false);
scheduler.Init();
Chromosome chromosomes =scheduler.Run(param,entrys); Chromosome chromosomes =scheduler.Run(param,entrys);
KpiCalculator kpiCalculator=new KpiCalculator(chromosomes); KpiCalculator kpiCalculator=new KpiCalculator(chromosomes);
kpiCalculator.calculatekpi(); kpiCalculator.calculatekpi();
......
package com.aps.demo;
import com.aps.service.Algorithm.NSGAIIUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
* 作者:佟礼
* 时间:2026-03-17
*/
@SpringBootTest
public class NSGAIIUtilsTest {
private NSGAIIUtils _nsgaIIUtils = new NSGAIIUtils();
@Test
public void test() {
_nsgaIIUtils.Test();
}
}
...@@ -39,7 +39,7 @@ public class PlanResultServiceTest { ...@@ -39,7 +39,7 @@ public class PlanResultServiceTest {
// TestSortService sortService=new TestSortService(); // TestSortService sortService=new TestSortService();
// sortService.test1(); // sortService.test1();
// nsgaiiUtils.Test(); // nsgaiiUtils.Test();
planResultService.execute2("5475E00B844847ACB6DC20227967BA2F"); planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D"); // planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
// planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2"); // planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2");
......
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