Commit ee581dc1 authored by Tong Li's avatar Tong Li

遗传算法

parent 4d69e6bd
......@@ -91,6 +91,7 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
......
This diff is collapsed.
package com.aps.controller.gantt;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.basic.ScheduleChromosome;
import com.aps.entity.Gantt.ProductGanttVO;
import com.aps.entity.Gantt.ResourceGanttVO;
......@@ -103,6 +104,16 @@ public class ResourceGanttController {
.collect(Collectors.toList());
}
@GetMapping("/getScene")
@Operation(summary = "获取所有场景ID", description = "获取所有场景ID")
public List<Chromosome> getScene() {
// 调用 PlanResultService 获取 ScheduleChromosome 列表
List<Chromosome> scheduleChromosomes = planResultService.execute1();
// 提取所有场景ID
return scheduleChromosomes;
}
/**
* 将 ScheduleChromosome 转换为 ResourceGanttVO 列表
* @param scheduleChromosome 调度结果
......
package com.aps.entity.Algorithm;
import com.aps.entity.Algorithm.ScheduleResult;
import com.aps.entity.basic.Machine;
import lombok.Data;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* 作者:佟礼
......@@ -12,16 +13,41 @@ import java.util.List;
*/
@Data
public class Chromosome {
private String ID = UUID.randomUUID().toString();
/// <summary>
/// 机器选择部分(可选机器集中的顺序号)
/// </summary>
private List<Integer> MachineSelection;
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
private String MachineStr;
public String getMachineStr() {
return MachineSelection.stream()
.map(String::valueOf) // 将每个 Integer 转换为 String
.collect(Collectors.joining(","));
};
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
private List<Integer> OperationSequencing;
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
private String OperationStr;
public String getOperationStr() {
return OperationSequencing.stream()
.map(String::valueOf) // 将每个 Integer 转换为 String
.collect(Collectors.joining("|"));
};
/// <summary>
/// 适应度值
/// </summary>
......@@ -35,7 +61,7 @@ public class Chromosome {
/// <summary>
/// 解码后的调度结果
/// </summary>
private List<ScheduleResult> Result;
private List<GAScheduleResult> Result;
/// <summary>
/// 最早完工时间
......
......@@ -9,7 +9,7 @@ import java.util.List;
* 时间:2025-11-21
*/
@Data
public class ScheduleResult {
public class GAScheduleResult {
private int GroupId;
private int ProductId;
private int OperationId;
......@@ -21,4 +21,9 @@ public class ScheduleResult {
private int OneTime; // 单件工时
private int ProcessingTime; // 绝对处理时间(分钟)
private int ChangeoverTime;
public int getFlowTime() {
return EndTime - StartTime;
};
}
package com.aps.entity.Algorithm;
import lombok.Data;
/**
* 作者:佟礼
* 时间:2025-11-25
*/
@Data
public class OpMachine {
/**
* 所属组ID
*/
private int GroupId;
/**
* 订单内工序顺序号
*/
private int Sequence;
/**
* 设备ID
*/
private int machineId;
/**
* 单件工时
*/
private int processingTime; // 加工时间
}
package com.aps.entity.Algorithm;
/**
* 作者:佟礼
* 时间:2025-11-24
*/
public class Pair<A, B> {
private final A first;
private final B second;
public Pair(A first, B second) {
this.first = first;
this.second = second;
}
public A getFirst() {
return first;
}
public B getSecond() {
return second;
}
}
......@@ -3,6 +3,7 @@ package com.aps.entity.Algorithm;
import com.aps.entity.basic.Entry;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
/**
......@@ -11,12 +12,9 @@ import java.util.Date;
*/
@Data
public class ScheduleParams {
private Date BaseTime = new Date(); // 当前基准时间
private LocalDateTime BaseTime ; // 当前基准时间
/// <summary>
/// 设备总数
/// </summary>
private int MachineCount; // 设备总数
/// <summary>
/// 交叉概率
......
......@@ -8,7 +8,7 @@ import lombok.Data;
@Data
public class MachineOption {
private int machineId;
private int processingTime; // 加工时间
private int processingTime; // 加工时间 (秒)
private int setupTime; // 换型时间(如果与前一个产品不同)
private int teardownTime; // 收尾时间(后处理时间)
private int contantTime; // 常数时间
......
......@@ -13,6 +13,8 @@ public class Order {
private int id;
private int productId;
private int quantity = 100; // 100个
private int sYQuantity;
private OffsetDateTime dueDate;
private LocalDateTime orderCompletion;
private double tardiness;
......
package com.aps.service.Algorithm;
import com.aps.entity.Algorithm.Chromosome;
/**
* 作者:佟礼
* 时间:2025-11-24
*/
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() );
// 适应度值(越大越好)
return w1 * normMakespan + w2 * normFlowTime + w3 * normChangeover + w4 * normLoadStd + w5 * normDelay;
}
}
package com.aps.service.Algorithm;
import com.aps.common.util.DeepCopyUtil;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GlobalOperationInfo;
import com.aps.entity.Algorithm.Pair;
import com.aps.entity.Algorithm.ScheduleParams;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.Machine;
import com.aps.entity.basic.Material;
import com.aps.entity.basic.Order;
import com.aps.service.plan.MachineSchedulerService;
import java.util.*;
import java.util.stream.Collectors;
/**
* 作者:佟礼
* 时间:2025-11-21
*/
public class GeneticAlgorithm {
public void Run() {
System.out.println("");
private final Random rnd = new Random();
private final List<Machine> machines;
private final MachineSchedulerService machineScheduler;
private final List<Order> orders;
private final List<Material> materials;
public GeneticAlgorithm(List<Machine> machines, List<Order> orders,
List<Material> materials, MachineSchedulerService machineScheduler) {
this.machines = machines;
this.orders = orders;
this.materials = materials;
this.machineScheduler = machineScheduler;
}
public List<Chromosome> Run(ScheduleParams param, List<Entry> allOperations) {
System.out.println("开始");
Initialization initialization = new Initialization(allOperations);
GeneticOperations geneticOps = new GeneticOperations(allOperations);
// 预生成全局工序列表(所有初始化方法共享同一顺序)
List<GlobalOperationInfo> globalOpList = initialization.generateGlobalOpList();
// 步骤1:初始化种群
List<Chromosome> population = initialization.generateInitialPopulation(param, globalOpList);
Chromosomedecode(param,allOperations,globalOpList,population);
int ordercount = globalOpList.stream()
.mapToInt(GlobalOperationInfo::getGroupId)
.max()
.orElse(0);
Chromosome best=new Chromosome();
double bestFitness=0;
int Iteration=0;
// 步骤2:迭代进化
for (int iter = 0; iter < param.getMaxIterations(); iter++) {
// 解码并计算适应度
// 检查终止条件(此处简化为迭代次数)
if (iter == param.getMaxIterations() - 1) {
break;
}
// 选择操作
List<Chromosome> selected = geneticOps.tournamentSelection(population);
// 交叉操作
List<Chromosome> nextPopulation = new ArrayList<>();
for (int i = 0; i < selected.size(); i += 2) {
if (i + 1 >= selected.size()) {
nextPopulation.add(selected.get(i));
break;
}
Chromosome parent1 = selected.get(i);
Chromosome parent2 = selected.get(i + 1);
if (rnd.nextDouble() < param.getCrossoverProb()) {
// 假设PoxCrossover返回包含两个子染色体的数组
Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
nextPopulation.add(children.getFirst());
nextPopulation.add(children.getSecond());
} else {
nextPopulation.add(parent1);
nextPopulation.add(parent2);
}
}
// 变异操作
for (Chromosome chromosome : nextPopulation) {
if (rnd.nextDouble() < param.getMutationProb()) {
geneticOps.mutate(chromosome, globalOpList);
}
}
// 精英保留
List<Chromosome> population1 = population.stream()
.sorted((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()))
.collect(Collectors.toList()); // 降序排序
List<Chromosome> elites = population1.subList(0, param.getElitismCount());
List<Chromosome> newPopulation = new ArrayList<>();
newPopulation.addAll(elites);
newPopulation.addAll(nextPopulation);
// 更新种群
population = newPopulation.stream()
.limit(param.getPopulationSize() )
.collect(Collectors.toList());
Chromosomedecode(param,allOperations,globalOpList,population);
best= population.stream()
.max(Comparator.comparingDouble(Chromosome::getFitness))
.orElse(null);
if(bestFitness<best.getFitness())
{
bestFitness=best.getFitness();
}else {
Iteration++;
}
if(Iteration>20)
{
break;
}
}
// 步骤3:返回最优解
return population.stream()
.sorted((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()))
.limit(10)
.collect(Collectors.toList());
}
private void Chromosomedecode(ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList,List<Chromosome> population)
{
GeneticDecoder decoder = new GeneticDecoder(param.getBaseTime(), machines, orders, materials, machineScheduler);
FitnessCalculator fitnessCalc = new FitnessCalculator();
population.parallelStream().forEach(chromosome -> {
chromosome.setResult(new ArrayList<>());
// 假设Machine类有拷贝方法,或使用MapStruct等工具进行映射
chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines)); // 简单拷贝,实际可能需要深拷贝
decoder.decodeChromosomeWithCache(chromosome, globalOpList, allOperations);
chromosome.setFitness(fitnessCalc.calculateFitness(chromosome));
});
}
}
This diff is collapsed.
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.OperationSequencingWeight;
import com.aps.entity.Algorithm.Pair;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.GlobalParam;
import com.aps.entity.basic.MachineOption;
import java.util.*;
import java.util.stream.Collectors;
/**
* 作者:佟礼
* 时间:2025-11-24
*/
public class GeneticOperations {
private final Random rnd = new Random();
private static List<Entry> allOperations;
public GeneticOperations(List<Entry> allOperations) {
GeneticOperations.allOperations = allOperations;
}
/**
* 锦标赛选择
*/
public List<Chromosome> tournamentSelection(List<Chromosome> population, int tournamentSize) {
List<Chromosome> selected = new ArrayList<>();
while (selected.size() < population.size()) {
// 随机选择k个个体
// List<Chromosome> candidates = population.stream()
// .sorted((a, b) -> rnd.nextInt())
// .limit(tournamentSize)
// .collect(Collectors.toList());
// 步骤1: 创建一个临时列表用于存放候选者
List<Chromosome> candidates = new ArrayList<>(population);
// 步骤2: 随机打乱候选者列表
Collections.shuffle(candidates, rnd);
// 步骤3: 截取前 tournamentSize 个元素作为本次锦标赛的参与者
if (tournamentSize < candidates.size()) {
candidates = candidates.subList(0, tournamentSize);
}
// 步骤4: 从参与者中选择适应度最高的个体
Chromosome best = candidates.stream()
.max(Comparator.comparingDouble(Chromosome::getFitness))
.orElseThrow(() -> new IllegalStateException("候选列表为空,无法选择最佳个体。"));
// 复制个体(假设Chromosome有复制方法或通过构造函数复制)
selected.add(ProductionDeepCopyUtil.deepCopy(best));
}
return selected;
}
// 重载,使用默认锦标赛大小3
public List<Chromosome> tournamentSelection(List<Chromosome> population) {
return tournamentSelection(population, 3);
}
/**
* 改进POX交叉(工序排序部分)
*/
public Pair<Chromosome, Chromosome> poxCrossover(Chromosome parent1, Chromosome parent2, int orderCount) {
// 步骤1:随机划分工件集
List<Integer> jobset1 = new ArrayList<>();
for (int i = 0; i < orderCount; i++) {
jobset1.add(i);
}
Collections.shuffle(jobset1, rnd);
jobset1 = jobset1.subList(0, orderCount / 2);
Set<Integer> jobset1Set = new HashSet<>(jobset1);
List<Integer> jobset2 = new ArrayList<>();
for (int i = 0; i < orderCount; i++) {
if (!jobset1Set.contains(i)) {
jobset2.add(i);
}
}
// 步骤2:生成子代1
List<Integer> child1Os = new ArrayList<>();
for (int i = 0; i < parent1.getOperationSequencing().size(); i++) {
int op1 = parent1.getOperationSequencing().get(i);
int op2 = parent2.getOperationSequencing().get(i);
if (jobset1Set.contains(op1) || jobset1Set.contains(op2)) {
child1Os.add(op1);
} else {
child1Os.add(op2);
}
}
// 步骤3:生成子代2
List<Integer> child2Os = new ArrayList<>();
for (int i = 0; i < parent2.getOperationSequencing().size(); i++) {
int op1 = parent1.getOperationSequencing().get(i);
int op2 = parent2.getOperationSequencing().get(i);
if (jobset1Set.contains(op2) || jobset1Set.contains(op1)) {
child2Os.add(op2);
} else {
child2Os.add(op1);
}
}
// 机器选择部分交叉
List<Integer> child1Ms = new ArrayList<>();
List<Integer> child2Ms = new ArrayList<>();
for (int i = 0; i < parent1.getMachineSelection().size(); i++) {
int m1 = parent1.getMachineSelection().get(i);
int m2 = parent2.getMachineSelection().get(i);
if (rnd.nextDouble() < 0.5) {
child1Ms.add(m1);
child2Ms.add(m2);
} else {
child1Ms.add(m2);
child2Ms.add(m1);
}
}
Chromosome child1 = new Chromosome();
child1.setMachineSelection(child1Ms);
child1.setOperationSequencing(child1Os);
Chromosome child2 = new Chromosome();
child2.setMachineSelection(child2Ms);
child2.setOperationSequencing(child2Os);
return new Pair<>(child1, child2);
}
/**
* 变异操作
*/
public void mutate(Chromosome chromosome, List<GlobalOperationInfo> globalOpList, double baseMutationProb) {
// 1. 机器选择部分变异
mutateMachineSelection(chromosome, globalOpList, baseMutationProb);
// 2. 工序排序部分变异
mutateOperationSequencing(chromosome);
}
// 重载,使用默认变异概率
public void mutate(Chromosome chromosome, List<GlobalOperationInfo> globalOpList) {
mutate(chromosome, globalOpList, 0.1);
}
private void mutateMachineSelection(Chromosome chromosome, List<GlobalOperationInfo> globalOpList, double baseMutationProb) {
// 计算变异位置数量
int r = Math.max(1, (int) (chromosome.getMachineSelection().size() * baseMutationProb));
int i = 0;
while (i < r) {
int pos = rnd.nextInt(chromosome.getMachineSelection().size());
// 获取对应工序
GlobalOperationInfo opInfo = globalOpList.get(pos);
Entry operation = opInfo.getOp();
int machineSeq = chromosome.getMachineSelection().get(pos);
if (operation.getMachineOptions().size() == 1) {
continue;
} else {
// 选择当前所选设备外最短加工时间的机器
List<MachineOption> optionalMachines = operation.getMachineOptions();
// 找到当前选中的机器
MachineOption currentMachine = optionalMachines.get(machineSeq - 1);
// 筛选其他机器并找到加工时间最短的
MachineOption minLoadMachine = optionalMachines.stream()
.filter(m -> m.getMachineId() != currentMachine.getMachineId())
.min(Comparator.comparingInt(m -> m.getProcessingTime()))
.orElse(currentMachine); // 如果没有其他机器,保持当前
machineSeq = optionalMachines.indexOf(minLoadMachine) + 1;
chromosome.getMachineSelection().set(pos, machineSeq);
i++;
}
}
}
/**
* 低优先级优先的工序排序变异
*/
private void mutateOperationSequencing(Chromosome chromosome) {
Random rnd = new Random();
// 选择变异方式(交换或反转)
if (rnd.nextDouble() < 0.5) {
// 交换:优先选择高优先级工序的索引
OperationSequencingWeight os1 = selectHighPriorityIndex(chromosome.getOperationSequencing(), 0);
int idx1 = os1.getIndex();
OperationSequencingWeight os2 = selectHighPriorityIndex(chromosome.getOperationSequencing(), os1.getWeight());
int idx2 = os2.getIndex();
// 交换位置
List<Integer> os = chromosome.getOperationSequencing();
Collections.swap(os, idx1, idx2);
} else {
// 反转:仅对高优先级工序集中的子序列反转
OperationSequencingWeight osStart = selectHighPriorityIndex(chromosome.getOperationSequencing(), 0);
int start = osStart.getIndex();
OperationSequencingWeight osEnd = selectHighPriorityIndex(chromosome.getOperationSequencing(), osStart.getWeight());
int end = osEnd.getIndex();
if (start > end) {
int temp = start;
start = end;
end = temp;
}
// 执行反转
List<Integer> os = chromosome.getOperationSequencing();
for (int i = 0; i < (end - start + 1) / 2; i++) {
int pos1 = start + i;
int pos2 = end - i;
Collections.swap(os, pos1, pos2);
}
}
}
/**
* 优先选择高优先级工序的索引(用于变异)
*/
private OperationSequencingWeight selectHighPriorityIndex(List<Integer> os, int weight) {
Random rnd = new Random();
List<OperationSequencingWeight> indexWeights = CommonCalculator.getOsw(os, allOperations);
if (!GlobalParam.IsBreakPriority) {
if (weight == 0) {
return indexWeights.get(rnd.nextInt(indexWeights.size()));
} else {
List<OperationSequencingWeight> filtered = indexWeights.stream()
.filter(t -> t.getWeight() == weight)
.collect(Collectors.toList());
return filtered.get(rnd.nextInt(filtered.size()));
}
}
return indexWeights.get(CommonCalculator.getOsIndex(indexWeights));
}
}
......@@ -43,33 +43,42 @@ public class Initialization {
*/
public List<Chromosome> generateInitialPopulation(ScheduleParams param, List<GlobalOperationInfo> globalOpList) {
List<Chromosome> population = new ArrayList<>();
// 按比例生成不同类型个体(GS:40%, LS:40%, RS:20%)
int gsCount = (int) (param.getPopulationSize() * param.getGsRatio());
int lsCount = (int) (param.getPopulationSize() * param.getLsRatio());
int lsCount =gsCount+ (int) (param.getPopulationSize() * param.getLsRatio());
int rsCount = param.getPopulationSize() - gsCount - lsCount;
int populationSize=param.getPopulationSize();
// 并行循环:对应 Parallel.For(0, PopulationSize, i => { ... })
IntStream.range(0, populationSize)
.parallel() // 开启并行
.forEach(i -> {
Chromosome chromo = new Chromosome(); // 初始化染色体
// 全局选择(GS):按GlobalOpId顺序生成MachineSelection
for (int i = 0; i < gsCount; i++) {
population.add(generateGSChromosome(globalOpList, param.getMachineCount()));
}
if (i < gsCount) {
generateGSChromosome(chromo,globalOpList); // 对应 C# GenerateGSChromosome
} else if (i < lsCount) {
// 局部选择(LS):按GlobalOpId顺序生成MachineSelection(仅负载计算范围不同)
for (int i = 0; i < lsCount; i++) {
population.add(generateLSChromosome(globalOpList, param.getMachineCount()));
}
generateLSChromosome(chromo,globalOpList);
} else {
// 随机选择(RS):按GlobalOpId顺序生成MachineSelection(仅机器选择随机)
for (int i = 0; i < rsCount; i++) {
population.add(generateRSChromosome(globalOpList, param.getMachineCount()));
generateRSChromosome(chromo,globalOpList);
}
population.add(chromo); // 赋值到数组,线程安全(数组索引唯一)
});
return population;
}
/**
* 全局选择(GS)生成染色体(按GlobalOpId顺序生成MachineSelection)
*/
private Chromosome generateGSChromosome(List<GlobalOperationInfo> globalOpList, int machineCount) {
Chromosome chromosome = new Chromosome();
private Chromosome generateGSChromosome(Chromosome chromosome,List<GlobalOperationInfo> globalOpList) {
Map<Integer, Integer> machineLoad = new HashMap<>();
// int[] machineLoad = new int[machineCount + 1]; // 设备负载(1-based,设备ID从1开始)
List<Integer> ms = new ArrayList<>(); // MachineSelection(顺序=GlobalOpId顺序)
......@@ -106,7 +115,7 @@ public class Initialization {
.findFirst();
// 计算该机器在“可选机器列表”中的顺序号(1-based)
int machineSeq =index.orElse(0) ;//findIndex(optionalMachines, minLoadMachine.getMachineId()) + 1;
int machineSeq =index.orElse(0)+1 ;//findIndex(optionalMachines, minLoadMachine.getMachineId()) + 1;
ms.add(machineSeq);
// 更新设备负载
......@@ -132,8 +141,9 @@ public class Initialization {
/**
* 局部选择(LS)生成染色体(按GlobalOpId顺序,每个订单重新初始化负载)
*/
private Chromosome generateLSChromosome(List<GlobalOperationInfo> globalOpList, int machineCount) {
Chromosome chromosome = new Chromosome();
private Chromosome generateLSChromosome(Chromosome chromosome,List<GlobalOperationInfo> globalOpList) {
List<Integer> ms = new ArrayList<>();
List<Integer> os = new ArrayList<>();
Random rnd = new Random();
......@@ -199,8 +209,9 @@ public class Initialization {
/**
* 随机选择(RS)生成染色体(按GlobalOpId顺序,随机选择机器)
*/
private Chromosome generateRSChromosome(List<GlobalOperationInfo> globalOpList, int machineCount) {
Chromosome chromosome = new Chromosome();
private Chromosome generateRSChromosome(Chromosome chromosome,List<GlobalOperationInfo> globalOpList) {
List<Integer> ms = new ArrayList<>();
List<Integer> os = new ArrayList<>();
Random rnd = new Random();
......
This diff is collapsed.
package com.aps.service.plan;
import com.aps.common.util.FileHelper;
import com.aps.common.util.JsonFileReader;
import com.aps.controller.gantt.FileUploadController;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GAScheduleResult;
import com.aps.entity.Algorithm.ScheduleParams;
import com.aps.entity.Algorithm.ScheduleResultDetail;
import com.aps.entity.basic.ScheduleChromosome;
import com.aps.entity.Schedule.GenVO;
import com.aps.entity.Schedule.MachineVO;
......@@ -13,9 +18,7 @@ import org.springframework.stereotype.Service;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@Service
......@@ -92,10 +95,9 @@ public class PlanResultService {
}
}
public List<ScheduleChromosome> execute1() {
public List<Chromosome> execute1() {
try {
Entry entry=new Entry();
// 1. 读取数据
List<Machine> machines = loadData("machines.json", Machine.class);
......@@ -122,6 +124,11 @@ public class PlanResultService {
}
}
}
ScheduleParams param = new ScheduleParams();
param.setBaseTime(LocalDateTime.of(2025, 10, 1, 0, 0, 0));
param.setPopulationSize(50);
param.setMaxIterations(100);
// 创建节假日
List<Holiday> holidays = Arrays.asList(
......@@ -134,34 +141,118 @@ public class PlanResultService {
// 3. 创建调度服务
MachineSchedulerService machineScheduler = new MachineSchedulerService(
holidays, LocalDateTime.of(2025, 10, 1, 0, 0, 0));
holidays, param.getBaseTime());
// 4. 初始化机器时间线
for (Machine machine : machines) {
MachineTimeline timeline = machineScheduler.getOrCreateTimeline(machine);
machine.setAvailability(timeline.getSegments());
}
// 3. 构建订单-工序数据
List<Entry> allOperations = new ArrayList<>();
Random rnd = new Random(); // 注意:此处变量声明但未使用,可根据实际需求保留或移除
int id = 1;
for (Order order : orders) {
// 假设products是一个List<Product>,根据Product的Id查找对应的产品
Product product = products.stream()
.filter(p -> p.getId() == order.getProductId())
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("未找到对应产品: " + order.getProductId()));
int sequence = 1;
for (Operation o : product.getOperations()) { // 假设Product类有getOperations()方法返回工序列表
Entry entry = new Entry();
entry.setId(id);
entry.setGroupId(order.getId());
entry.setSequence(sequence);
entry.setMachineOptions(o.getMachineOptions()); // 假设Operation类有获取机器选项的方法
entry.setPriority(order.getPriority());
entry.setQuantity(order.getQuantity());
// entry.setMaterialRequirements(o.getMaterialRequirements()); // 假设Operation类有获取物料需求的方法
if (sequence != 1) {
entry.getPrevEntryIds().add(id - 1); // 假设Entry类有getPrevEntryIds()返回List<Integer>
}
allOperations.add(entry);
sequence++;
id++;
}
}
// 5. 执行调度算法
GeneticAlgorithm scheduler =new GeneticAlgorithm(); //new GeneticAlgorithm(products, machines, orders, machineScheduler);
List<ScheduleChromosome> scheduleChromosomes =null;
scheduler.Run();
GeneticAlgorithm scheduler =new GeneticAlgorithm(machines,orders,null,machineScheduler); //new GeneticAlgorithm(products, machines, orders, machineScheduler);
List<Chromosome> Chromosomes =scheduler.Run(param,allOperations);
// 对调度结果按照 fitness 由高到低排序
scheduleChromosomes.sort((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()));
Chromosomes.forEach(this::WriteScheduleSummary);
// 为每个 ScheduleChromosome 分配场景ID(基于排序后的位置)
for (int i = 0; i < scheduleChromosomes.size(); i++) {
scheduleChromosomes.get(i).setSceneId(i + 1); // 场景ID从1开始
}
return scheduleChromosomes;
return Chromosomes;
} catch (Exception e) {
throw new RuntimeException("调度执行失败", e);
}
}
public void WriteScheduleSummary(Chromosome schedule) {
// 写入日志
FileHelper.writeLogFile(String.format("\n=== Schedule Summary === %f", schedule.getFitness()));
FileHelper.writeLogFile(String.format("Operation: %s", schedule.getOperationStr()));
FileHelper.writeLogFile(String.format("Makespan: %f minutes", schedule.getMakespan()));
FileHelper.writeLogFile(String.format("Total Tardiness: %f hours", schedule.getDelayTime()));
FileHelper.writeLogFile(String.format("Setup Time: %f minutes", schedule.getTotalChangeoverTime()));
FileHelper.writeLogFile(String.format("Flow Time: %f minutes", schedule.getTotalFlowTime()));
FileHelper.writeLogFile(String.format("Machine Load Balance: %.2f%%", schedule.getMachineLoadStd() * 100));
FileHelper.writeLogFile("-------------------------");
// 按订单分组写入
Map<Integer, List<GAScheduleResult>> orderGroups = schedule.getResult().stream()
.collect(Collectors.groupingBy(GAScheduleResult::getGroupId));
for (Map.Entry<Integer, List<GAScheduleResult>> group : orderGroups.entrySet()) {
List<GAScheduleResult> sortedJobs = group.getValue().stream()
.sorted(Comparator.comparingInt(GAScheduleResult::getOperationId))
.collect(Collectors.toList());
for (GAScheduleResult job : sortedJobs) {
StringBuilder sb = new StringBuilder();
sb.append(String.format(
"[%d-%d]:[%s-%s] Order %d, Machine %d, Operation %d, Batch %d, processingTime %d",
job.getStartTime(),
job.getEndTime(),
ConvertTime(job.getStartTime()),
ConvertTime(job.getEndTime()),
job.getGroupId(),
job.getMachineId(),
job.getOperationId(),
job.getQuantity(),
job.getProcessingTime()
));
// 追加基因详情
for (ScheduleResultDetail d : job.getGeneDetails()) {
sb.append(String.format(
"\n\t\t\t\t\t\t\t\t\t\t [%d-%d]:[%s-%s] %d",
d.getStartTime(),
d.getEndTime(),
ConvertTime(d.getStartTime()),
ConvertTime(d.getEndTime()),
d.getEndTime() - d.getStartTime()
));
}
FileHelper.writeLogFile(sb.toString());
}
FileHelper.writeLogFile("");
}
}
private String ConvertTime(int minute) {
return baseTime.plusMinutes(minute).format(java.time.format.DateTimeFormatter.ofPattern("MM-dd HH:mm"));
}
/**
* 加载数据,优先从上传文件夹加载,如果不存在则从resources加载
......
......@@ -23,23 +23,23 @@ spring:
# 默认数据源
strict: false # 关闭严格模式
datasource:
# MySQL数据源
mysql:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.0.181:3310/mes?useSSL=false&serverTimezone=UTC
username: root # 替换为你的MySQL用户名
password: root_mes@123456~ # 替换为你的MySQL密码
# # MySQL数据源
# mysql:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.0.181:3310/mes?useSSL=false&serverTimezone=UTC
# username: root # 替换为你的MySQL用户名
# password: root_mes@123456~ # 替换为你的MySQL密码
# Oracle数据源
oracle:
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@//192.168.0.181:1522/ORCLPDB1 # ORCL为你的Oracle实例名
url: jdbc:oracle:thin:@//39.100.78.207:7002/ORCLPDB1 # ORCL为你的Oracle实例名
username: mes # 替换为你的Oracle用户名
password: root_mes123456 # 替换为你的Oracle密码
sqlserver:
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://192.168.0.181:1434;databaseName=mes;encrypt=false
username: sa
password: root_mes123456
# sqlserver:
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://192.168.0.181:1434;databaseName=mes;encrypt=false
# username: sa
# password: root_mes123456
# 文件上传配置
......
......@@ -5,6 +5,8 @@
"startTime": "08:00:00",
"endTime": "18:00:00",
"days": [1, 2, 3, 4, 5],
"startDate": "2025-10-10T00:00:00",
"endDate": "2025-11-10T00:00:00",
"shiftDate": "0001-01-01T00:00:00",
"temporaryShift": false,
"priority": 0,
......
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