Commit 681b20a8 authored by Tong Li's avatar Tong Li

遗传算法

parent 15b3d7d4
......@@ -15,52 +15,52 @@ public class Chromosome {
/// <summary>
/// 机器选择部分(可选机器集中的顺序号)
/// </summary>
public List<Integer> MachineSelection;
private List<Integer> MachineSelection;
/// <summary>
/// 工序排序部分(工件/订单ID)
/// </summary>
public List<Integer> PperationSequencing;
private List<Integer> OperationSequencing;
/// <summary>
/// 适应度值
/// </summary>
public double Fitness;
private double Fitness;
/// <summary>
/// 机器
/// </summary>
public List<Machine> Machines;
private List<Machine> Machines;
/// <summary>
/// 解码后的调度结果
/// </summary>
public List<ScheduleResult> Result;
private List<ScheduleResult> Result;
/// <summary>
/// 最早完工时间
/// </summary>
public double Makespan;
private double Makespan;
/// <summary>
/// 总流程时间
/// </summary>
public double TotalFlowTime;
private double TotalFlowTime;
/// <summary>
/// 总换型时间
/// </summary>
public double TotalChangeoverTime;
private double TotalChangeoverTime;
/// <summary>
/// 机器负载标准差(越小越均衡)
/// </summary>
public double MachineLoadStd;
private double MachineLoadStd;
/// <summary>
/// 交付期延迟时间
/// </summary>
public double DelayTime;
private double DelayTime;
}
......@@ -7,24 +7,24 @@ import lombok.Data;
* 时间:2025-11-21
*/
@Data
public class GlobalOperationInfo {
public class GlobalOperationInfo {
/**
* 全局唯一工序ID(0开始递增)
*/
public int GlobalOpId;
private int GlobalOpId;
/**
* 所属组ID
*/
public int GroupId;
private int GroupId;
/**
* 订单内工序顺序号
*/
public int Sequence;
private int Sequence;
/**
* 对应的工序实例
*/
public Entry Op;
private Entry Op;
}
......@@ -11,13 +11,13 @@ public class OperationSequencingWeight {
/**
* 工序基因的序号
*/
public int Index ;
private int Index ;
/**
* 工序基因的值
*/
public int OsValue;
private int OsValue;
/**
* 权重
*/
public int Weight;
private int Weight;
}
......@@ -10,39 +10,39 @@ import java.util.Date;
* 时间:2025-11-21
*/
@Data
public class ScheduleParams {
public Date BaseTime = new Date(); // 当前基准时间
public class ScheduleParams {
private Date BaseTime = new Date(); // 当前基准时间
/// <summary>
/// 设备总数
/// </summary>
public int MachineCount; // 设备总数
private int MachineCount; // 设备总数
/// <summary>
/// 交叉概率
/// </summary>
public double CrossoverProb = 0.8;
private double CrossoverProb = 0.8;
/// <summary>
/// 变异概率
/// </summary>
public double MutationProb = 0.1; // 变异概率
private double MutationProb = 0.1; // 变异概率
/// <summary>
/// 种群规模
/// </summary>
public int PopulationSize = 50; // 种群规模
private int PopulationSize = 50; // 种群规模
/// <summary>
/// 最大迭代次数
/// </summary>
public int MaxIterations = 100; // 最大迭代次数
private int MaxIterations = 100; // 最大迭代次数
/// <summary>
/// 精英保留计数
/// </summary>
public int ElitismCount = 5;
private int ElitismCount = 5;
......@@ -50,17 +50,17 @@ public class ScheduleParams {
/// <summary>
/// 全局选择占比
/// </summary>
public double GsRatio = 0.4; // 全局选择占比
private double GsRatio = 0.4; // 全局选择占比
/// <summary>
/// 局部选择占比
/// </summary>
public double LsRatio = 0.4; // 局部选择占比
private double LsRatio = 0.4; // 局部选择占比
/// <summary>
/// 随机选择占比
/// </summary>
public double RsRatio = 0.2; // 随机选择占比
private double RsRatio = 0.2; // 随机选择占比
}
......@@ -10,15 +10,15 @@ import java.util.List;
*/
@Data
public class ScheduleResult {
public int GroupId;
public int ProductId;
public int OperationId;
public int MachineId;
public int StartTime; // 相对开始时间(分钟)
public int EndTime; // 相对结束时间(分钟)
public int Quantity; // 批次大小(订单可拆分)
public List<ScheduleResultDetail> GeneDetails; // 时间详情
public int OneTime; // 单件工时
public int ProcessingTime; // 绝对处理时间(分钟)
public int ChangeoverTime;
private int GroupId;
private int ProductId;
private int OperationId;
private int MachineId;
private int StartTime; // 相对开始时间(分钟)
private int EndTime; // 相对结束时间(分钟)
private int Quantity; // 批次大小(订单可拆分)
private List<ScheduleResultDetail> GeneDetails; // 时间详情
private int OneTime; // 单件工时
private int ProcessingTime; // 绝对处理时间(分钟)
private int ChangeoverTime;
}
......@@ -8,7 +8,7 @@ import lombok.Data;
*/
@Data
public class ScheduleResultDetail {
public String Key;
public int StartTime; // 相对开始时间(分钟)
public int EndTime; // 相对结束时间(分钟)
private String Key;
private int StartTime; // 相对开始时间(分钟)
private int EndTime; // 相对结束时间(分钟)
}
......@@ -17,17 +17,17 @@ public class MaterialRequirement {
/**
* 物料ID
*/
public int MaterialId;
private int MaterialId;
/**
* 物料类型
*/
public MaterialType MaterialType;
private MaterialType MaterialType;
/**
* 该工序需要的物料数量
*/
public BigDecimal RequiredQuantity;
private BigDecimal RequiredQuantity;
@Override
public String toString() {
......
......@@ -17,17 +17,17 @@ public class MaterialSupply {
/**
* 物料ID
*/
public int MaterialId;
private int MaterialId;
/**
* 数量
*/
public double Quantity;
private double Quantity;
/**
* 预计到货时间
*/
public LocalDateTime ArrivalTime;
private LocalDateTime ArrivalTime;
@Override
public String toString() {
......
package com.aps.service.Algorithm;
import com.aps.entity.Algorithm.OperationSequencingWeight;
import com.aps.entity.basic.Entry;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 作者:佟礼
* 时间:2025-11-21
*/
public class CommonCalculator {
public static List<OperationSequencingWeight> getOsw(List<Integer> os, List<Entry> allOperations) {
// 计算最大优先级并加1
int maxPriority = allOperations.stream()
.mapToInt(Entry::getPriority)
.max()
.orElse(0) + 1;
// 为每个工序分配权重
List<OperationSequencingWeight> weightedOs = new ArrayList<>();
for (int idx = 0; idx < os.size(); idx++) {
int groupId = os.get(idx);
// 查找对应groupId的第一个操作
Entry entry = allOperations.stream()
.filter(o -> o.getGroupId() == groupId)
.findFirst()
.orElse(null);
OperationSequencingWeight osw = new OperationSequencingWeight();
osw.setIndex(idx);
osw.setOsValue(groupId);
osw.setWeight(maxPriority - entry.getPriority());
weightedOs.add(osw);
}
return weightedOs;
}
public static int getOsIndex(List<OperationSequencingWeight> indexWeights) {
Random rnd = new Random();
int totalWeight = indexWeights.stream()
.mapToInt(OperationSequencingWeight::getWeight)
.sum();
int randomWeight = rnd.nextInt(totalWeight);
int cumulativeWeight = 0;
for (OperationSequencingWeight w : indexWeights) {
cumulativeWeight += w.getWeight();
if (cumulativeWeight >= randomWeight) {
return w.getIndex();
}
}
return 0;
}
public static int getOsIndex2(List<OperationSequencingWeight> weightedOs) {
Random rnd = new Random();
int totalWeight = weightedOs.stream()
.mapToInt(OperationSequencingWeight::getWeight)
.sum();
int randomWeight = rnd.nextInt(totalWeight);
int cumulativeWeight = 0;
int selectedIndex = -1;
for (int i = 0; i < weightedOs.size(); i++) {
cumulativeWeight += weightedOs.get(i).getWeight();
if (cumulativeWeight >= randomWeight) {
selectedIndex = i;
break;
}
}
return 0;
}
}
package com.aps.service.Algorithm;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GlobalOperationInfo;
import com.aps.entity.Algorithm.ScheduleParams;
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;
import java.util.stream.IntStream;
/**
* 作者:佟礼
* 时间:2025-11-21
*/
public class Initialization {
private static List<Entry> allOperations;
public Initialization(List<Entry> allOperations) {
Initialization.allOperations = allOperations;
}
/**
* 预生成全局工序列表(按“订单0→订单1→…+订单内工序1→2→…”排序,分配GlobalOpId)
*/
public List<GlobalOperationInfo> generateGlobalOpList() {
List<GlobalOperationInfo> globalOpList = new ArrayList<>();
int globalOpId = 0;
for (Entry op : allOperations) {
GlobalOperationInfo info = new GlobalOperationInfo();
info.setGlobalOpId(globalOpId);
info.setGroupId(op.getGroupId());
info.setSequence(op.getSequence());
info.setOp(op);
globalOpList.add(info);
globalOpId++;
}
return globalOpList;
}
/**
* 生成初始种群
*/
public List<Chromosome> generateInitialPopulation(ScheduleParams param, List<GlobalOperationInfo> globalOpList) {
List<Chromosome> population = new ArrayList<>();
int gsCount = (int) (param.getPopulationSize() * param.getGsRatio());
int lsCount = (int) (param.getPopulationSize() * param.getLsRatio());
int rsCount = param.getPopulationSize() - gsCount - lsCount;
// 全局选择(GS):按GlobalOpId顺序生成MachineSelection
for (int i = 0; i < gsCount; i++) {
population.add(generateGSChromosome(globalOpList, param.getMachineCount()));
}
// 局部选择(LS):按GlobalOpId顺序生成MachineSelection(仅负载计算范围不同)
for (int i = 0; i < lsCount; i++) {
population.add(generateLSChromosome(globalOpList, param.getMachineCount()));
}
// 随机选择(RS):按GlobalOpId顺序生成MachineSelection(仅机器选择随机)
for (int i = 0; i < rsCount; i++) {
population.add(generateRSChromosome(globalOpList, param.getMachineCount()));
}
return population;
}
/**
* 全局选择(GS)生成染色体(按GlobalOpId顺序生成MachineSelection)
*/
private Chromosome generateGSChromosome(List<GlobalOperationInfo> globalOpList, int machineCount) {
Chromosome chromosome = new Chromosome();
Map<Integer, Integer> machineLoad = new HashMap<>();
// int[] machineLoad = new int[machineCount + 1]; // 设备负载(1-based,设备ID从1开始)
List<Integer> ms = new ArrayList<>(); // MachineSelection(顺序=GlobalOpId顺序)
List<Integer> os = new ArrayList<>(); // OperationSequencing
List<Integer> osp = new ArrayList<>(); // 相同优先级OperationSequencing
int prevPriority = -1;
Random rnd = new Random();
// 步骤1:按GlobalOpId顺序为每道工序选择机器
for (GlobalOperationInfo globalOp : globalOpList) {
Entry op = globalOp.getOp();
int groupId = globalOp.getGroupId();
if (prevPriority != op.getPriority()) {
prevPriority = op.getPriority();
if (!osp.isEmpty()) {
// 打乱工序排序部分
Collections.shuffle(osp);
os.addAll(osp);
osp.clear();
}
}
// 选择“设备当前负载+工序加工时间”最小的机器(全局负载均衡)
List<MachineOption> optionalMachines = op.getMachineOptions();
MachineOption minLoadMachine = optionalMachines.stream()
.min(Comparator.comparingInt(m ->machineLoad.getOrDefault(m.getMachineId(), 0) + m.getProcessingTime()))
.orElseThrow(() -> new NoSuchElementException("MachineOption not found for machine: " ));
OptionalInt index = IntStream.range(0, optionalMachines.size())
.filter(i -> minLoadMachine.getMachineId()==optionalMachines.get(i).getMachineId())
.findFirst();
// 计算该机器在“可选机器列表”中的顺序号(1-based)
int machineSeq =index.orElse(0) ;//findIndex(optionalMachines, minLoadMachine.getMachineId()) + 1;
ms.add(machineSeq);
// 更新设备负载
machineLoad.put(minLoadMachine.getMachineId(),
machineLoad.getOrDefault(minLoadMachine.getMachineId(), 0) + minLoadMachine.getProcessingTime());
osp.add(groupId);
}
if (!osp.isEmpty()) {
Collections.shuffle(osp, rnd);
os.addAll(osp);
osp.clear();
}
// 步骤2:打乱工序排序部分(OS)
chromosome.setOperationSequencing(shuffleWithPriority(os));
chromosome.setMachineSelection(ms);
return chromosome;
}
/**
* 局部选择(LS)生成染色体(按GlobalOpId顺序,每个订单重新初始化负载)
*/
private Chromosome generateLSChromosome(List<GlobalOperationInfo> globalOpList, int machineCount) {
Chromosome chromosome = new Chromosome();
List<Integer> ms = new ArrayList<>();
List<Integer> os = new ArrayList<>();
Random rnd = new Random();
int currentOrderId = -1;
Map<Integer, Integer> machineLoad = new HashMap<>();
List<Integer> osp = new ArrayList<>();
int prevPriority = -1;
for (GlobalOperationInfo globalOp : globalOpList) {
Entry op = globalOp.getOp();
int groupId = globalOp.getGroupId();
if (prevPriority != op.getPriority()) {
prevPriority = op.getPriority();
if (!osp.isEmpty()) {
Collections.shuffle(osp, rnd);
os.addAll(osp);
osp.clear();
}
}
// 若切换到新订单,重置设备负载
if (groupId != currentOrderId) {
machineLoad.clear();
currentOrderId = groupId;
}
// 选择“当前订单内设备负载+加工时间”最小的机器
List<MachineOption> optionalMachines = op.getMachineOptions();
MachineOption minLoadMachine = optionalMachines.stream()
.min(Comparator.comparingInt(m -> machineLoad.getOrDefault(m.getMachineId(), 0) + m.getProcessingTime()))
.orElseThrow(() -> new NoSuchElementException("MachineOption not found for machine: " ));
OptionalInt index = IntStream.range(0, optionalMachines.size())
.filter(i -> minLoadMachine.getMachineId()==optionalMachines.get(i).getMachineId())
.findFirst();
int machineSeq = index.orElse(0) + 1;
ms.add(machineSeq);
// 更新设备负载
machineLoad.put(minLoadMachine.getMachineId(),
machineLoad.getOrDefault(minLoadMachine.getMachineId(), 0) + minLoadMachine.getProcessingTime());
osp.add(groupId);
}
if (!osp.isEmpty()) {
Collections.shuffle(osp, rnd);
os.addAll(osp);
osp.clear();
}
chromosome.setOperationSequencing(shuffleWithPriority(os));
chromosome.setMachineSelection(ms);
return chromosome;
}
/**
* 随机选择(RS)生成染色体(按GlobalOpId顺序,随机选择机器)
*/
private Chromosome generateRSChromosome(List<GlobalOperationInfo> globalOpList, int machineCount) {
Chromosome chromosome = new Chromosome();
List<Integer> ms = new ArrayList<>();
List<Integer> os = new ArrayList<>();
Random rnd = new Random();
List<Integer> osp = new ArrayList<>();
int prevPriority = -1;
for (GlobalOperationInfo globalOp : globalOpList) {
Entry op = globalOp.getOp();
int groupId = globalOp.getGroupId();
if (prevPriority != op.getPriority()) {
prevPriority = op.getPriority();
if (!osp.isEmpty()) {
Collections.shuffle(osp, rnd);
os.addAll(osp);
osp.clear();
}
}
// 随机选择一道工序的可选机器(1-based顺序号)
List<MachineOption> optionalMachines = op.getMachineOptions();
int randomSeq = rnd.nextInt(optionalMachines.size()) + 1;
ms.add(randomSeq);
osp.add(groupId);
}
if (!osp.isEmpty()) {
Collections.shuffle(osp, rnd);
os.addAll(osp);
osp.clear();
}
chromosome.setOperationSequencing(shuffleWithPriority(os));
chromosome.setMachineSelection(ms);
return chromosome;
}
/**
* 按优先级加权打乱工序排序(高优先级订单的工序更可能靠前)
*/
private List<Integer> shuffleWithPriority(List<Integer> os) {
if (!GlobalParam.IsBreakPriority) {
return new ArrayList<>(os);
}
Random rnd = new Random();
int maxPriority = allOperations.stream()
.mapToInt(Entry::getPriority)
.max()
.orElse(0) + 1;
// 为每个工序分配权重:低优先级订单的工序权重更高
List<WeightedGroup> weightedOs = os.stream()
.map(groupId -> {
Entry entry = allOperations.stream()
.filter(o -> o.getGroupId() == groupId)
.findFirst().orElse(null);
return new WeightedGroup(groupId, maxPriority - entry.getPriority());
})
.collect(Collectors.toList());
// 按权重随机排序(权重越高,被选中的概率越大)
List<Integer> shuffled = new ArrayList<>();
while (!weightedOs.isEmpty()) {
int totalWeight = weightedOs.stream().mapToInt(WeightedGroup::getWeight).sum();
int randomWeight = rnd.nextInt(totalWeight);
int cumulativeWeight = 0;
int selectedIndex = -1;
for (int i = 0; i < weightedOs.size(); i++) {
cumulativeWeight += weightedOs.get(i).getWeight();
if (cumulativeWeight >= randomWeight) {
selectedIndex = i;
break;
}
}
shuffled.add(weightedOs.get(selectedIndex).getGroupId());
weightedOs.remove(selectedIndex);
}
return shuffled;
}
/**
* 辅助类:用于权重排序
*/
private static class WeightedGroup {
private final int groupId;
private final int weight;
public WeightedGroup(int groupId, int weight) {
this.groupId = groupId;
this.weight = weight;
}
public int getGroupId() {
return groupId;
}
public int getWeight() {
return weight;
}
}
}
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