Commit 6430785e authored by DESKTOP-VKRD9QF\Administration's avatar DESKTOP-VKRD9QF\Administration
parents 247fcbd2 ff8e1628
......@@ -7,6 +7,7 @@ import java.util.List;
public class OrderSortRule {
private boolean enabled;
private List<SortCondition> conditions;
//private boolean minimizeChangeover=false;
@Data
public static class SortCondition {
......
......@@ -176,4 +176,11 @@ public class Order {
* 物料需求
*/
private List<OrderMaterialRequirement> materialRequirementList;
/**
* 换线成本
*/
private double changeoverCost;
private int changeoverPriority;
}
\ No newline at end of file
......@@ -479,19 +479,19 @@ if(finishedOrder==null||finishedOrder.size()==0)
}
int setupTime=0;
CopyOnWriteArrayList<GAScheduleResult> machineTasks=null;
CopyOnWriteArrayList<GAScheduleResult> machineTasks1 =chromosome.getResult().stream()
CopyOnWriteArrayList<GAScheduleResult> machineTasks =chromosome.getResult().stream()
.filter(t -> t.getMachineId() == machine.getId())
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
GAScheduleResult lastGeneOnMachine = null;
if(machineTasks1!=null&&machineTasks1.size()>0)
if(machineTasks!=null&&machineTasks.size()>0)
{
lastGeneOnMachine=machineTasks1.get(machineTasks1.size()-1);
lastGeneOnMachine=machineTasks.get(machineTasks.size()-1);
}
if(lastGeneOnMachine!=null)
if(lastGeneOnMachine!=null&&_globalParam.is_smoothChangeOver())
{
earliestStartTime = Math.max(earliestStartTime,lastGeneOnMachine.getEndTime());
}
......@@ -533,16 +533,16 @@ if(finishedOrder==null||finishedOrder.size()==0)
}
machineTasks1 =chromosome.getResult().stream()
machineTasks =chromosome.getResult().stream()
.filter(t -> t.getMachineId() == machine.getId())
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
if(machineTasks1!=null&&machineTasks1.size()>0)
if(machineTasks!=null&&machineTasks.size()>0&&_globalParam.is_smoothChangeOver())
{
lastGeneOnMachine=machineTasks1.get(machineTasks1.size()-1);
lastGeneOnMachine=machineTasks.get(machineTasks.size()-1);
}
if (_globalParam.is_smoothChangeOver()) {
......@@ -702,6 +702,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
}
}
}
//重叠
List<OperationDependency> SSOperations = currentOp.getPrevEntryIds().stream()
.filter(t -> t.getDependencyType() == DependencyType.StartToStart)
.collect(Collectors.toList());//重叠
......@@ -726,6 +727,18 @@ if(finishedOrder==null||finishedOrder.size()==0)
.orElse(0);
prevtime = calculateNextOperationStartTime(newScheduleResult, newScheduleResultDetails, 0, processTime);
// 下一工序结束时间需晚于上一工序结束时间一个产品加工时间
// int ssStartTimeWithCalendar = calculateSSStartTimeWithCalendar(
// newScheduleResult,
// newScheduleResultDetails,
// currentOp,
// machine,
// processTime,
// prevtime);
//
// prevtime = Math.max(prevtime, ssStartTimeWithCalendar);
double nextopplanend = prevperationEndTime + processTime;
List<ScheduleResultDetail> geneDetails1 = machineCalculator.checkMachineStartTime(machine, (int) (processTime * currentOp.getQuantity()),
......@@ -1054,6 +1067,155 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
// 单设备时使用原逻辑
return (int)calculateWithSingleMachine(details, leadCount, time1);
}
/**
* 计算基于日历重叠约束的开始时间
* 整合了产能计算和连续性检查
* @param prevScheduleResults 前一工序的调度结果
* @param prevDetails 前一工序的详细调度信息
* @param currentOp 当前工序
* @param machine 当前工序的目标机器
* @param processTime 当前工序的处理时间
* @param prevtime 基础前序时间
* @return 修正后的开始时间
*/
private int calculateSSStartTimeWithCalendar(List<GAScheduleResult> prevScheduleResults,
List<ScheduleResultDetail> prevDetails,
Entry currentOp, Machine machine,
double processTime, int prevtime) {
if (prevScheduleResults == null || prevScheduleResults.isEmpty()) {
return prevtime;
}
//前工序生产数量和
double qty = prevScheduleResults.stream()
.mapToDouble(GAScheduleResult::getQuantity)
.sum();
if (qty <= 0) {
return prevtime;
}
double prevTimePerUnit = prevScheduleResults.stream()
.mapToDouble(r -> r.getOneTime())
.sum() / qty;
double currentTimePerUnit = processTime;
int leadCount = (int) calculateLeadProductionItems(qty, prevTimePerUnit, currentTimePerUnit);
int productionTimeForLeadCount = calculateProductionTimeWithCalendar(
prevDetails, leadCount, machine, currentOp);
int prevEndTime = prevScheduleResults.stream()
.mapToInt(GAScheduleResult::getEndTime)
.max()
.orElse(0);
int minEndTimeForContinuity = prevEndTime - (int) ((qty - leadCount) * prevTimePerUnit);
int adjustedStartTime = Math.max(productionTimeForLeadCount, minEndTimeForContinuity);
adjustedStartTime = Math.max(adjustedStartTime, prevtime);
int totalProcessingTime = (int) (currentTimePerUnit * qty);
int continuityAdjustedTime = ensureContinuousProduction(machine, adjustedStartTime,
totalProcessingTime, currentOp);
return Math.max(adjustedStartTime, continuityAdjustedTime);
}
/**
* 确保下一工序能够连续生产(不中断)
* 检查并调整开始时间以保证生产连续性
*/
private int ensureContinuousProduction(Machine machine, int proposedStartTime,
int processingTime, Entry currentOp) {
if (machine == null || processingTime <= 0) {
return proposedStartTime;
}
LocalDateTime proposedStart = baseTime.plusSeconds(proposedStartTime);
LocalDateTime proposedEnd = proposedStart.plusSeconds(processingTime);
CopyOnWriteArrayList<TimeSegment> availableSegments = machineCalculator.getMachineAvailableTime(
machine, proposedStartTime, processingTime, null, currentOp.getIsInterrupt() != 1);
if (availableSegments == null || availableSegments.isEmpty()) {
return proposedStartTime;
}
for (TimeSegment segment : availableSegments) {
LocalDateTime segStart = segment.getStart();
LocalDateTime segEnd = segment.getEnd();
if (!segStart.isAfter(proposedStart) && !segEnd.isBefore(proposedEnd)) {
return proposedStartTime;
}
if (segEnd.isAfter(proposedStart) && segEnd.isBefore(proposedEnd)) {
int newStartTime = (int) ChronoUnit.SECONDS.between(baseTime, segEnd);
return ensureContinuousProduction(machine, newStartTime, processingTime, currentOp);
}
if (segStart.isAfter(proposedStart) && segStart.isBefore(proposedEnd)) {
int newStartTime = (int) ChronoUnit.SECONDS.between(baseTime, segStart);
return newStartTime;
}
}
TimeSegment firstSegment = availableSegments.get(0);
int segStart = (int) ChronoUnit.SECONDS.between(baseTime, firstSegment.getStart());
if (segStart > proposedStartTime) {
return segStart;
}
return proposedStartTime;
}
/**
* 根据日历计算生产指定数量所需时间(考虑效率系数)
*/
private int calculateProductionTimeWithCalendar(List<ScheduleResultDetail> details, int leadCount,
Machine machine, Entry currentOp) {
if (details == null || details.isEmpty() || leadCount <= 0) {
return 0;
}
Set<Integer> timePoints = new TreeSet<>();
for (ScheduleResultDetail detail : details) {
timePoints.add(detail.getStartTime());
timePoints.add(detail.getEndTime());
}
List<Integer> sortedTimes = new ArrayList<>(timePoints);
double accumulatedQty = 0.0;
for (int i = 0; i < sortedTimes.size() - 1; i++) {
int startTime = sortedTimes.get(i);
int endTime = sortedTimes.get(i + 1);
int duration = endTime - startTime;
if (duration <= 0) continue;
double efficiency = details.stream()
.filter(d -> d.getStartTime() <= startTime && d.getEndTime() >= endTime)
.mapToDouble(d -> d.getProcessingTime() > 0 ? 1.0 / d.getOneTime() : 0)
.sum();
double segmentQty = efficiency * duration;
if (accumulatedQty + segmentQty >= leadCount) {
double remainingQty = leadCount - accumulatedQty;
int requiredTime = (int) Math.ceil(remainingQty / efficiency);
return startTime + requiredTime;
}
accumulatedQty += segmentQty;
}
return details.stream()
.mapToInt(ScheduleResultDetail::getEndTime)
.max()
.orElse(0);
}
/**
* 多设备并行时计算满足提前量的最早时间
*/
......
......@@ -1617,6 +1617,9 @@ if(headers1==null)
redisUtils.del(sceneId+routingDiscreteParamCacheKey);
GlobalCacheUtil.remove(sceneId+routingDiscreteParamCacheKey);
redisUtils.del(sceneId+materialsCacheKey);
GlobalCacheUtil.remove(sceneId+materialsCacheKey);
}
......
package com.aps.service.Algorithm;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.OrderSortRule;
import com.aps.entity.basic.Order;
import lombok.extern.slf4j.Slf4j;
......@@ -14,6 +15,7 @@ import java.time.OffsetDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 增强版订单排序服务(最终版:严格匹配条件数格式)
......@@ -90,6 +92,457 @@ public class OrderSortService {
orders.addAll(sortedOrders);
}
/**
* 计算两个订单之间的换线成本
*/
private double calculateChangeoverCost(Order order1, Order order2) {
if (order1 == null || order2 == null) {
return Double.MAX_VALUE;
}
double cost = 0.0;
// 1. 工艺路线不同,增加换线成本
if (!Objects.equals(order1.getRoutingId(), order2.getRoutingId())) {
cost += 100.0;
}
// 2. 物料系列不同,增加换线成本
if (!Objects.equals(order1.getSerie(), order2.getSerie())) {
cost += 50.0;
}
// 3. 物料代码不同,增加换线成本
if (!Objects.equals(order1.getMaterialCode(), order2.getMaterialCode())) {
cost += 25.0;
}
return cost;
}
/**
* 基于最小化换线成本的排序
*/
private List<Order> sortByMinimizeChangeover(List<Order> orders) {
if (CollectionUtils.isEmpty(orders)) {
return new ArrayList<>();
}
// 定义阈值:当订单数量小于等于这个值时,遍历所有起始点
int threshold = 10;
if (orders.size() <= threshold) {
// 订单数量较少,遍历所有起始点
return sortByMinimizeChangeoverWithAllStarts(orders);
} else {
// 订单数量较多,使用局部搜索
return sortByMinimizeChangeoverWithLocalSearch(orders);
}
}
/**
* 基于遍历所有起始点的最小化换线排序
*/
private List<Order> sortByMinimizeChangeoverWithAllStarts(List<Order> orders) {
if (CollectionUtils.isEmpty(orders)) {
return new ArrayList<>();
}
List<Map.Entry<List<Order>, Double>> results = IntStream.range(0, orders.size())
.parallel()
.mapToObj(i -> {
List<Order> sortedOrders= generateInitialSolution(ProductionDeepCopyUtil.deepCopyList(orders) ,i);
// 计算总换线成本
double totalCost = calculateTotalChangeoverCost(sortedOrders);
return new AbstractMap.SimpleEntry<>(sortedOrders, totalCost);
})
.collect(Collectors.toList());
List<Order> bestSortedOrders = null;
double minTotalCost = Double.MAX_VALUE;
for (Map.Entry<List<Order>, Double> entry : results) {
if (entry.getValue() < minTotalCost) {
minTotalCost = entry.getValue();
bestSortedOrders = entry.getKey();
}
}
return bestSortedOrders;
}
/**
* 基于局部搜索的最小化换线排序
*/
private List<Order> sortByMinimizeChangeoverWithLocalSearch(List<Order> orders) {
if (CollectionUtils.isEmpty(orders)) {
return new ArrayList<>();
}
// 1. 生成多个初始解,选择最优的一个
// 尝试多个随机起始点
Set<Integer> selectedIndices = new HashSet<>();
Random random = new Random();
int maxAttempts = Math.min(5, orders.size());
while (selectedIndices.size() < maxAttempts) {
int randomIndex = random.nextInt(orders.size());
selectedIndices.add(randomIndex);
}
List<Map.Entry<List<Order>, Double>> initialSolutions = selectedIndices.parallelStream()
.map(index -> {
List<Order> initialSolution = generateInitialSolution(ProductionDeepCopyUtil.deepCopyList(orders), index);
double initialCost = calculateTotalChangeoverCost(initialSolution);
return new AbstractMap.SimpleEntry<>(initialSolution, initialCost);
})
.collect(Collectors.toList());
// 选择最优初始解
List<Order> bestInitialSolution = null;
double bestInitialCost = Double.MAX_VALUE;
for (Map.Entry<List<Order>, Double> entry : initialSolutions) {
if (entry.getValue() < bestInitialCost) {
bestInitialCost = entry.getValue();
bestInitialSolution = entry.getKey();
}
}
List<Order> currentSolution = bestInitialSolution != null ? bestInitialSolution : generateInitialSolution(orders,0);
double currentCost = bestInitialCost;
// 2. 局部搜索(允许所有相邻订单交换)
boolean improved;
int maxIterations = 50;
int iteration = 0;
// do {
// improved = false;
// List<Order> bestNeighbor = new ArrayList<>(currentSolution);
// double bestNeighborCost = currentCost;
//
// // 遍历所有相邻订单对,尝试交换
// for (int i = 0; i < currentSolution.size() - 1; i++) {
// // 交换相邻订单
// List<Order> neighbor = new ArrayList<>(currentSolution);
// Collections.swap(neighbor, i, i + 1);
//
//
// double neighborCost = calculateTotalChangeoverCost2(neighbor);
//
// // 如果交换后成本更低,更新最佳邻居
// if (neighborCost < bestNeighborCost) {
// bestNeighbor = neighbor;
// bestNeighborCost = neighborCost;
// improved = true;
// }
// }
//
// // 如果找到更优解,更新当前解
// if (improved) {
// currentSolution = bestNeighbor;
// // assignChangeoverPriority(currentSolution);
// currentCost = bestNeighborCost;
// }
//
// iteration++;
// } while (improved && iteration < maxIterations);
do {
improved = false;
List<Order> bestNeighbor = new ArrayList<>(currentSolution);
double bestNeighborCost = currentCost;
// 并行处理邻域搜索
List<Order> finalCurrentSolution = currentSolution;
List<Map.Entry<List<Order>, Double>> neighbors = IntStream.range(0, currentSolution.size() - 1)
.parallel()
.mapToObj(i -> {
// 交换相邻订单
List<Order> neighbor = new ArrayList<>(finalCurrentSolution);
Collections.swap(neighbor, i, i + 1);
double neighborCost = calculateTotalChangeoverCost2(neighbor);
return new AbstractMap.SimpleEntry<>(neighbor, neighborCost);
})
.collect(Collectors.toList());
// 找到最佳邻居
for (Map.Entry<List<Order>, Double> entry : neighbors) {
if (entry.getValue() < bestNeighborCost) {
bestNeighbor = entry.getKey();
bestNeighborCost = entry.getValue();
improved = true;
}
}
// 如果找到更优解,更新当前解
if (improved) {
currentSolution = bestNeighbor;
currentCost = bestNeighborCost;
}
iteration++;
} while (improved && iteration < maxIterations);
return currentSolution;
}
/**
* 计算订单序列的总换线成本
*/
/**
* 计算订单序列的总换线成本(考虑ChangeoverPriority分组)
*/
private double calculateTotalChangeoverCost2(List<Order> orders) {
if (CollectionUtils.isEmpty(orders) || orders.size() <= 1) {
return 0.0;
}
double totalCost = 0.0;
// 首先为订单分配ChangeoverPriority
assignChangeoverPriority(orders);
totalCost=calculateTotalChangeoverCost(orders);
return totalCost;
}
/**
* 生成初始解(使用贪心算法)
*/
private List<Order> generateInitialSolution(List<Order> orders,int i) {
if (CollectionUtils.isEmpty(orders)) {
return new ArrayList<>();
}
List<Order> sortedOrders = new ArrayList<>();
List<Order> remainingOrders = new ArrayList<>(orders);
// 选择第一个订单作为起始点
Order currentOrder = remainingOrders.remove(i);
currentOrder.setChangeoverPriority(1);
sortedOrders.add(currentOrder);
int priority=2;
// 每次选择与当前最后一个订单换线成本最低的订单
while (!remainingOrders.isEmpty()) {
double minCost = Double.MAX_VALUE;
List<Order> bestOrders = new ArrayList<>();
// 找到换线成本最低的所有订单
for (Order order : remainingOrders) {
double cost = calculateChangeoverCost(currentOrder, order);
if (cost < minCost) {
minCost = cost;
order.setChangeoverCost(cost);
if(minCost==0){
order.setChangeoverPriority(currentOrder.getChangeoverPriority());
}else {
order.setChangeoverPriority(priority);
}
bestOrders.clear();
bestOrders.add(order);
} else if (cost == minCost) {
order.setChangeoverCost(cost);
if(minCost==0){
order.setChangeoverPriority(currentOrder.getChangeoverPriority());
}else {
order.setChangeoverPriority(priority);
}
bestOrders.add(order);
}
}
// 如果有多个成本相同的订单,将它们作为一组添加
if (!bestOrders.isEmpty()) {
sortedOrders.addAll(bestOrders);
remainingOrders.removeAll(bestOrders);
// 更新当前订单为最后添加的订单
currentOrder = bestOrders.get(bestOrders.size() - 1);
if(minCost!=0) {
priority++;
}
} else {
// 以防万一,添加剩余的第一个订单
Order nextOrder = remainingOrders.remove(0);
sortedOrders.add(nextOrder);
currentOrder = nextOrder;
if(minCost!=0) {
priority++;
}
}
}
return sortedOrders;
}
/**
* 为排序后的订单分配ChangeoverPriority
*/
private void assignChangeoverPriority(List<Order> orders) {
if (CollectionUtils.isEmpty(orders)) {
return;
}
int priority = 1;
orders.get(0).setChangeoverPriority(priority);
for (int i = 1; i < orders.size(); i++) {
double cost = calculateChangeoverCost(orders.get(i - 1), orders.get(i));
if (cost > 0) {//成本为0 ,则在同一级
priority++;
orders.get(i).setChangeoverCost(cost);
}else {
orders.get(i).setChangeoverCost(orders.get(i - 1).getChangeoverCost());
}
orders.get(i).setChangeoverPriority(priority);
}
}
/**
* 计算订单序列的总换线成本
*/
private double calculateTotalChangeoverCost(List<Order> orders) {
if (CollectionUtils.isEmpty(orders) || orders.size() <= 1) {
return 0.0;
}
double totalCost = 0.0;
// 001>002 2 cost 75
// 001>003 2 cost 75
//有一点问题,相同ChangeoverPriority 直接换型应该是0,002>003, 然而对象中存的是,
// 001>002,001>003 ,所以相同ChangeoverPriority 不加成本了
// 只计算不同优先级组之间的换线成本
for (int i = 0; i < orders.size() - 1; i++) {
Order currentOrder = orders.get(i);
Order nextOrder = orders.get(i + 1);
// 只有当两个订单的ChangeoverPriority不同时,才计算换线成本
if (currentOrder.getChangeoverPriority() != nextOrder.getChangeoverPriority()) {
totalCost += orders.get(i + 1).getChangeoverCost();
}
}
return totalCost;
}
/**
* 处理排序条件,支持在任意位置应用最小化换线策略
*/
private void processConditionsWithMinimizeChangeover(List<Order> orders,
List<OrderSortRule.SortCondition> conditions,
int conditionIndex,
Map<Integer, List<Integer>> priorityPaths) {
// 递归终止:处理完所有条件后停止
if (conditionIndex >= conditions.size() || CollectionUtils.isEmpty(orders)) {
return;
}
OrderSortRule.SortCondition currentCondition = conditions.get(conditionIndex);
// 检查是否是最小化换线策略
if ("minimize_changeover".equals(currentCondition.getFieldName())) {
// 应用最小化换线策略
List<Order> optimizedOrders = sortByMinimizeChangeover(orders);
// 为最小化换线后的订单分配层级序号
// 相同成本的订单分配相同的序号
for (Order order : optimizedOrders) {
priorityPaths.get(order.getId()).add(order.getChangeoverPriority());
}
Map<Integer, List<Order>> priorityGroups = new HashMap<>();
for (Order order : optimizedOrders) {
int priority = order.getChangeoverPriority();
priorityGroups.computeIfAbsent(priority, k -> new ArrayList<>()).add(order);
}
// 按优先级分组顺序处理
List<Integer> sortedPriorities = priorityGroups.keySet().stream()
.sorted()
.collect(Collectors.toList());
for (Integer priority : sortedPriorities) {
List<Order> groupOrders = priorityGroups.get(priority);
// 递归处理下一个条件
processConditionsWithMinimizeChangeover(groupOrders, conditions, conditionIndex + 1, priorityPaths);
}
// 递归处理下一个条件
// processConditionsWithMinimizeChangeover(optimizedOrders, conditions, conditionIndex + 1, priorityPaths);
} else {
// 处理普通排序条件
String fieldName = currentCondition.getFieldName();
Function<Order, ?> keyExtractor = getFieldExtractor(fieldName);
if (keyExtractor == null) {
log.warn("跳过无效排序字段:{}", currentCondition.getFieldName());
processConditionsWithMinimizeChangeover(orders, conditions, conditionIndex + 1, priorityPaths);
return;
}
// 1. 按当前条件分组 处理null键
Map<Object, List<Order>> groups = new HashMap<>();
orders.forEach(order -> {
Object key = keyExtractor.apply(order);
groups.computeIfAbsent(key, k -> new ArrayList<>()).add(order);
});
// 2. 对分组键排序(关键:按条件配置的方向排序)
List<Object> sortedKeys = getSortedKeys(groups, currentCondition);
// 3. 为每个分组分配层级序号(从1开始)
for (int groupIndex = 0; groupIndex < sortedKeys.size(); groupIndex++) {
Object key = sortedKeys.get(groupIndex);
List<Order> groupOrders = groups.get(key);
// 分配当前层级序号(1、2、3...)
int levelNumber = groupIndex + 1;
groupOrders.forEach(order -> priorityPaths.get(order.getId()).add(levelNumber));
// 递归处理下一级条件
processConditionsWithMinimizeChangeover(groupOrders, conditions, conditionIndex + 1, priorityPaths);
}
}
}
private List<Order> sortWithConfiguredStrategy(List<Order> orders, OrderSortRule rule) {
// if (rule.getConditions().size()==1&&rule.getConditions().get(0).getFieldName().equals("minimize_changeover")) {
// return sortByMinimizeChangeover(orders);
// }
List<Order> currentOrders = new ArrayList<>(orders);
List<OrderSortRule.SortCondition> conditions = rule.getConditions().stream()
.sorted(Comparator.comparingInt(OrderSortRule.SortCondition::getSequence))
.collect(Collectors.toList());
// 为每个订单初始化优先级路径
Map<Integer, List<Integer>> priorityPaths = new HashMap<>();
currentOrders.forEach(order -> priorityPaths.put(order.getId(), new ArrayList<>()));
// 处理排序条件
processConditionsWithMinimizeChangeover(currentOrders, conditions, 0, priorityPaths);
// 将路径转换为最终格式
convertPriorityPathsToNumeric(currentOrders, priorityPaths);
// 按优先级升序排序(数值越小越优先)
return currentOrders.stream()
.sorted(Comparator.comparingDouble(Order::getActualPriority))
.collect(Collectors.toList());
}
/**
* 根据数据库配置的规则对订单排序
......@@ -136,25 +589,36 @@ public class OrderSortService {
return new ArrayList<>(orders);
}
// 按条件顺序排序(sequence越小越先执行)
List<OrderSortRule.SortCondition> sortedConditions = rule.getConditions().stream()
.sorted(Comparator.comparingInt(OrderSortRule.SortCondition::getSequence))
.collect(Collectors.toList());
boolean hasMinimizeChangeover = rule.getConditions().stream()
.anyMatch(condition -> "minimize_changeover".equals(condition.getFieldName()));
// 为每个订单初始化优先级路径
Map<Order, List<Integer>> priorityPaths = new HashMap<>();
orders.forEach(order -> priorityPaths.put(order, new ArrayList<>()));
// 递归分配层级化优先级(核心逻辑)
assignHierarchicalPriority(orders, sortedConditions, 0, priorityPaths);
if (hasMinimizeChangeover) {
// 将路径转换为最终格式
convertPriorityPathsToNumeric(orders, priorityPaths);
// 仅使用最小化换线策略
return sortWithConfiguredStrategy(orders,rule);
// 按优先级升序排序(数值越小越优先)
return orders.stream()
.sorted(Comparator.comparingDouble(Order::getActualPriority))
.collect(Collectors.toList());
} else {
// 按条件顺序排序(sequence越小越先执行)
List<OrderSortRule.SortCondition> sortedConditions = rule.getConditions().stream()
.sorted(Comparator.comparingInt(OrderSortRule.SortCondition::getSequence))
.collect(Collectors.toList());
// 为每个订单初始化优先级路径
Map<Integer, List<Integer>> priorityPaths = new HashMap<>();
orders.forEach(order -> priorityPaths.put(order.getId(), new ArrayList<>()));
// 递归分配层级化优先级(核心逻辑)
assignHierarchicalPriority(orders, sortedConditions, 0, priorityPaths);
// 将路径转换为最终格式
convertPriorityPathsToNumeric(orders, priorityPaths);
// 按优先级升序排序(数值越小越优先)
return orders.stream()
.sorted(Comparator.comparingDouble(Order::getActualPriority))
.collect(Collectors.toList());
}
}
/**
......@@ -163,7 +627,7 @@ public class OrderSortService {
private void assignHierarchicalPriority(List<Order> orders,
List<OrderSortRule.SortCondition> conditions,
int conditionIndex,
Map<Order, List<Integer>> priorityPaths) {
Map<Integer, List<Integer>> priorityPaths) {
// 递归终止:处理完所有条件后停止,不再添加额外序号
if (conditionIndex >= conditions.size() || CollectionUtils.isEmpty(orders)) {
return;
......@@ -196,7 +660,7 @@ public class OrderSortService {
// 分配当前层级序号(1、2、3...)
int levelNumber = groupIndex + 1;
groupOrders.forEach(order -> priorityPaths.get(order).add(levelNumber));
groupOrders.forEach(order -> priorityPaths.get(order.getId()).add(levelNumber));
// 递归处理下一级条件
assignHierarchicalPriority(groupOrders, conditions, conditionIndex + 1, priorityPaths);
......@@ -208,9 +672,9 @@ public class OrderSortService {
* 3个条件 → [1,1,1] → 1.11
* 4个条件 → [1,1,1,1] → 1.111
*/
private void convertPriorityPathsToNumeric(List<Order> orders, Map<Order, List<Integer>> priorityPaths) {
private void convertPriorityPathsToNumeric(List<Order> orders, Map<Integer, List<Integer>> priorityPaths) {
for (Order order : orders) {
List<Integer> path = priorityPaths.get(order);
List<Integer> path = priorityPaths.get(order.getId());
if (CollectionUtils.isEmpty(path)) {
order.setActualPriority(0.0);
continue;
......
......@@ -1983,6 +1983,16 @@ private GlobalParam InitGlobalParam()
conditions.add(condition);
files.add("orderCode");
i++;
}else if (strategy.getName().equals("minimize_tool_changeovers")) {
// 最小化换线策略需要特殊处理,这里只做标记
// 实际排序逻辑将在orderSortService中处理
OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
condition.setSequence(i);
condition.setFieldName("minimize_changeover");
condition.setReverse(false);
conditions.add(condition);
files.add("minimize_changeover");
i++;
}
}
......
......@@ -13,9 +13,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
......@@ -45,18 +43,68 @@ class OrderSortServiceTest {
// 创建多条件排序规则:先按dueDate,再按priority
OrderSortRule rule = createMultiConditionRule();
List<Order> orders=new ArrayList<>();
Order order=new Order();
order.setId(1);
order.setOrderId("001");
order.setRoutingId(1);
order.setMaterialCode("M001");
order.setSerie("S001");
orders.add(order);
Order order2=new Order();
order2.setId(2);
order2.setOrderId("002");
order2.setRoutingId(1);
order2.setMaterialCode("M002");
order2.setSerie("S001");
orders.add(order2);
Order order3=new Order();
order3.setId(3);
order3.setOrderId("003");
order3.setRoutingId(1);
order3.setMaterialCode("M002");
order3.setSerie("S001");
orders.add(order3);
Order order4=new Order();
order4.setId(4);
order4.setOrderId("004");
order4.setRoutingId(2);
order4.setMaterialCode("M001");
order4.setSerie("S002");
orders.add(order4);
Order order5=new Order();
order5.setId(5);
order5.setOrderId("005");
order5.setRoutingId(2);
order5.setMaterialCode("M002");
order5.setSerie("S003");
orders.add(order5);
Order order6=new Order();
order6.setId(6);
order6.setOrderId("006");
order6.setRoutingId(2);
order6.setMaterialCode("M002");
order6.setSerie("S003");
orders.add(order6);
// 执行测试
// 执行测试
orderSortService.assignPriority(testOrders, rule);
orderSortService.assignPriorityValues(orders, rule);
// 按照优先级排序
testOrders.sort(
orders.sort(
Comparator.comparing(Order::getActualPriority).reversed()
);
// 验证多级优先级分配
printOrderPriorities(testOrders); // 调试输出
printOrderPriorities(orders); // 调试输出
}
......@@ -102,17 +150,18 @@ class OrderSortServiceTest {
// 条件2:按到期日
OrderSortRule.SortCondition condition2 = new OrderSortRule.SortCondition();
condition2.setSequence(2);
condition2.setFieldName("dueDate");
condition2.setFieldName("minimize_changeover");
condition2.setReverse(false); // 早到期在前
conditions.add(condition2);
// 条件3:按优先级
OrderSortRule.SortCondition condition3 = new OrderSortRule.SortCondition();
condition3.setSequence(3);
condition3.setFieldName("priority");
condition3.setFieldName("materialCode");
condition3.setReverse(true); // 高优先级在前
conditions.add(condition3);
// conditions.add(condition3);
rule.setConditions(conditions);
return rule;
}
......
......@@ -42,7 +42,7 @@ public class PlanResultServiceTest {
// planResultService.execute2("5475E00B844847ACB6DC20227967BA2F");
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
planResultService.execute2("31F0FF4DFAD844BD9C72EDEEF3430A1F");
planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2");
// planResultService.execute2("265F24B6DF3C40E4B17D193B0CC8AAF2");
// LocalDateTime t= LocalDateTime.of(2026, 02, 14, 1, 25, 52);
// List<Integer> opids=new ArrayList<>();//BCA6FA43FFA444D3952CF8F6E1EA291B
......
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