Commit a9f7d0cc authored by Tong Li's avatar Tong Li

遗传算法-增加kpi

parent 9640e865
...@@ -115,4 +115,45 @@ public class Chromosome { ...@@ -115,4 +115,45 @@ public class Chromosome {
private String ScenarioName; private String ScenarioName;
private LocalDateTime BaseTime ; // 当前基准时间 private LocalDateTime BaseTime ; // 当前基准时间
//最大设备利用率
private double machineMaxRate;
//最小设备利用率
private double machineMinRate;
//设备等待时长
private double machineWaitTime;
//订单及时完成率
private double orderOnTime;
//最大延迟
private double orderMaxDelay;
//最小延迟
private double orderMinDelay;
//平均延迟
private double orderAvgDelay;
//最长生产周期
private double orderMaxProductTime;
//最短生产周期
private double orderMinProductTime;
//平均生产周期
private double orderAvgProductTime;
//最大流量
private double orderMaxFlow;
//最小流量
private double orderMinFlow;
//平均流量
private double orderAvgFlow;
} }
...@@ -19,6 +19,10 @@ public class Machine { ...@@ -19,6 +19,10 @@ public class Machine {
private List<Holiday> holidays; private List<Holiday> holidays;
private double actualWorkTime;
private double rate;
// 事件回调 // 事件回调
private Consumer<Void> shiftsChanged; private Consumer<Void> shiftsChanged;
private Consumer<Void> maintenanceWindowsChanged; private Consumer<Void> maintenanceWindowsChanged;
......
...@@ -22,6 +22,12 @@ public class Order { ...@@ -22,6 +22,12 @@ public class Order {
private LocalDateTime dueDate; private LocalDateTime dueDate;
private LocalDateTime orderCompletion; private LocalDateTime orderCompletion;
private LocalDateTime orderStart;
private double machineProcessingTime;
private double orderFlow;
private double orderProductTime;
private double tardiness; private double tardiness;
private int priority; private int priority;
private boolean canSplit = false; private boolean canSplit = false;
...@@ -30,4 +36,6 @@ public class Order { ...@@ -30,4 +36,6 @@ public class Order {
private String mainId; private String mainId;
/*使用这个半成品的成品工单*/ /*使用这个半成品的成品工单*/
public List<String> FinishOrderId ; public List<String> FinishOrderId ;
private double delayHours;//延迟时间
} }
\ No newline at end of file
package com.aps.service.Algorithm;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GAScheduleResult;
import com.aps.entity.basic.Machine;
import com.aps.entity.basic.Order;
import com.aps.entity.basic.TimeSegment;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 作者:佟礼
* 时间:2025-12-10
*/
public class KpiCalculator {
private Chromosome chromosome;
private LocalDateTime baseTime;
public KpiCalculator(Chromosome _chromosome)
{
chromosome=_chromosome;
baseTime=_chromosome.getBaseTime();
}
public void calculatekpi() {
calculateMachine();
calculateOrder();
//最大设备利用率
double machineMaxRate = chromosome.getMachines().stream()
.mapToDouble(Machine::getRate)
.max()
.orElse(0);
chromosome.setMachineMaxRate(machineMaxRate);
//最小设备利用率
double machineMinRate = chromosome.getMachines().stream()
.mapToDouble(Machine::getRate)
.min()
.orElse(0);
chromosome.setMachineMinRate(machineMinRate);
double machineActualWorkTime = chromosome.getMachines().stream()
.mapToDouble(Machine::getActualWorkTime)
.sum();
double machineallWorkTime= calculateAllTimeSegmentsTotalDuration();
chromosome.setMachineWaitTime((machineallWorkTime-machineActualWorkTime)/60/60);
// 订单按时完成的数量
double orderNoDelayCount = chromosome.getOrders().stream()
.filter(t -> t.getDelayHours() <= 0)
.count();
//
double orderOnTime = Math.round(orderNoDelayCount / chromosome.getOrders().size() * 10000) / 10000 * 100;
chromosome.setOrderOnTime(orderOnTime);
//最大延迟
double OrderMaxDelay = chromosome.getOrders().stream()
.mapToDouble(Order::getDelayHours)
.max()
.orElse(0);
chromosome.setOrderMaxDelay(OrderMaxDelay);
//最小延迟
double OrderMinDelay = chromosome.getOrders().stream()
.mapToDouble(Order::getDelayHours)
.min()
.orElse(0);
chromosome.setOrderMinDelay(OrderMinDelay);
double OrderSumDelay = chromosome.getOrders().stream()
.mapToDouble(Order::getDelayHours)
.sum();
//平均延迟
double OrderDelay = Math.round(OrderSumDelay / chromosome.getOrders().size() * 100) / 100;
chromosome.setOrderAvgDelay(OrderDelay);
//最长生产周期
double OrderMaxProductTime = chromosome.getOrders().stream()
.mapToDouble(Order::getOrderProductTime)
.max()
.orElse(0);
chromosome.setOrderMaxProductTime(OrderMaxProductTime);
//最小生产周期
double OrderMinProductTime = chromosome.getOrders().stream()
.mapToDouble(Order::getOrderProductTime)
.min()
.orElse(0);
chromosome.setOrderMinProductTime(OrderMinProductTime);
double OrderSumProductTime = chromosome.getOrders().stream()
.mapToDouble(Order::getOrderProductTime)
.sum();
//平均生产周期
double OrderProductTime= Math.round(OrderSumProductTime / chromosome.getOrders().size() * 100) / 100;
chromosome.setOrderAvgProductTime(OrderProductTime);
//最大流量
double OrderMaxFlow = chromosome.getOrders().stream()
.mapToDouble(Order::getOrderFlow)
.max()
.orElse(0);
chromosome.setOrderMaxFlow(OrderMaxFlow);
//最小流量
double OrderMinFlow = chromosome.getOrders().stream()
.mapToDouble(Order::getOrderFlow)
.min()
.orElse(0);
chromosome.setOrderMinFlow(OrderMinFlow);
double OrderSumFlow = chromosome.getOrders().stream()
.mapToDouble(Order::getDelayHours)
.sum();
//平均流量
double OrderFlow= Math.round(OrderSumFlow / chromosome.getOrders().size() * 100) / 100;
chromosome.setOrderAvgFlow(OrderFlow);
}
/**
* 计算每台设备的利用率(实际工作时间/计划工作时间)
*
* @return 设备ID与利用率的Map
*/
private void calculateMachine() {
// 按设备ID分组工序列表(对应C# GroupBy + ToList)
Map<Long, List<GAScheduleResult>> machineTasks = chromosome.getResult().stream()
.collect(Collectors.groupingBy(GAScheduleResult::getMachineId));
// 计划工作时间:最后一个任务结束时间 - 第一个任务开始时间
int firstTaskStart = chromosome.getResult().stream()
.mapToInt(GAScheduleResult::getStartTime)
.max()
.orElse(0);
int lastTaskEnd = chromosome.getResult().stream()
.mapToInt(GAScheduleResult::getEndTime)
.max()
.orElse(0);
double plannedWorkTime = lastTaskEnd - firstTaskStart;
// 遍历每个设备的任务组计算利用率
for (Map.Entry<Long, List<GAScheduleResult>> entry : machineTasks.entrySet()) {
Long machineId = entry.getKey();
List<GAScheduleResult> tasks = entry.getValue();
// 按开始时间排序(对应C# OrderBy + ToList)
List<GAScheduleResult> sortedTasks = tasks.stream()
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toList());
// 计算实际工作时间:所有任务加工时间总和
double actualWorkTime = sortedTasks.stream()
.mapToDouble(GAScheduleResult::getProcessingTime)
.sum();
Machine machine= chromosome.getMachines().stream()
.filter(t->t.getId()==machineId)
.findFirst()
.orElse(null);
if(machine==null)
{
continue;
}
machine.setActualWorkTime(actualWorkTime);
// // 计划工作时间:最后一个任务结束时间 - 第一个任务开始时间
// int firstTaskStart = sortedTasks.get(0).getStartTime();
// int lastTaskEnd = sortedTasks.get(sortedTasks.size() - 1).getEndTime();
// double plannedWorkTime = lastTaskEnd - firstTaskStart;
double rate = Math.round((actualWorkTime / plannedWorkTime) * 10000) / 10000.0*100;
machine.setRate(rate);
}
}
/**
* 计算每个订单
*
* @return 订单ID与延迟时间(小时)的Map
*/
private void calculateOrder() {
// 按GroupId(订单ID)分组 - 对应C#的GroupBy
Map<String, List<GAScheduleResult>> orderGroups = chromosome.getResult().stream()
.collect(Collectors.groupingBy(GAScheduleResult::getOrderId));
for (Map.Entry<String, List<GAScheduleResult>> entry : orderGroups.entrySet()) {
String orderId = entry.getKey();
List<GAScheduleResult> processList = entry.getValue();
// 订单实际完工时间(该订单所有工序的最大结束时间)
int orderCompletion = processList.stream()
.mapToInt(GAScheduleResult::getEndTime)
.max()
.orElse(0);
// 订单实际开工时间(该订单所有工序的最早开工时间)
int orderStart = processList.stream()
.mapToInt(GAScheduleResult::getStartTime)
.min()
.orElse(0);
LocalDateTime actualCompletionTime = baseTime.plusSeconds(orderCompletion);
LocalDateTime actualStartTime = baseTime.plusSeconds(orderStart);
double orderProcessingTime = processList.stream()
.mapToDouble(GAScheduleResult::getProcessingTime)
.sum();
Order order= chromosome.getOrders().stream()
.filter(t->t.getOrderId()==orderId)
.findFirst()
.orElse(null);
if(order==null)
{
continue;
}
order.setOrderCompletion(actualCompletionTime);
order.setOrderStart(actualStartTime);
order.setMachineProcessingTime(orderProcessingTime);
Duration Orderduration = Duration.between(actualCompletionTime, actualStartTime);
double orderProductTime =Orderduration.getSeconds();
order.setOrderProductTime(orderProductTime/60/60);
double flow=Math.round(orderProcessingTime/orderProductTime *10000)/10000*100;
order.setOrderFlow(flow);
// 计算延迟时间(若提前完成则延迟为0)
if (actualCompletionTime.isAfter(order.getDueDate())) {
Duration duration = Duration.between(order.getDueDate(), actualCompletionTime);
double delayHours = duration.toMinutes() / 60.0; // 转换为小时
order.setDelayHours(delayHours);
} else {
Duration duration = Duration.between(actualCompletionTime,order.getDueDate());
double delayHours = duration.toMinutes() / 60.0; // 转换为小时
order.setDelayHours(0-delayHours);
}
}
}
/**
* 计算所有机器的所有TimeSegment时间段总时长(返回总秒数,便于转换单位)
*
* @return 所有时间段的总时长(秒)
*/
public long calculateAllTimeSegmentsTotalDuration() {
// 初始化总时长(秒)
long totalSeconds = 0;
// 遍历每台机器
for (Machine machine :chromosome.getMachines()) {
// 空值保护:若当前机器的时间段列表为空/Null,跳过
if (machine.getAvailability() == null || machine.getAvailability().isEmpty()) {
continue;
}
// 遍历当前机器的所有时间段,累加时长
for (TimeSegment segment : machine.getAvailability()) {
// 空值保护:跳过无效的时间段(开始/结束时间为Null)
if (segment.getStart() == null || segment.getEnd() == null) {
continue;
}
// 计算单个时间段的时长(秒),确保结束时间≥开始时间
LocalDateTime start = segment.getStart();
LocalDateTime end = segment.getEnd();
long segmentSeconds = Math.max(0, Duration.between(start, end).getSeconds());
totalSeconds += segmentSeconds;
}
}
return totalSeconds;
}
}
...@@ -650,6 +650,10 @@ public class ScheduleOperationService { ...@@ -650,6 +650,10 @@ public class ScheduleOperationService {
decoder.decode(chromosome); decoder.decode(chromosome);
KpiCalculator kpiCalculator=new KpiCalculator(chromosome);
kpiCalculator.calculatekpi();
// if(chromosome.getWeightedObjective()==0) { // if(chromosome.getWeightedObjective()==0) {
// //
// double[] normalized = objectiveWeights.normalizeObjectives(chromosome.getObjectives(), null, null); // double[] normalized = objectiveWeights.normalizeObjectives(chromosome.getObjectives(), null, null);
......
...@@ -13,10 +13,7 @@ import com.aps.entity.Schedule.GenVO; ...@@ -13,10 +13,7 @@ import com.aps.entity.Schedule.GenVO;
import com.aps.entity.Schedule.MachineVO; import com.aps.entity.Schedule.MachineVO;
import com.aps.entity.basic.*; import com.aps.entity.basic.*;
import com.aps.service.*; import com.aps.service.*;
import com.aps.service.Algorithm.GeneticAlgorithm; import com.aps.service.Algorithm.*;
import com.aps.service.Algorithm.IdGroupingWithDualSerial;
import com.aps.service.Algorithm.RoutingDataService;
import com.aps.service.Algorithm.ScheduleOperationService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -309,8 +306,11 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0)); ...@@ -309,8 +306,11 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
// 5. 执行调度算法 // 5. 执行调度算法
GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,null,machineScheduler,entryRel); //new GeneticAlgorithm(products, machines, orders, machineScheduler); GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,null,machineScheduler,entryRel); //new GeneticAlgorithm(products, machines, orders, machineScheduler);
param.initAdaptiveParams(entrys.size()); param.initAdaptiveParams(entrys.size());
Chromosome chromosome =scheduler.Run(param,entrys); Chromosome chromosome =scheduler.Run(param,entrys);
KpiCalculator kpiCalculator=new KpiCalculator(chromosome);
kpiCalculator.calculatekpi();
_sceneService.saveChromosomeToFile(chromosome, SceneId); _sceneService.saveChromosomeToFile(chromosome, SceneId);
// Chromosomes.forEach(this::WriteScheduleSummary); // Chromosomes.forEach(this::WriteScheduleSummary);
...@@ -524,7 +524,8 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0)); ...@@ -524,7 +524,8 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,null,machineScheduler,entryRel); //new GeneticAlgorithm(products, machines, orders, machineScheduler); GeneticAlgorithm scheduler =new GeneticAlgorithm(globalParam,machines,orders,null,machineScheduler,entryRel); //new GeneticAlgorithm(products, machines, orders, machineScheduler);
param.initAdaptiveParams(entrys.size()); param.initAdaptiveParams(entrys.size());
Chromosome chromosomes =scheduler.Run(param,entrys); Chromosome chromosomes =scheduler.Run(param,entrys);
KpiCalculator kpiCalculator=new KpiCalculator(chromosomes);
kpiCalculator.calculatekpi();
chromosomes.setScenarioID(SceneId); chromosomes.setScenarioID(SceneId);
chromosomes.setBaseTime(param.getBaseTime()); chromosomes.setBaseTime(param.getBaseTime());
chromosomes.setOperatRel(entryRel); chromosomes.setOperatRel(entryRel);
......
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