Commit b9d3b3e5 authored by Tong Li's avatar Tong Li

策略最小化换线:小于10全部遍历,大于10用变邻域搜索方法

parent 9a0c5df9
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;
/**
* 增强版订单排序服务(最终版:严格匹配条件数格式)
......@@ -120,10 +122,157 @@ public class OrderSortService {
/**
* 基于最小化换线成本的排序
*/
private List<Order> sortByMinimizeChangeover(List<Order> orders) {
if (CollectionUtils.isEmpty(orders)) {
return new ArrayList<>();
}
// 定义阈值:当订单数量小于等于这个值时,遍历所有起始点
int threshold = 5;
if (orders.size() <= threshold) {
// 订单数量较少,遍历所有起始点
return sortByMinimizeChangeoverWithAllStarts(orders);
} else {
// 订单数量较多,使用局部搜索
return sortByMinimizeChangeoverWithLocalSearch(orders);
}
}
/**
* 基于最小化换线成本的排序,并返回带有优先级信息的订单列表
* 基于遍历所有起始点的最小化换线排序
*/
private List<Order> sortByMinimizeChangeover(List<Order> 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. 生成多个初始解,选择最优的一个
List<Order> bestInitialSolution = null;
double bestInitialCost = Double.MAX_VALUE;
// 尝试多个随机起始点
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());
if (selectedIndices.add(randomIndex)) {
List<Order> initialSolution= generateInitialSolution(ProductionDeepCopyUtil.deepCopyList(orders) ,randomIndex);
double initialCost = calculateTotalChangeoverCost(initialSolution);
if (initialCost < bestInitialCost) {
bestInitialCost = initialCost;
bestInitialSolution = initialSolution;
}
}
}
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);
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<>();
}
......@@ -132,7 +281,7 @@ public class OrderSortService {
List<Order> remainingOrders = new ArrayList<>(orders);
// 选择第一个订单作为起始点
Order currentOrder = remainingOrders.remove(0);
Order currentOrder = remainingOrders.remove(i);
currentOrder.setChangeoverPriority(1);
sortedOrders.add(currentOrder);
int priority=2;
......@@ -149,7 +298,7 @@ public class OrderSortService {
minCost = cost;
order.setChangeoverCost(cost);
if(minCost==0){
order.setChangeoverPriority(currentOrder.getPriority());
order.setChangeoverPriority(currentOrder.getChangeoverPriority());
}else {
order.setChangeoverPriority(priority);
}
......@@ -158,7 +307,7 @@ public class OrderSortService {
} else if (cost == minCost) {
order.setChangeoverCost(cost);
if(minCost==0){
order.setChangeoverPriority(currentOrder.getPriority());
order.setChangeoverPriority(currentOrder.getChangeoverPriority());
}else {
order.setChangeoverPriority(priority);
}
......@@ -175,7 +324,6 @@ public class OrderSortService {
if(minCost!=0) {
priority++;
}
} else {
// 以防万一,添加剩余的第一个订单
Order nextOrder = remainingOrders.remove(0);
......@@ -190,20 +338,59 @@ public class OrderSortService {
return sortedOrders;
}
public void sortByMinimizeChangeover1(List<Order> orders,Map<Integer, List<Integer>> priorityPaths)
{
List<Order> optimizedOrders = sortByMinimizeChangeover(orders);
/**
* 为排序后的订单分配ChangeoverPriority
*/
private void assignChangeoverPriority(List<Order> orders) {
if (CollectionUtils.isEmpty(orders)) {
return;
}
for (Order order : optimizedOrders) {
int priority = 1;
orders.get(0).setChangeoverPriority(priority);
priorityPaths.get(order.getId()).add(order.getChangeoverPriority());
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);
}
}
// convertPriorityPathsToNumeric(optimizedOrders, priorityPaths);
int i=0;
/**
* 计算订单序列的总换线成本
*/
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;
}
/**
* 处理排序条件,支持在任意位置应用最小化换线策略
*/
......
......@@ -53,8 +53,6 @@ class OrderSortServiceTest {
orders.add(order);
Order order2=new Order();
order2.setId(2);
order2.setOrderId("002");
......@@ -89,7 +87,7 @@ class OrderSortServiceTest {
Order order6=new Order();
order6.setId(6);
order6.setOrderId("005");
order6.setOrderId("006");
order6.setRoutingId(2);
order6.setMaterialCode("M002");
order6.setSerie("S003");
......@@ -161,7 +159,7 @@ class OrderSortServiceTest {
condition3.setSequence(3);
condition3.setFieldName("materialCode");
condition3.setReverse(true); // 高优先级在前
conditions.add(condition3);
// conditions.add(condition3);
rule.setConditions(conditions);
......
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