Commit 47286670 authored by Tong Li's avatar Tong Li

算法优化

parent e56eef9d
...@@ -23,7 +23,7 @@ public class Chromosome { ...@@ -23,7 +23,7 @@ public class Chromosome {
private String ID = UUID.randomUUID().toString(); private String ID = UUID.randomUUID().toString();
private String generateType;
private Integer version=0; private Integer version=0;
...@@ -117,6 +117,12 @@ public class Chromosome { ...@@ -117,6 +117,12 @@ public class Chromosome {
*/ */
private double[] WeightedObjectives;//越靠近1越优 private double[] WeightedObjectives;//越靠近1越优
private double WeightedObjective =0; // 加权目标值(用于自定义权重) private double WeightedObjective =0; // 加权目标值(用于自定义权重)
/// <summary>
/// 适应度值
/// </summary>
private double[] fitnessLevel;
/// <summary> /// <summary>
/// 适应度值 /// 适应度值
/// </summary> /// </summary>
......
...@@ -2,10 +2,7 @@ package com.aps.entity.basic; ...@@ -2,10 +2,7 @@ package com.aps.entity.basic;
import lombok.Data; import lombok.Data;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* 作者:佟礼 * 作者:佟礼
...@@ -81,6 +78,8 @@ public class GlobalParam { ...@@ -81,6 +78,8 @@ public class GlobalParam {
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_SETUP_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_MACHINE_LOAD, false, 3, 0.1));
objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_TARDINESS, true, 1, 0.3)); objectiveConfigs.add(new ObjectiveConfig(OBJECTIVE_TARDINESS, true, 1, 0.3));
objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel()));
} }
/// <summary> /// <summary>
...@@ -146,6 +145,8 @@ public class GlobalParam { ...@@ -146,6 +145,8 @@ public class GlobalParam {
/// </summary> /// </summary>
public void addObjectiveConfig(ObjectiveConfig config) { public void addObjectiveConfig(ObjectiveConfig config) {
objectiveConfigs.add(config); objectiveConfigs.add(config);
objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel()));
} }
/// <summary> /// <summary>
...@@ -158,6 +159,8 @@ public class GlobalParam { ...@@ -158,6 +159,8 @@ public class GlobalParam {
return; return;
} }
} }
objectiveConfigs.sort(Comparator.comparing((ObjectiveConfig op) -> op.getLevel()));
} }
/// <summary> /// <summary>
......
...@@ -18,6 +18,11 @@ public class ObjectiveConfig { ...@@ -18,6 +18,11 @@ public class ObjectiveConfig {
*/ */
private boolean enabled; private boolean enabled;
/**
* 越小越好
*/
private boolean isMinimize;
/** /**
* 层级,层级越低优先级越高,1为最高 * 层级,层级越低优先级越高,1为最高
*/ */
...@@ -28,6 +33,11 @@ public class ObjectiveConfig { ...@@ -28,6 +33,11 @@ public class ObjectiveConfig {
*/ */
private double weight; private double weight;
/**
* 值
*/
private double val;
/** /**
* 构造函数 * 构造函数
*/ */
......
...@@ -2,7 +2,10 @@ package com.aps.service.Algorithm; ...@@ -2,7 +2,10 @@ package com.aps.service.Algorithm;
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 com.aps.entity.basic.ObjectiveConfig;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
...@@ -10,6 +13,84 @@ import java.util.List; ...@@ -10,6 +13,84 @@ import java.util.List;
* 时间:2025-11-24 * 时间:2025-11-24
*/ */
public class FitnessCalculator { public class FitnessCalculator {
/**
* 多目标适应度计算(加权求和)
*/
public double[] calculateFitness(Chromosome chromosome, GlobalParam param) {
ArrayList<Double> list = new ArrayList<>();
double fitness=0;
int i=0;
int level=-1;
for (ObjectiveConfig config : param.getObjectiveConfigs()) {
if( config.isEnabled()) {
if(level==-1)
{
level=config.getLevel();
}else if(level!=config.getLevel())
{
list.add(fitness);
fitness=0;
level=config.getLevel();
}
double obj = chromosome.getObjectives()[i];
// 防御:处理负数(目标值应为非负,若为负则兜底为0)
obj = Math.max(0, obj);
//转化为0,1 越靠近1 越优
double val = 0;
if (config.isMinimize()) {
// ============================
// 最小化目标:越小越优 → 归一化后越大越优,越优
// ============================
//0/1+ 0 =0 min max 最优
//1/1+ 1 =0.5 min max 最优
//1/1+ 2 =0.33
//1/1+ 3 =0.25
val = 1.0 / (1.0 + obj);
} else {
// ============================
// 最大化目标:越大越优 → 反转成 越大越优
// ============================
// 1/1+ 1 = 0.5
// 2/1+ 2 = 0.66
// 3/1+ 3 = 0.75 max max 最优
val = obj / (1.0 + obj);
}
// 兜底:避免极端情况归一化值为0(最小设为1e-6)
// val = Math.max(val, 1e-6);
if (!param.isPureNSGAIIMode()) {
val = val * config.getWeight();
}
fitness += val;
i++;
}
}
list.add(fitness);
// 归一化(假设最大可能值,实际应根据问题规模调整)
// makespan = 10 → val = 1/11 = 0.09
// makespan = 20 → val = 1/21 = 0.045
// makespan = 100 → val = 1/101 = 0.009
// 值越大 归一化 后越小, 越大越好
//原目标(工期、延迟、负载)越小 → 生产越好
//原目标越小,归一化后 → f1、f2、f3 越大
// 方案 A:工期短、延迟小 → 很好
// makespan=10 → f1=1/(11)=0.09
// fitness ≈ 0.08
// 方案 B:工期长、延迟大 → 很差
// makespan=100 → f1=1/(101)=0.009
// fitness ≈ 0.01
// 适应度值(越大越好)
return list.stream().mapToDouble(Double::doubleValue).toArray();
}
/** /**
* 多目标适应度计算(加权求和) * 多目标适应度计算(加权求和)
*/ */
...@@ -29,11 +110,25 @@ public class FitnessCalculator { ...@@ -29,11 +110,25 @@ public class FitnessCalculator {
// 1/1+1 0.5 // 1/1+1 0.5
// 1/1+2 0.3 // 1/1+2 0.3
// 1/1+3 0.25 // 1/1+3 0.25
// 值越大 归一化 后越小
// makespan = 10 → val = 1/11 = 0.09
// makespan = 20 → val = 1/21 = 0.045
// makespan = 100 → val = 1/101 = 0.009
// 值越大 归一化 后越小, 越大越好
//原目标(工期、延迟、负载)越小 → 生产越好
//原目标越小,归一化后 → f1、f2、f3 越大
// 方案 A:工期短、延迟小 → 很好
// makespan=10 → f1=1/(11)=0.09
// fitness ≈ 0.08
// 方案 B:工期长、延迟大 → 很差
// makespan=100 → f1=1/(101)=0.009
// fitness ≈ 0.01
} }
// 适应度值(越大越好) // 适应度值(越大越好)
return fitness; return fitness;
} }
/** /**
* 计算种群适应度标准差(用于参数微调) * 计算种群适应度标准差(用于参数微调)
* @param population 染色体种群数组 * @param population 染色体种群数组
......
...@@ -21,9 +21,7 @@ import java.time.Duration; ...@@ -21,9 +21,7 @@ import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
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.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
...@@ -78,6 +76,36 @@ public class GeneticDecoder { ...@@ -78,6 +76,36 @@ public class GeneticDecoder {
// this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0); // this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
} }
private final ExecutorService decodeExecutor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors() - 1, // 核心线程数=CPU-1,无切换开销
Runtime.getRuntime().availableProcessors() - 1, // 最大线程数=核心数
0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(200), // 有界队列,避免内存溢出
new ThreadPoolExecutor.CallerRunsPolicy() // 任务满了主线程执行,不丢失任务
);
public void Chromosomedecode(List<Chromosome> population)
{
FileHelper.writeLogFile("解码---------------"+population.size() );
boolean ismore=false;
if(ismore) {
CompletableFuture.allOf(population.stream()
.map(chromosome -> CompletableFuture.runAsync(() -> decodeChromosomeWithCache(chromosome), decodeExecutor))
.toArray(CompletableFuture[]::new))
.join();
} else {
if (population != null && population.size() > 0) {
population.forEach(chromosome -> {
decodeChromosomeWithCache( chromosome);
});
}
}
}
// public Chromosome decodeChromosomeWithCache(Chromosome chromosome) { // public Chromosome decodeChromosomeWithCache(Chromosome chromosome) {
// String cacheKey = createCacheKey(chromosome); // String cacheKey = createCacheKey(chromosome);
// // FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey ); // // FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey );
...@@ -345,18 +373,18 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -345,18 +373,18 @@ if(finishedOrder==null||finishedOrder.size()==0)
// //
// // 根据工序数量和CPU核心数决定是否使用内部并行 // // 根据工序数量和CPU核心数决定是否使用内部并行
if (operationCount > 500 && cpuCores > 4) { if (operationCount > 500 && cpuCores > 4) {
// 使用并行处理 // 使用设备并行处理
FileHelper.writeLogFile("使用并行处理 _s"); // FileHelper.writeLogFile("使用并行处理 _s");
parallelDecodeByMachine(chromosome); parallelDecodeByMachine(chromosome);
FileHelper.writeLogFile("使用并行处理 _e"); // FileHelper.writeLogFile("使用并行处理 _e");
} }
// else { else {
// 使用串行处理 // 使用串行处理
// FileHelper.writeLogFile("使用串行处理 _s"); // FileHelper.writeLogFile("使用串行处理 _s");
// serialDecode(chromosome); serialDecode(chromosome);
// FileHelper.writeLogFile("使用串行处理 _e"); // FileHelper.writeLogFile("使用串行处理 _e");
//} }
} }
/** /**
* 染色体解码为调度方案 * 染色体解码为调度方案
...@@ -555,6 +583,8 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -555,6 +583,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>(); Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>();
Map<Long, Machine> machineIdMap = chromosome.getMachines().stream() Map<Long, Machine> machineIdMap = chromosome.getMachines().stream()
.collect(Collectors.toMap(Machine::getId, m -> m)); .collect(Collectors.toMap(Machine::getId, m -> m));
// 构建工序ID索引:opId -> Entry(O(1)查找)
Map<Integer, Entry> opIdIndex = buildOpIdIndex(chromosome);
for (GlobalOperationInfo globalOp : globalOpList) { for (GlobalOperationInfo globalOp : globalOpList) {
int globalOpId = globalOp.getGlobalOpId(); int globalOpId = globalOp.getGlobalOpId();
...@@ -590,7 +620,8 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -590,7 +620,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
FileHelper.writeLogFile("预处理工序信息 _s"); FileHelper.writeLogFile("预处理工序信息 _s");
// 预处理工序信息 // 预处理工序信息
for (int opId : topologicalOrder) { for (int opId : topologicalOrder) {
Entry op = findOperationById(chromosome, opId); // Entry op = findOperationById(chromosome, opId);
Entry op = opIdIndex.get(opId);
if (op != null) { if (op != null) {
// 假设已经为工序分配了设备 // 假设已经为工序分配了设备
...@@ -610,7 +641,8 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -610,7 +641,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
FileHelper.writeLogFile("并行处理 _s"); FileHelper.writeLogFile("并行处理 _s");
for (int opId : topologicalOrder) { for (int opId : topologicalOrder) {
// 获取当前工序的依赖 // 获取当前工序的依赖
Entry op = findOperationById(chromosome, opId); // Entry op = findOperationById(chromosome, opId);
Entry op = opIdIndex.get(opId);
List<Integer> dependencies = dependencyGraph.getOrDefault(opId, Collections.emptyList()); List<Integer> dependencies = dependencyGraph.getOrDefault(opId, Collections.emptyList());
// 等待所有依赖完成 // 等待所有依赖完成
...@@ -661,10 +693,8 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -661,10 +693,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 1. 获取工序处理顺序 // 1. 获取工序处理顺序
List<Integer> operationSequencing = chromosome.getOperationSequencing(); List<Integer> operationSequencing = chromosome.getOperationSequencing();
List<GlobalOperationInfo> globalOpList=chromosome.getGlobalOpList(); List<GlobalOperationInfo> globalOpList = chromosome.getGlobalOpList();
List<Entry> allOperations=chromosome.getAllOperations(); List<Entry> allOperations = chromosome.getAllOperations();
// 2. 构建工序依赖图 // 2. 构建工序依赖图
...@@ -696,7 +726,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -696,7 +726,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 获取选择的设备ID和加工时间 // 获取选择的设备ID和加工时间
MachineOption selectedMachine = optionalMachines.get(machineSeq - 1); MachineOption selectedMachine = optionalMachines.get(machineSeq - 1);
OpMachine opMachine=new OpMachine(); OpMachine opMachine = new OpMachine();
opMachine.setGroupId(groupId); opMachine.setGroupId(groupId);
opMachine.setSequence(sequence); opMachine.setSequence(sequence);
opMachine.setMachineId(selectedMachine.getMachineId()); opMachine.setMachineId(selectedMachine.getMachineId());
...@@ -849,12 +879,12 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -849,12 +879,12 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 工序超过500的设备直接在主线程串行处理 // 工序超过500的设备直接在主线程串行处理
if (ops.size() > 500) { if (ops.size() > 500) {
// FileHelper.writeLogFile("设备 " + machineId + " 有 " + ops.size() + " 个工序,直接串行处理"); // FileHelper.writeLogFile("设备 " + machineId + " 有 " + ops.size() + " 个工序,直接串行处理");
processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock,opMachineKeyMap,machineIdMap,machineTasksCache); processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock, opMachineKeyMap, machineIdMap, machineTasksCache);
} else { } else {
// 工序少的设备创建线程处理 // 工序少的设备创建线程处理
Thread thread = new Thread(() -> { Thread thread = new Thread(() -> {
processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock,opMachineKeyMap,machineIdMap,machineTasksCache); processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock, opMachineKeyMap, machineIdMap, machineTasksCache);
}); });
thread.start(); thread.start();
threads.add(thread); threads.add(thread);
...@@ -870,14 +900,14 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -870,14 +900,14 @@ if(finishedOrder==null||finishedOrder.size()==0)
} }
} }
// 9. 等待所有设备处理完成 // 9. 等待所有设备处理完成
// CompletableFuture.allOf(allMachineFutures.toArray(new CompletableFuture[0])).join(); // CompletableFuture.allOf(allMachineFutures.toArray(new CompletableFuture[0])).join();
if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) { if (chromosome.getReOrderids() != null && chromosome.getReOrderids().size() > 0) {
chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t)); chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t));
} }
calculateScheduleResult(chromosome); calculateScheduleResult(chromosome);
} }
/** /**
* 处理单个设备的工序 * 处理单个设备的工序
...@@ -1051,8 +1081,19 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -1051,8 +1081,19 @@ if(finishedOrder==null||finishedOrder.size()==0)
return result; return result;
} }
/**
* 构建工序ID索引:opId -> Entry(O(1)查找)
*/
private Map<Integer, Entry> buildOpIdIndex(Chromosome chromosome) {
Map<Integer, Entry> index = new HashMap<>();
for (Entry op : chromosome.getAllOperations()) {
index.put(op.getId(), op);
}
return index;
}
/** /**
* 根据工序ID查找工序 * 根据工序ID查找工序
*/ */
...@@ -2367,7 +2408,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2367,7 +2408,7 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
if(config.getName()==GlobalParam.OBJECTIVE_MAKESPAN) if(config.getName()==GlobalParam.OBJECTIVE_MAKESPAN)
{ {
// 1. 最早完工时间(最小化) // 1. 最早完工时间(最小化)
double makespan = chromosome.getResult().stream() double makespan = chromosome.getResult().stream()
.mapToInt(GAScheduleResult::getEndTime) .mapToInt(GAScheduleResult::getEndTime)
.max() .max()
.orElse(0); .orElse(0);
...@@ -2444,6 +2485,10 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -2444,6 +2485,10 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
} }
chromosome.setObjectives(Objectives); chromosome.setObjectives(Objectives);
FitnessCalculator fitnessCalculator=new FitnessCalculator();
if (chromosome.getFitnessLevel()==null) {
chromosome.setFitnessLevel(fitnessCalculator.calculateFitness(chromosome, _globalParam));
}
} }
private double calculateTotalFlowTime(Chromosome chromosome) { private double calculateTotalFlowTime(Chromosome chromosome) {
......
This diff is collapsed.
...@@ -48,10 +48,10 @@ public class ParallelLocalSearch { ...@@ -48,10 +48,10 @@ public class ParallelLocalSearch {
}); });
// 添加模拟退火任务 // 添加模拟退火任务
tasks.add(() -> { // tasks.add(() -> {
SimulatedAnnealing sa = new SimulatedAnnealing(globalParam, allOperations, globalOpList, fitnessCalculator, objectiveWeights); // SimulatedAnnealing sa = new SimulatedAnnealing(globalParam, allOperations, globalOpList, fitnessCalculator, objectiveWeights);
return sa.search(chromosome, decoder, param); // return sa.search(chromosome, decoder, param);
}); // });
// 执行所有任务 // 执行所有任务
List<Chromosome> results = new ArrayList<>(); List<Chromosome> results = new ArrayList<>();
......
...@@ -210,7 +210,7 @@ public class PlanResultService { ...@@ -210,7 +210,7 @@ public class PlanResultService {
.collect(Collectors.toList()); .collect(Collectors.toList());
globalParam.setPureNSGAIIMode(false); 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); HybridAlgorithm scheduler =new HybridAlgorithm(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
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间 //完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
......
...@@ -39,7 +39,9 @@ public class PlanResultServiceTest { ...@@ -39,7 +39,9 @@ public class PlanResultServiceTest {
// TestSortService sortService=new TestSortService(); // TestSortService sortService=new TestSortService();
// sortService.test1(); // sortService.test1();
// nsgaiiUtils.Test(); // nsgaiiUtils.Test();
planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4"); // planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//2000
planResultService.execute2("C8B533BD8944405B9A2F8823C575C204");//500
// planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");//20
// 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