Commit 6430785e authored by DESKTOP-VKRD9QF\Administration's avatar DESKTOP-VKRD9QF\Administration
parents 247fcbd2 ff8e1628
...@@ -7,6 +7,7 @@ import java.util.List; ...@@ -7,6 +7,7 @@ import java.util.List;
public class OrderSortRule { public class OrderSortRule {
private boolean enabled; private boolean enabled;
private List<SortCondition> conditions; private List<SortCondition> conditions;
//private boolean minimizeChangeover=false;
@Data @Data
public static class SortCondition { public static class SortCondition {
......
...@@ -176,4 +176,11 @@ public class Order { ...@@ -176,4 +176,11 @@ public class Order {
* 物料需求 * 物料需求
*/ */
private List<OrderMaterialRequirement> materialRequirementList; 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) ...@@ -479,19 +479,19 @@ if(finishedOrder==null||finishedOrder.size()==0)
} }
int setupTime=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()) .filter(t -> t.getMachineId() == machine.getId())
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime)) .sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toCollection(CopyOnWriteArrayList::new)); .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
GAScheduleResult lastGeneOnMachine = null; 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()); earliestStartTime = Math.max(earliestStartTime,lastGeneOnMachine.getEndTime());
} }
...@@ -533,16 +533,16 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -533,16 +533,16 @@ if(finishedOrder==null||finishedOrder.size()==0)
} }
machineTasks1 =chromosome.getResult().stream() machineTasks =chromosome.getResult().stream()
.filter(t -> t.getMachineId() == machine.getId()) .filter(t -> t.getMachineId() == machine.getId())
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime)) .sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toCollection(CopyOnWriteArrayList::new)); .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()) { if (_globalParam.is_smoothChangeOver()) {
...@@ -702,6 +702,7 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -702,6 +702,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
} }
} }
} }
//重叠
List<OperationDependency> SSOperations = currentOp.getPrevEntryIds().stream() List<OperationDependency> SSOperations = currentOp.getPrevEntryIds().stream()
.filter(t -> t.getDependencyType() == DependencyType.StartToStart) .filter(t -> t.getDependencyType() == DependencyType.StartToStart)
.collect(Collectors.toList());//重叠 .collect(Collectors.toList());//重叠
...@@ -726,6 +727,18 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -726,6 +727,18 @@ if(finishedOrder==null||finishedOrder.size()==0)
.orElse(0); .orElse(0);
prevtime = calculateNextOperationStartTime(newScheduleResult, newScheduleResultDetails, 0, processTime); prevtime = calculateNextOperationStartTime(newScheduleResult, newScheduleResultDetails, 0, processTime);
// 下一工序结束时间需晚于上一工序结束时间一个产品加工时间 // 下一工序结束时间需晚于上一工序结束时间一个产品加工时间
// int ssStartTimeWithCalendar = calculateSSStartTimeWithCalendar(
// newScheduleResult,
// newScheduleResultDetails,
// currentOp,
// machine,
// processTime,
// prevtime);
//
// prevtime = Math.max(prevtime, ssStartTimeWithCalendar);
double nextopplanend = prevperationEndTime + processTime; double nextopplanend = prevperationEndTime + processTime;
List<ScheduleResultDetail> geneDetails1 = machineCalculator.checkMachineStartTime(machine, (int) (processTime * currentOp.getQuantity()), List<ScheduleResultDetail> geneDetails1 = machineCalculator.checkMachineStartTime(machine, (int) (processTime * currentOp.getQuantity()),
...@@ -1054,6 +1067,155 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0) ...@@ -1054,6 +1067,155 @@ if(MaterialRequirements==null||MaterialRequirements.size()==0)
// 单设备时使用原逻辑 // 单设备时使用原逻辑
return (int)calculateWithSingleMachine(details, leadCount, time1); 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) ...@@ -1617,6 +1617,9 @@ if(headers1==null)
redisUtils.del(sceneId+routingDiscreteParamCacheKey); redisUtils.del(sceneId+routingDiscreteParamCacheKey);
GlobalCacheUtil.remove(sceneId+routingDiscreteParamCacheKey); GlobalCacheUtil.remove(sceneId+routingDiscreteParamCacheKey);
redisUtils.del(sceneId+materialsCacheKey);
GlobalCacheUtil.remove(sceneId+materialsCacheKey);
} }
......
...@@ -1983,6 +1983,16 @@ private GlobalParam InitGlobalParam() ...@@ -1983,6 +1983,16 @@ private GlobalParam InitGlobalParam()
conditions.add(condition); conditions.add(condition);
files.add("orderCode"); files.add("orderCode");
i++; 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; ...@@ -13,9 +13,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.*;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -45,18 +43,68 @@ class OrderSortServiceTest { ...@@ -45,18 +43,68 @@ class OrderSortServiceTest {
// 创建多条件排序规则:先按dueDate,再按priority // 创建多条件排序规则:先按dueDate,再按priority
OrderSortRule rule = createMultiConditionRule(); 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() Comparator.comparing(Order::getActualPriority).reversed()
); );
// 验证多级优先级分配 // 验证多级优先级分配
printOrderPriorities(testOrders); // 调试输出 printOrderPriorities(orders); // 调试输出
} }
...@@ -102,17 +150,18 @@ class OrderSortServiceTest { ...@@ -102,17 +150,18 @@ class OrderSortServiceTest {
// 条件2:按到期日 // 条件2:按到期日
OrderSortRule.SortCondition condition2 = new OrderSortRule.SortCondition(); OrderSortRule.SortCondition condition2 = new OrderSortRule.SortCondition();
condition2.setSequence(2); condition2.setSequence(2);
condition2.setFieldName("dueDate"); condition2.setFieldName("minimize_changeover");
condition2.setReverse(false); // 早到期在前 condition2.setReverse(false); // 早到期在前
conditions.add(condition2); conditions.add(condition2);
// 条件3:按优先级 // 条件3:按优先级
OrderSortRule.SortCondition condition3 = new OrderSortRule.SortCondition(); OrderSortRule.SortCondition condition3 = new OrderSortRule.SortCondition();
condition3.setSequence(3); condition3.setSequence(3);
condition3.setFieldName("priority"); condition3.setFieldName("materialCode");
condition3.setReverse(true); // 高优先级在前 condition3.setReverse(true); // 高优先级在前
conditions.add(condition3); // conditions.add(condition3);
rule.setConditions(conditions); rule.setConditions(conditions);
return rule; return rule;
} }
......
...@@ -42,7 +42,7 @@ public class PlanResultServiceTest { ...@@ -42,7 +42,7 @@ public class PlanResultServiceTest {
// planResultService.execute2("5475E00B844847ACB6DC20227967BA2F"); // planResultService.execute2("5475E00B844847ACB6DC20227967BA2F");
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D"); // planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
planResultService.execute2("31F0FF4DFAD844BD9C72EDEEF3430A1F"); planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2");
// planResultService.execute2("265F24B6DF3C40E4B17D193B0CC8AAF2"); // planResultService.execute2("265F24B6DF3C40E4B17D193B0CC8AAF2");
// LocalDateTime t= LocalDateTime.of(2026, 02, 14, 1, 25, 52); // LocalDateTime t= LocalDateTime.of(2026, 02, 14, 1, 25, 52);
// List<Integer> opids=new ArrayList<>();//BCA6FA43FFA444D3952CF8F6E1EA291B // 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