Commit 34bcb88f authored by Tong Li's avatar Tong Li

Merge remote-tracking branch 'origin/tl'

parents f96d4ca7 4562cda0
......@@ -28,36 +28,49 @@ public class Chromosome {
/// <summary>
/// 机器选择部分(可选机器集中的顺序号)
/// </summary>
private List<Integer> MachineSelection;
private List<Integer> machineSelection;
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
private String MachineStr;
private String machineStr;
public String getMachineStr() {
if(MachineSelection==null) return "";
return MachineSelection.stream()
/// <summary>
/// 机器选择部分 + 工序排序部分
/// </summary>
private String geneStr;
public void setMachineSelection(List<Integer> val) {
machineSelection = val;
machineStr = machineSelection.stream()
.map(String::valueOf) // 将每个 Integer 转换为 String
.collect(Collectors.joining(","));
};
geneStr=machineStr+ "_" +operationStr;
}
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
private List<Integer> OperationSequencing;
private List<Integer> operationSequencing;
public void setOperationSequencing(List<Integer> val) {
operationSequencing = val;
operationStr = operationSequencing.stream()
.map(String::valueOf) // 将每个 Integer 转换为 String
.collect(Collectors.joining(","));
geneStr=machineStr+ "_" +operationStr;
}
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
private String OperationStr;
private String operationStr;
public String getOperationStr() {
if(OperationSequencing==null) return "";
return OperationSequencing.stream()
.map(String::valueOf) // 将每个 Integer 转换为 String
.collect(Collectors.joining("|"));
};
private List<GlobalOperationInfo> globalOpList;
private List<Entry> allOperations;
......@@ -68,9 +81,19 @@ public class Chromosome {
private List<GroupResult> OperatRel;
private ObjectiveWeights objectiveWeights;
/*
* 最早完工时间(最小化) 最小化总加工时间 最小总换型时间
*/
private double[] Objectives ; // 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay]
private double[] MaxObjectives ; //
private double[] MinObjectives ; //
private int Rank; // 非支配排序等级(1最优)
private double CrowdingDistance =0; // 拥挤距离
private double CrowdingDistance =0; // 拥挤距离 越小越优
/*
*(Objectives - min) / (max - min);
*/
private double[] WeightedObjectives;//越靠近1越优
private double WeightedObjective =0; // 加权目标值(用于自定义权重)
/// <summary>
/// 适应度值
......
......@@ -41,7 +41,7 @@ public class ObjectiveWeights {
* @param minValues 各维度目标值的最小值
* @param maxValues 各维度目标值的最大值
* @param isMinimize 各维度是否为最小化目标(true:值越小越优;false:值越大越优)
* @return 归一化后目标值(范围:[0,1],无0值兜底)
* @return 归一化后目标值(范围:[0,1],无0值兜底) 越靠近1越优
*/
public double[] normalizeObjectives(double[] objectives, double[] minValues, double[] maxValues, boolean[] isMinimize) {
if (objectives == null || objectives.length == 0) {
......@@ -89,7 +89,7 @@ public class ObjectiveWeights {
}
}
// 兜底:限制范围[1e-6,1],彻底避免0值
normalized[i] = Math.max(Math.min(normalized[i], 1.0), 1e-6);
normalized[i] = Math.max(Math.min(normalized[i], 1.0), 0.0001);
}
}
return normalized;
......
......@@ -20,8 +20,8 @@ public class ScheduleParams {
private static final int MAX_MAX_ITERATIONS = 200;
private static final float MIN_CROSSOVER_PROB = 0.6f;
private static final float MAX_CROSSOVER_PROB = 0.9f;
private static final float MIN_MUTATION_PROB = 0.05f;
private static final float MAX_MUTATION_PROB = 0.2f;
private static final float MIN_MUTATION_PROB = 0.3f;
private static final float MAX_MUTATION_PROB = 0.7f;
private static final int MIN_TOURNAMENT_SIZE = 3;
private static final int MAX_TOURNAMENT_SIZE = 7;
......
......@@ -23,7 +23,7 @@ private LocalDateTime effectiveStartTime;
private LocalDateTime effectiveEndTime;
private Long referenceId;
private Integer referenceType;
private BigDecimal efficiencyCoeff;
private Double efficiencyCoeff;
private Integer minUtilization;
private Integer maxUtilization;
private String referenceName;
......
......@@ -15,7 +15,7 @@ private LocalDateTime endDate;
private String shiftWorkSchedCode;
private String periodDesc;
private Integer equipId;
private Long efficiencyCoeff;
private double efficiencyCoeff;
private Long referenceId;
private String referenceName;
private Long creatorUserId;
......
......@@ -19,7 +19,7 @@ public class Shift {
private int priority;
private boolean isSpecial;
private Integer status;//0:正常班次 1:临时班次 2:维修
private double efficiency=1;
// 添加设备ID和名称字段
private Long machineId;
private String machineName;
......
......@@ -18,10 +18,17 @@ public class TimeSegment {
private SegmentType type; // 时间段类型(关联SegmentType枚举)
private boolean isHoliday; // 是否节假日(true=节假日)
private boolean isUsed; // 是否已被占用(true=已分配任务)
private double efficiency=1;//效率
// 无参构造(Lombok默认生成)
public TimeSegment() {}
public TimeSegment(LocalDateTime start, LocalDateTime end) {
this.start = start;
this.end = end;
}
......
package com.aps.service.Algorithm;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.ObjectiveWeights;
import java.util.List;
......@@ -12,23 +13,26 @@ public class FitnessCalculator {
/**
* 多目标适应度计算(加权求和)
*/
public double calculateFitness(Chromosome chromosome) {
// 权重可根据实际需求调整
double w1 = 0.3; // 最早完工时间(越小越好,归一化后取反)
double w2 = 0.2; // 总流程时间(越小越好)
double w3 = 0.15; // 总换型时间(越小越好)
double w4 = 0.2; // 机器负载均衡(标准差越小越好)
double w5 = 0.15; // 交付期延迟(越小越好)
// 归一化(假设最大可能值,实际应根据问题规模调整)
double normMakespan =1/ (1 +(double) chromosome.getMakespan());
double normFlowTime = 1/ (1 + (double) chromosome.getTotalFlowTime() );
double normChangeover = 1/ (1 + (double) chromosome.getTotalChangeoverTime());
double normLoadStd = chromosome.getMachineLoadStd();
double normDelay = 1/ (1 + (double) chromosome.getDelayTime() );
public double calculateFitness(Chromosome chromosome,ObjectiveWeights objectiveWeights) {
double fitness=0;
for(int i=0;i<chromosome.getObjectives().length;i++)
{
// 归一化(假设最大可能值,实际应根据问题规模调整)
double val=1/ (1 +chromosome.getObjectives()[i]);
if(!objectiveWeights.isPureNSGAIIMode())
{
val=val*objectiveWeights.getWeights()[i];
}
fitness+=val;
// 1/1+1 0.5
// 1/1+2 0.3
// 1/1+3 0.25
// 值越大 归一化 后越小
}
// 适应度值(越大越好)
return w1 * normMakespan + w2 * normFlowTime + w3 * normChangeover + w4 * normLoadStd + w5 * normDelay;
return fitness;
}
/**
* 计算种群适应度标准差(用于参数微调)
......
......@@ -62,6 +62,12 @@ public class GeneticAlgorithm {
}
public Chromosome Run(ScheduleParams param, List<Entry> allOperations) {
if(allOperations==null||allOperations.size()==0)
{
throw new RuntimeException("没有待排产工单");
}
if(materials!=null&&materials.size()>0) {
materialRequirementService.init(materials, orders, allOperations, _entryRel, machineScheduler, machines,_GlobalParam);
......@@ -70,17 +76,22 @@ public class GeneticAlgorithm {
LocalDateTime starttime=LocalDateTime.now();
FileHelper.writeLogFile("排产-----------开始-----------"+allOperations.get(0).getSceneId());
Initialization initialization = new Initialization(_GlobalParam,allOperations,orders,machines);
Initialization initialization = new Initialization(_GlobalParam,allOperations,orders,machines,_objectiveWeights);
GeneticOperations geneticOps = new GeneticOperations(_GlobalParam,allOperations,param);
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List<GlobalOperationInfo> globalOpList = initialization.generateGlobalOpList();
FileHelper.writeLogFile("初始化种群-----------开始-------");
Machine ms= machines.stream().filter(t->t.getName().equals("铲车-2")).findFirst().orElse(null);
// 步骤1:初始化种群
List<Chromosome> population = initialization.generateInitialPopulation(param, globalOpList);
population= chromosomeDistinct(population);
FileHelper.writeLogFile("初始化种群-----------结束-------");
FileHelper.writeLogFile("初始化批量解码-----------开始-------");
Chromosomedecode(param,allOperations,globalOpList,population);
......@@ -90,18 +101,13 @@ public class GeneticAlgorithm {
.mapToInt(GlobalOperationInfo::getGroupId)
.max()
.orElse(0);
Chromosome best=new Chromosome();
Chromosome best=GetBest(fronts,"初始");
// best=fronts.get(0).stream()
// .max(Comparator.comparingDouble(Chromosome::getFitness))
// .orElse(null);
WriteKpis(fronts,"初始");
best = fronts.get(0).stream()
.sorted((c1, c2) -> Double.compare(c2.getWeightedObjective(), c1.getWeightedObjective()))
.findFirst()
.orElse(null);
WriteKpi(best,"最大");
double bestFitness=best.getWeightedObjective();
double bestFitness=best.getFitness();
int Iteration=0;
// 步骤2:迭代进化
FileHelper.writeLogFile("迭代进化-----------开始-------"+param.getMaxIterations());
......@@ -149,13 +155,20 @@ public class GeneticAlgorithm {
FileHelper.writeLogFile("交叉操作-----------结束-------");
FileHelper.writeLogFile("变异操作-----------开始-------");
// 变异操作
List<Chromosome> nextPopulation1 = new ArrayList<>();
for (Chromosome chromosome : nextPopulation) {
if (rnd.nextDouble() < param.getMutationProb()) {
geneticOps.mutate(chromosome, globalOpList);
Chromosome chromosome1= ProductionDeepCopyUtil.deepCopy(chromosome,Chromosome.class);
geneticOps.mutate(chromosome1, globalOpList);
nextPopulation1.add(chromosome1);
}
}
nextPopulation.addAll(nextPopulation1);
FileHelper.writeLogFile("变异操作-----------结束-------");
FileHelper.writeLogFile("变异批量解码-----------开始-------");
nextPopulation= chromosomeDistinct(nextPopulation);
Chromosomedecode(param,allOperations,globalOpList,nextPopulation);
FileHelper.writeLogFile("变异批量解码-----------开始-------");
// // 精英保留
......@@ -169,6 +182,7 @@ public class GeneticAlgorithm {
List<Chromosome> newPopulation = new ArrayList<>();
newPopulation.addAll(population);
newPopulation.addAll(nextPopulation);
newPopulation= chromosomeDistinct(newPopulation);
FileHelper.writeLogFile("非支配排序-----------开始-------");
// 2.7 非支配排序
List<List<Chromosome>> combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(newPopulation);
......@@ -181,17 +195,11 @@ public class GeneticAlgorithm {
// .collect(Collectors.toList());
fronts = _nsgaIIUtils.parallelFastNonDominatedSort(population);
WriteKpis(fronts,String.valueOf(iter));
best = fronts.get(0).stream()
.sorted((c1, c2) -> Double.compare(c2.getWeightedObjective(), c1.getWeightedObjective()))
.findFirst()
.orElse(null);
WriteKpi(best,"最大");
if(bestFitness<best.getWeightedObjective())
best= GetBest(combinedFronts,String.valueOf(iter));
if(bestFitness<best.getFitness())
{
bestFitness=best.getWeightedObjective();
bestFitness=best.getFitness();
Iteration=1;
......@@ -222,6 +230,36 @@ public class GeneticAlgorithm {
}
private Chromosome GetBest(List<List<Chromosome>> fronts,String msg)
{
WriteKpis(fronts,msg);
List<Chromosome> fChromosomes= fronts.get(0);
fChromosomes.sort((c1, c2) -> {
int rankCompare = Double.compare(c1.getCrowdingDistance(), c2.getCrowdingDistance());
return rankCompare != 0 ? rankCompare : Double.compare(c1.getFitness(), c2.getFitness());
});
Chromosome best=fChromosomes.get(0);
WriteKpi(best,"最大");
return best;
}
private List<Chromosome> chromosomeDistinct(List<Chromosome> population)
{
if(orders.size()<10)
{
population = population.stream()
.collect(Collectors.toMap(
Chromosome::getGeneStr, // key:去重的字段(GeneStr)
u -> u, // value:Chromosome对象
(u1, u2) -> u1 // 重复时保留第一个元素
))
.values() // 获取去重后的
.stream()
.collect(Collectors.toList());
}
return population;
}
private void WriteKpis(List<List<Chromosome>> fronts,String index) {
for (int i=0;i<fronts.size();i++)
{
......@@ -253,10 +291,10 @@ public class GeneticAlgorithm {
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines)); // 简单拷贝,实际可能需要深拷贝
chromosome.setAllOperations(allOperations); // 简单拷贝,实际可能需要深拷贝
chromosome.setGlobalOpList(globalOpList); // 简单拷贝,实际可能需要深拷贝
//chromosome.setObjectiveWeights(_objectiveWeights);
decoder.decodeChromosomeWithCache(chromosome);
if (chromosome.getFitness() == 0) {
chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome));
chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome,_objectiveWeights));
}
});
......
......@@ -92,6 +92,7 @@ public class GeneticDecoder {
chromosome.setDelayTime(cachedResult.getDelayTime());
chromosome.setResult(ProductionDeepCopyUtil.deepCopyList(cachedResult.getResult(),GAScheduleResult.class));
// Chromosome chromosomen= ProductionDeepCopyUtil.deepCopy(cachedResult);
FileHelper.writeLogFile("解码-----------结束-------"+chromosome.getID());
return chromosome;
}
......@@ -373,7 +374,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
int setupTime = calculateSetupTime(chromosome.getResult(), operation, machine, machineOption);
FileHelper.writeLogFile(" "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId());
", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt());
// 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理)
......@@ -429,7 +430,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
List<ScheduleResultDetail> geneDetails = machineCalculator.getNextAvailableTime(machine, earliestStartTime, -1,
processingTimeTotal, chromosome.getResult(), false, true,processingTime, operation.getQuantity(), true);
processingTimeTotal, chromosome.getResult(), operation.IsInterrupt!=1, true,processingTime, operation.getQuantity(), true);
......@@ -929,7 +930,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 3. 最小总换型时间
double totalSetupTime = calculateTotalSetupTime(chromosome);
// 4. 最小化总流程时间
// 4. 最小化总流程时间 所有工序加工时间的总和
double totalFlowTime = calculateTotalFlowTime(chromosome);
// 5. 机器负载均衡
......@@ -945,7 +946,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
double[] Objectives=new double[5];
Objectives[0] = makespan;
Objectives[1] = totalFlowTime;
Objectives[2] = totalSetupTime;
Objectives[2] = totalSetupTime;
Objectives[3] = machineLoadBalance;
Objectives[4] = tardiness;
chromosome.setObjectives(Objectives);
......@@ -969,36 +970,34 @@ if(finishedOrder==null||finishedOrder.size()==0)
// 计算机器负载均衡指标
private double calculateMachineLoadBalance(Chromosome chromosome) {
Map<Long, Double> machineUtilization = new HashMap<>();
int maxEndTime = chromosome.getResult().stream()
.mapToInt(GAScheduleResult::getEndTime)
.max()
.orElse(0);
int sumWork = chromosome.getResult().stream()
.mapToInt(GAScheduleResult::getFlowTime)
.sum();//总的加工时间
if (maxEndTime == 0) return 0;
if (sumWork == 0) return 0;
for (Machine machine : chromosome.getMachines()) {
List<GAScheduleResult> machineGenes = chromosome.getResult().stream()
double busyTime = chromosome.getResult().stream()
.filter(g -> g.getMachineId() == machine.getId())
.collect(Collectors.toList());
double busyTime = machineGenes.stream()
.mapToInt(g -> g.getEndTime() - g.getStartTime())
.mapToInt(g -> g.getFlowTime())
.sum();
machineUtilization.put(machine.getId(), busyTime / maxEndTime);
machineUtilization.put(machine.getId(), busyTime / sumWork);
}
double avgUtilization = machineUtilization.values().stream()
.mapToDouble(Double::doubleValue)
.average()
.orElse(0);
.sum()/ chromosome.getMachines().size();
double variance = machineUtilization.values().stream()
.mapToDouble(u -> Math.pow(u - avgUtilization, 2))
.sum() / chromosome.getMachines().size();
// 方差越小,负载越均衡
return 1.0 / (1 + variance);
// 标准差与平均值的比值衡量负载离散程度,值越小说明均衡度越高
return Math.sqrt(variance)/avgUtilization ;
}
/**
* 补全:创建缓存键(核心逻辑,需与原 C# CreateCacheKey 一致)
......@@ -1006,13 +1005,15 @@ if(finishedOrder==null||finishedOrder.size()==0)
*/
private String createCacheKey(Chromosome chromosome) {
return chromosome.getGeneStr();
// 拼接机器选择:用 "," 分隔(例:1,3,2,4)
String machineStr = chromosome.getMachineStr();
// String machineStr = chromosome.getMachineStr();
// 拼接工序排序:用 "|" 分隔(例:2|1|3|4)
String operationStr = chromosome.getOperationStr();
// String operationStr = chromosome.getOperationStr();
// 组合最终键(用 "_" 分隔两部分,避免冲突)
return machineStr + "_" + operationStr;
// return machineStr + "_" + operationStr;
}
}
......@@ -34,39 +34,23 @@ public class GeneticOperations {
*/
public List<Chromosome> tournamentSelection(List<Chromosome> population, int tournamentSize) {
int populationSize = population.size();
List<Chromosome> selected = new ArrayList<>(populationSize); // 预初始化容量
List<Chromosome> selected = new ArrayList<>(); // 预初始化容量
// 边界值处理:锦标赛规模不能超过种群规模,且至少为1
int effectiveTournamentSize = Math.max(1, Math.min(tournamentSize, populationSize));
while (selected.size() < populationSize) {
while (selected.size() < populationSize-tournamentSize) {
// 优化1:不复制整个种群,直接随机抽取有效锦标赛规模的个体,避免大量内存拷贝和shuffle开销
Chromosome bestCandidate = null;
int bestRank = Integer.MAX_VALUE;
double bestCrowdingDistance = -Double.MAX_VALUE;
// 优化2:单次循环随机抽取+实时比较,无需创建候选列表、无需排序,O(k)时间复杂度(k为锦标赛规模)
for (int i = 0; i < effectiveTournamentSize; i++) {
// 随机获取一个种群个体(直接通过索引访问,无需打乱整个列表)
int randomIndex = rnd.nextInt(populationSize);
Chromosome current = population.get(randomIndex);
// 优化3:手动实现排序逻辑的比较,避免Stream API的额外开销
if (bestCandidate == null) {
bestCandidate = current;
bestRank = current.getRank();
bestCrowdingDistance = current.getCrowdingDistance();
} else {
// 先比较Rank(升序:Rank越小越优)
if (current.getRank() < bestRank) {
updateBestCandidate(current, bestCandidate, bestRank, bestCrowdingDistance);
} else if (current.getRank() == bestRank) {
// Rank相同时,比较拥挤距离(降序:值越大越优)
if (current.getCrowdingDistance() > bestCrowdingDistance) {
updateBestCandidate(current, bestCandidate, bestRank, bestCrowdingDistance);
}
}
}
}
Collections.shuffle(population, new Random());//随机排序
int endIndex = Math.min(effectiveTournamentSize, population.size());
List<Chromosome> chromosomes=population.subList(0, endIndex);
chromosomes.sort((c1, c2) -> {
int rankCompare = Integer.compare(c1.getRank(), c2.getRank());
return rankCompare != 0 ? rankCompare : Double.compare(c1.getCrowdingDistance(), c2.getCrowdingDistance());
});
Chromosome bestCandidate = chromosomes.get(0);
// 深拷贝最优个体并加入选中列表(确保线程安全和种群独立性)
if (bestCandidate != null) {
......@@ -75,12 +59,7 @@ public class GeneticOperations {
}
return selected;
}
private void updateBestCandidate(Chromosome current, Chromosome bestCandidate,
int bestRank, double bestCrowdingDistance) {
bestRank = current.getRank();
bestCrowdingDistance = current.getCrowdingDistance();
bestCandidate = current;
}
// 重载,使用默认锦标赛大小3
public List<Chromosome> tournamentSelection(List<Chromosome> population) {
return tournamentSelection(population, param.getTournamentSize());
......@@ -239,11 +218,19 @@ public class GeneticOperations {
* 变异操作
*/
public void mutate(Chromosome chromosome, List<GlobalOperationInfo> globalOpList, double baseMutationProb) {
// 1. 机器选择部分变异
mutateMachineSelection(chromosome, globalOpList, baseMutationProb);
// 2. 工序排序部分变异
mutateOperationSequencing(chromosome);
int i= rnd.nextInt(2);
if(i==0) {
// 1. 机器选择部分变异
boolean state= mutateMachineSelection(chromosome, globalOpList, baseMutationProb);
if(!state)
{
i=1;
}
}
if(i==1) {
// 2. 工序排序部分变异
mutateOperationSequencing(chromosome);
}
}
// 重载,使用默认变异概率
......@@ -251,13 +238,13 @@ public class GeneticOperations {
mutate(chromosome, globalOpList, 0.1);
}
private void mutateMachineSelection(Chromosome chromosome, List<GlobalOperationInfo> globalOpList, double baseMutationProb) {
private boolean mutateMachineSelection(Chromosome chromosome, List<GlobalOperationInfo> globalOpList, double baseMutationProb) {
// 计算变异位置数量
List<Entry> entrys= allOperations.stream().filter(t->t.getMachineOptions().size()>1).collect(Collectors.toList());
if(entrys==null||entrys.size()==0)
{
return;
return false;
}
Integer count=entrys.size();
int r = Math.max(1, (int) (count * baseMutationProb));
......@@ -291,6 +278,7 @@ public class GeneticOperations {
i++;
}
return true;
}
/**
......
......@@ -3,6 +3,7 @@ package com.aps.service.Algorithm;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GlobalOperationInfo;
import com.aps.entity.Algorithm.ObjectiveWeights;
import com.aps.entity.Algorithm.ScheduleParams;
import com.aps.entity.basic.*;
......@@ -22,11 +23,14 @@ public class Initialization {
private static List<Machine> machines;
public Initialization(GlobalParam globalParam,List<Entry> allOperations,List<Order> _orders,List<Machine> _machines) {
private ObjectiveWeights _objectiveWeights = new ObjectiveWeights();
public Initialization(GlobalParam globalParam,List<Entry> allOperations,List<Order> _orders,List<Machine> _machines,ObjectiveWeights objectiveWeights) {
Initialization.allOperations = allOperations;
_globalParam= globalParam;
orders=_orders;
machines=_machines;
_objectiveWeights= objectiveWeights;
}
/**
* 预生成全局工序列表(按“订单0→订单1→…+订单内工序1→2→…”排序,分配GlobalOpId)
......@@ -60,6 +64,7 @@ int populationSize=param.getPopulationSize();
.parallel() // 开启并行
.forEach(i -> {
Chromosome chromo = new Chromosome(); // 初始化染色体
// chromo.setObjectiveWeights(_objectiveWeights);
chromo.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines));
chromo.setOrders(orders);
// 全局选择(GS):按GlobalOpId顺序生成MachineSelection
......
package com.aps.service.Algorithm;
import com.aps.common.util.GlobalCacheUtil;
import com.aps.common.util.SnowFlackIdWorker;
import com.aps.common.util.redis.RedisUtils;
import com.aps.entity.*;
import com.aps.entity.Algorithm.BOMBuildResult;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
......@@ -54,6 +56,8 @@ public class MaterialRequirementService {
@Autowired
RoutingDetailConnectService routingDetailConnectService;
@Autowired
private RedisUtils redisUtils;
private List<Order> orders;
......@@ -153,7 +157,7 @@ if(routingIds.size()==0)
allRequirements.addAll(result.getMaterialRequirements());
childorders.addAll(result.getChildOrders());
_newEntrys.addAll(result.getNewEntrys());
// _newMachines.addAll(result.getNewMachines());
_newMachines.addAll(result.getNewMachines());
}
......@@ -163,10 +167,10 @@ if(routingIds.size()==0)
orders.addAll(childorders);
// _allOperations.addAll(_newEntrys);
Set<Long> existIds = new HashSet<>();
// _Machines.addAll(_newMachines.stream()
// .filter(t->existIds.add(t.getId()))//HashSet.add() 方法:添加成功返回 true,重复返回 false;
// .collect(Collectors.toList()));
_Machines.addAll(_newMachines);
_Machines=_Machines.stream()
.filter(t->existIds.add(t.getId()))//HashSet.add() 方法:添加成功返回 true,重复返回 false;
.collect(Collectors.toList());
}
return allRequirements;
......@@ -227,7 +231,7 @@ if(routingIds.size()==0)
materialRequirements.addAll(operationResult.getMaterialRequirements());
childorders2.addAll(operationResult.getChildOrders());
_newEntrys.addAll(operationResult.getNewEntrys());
// _newMachines.addAll(operationResult.getNewMachines());
_newMachines.addAll(operationResult.getNewMachines());
}
}
}
......@@ -369,9 +373,25 @@ if(routingIds.size()==0)
ProdLaunchOrders.add(order);
Map<Integer, Object> list=_routingDataService.CreateEntry( sceneId, ProdEquipmentList, ProdLaunchOrders, routingDiscreteParams, ProdOrderProcesslist, processExecList,_entryRel,finishOpertionID );
List<Machine> machines=new ArrayList<>();
List<Machine> allmachines = (List<Machine>) GlobalCacheUtil.get("machines");
if (allmachines == null || allmachines.size() == 0) {
allmachines = (List<Machine>) redisUtils.get("machines");
if (allmachines == null || allmachines.size() == 0) {
List<Long> equipIds = ProdEquipmentList.stream()
.map(ProdEquipment::getEquipId)
.distinct() // 提取Exec_ID
.collect(Collectors.toList());
machines=allmachines.stream().filter(t->equipIds.contains(t.getId())).collect(Collectors.toList());
}
// List<Machine> machines= _routingDataService.InitCalendarToAllMachines(sceneId,ProdEquipmentList,machineScheduler, globalParam.isIsUseCalendar());
}
if (machines == null || machines.size() == 0) {
machines= _routingDataService.InitCalendarToAllMachines(sceneId,ProdEquipmentList,machineScheduler, globalParam.isIsUseCalendar());
}
if(list.get(1)!=null)
{
......@@ -380,7 +400,7 @@ if(routingIds.size()==0)
}
Map<Integer, Object> rest=new HashMap<>();
rest.put(1,list.get(1));
// rest.put(2,machines);
rest.put(2,machines);
return rest;
}
......@@ -606,7 +626,7 @@ if(routingIds.size()==0)
_childorders.add(childorder);
List<Entry> newentrys=(List<Entry>)list.get(1);
_newEntrys.addAll(newentrys);
// _newMachines.addAll((List<Machine>)list.get(2));
_newMachines.addAll((List<Machine>)list.get(2));
orderMaterial.getProductOrderID().add(childorder.getId());
operation.getDependentOnOrderIds().add(childorder.getId());
// 递归构建BOM
......@@ -617,7 +637,7 @@ if(routingIds.size()==0)
materialRequirements.addAll(childResult.getMaterialRequirements());
_childorders.addAll(childResult.getChildOrders());
_newEntrys.addAll(childResult.getNewEntrys());
// _newMachines.addAll(childResult.getNewMachines());
_newMachines.addAll(childResult.getNewMachines());
}
}
}
......
......@@ -136,7 +136,7 @@ public class RoutingDataService {
}
List<Entry> entrys=new ArrayList<>();
Set<Long> machineIds=new HashSet<>();
for (int i = index; i < results.size(); i++) {
GroupResult groupResult = results.get(i);
List<NodeInfo> nodeInfoList = groupResult.getNodeInfoList();
......@@ -234,6 +234,7 @@ public class RoutingDataService {
if (Equipments != null && Equipments.size() > 0) {
List<MachineOption> mos = new ArrayList<>();
for (ProdEquipment e : Equipments) {
machineIds.add(e.getEquipId());
MachineOption mo = new MachineOption();
mo.setMachineId(e.getEquipId());
mo.setRuntime(e.getRuntime());
......@@ -261,7 +262,7 @@ public class RoutingDataService {
}
list.put(1,entrys);
list.put(2,results);
list.put(3,machineIds);
return list;
}
......@@ -465,7 +466,11 @@ public class RoutingDataService {
shift.setMachineId(machine.getId());
shift.setStartDate(machineProdEquipSpecialCal.getEffectiveStartTime());
shift.setEndDate(machineProdEquipSpecialCal.getEffectiveEndTime());
if(machineProdEquipSpecialCal.getEfficiencyCoeff()!=null) {
shift.setEfficiency(machineProdEquipSpecialCal.getEfficiencyCoeff());
}
shifts1.add(shift);
}
}
......@@ -621,6 +626,7 @@ public class RoutingDataService {
days.add(6);
days.add(0);
shift.setDays(days);
shift.setStartDate(LocalDateTime.of(2000, 1, 1, 0, 0, 0));
shift.setEndDate(LocalDateTime.of(2000, 1, 1, 0, 0, 0));
shifts1.add(shift);
......
......@@ -79,7 +79,9 @@ public class ProdEquipSpecialCalServiceImpl extends ServiceImpl<ProdEquipSpecial
specialCal.setPlanResourceId(capacityDef.getPlanResourceId());
// 处理数值类型转换的空值
if (capacityDef.getEfficiencyCoeff() != null) {
specialCal.setEfficiencyCoeff(capacityDef.getEfficiencyCoeff().longValue());
specialCal.setEfficiencyCoeff(capacityDef.getEfficiencyCoeff().doubleValue());
}else {
specialCal.setEfficiencyCoeff(1);
}
specialCal.setReferenceId(capacityDef.getReferenceId());
......
......@@ -10,14 +10,17 @@ import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
public class MachineSchedulerService {
// 全局缓存(线程安全)
private static final ConcurrentHashMap<Long, MachineTimeline> timelineCache = new ConcurrentHashMap<>();
private final ReentrantLock cacheLock = new ReentrantLock();
private LocalDateTime currentTime;
private List<Holiday> holidays;
......@@ -34,19 +37,19 @@ public class MachineSchedulerService {
long machineId = machine.getId();
// 尝试从缓存获取
// MachineTimeline timeline = timelineCache.get(machineId);
// if (timeline != null) {
// // 检查有效期(4小时刷新)
// if (Duration.between(timeline.getLastUpdated(), LocalDateTime.now()).toHours() < 4) {
// return timeline;
// }
// }
MachineTimeline timeline = timelineCache.get(machineId);
if (timeline != null) {
// 检查有效期(4小时刷新)
if (Duration.between(timeline.getLastUpdated(), LocalDateTime.now()).toMinutes() < 10) {
return timeline;
}
}
// 创建新时间线(60天范围)
MachineTimeline newTimeline = generateTimeline(machine);
newTimeline.setSegments(mergeSegments(newTimeline.getSegments()));
// timelineCache.put(machineId, newTimeline);
timelineCache.put(machineId, newTimeline);
return newTimeline;
}
......@@ -54,11 +57,11 @@ public class MachineSchedulerService {
MachineTimeline timeline = new MachineTimeline();
timeline.setMachineId(machine.getId());
timeline.setValidFrom(currentTime);
timeline.setValidTo(currentTime.plusDays(60));
timeline.setValidTo(currentTime.plusDays(200));
timeline.setLastUpdated(LocalDateTime.now());
LocalDate currentDate = currentTime.toLocalDate();
LocalDate endDate = currentTime.plusDays(60).toLocalDate();
LocalDate endDate = currentTime.plusDays(200).toLocalDate();
List<TimeSegment> allSegments = new ArrayList<>();
......@@ -110,23 +113,37 @@ public class MachineSchedulerService {
}
public List<TimeSegment> generateTimeSegment(Machine machine, LocalDateTime currentTime) {
cacheLock.lock();
Long machineId = machine.getId();
MachineTimeline timeline = timelineCache.get(machineId);
try {
if (timeline == null) {
timeline = new MachineTimeline();
timeline.setMachineId(machine.getId());
timeline.setValidFrom(currentTime);
timeline.setValidTo(currentTime.plusDays(200));
timeline.setLastUpdated(LocalDateTime.now());
timeline.setSegments(new ArrayList<>());
} else {
if (timeline.getValidTo().compareTo(currentTime) > 0) {
LocalDateTime currentTime1=currentTime;
List<TimeSegment> timeSegments= timeline.getSegments().stream()
.filter(t->t.getStart().isAfter(currentTime1)||t.getStart().isBefore(currentTime1))
.collect(Collectors.toList());
return ProductionDeepCopyUtil.deepCopyList(timeSegments,TimeSegment.class);
if (timeline == null) {
timeline = new MachineTimeline();
timeline.setMachineId(machine.getId());
timeline.setValidFrom(currentTime);
timeline.setValidTo(currentTime.plusDays(60));
timeline.setLastUpdated(LocalDateTime.now());
timeline.setSegments(new ArrayList<>());
} else {
timeline.setValidTo(currentTime.plusDays(60));
timeline.setValidTo(currentTime.plusDays(200));
timeline.setLastUpdated(LocalDateTime.now());
}
}
}finally {
cacheLock.unlock();
}
LocalDate currentDate = currentTime.toLocalDate();
LocalDate endDate = currentTime.plusDays(60).toLocalDate();
LocalDate endDate = currentTime.plusDays(200).toLocalDate();
List<TimeSegment> segments = new ArrayList<>();
......@@ -173,6 +190,14 @@ public class MachineSchedulerService {
timeline.setSegments(mergeSegments(timeline.getSegments()));
segments = mergeSegments(segments);
cacheLock.lock();
try {
timelineCache.put(machineId, timeline);
}finally {
cacheLock.unlock();
}
return segments;
}
......@@ -213,13 +238,14 @@ public class MachineSchedulerService {
LocalDateTime shiftEnd = shift.getEndTime().isBefore(shift.getStartTime()) ?
date.plusDays(1).atTime(shift.getEndTime()) :
date.atTime(shift.getEndTime());
segments.add(new TimeSegment(
TimeSegment timeSegment= new TimeSegment(
shiftStart,
shiftEnd,
shift.isTemporaryShift() ? SegmentType.TEMP : SegmentType.REGULAR,
false
));
);
timeSegment.setEfficiency(shift.getEfficiency());
segments.add(timeSegment);
}
} else {
// 非假期:处理常规班次
......@@ -231,24 +257,42 @@ public class MachineSchedulerService {
&& containsDay(s.getDays(), date.getDayOfWeek()))
.collect(Collectors.toList());
if(shifts==null||shifts.size()==0) {
LocalDate sd= LocalDate.of(2000, 1, 1);
shifts = machine.getShifts().stream()
.filter(s ->sd.compareTo(s.getStartDate().toLocalDate())==0&& s.getDays() != null
&& containsDay(s.getDays(), date.getDayOfWeek()))
.collect(Collectors.toList());
long days=Math.abs(ChronoUnit.DAYS.between(LocalDate.now(),date));
if(days>600)
{
segments.add(new TimeSegment
(
date.atTime(0,0,0),
date.atTime(23,59,59),
SegmentType.REGULAR,
false
));
return segments;
}else {
LocalDate sd = LocalDate.of(2000, 1, 1);
shifts = machine.getShifts().stream()
.filter(s -> sd.compareTo(s.getStartDate().toLocalDate()) == 0 && s.getDays() != null
&& containsDay(s.getDays(), date.getDayOfWeek()))
.collect(Collectors.toList());
}
}
for (Shift shift : shifts) {
LocalDateTime shiftStart = date.atTime(shift.getStartTime());
LocalDateTime shiftEnd = shift.getEndTime().isBefore(shift.getStartTime()) ?
date.plusDays(1).atTime(shift.getEndTime()) :
date.atTime(shift.getEndTime());
segments.add(new TimeSegment(
TimeSegment timeSegment= new TimeSegment(
shiftStart,
shiftEnd,
shift.isTemporaryShift() ? SegmentType.TEMP : SegmentType.REGULAR,
false
));
);
timeSegment.setEfficiency(shift.getEfficiency());
segments.add(timeSegment);
}
}
......
......@@ -339,13 +339,17 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
List<GroupResult> entryRel=(List<GroupResult>)list.get(2);
Set<Long> machineIds=(Set<Long>)list.get(3);
machines= machines.stream().filter(t->machineIds.contains(t.getId())).collect(Collectors.toList());
// 5. 执行调度算法
GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,Materials,machineScheduler,entryRel,materialRequirementService); //new GeneticAlgorithm(products, machines, orders, machineScheduler);
param.initAdaptiveParams(entrys.size());
double[] customWeights = new double[] { 0.2, 0.1, 0.1, 0.1, 0.5 }; // 延迟时间权重提升到0.5
scheduler.Init(null,false);
double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
scheduler.Init(customWeights,false);
Chromosome chromosome =scheduler.Run(param,entrys);
KpiCalculator kpiCalculator=new KpiCalculator(chromosome);
......@@ -648,14 +652,16 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
List<Entry> entrys=(List<Entry>)list.get(1);
List<GroupResult> entryRel=(List<GroupResult>)list.get(2);
Set<Long> machineIds=(Set<Long>)list.get(3);
machines= machines.stream().filter(t->machineIds.contains(t.getId())).collect(Collectors.toList());
// 5. 执行调度算法
GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,Materials,machineScheduler,entryRel,materialRequirementService); //new GeneticAlgorithm(products, machines, orders, machineScheduler);
param.initAdaptiveParams(entrys.size());
// double[] customWeights = new double[] { 0.2, 0.1, 0.1, 0.1, 0.5 }; // 延迟时间权重提升到0.5
scheduler.Init(null,true);
double[] customWeights = new double[] { 0.4, 0.1, 0.1, 0.1, 0.3 }; // 延迟时间权重提升到0.5
//完工时间、总流程时间、总换型时间、机器负载标准差、延迟时间
scheduler.Init(customWeights,false);
Chromosome chromosomes =scheduler.Run(param,entrys);
KpiCalculator kpiCalculator=new KpiCalculator(chromosomes);
kpiCalculator.calculatekpi();
......@@ -783,14 +789,15 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
private List<Machine> InitCalendarToAllMachines(String SceneId,List<ProdEquipment> ProdEquipments,MachineSchedulerService machineScheduler,boolean IsUseCalendar) {
// 按设备分组
FileHelper.writeLogFile("初始化设备日历-----------开始-------");
ScheduleParams param = InitScheduleParams();
List<Machine> machines=new ArrayList<>();
if(!IsUseCalendar) {
ScheduleParams param = InitScheduleParams();
return _routingDataService.InitNoCalendarToAllMachines(machineScheduler,param.getBaseTime());
machines = _routingDataService.InitNoCalendarToAllMachines(machineScheduler,param.getBaseTime());
}else {
ScheduleParams param = InitScheduleParams();
return _routingDataService.InitCalendarToAllMachines( machineScheduler,param.getBaseTime());
machines = _routingDataService.InitCalendarToAllMachines( machineScheduler,param.getBaseTime());
// List<Machine> machines = _routingDataService.InitCalendarToAllMachines(SceneId, ProdEquipments, machineScheduler, IsUseCalendar);
// List<Machine> machines = (List<Machine>) GlobalCacheUtil.get("machines");
......@@ -805,11 +812,12 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
// }
// }
//
// FileHelper.writeLogFile("初始化设备日历-----------结束-------");
// GlobalCacheUtil.put("machines", machines, 10, TimeUnit.MINUTES);
// return machines;
}
}
FileHelper.writeLogFile("初始化设备日历-----------结束-------");
redisUtils.set("machines",machines);
GlobalCacheUtil.put("machines", machines, 10, TimeUnit.MINUTES);
return machines;
}
public List<Machine> InitCalendarToAllMachines ()
......
......@@ -3,8 +3,10 @@ package com.aps.demo;
import com.aps.ApsApplication;
import com.aps.common.util.RangeSubtractUtil;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.ObjectiveWeights;
import com.aps.entity.Gantt.ProductGanttVO;
import com.aps.entity.basic.Machine;
import com.aps.service.Algorithm.NSGAIIUtils;
import com.aps.service.plan.PlanResultService;
import com.aps.service.plan.SceneService;
import org.junit.jupiter.api.Test;
......@@ -30,9 +32,11 @@ public class PlanResultServiceTest {
// RangeSubtractUtil.test();
// planResultService.testSceneChromsome("qwerty");
// Chromosome chromosome= planResultService.moveChromosome("qwerty",3);
planResultService.execute2("B7881EF032044B9BA4F6007875510B70");
// planResultService.execute2("BE037838EF074B07B87D7DE763107398");
// planResultService.execute2("31EC5BAF7F6B41DFB79AB031D81C53C0");
// planResultService.execute2("B7881EF032044B9BA4F6007875510B70");
// NSGAIIUtils nsgaiiUtils=new NSGAIIUtils();
// nsgaiiUtils.Test();
planResultService.execute2("31EC5BAF7F6B41DFB79AB031D81C53C0");
// LocalDateTime t= LocalDateTime.of(2025, 11, 15, 6, 51, 11);
// List<Integer> opids=new ArrayList<>();
// 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