Commit 34d7e700 authored by Tong Li's avatar Tong Li

优化速度

parent 993afbe6
package com.aps.entity.Algorithm;
import com.aps.entity.basic.TimeSegment;
import lombok.Data;
import java.util.List;
/**
* 作者:佟礼
* 时间:2025-11-21
......@@ -14,6 +17,9 @@ public class ScheduleResultDetail {
private double OneTime; // 单件工时
private double Quantity; // 时间段
private List<TimeSegment> usedSegment;
// Key 的 getter/setter
public String getKey() {
return Key;
......
......@@ -374,6 +374,7 @@ if(finishedOrder==null||finishedOrder.size()==0)
int teardownTime = machineOption.getTeardownTime();
int preTime = machineOption.getPreTime();
int setupTime = calculateSetupTime(chromosome.getResult(), operation, machine, machineOption);
......
......@@ -92,7 +92,7 @@ public class MachineCalculator {
time.setQuantity(quantity);
times.add(time);
if(islockMachineTime) {
RemoveMachineAvailable(machine, time);
RemoveMachineAvailable(machine, time,slot);
}
return times;
}
......@@ -159,7 +159,7 @@ public class MachineCalculator {
times.add(time);
if (islockMachineTime) {
// 还原未使用的时间段
RemoveMachineAvailable(machine, time);
RemoveMachineAvailable(machine, time,shift);
}
}
......@@ -183,10 +183,81 @@ public class MachineCalculator {
List<ScheduleResultDetail> oldTimes = new ArrayList<>();
List<TimeSegment> timeSegments= findAvailableSegments(machine, currentTime, machineTasks, remainingTime, isInterrupt);
int estimateIndex= (int) Math.ceil(remainingTime / (double) ONE_DAY_MINUTES);
List<TimeSegment> timeSegments1=null;
if(estimateIndex>10)
{
timeSegments1= getEnoughSegmentsByEstimateIndex(timeSegments,currentTime,remainingTime);
}
int i=0;
if(timeSegments1==null) {
int i = 0;
while (remainingTime > 0) {
TimeSegment shift= timeSegments.get(i);
TimeSegment shift = timeSegments.get(i);
Map<Integer, Object> outMap = CreateScheduleResultDetail(shift, st, remainingTime, oneTime);
remainingTime = (int) outMap.get(1);
ScheduleResultDetail time = (ScheduleResultDetail) outMap.get(2);
times.add(time);
// 还原未使用的时间段
RemoveMachineAvailable(machine, time,shift);
i++;
}
}else {
times= CaldScheduleResultDetail(timeSegments1,machine,st,remainingTime,oneTime);
}
return times;
}
private List<ScheduleResultDetail> CaldScheduleResultDetail(List<TimeSegment> timeSegments,Machine machine,LocalDateTime st,int remainingTime,double oneTime)
{
int processable1 =(int)calculateTotalAvailableSecond(timeSegments, st);
List<ScheduleResultDetail> times = new ArrayList<>();
TimeSegment shiftfrist= timeSegments.get(0);
Map<Integer, Object> outMap= CreateScheduleResultDetail(shiftfrist,st,remainingTime,oneTime);
remainingTime=(int)outMap.get(1);
ScheduleResultDetail time1=(ScheduleResultDetail)outMap.get(2);
times.add(time1);
RemoveMachineAvailable(machine, time1,shiftfrist);
// 计算有效时间
List<TimeSegment> timeSegments2= timeSegments.subList(1,timeSegments.size()-1);
LocalDateTime effectiveStart=timeSegments2.get(0).getStart();
LocalDateTime effectiveend=timeSegments2.get(timeSegments2.size()-1).getEnd();
int processable =(int)calculateTotalAvailableSecond(timeSegments2, st);
ScheduleResultDetail time = new ScheduleResultDetail();
time.setKey(UUID.randomUUID().toString());
time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, effectiveStart));
time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, effectiveend));
time.setQuantity((int)(processable/oneTime));
time.setOneTime(oneTime);
time.setUsedSegment(timeSegments2);
timeSegments2.forEach(t->t.setUsed(true));
remainingTime-=processable;
times.add(time);
TimeSegment shiftlast= timeSegments.get(timeSegments.size()-1);
Map<Integer, Object> outMaplast= CreateScheduleResultDetail(shiftlast,st,remainingTime,oneTime);
remainingTime=(int)outMaplast.get(1);
ScheduleResultDetail timelast=(ScheduleResultDetail)outMaplast.get(2);
times.add(timelast);
RemoveMachineAvailable(machine, timelast,shiftlast);
return times;
}
private Map<Integer, Object> CreateScheduleResultDetail(TimeSegment shift,LocalDateTime st,int remainingTime,double oneTime)
{
LocalDateTime shiftStart = shift.getStart();
LocalDateTime shiftEnd = shift.getEnd();
......@@ -199,7 +270,9 @@ public class MachineCalculator {
// 处理当前班次
int processable = Math.min(remainingTime, (int) availableSeconds_e);
remainingTime -= processable;
currentTime = effectiveStart.plusSeconds(availableSeconds/availableSeconds_e*processable);
double e= (double)availableSeconds/availableSeconds_e*processable;
LocalDateTime currentTime = effectiveStart.plusSeconds((int)Math.ceil(e));
// 添加时间详情
ScheduleResultDetail time = new ScheduleResultDetail();
......@@ -208,16 +281,12 @@ public class MachineCalculator {
time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, currentTime));
time.setQuantity((int)(processable/oneTime));
time.setOneTime(oneTime);
times.add(time);
// 还原未使用的时间段
RemoveMachineAvailable(machine, time);
i++;
Map<Integer, Object> outMap=new HashMap<>();
outMap.put(1, remainingTime);
outMap.put(2, time);
return outMap;
}
return times;
}
/**
* 查找满足时长要求的无冲突可用时段
......@@ -320,7 +389,7 @@ i++;
}
}
private static final int ONE_DAY_MINUTES = 24 * 60; // 固定锚点:一天1440分钟,永不改变
private static final int ONE_DAY_MINUTES = 24 * 60*60; // 固定锚点:一天1440分钟,永不改变
/**
* 按预估索引快速获取满足时长的时段数组
......@@ -330,7 +399,7 @@ i++;
* @return 刚好满足时长的片段数组
* @throws IllegalArgumentException 总时长不足时抛出
*/
public TimeSegment[] getEnoughSegmentsByEstimateIndex(
public List<TimeSegment> getEnoughSegmentsByEstimateIndex(
List<TimeSegment> availableSegments,
LocalDateTime currentTime,
int requiredMinutes) {
......@@ -339,7 +408,7 @@ i++;
throw new IllegalArgumentException("可用时段列表不能为空");
}
if (requiredMinutes <= 0) {
return new TimeSegment[0];
return null;
}
int totalSegmentCount = availableSegments.size();
......@@ -371,8 +440,11 @@ i++;
}
break; // 找到最小满足索引,退出循环
} else {
double syday= (int)Math.ceil((requiredMinutes-currentTotal)/(double) ONE_DAY_MINUTES);
// ❌ 总时长不足,往后加索引(每次加5,大步前进,加快逼近速度)
targetIndex += 5;
targetIndex +=Math.max(syday, 5);
if (targetIndex >= totalSegmentCount) {
// 所有片段总时长不足,抛出异常
double allTotal = calculateTotalMinutesByIndex(availableSegments, currentTime, totalSegmentCount - 1);
......@@ -388,7 +460,7 @@ i++;
}
else if(allTotal==requiredMinutes)
{
return availableSegments.toArray(new TimeSegment[0]);
return availableSegments;
}else {
return null;
}
......@@ -398,7 +470,7 @@ i++;
// ========== 步骤3:精准裁剪片段,返回最终结果 ==========
List<TimeSegment> resultList = availableSegments.subList(0,targetIndex);
return resultList.toArray(new TimeSegment[0]);
return resultList;
}
/**
......@@ -904,7 +976,43 @@ i++;
return times;
}
private void RemoveMachineAvailable(Machine machine, ScheduleResultDetail geneDetails) {
private void RemoveMachineAvailable(Machine machine, ScheduleResultDetail geneDetails,TimeSegment targetSegment) {
// 关键修复2:加锁(若多线程访问),避免并发修改
synchronized (machine.getAvailability()) {
List<TimeSegment> availabilitySnapshot = new ArrayList<>(machine.getAvailability());
LocalDateTime geneEndTime = baseTime.plusSeconds(geneDetails.getEndTime());
if (targetSegment.getEnd().isAfter(geneEndTime)) {
TimeSegment usedSegment = new TimeSegment();
usedSegment.setStart(baseTime.plusSeconds(geneDetails.getStartTime()));
usedSegment.setEnd(geneEndTime);
usedSegment.setHoliday(false);
usedSegment.setKey(UUID.randomUUID().toString());
usedSegment.setType(SegmentType.REGULAR);
usedSegment.setUsed(true);
availabilitySnapshot.add(usedSegment);
geneDetails.setKey(usedSegment.getKey());
targetSegment.setStart(geneEndTime);
} else {
targetSegment.setUsed(true);
}
availabilitySnapshot.sort(Comparator.comparing(TimeSegment::getStart));
machine.setAvailability(availabilitySnapshot);
}
}
private void RemoveMachineAvailable1(Machine machine, ScheduleResultDetail geneDetails) {
List<TimeSegment> timeSegments = new ArrayList<>();
List<TimeSegment> availabilitySnapshot = new ArrayList<>(machine.getAvailability());
......@@ -946,15 +1054,46 @@ i++;
}
public void AddMachineAvailable(Machine machine, List<ScheduleResultDetail> geneDetails) {
if (geneDetails == null || geneDetails.isEmpty()) return;
synchronized (machine.getAvailability()) {
List<String> keys= geneDetails.stream().
filter(t->t.getUsedSegment()==null||t.getUsedSegment().size()==0)
.map(ScheduleResultDetail::getKey)
.collect(Collectors.toList());
List<String> keys1= geneDetails.stream().
filter(t->t.getUsedSegment()!=null)
.flatMap(detail -> detail.getUsedSegment().stream())
.map(TimeSegment::getKey).collect(Collectors.toList());
if(keys1!=null&&keys1.size()>0) {
keys.addAll(keys1);
}
machine.getAvailability().stream()
.filter(t ->keys.contains(t.getKey()))
.forEach(t->t.setUsed(false));
}
}
public void AddMachineAvailable1(Machine machine, List<ScheduleResultDetail> geneDetails) {
if (geneDetails == null || geneDetails.isEmpty()) return;
List<TimeSegment> availabilitySnapshot = new ArrayList<>(machine.getAvailability());
for (ScheduleResultDetail detail : geneDetails) {
if(detail.getUsedSegment()!=null&&detail.getUsedSegment().size()>0)
{
List<TimeSegment> availabilitySnapshot1= detail.getUsedSegment();
availabilitySnapshot1.forEach(t->t.setUsed(false));
}else {
availabilitySnapshot.stream()
.filter(t -> t.getKey().equals(detail.getKey()))
.findFirst()
.ifPresent(t -> t.setUsed(false));
}
}
availabilitySnapshot= MergeSegments(availabilitySnapshot);
synchronized (machine.getAvailability()) {
machine.setAvailability(availabilitySnapshot);
......
......@@ -97,7 +97,8 @@ public class PlanResultService {
@Autowired
private MaterialInfoMapper materialInfoMapper;
@Autowired
private MaterialPurchaseMapper materialPurchaseMapper;
@Autowired
private StockMapper stockMapper;
......@@ -1137,14 +1138,19 @@ private GlobalParam InitGlobalParam()
public List<Material> getMaterials(){
List<Material> materials=new ArrayList<>();
System.out.println("开始初始化物料数据");
LambdaQueryWrapper<MaterialInfo> MaterialInfoWrapper = new LambdaQueryWrapper<>();
MaterialInfoWrapper.eq(MaterialInfo::getIsdeleted,0);
List<MaterialInfo> materiallist=materialInfoMapper.selectList(MaterialInfoWrapper);
LambdaQueryWrapper<MaterialPurchase> materialPurchaseWrapper= new LambdaQueryWrapper<>();
materialPurchaseWrapper.eq(MaterialPurchase::getIsdeleted,0);
List<MaterialPurchase> MaterialPurchaselist=materialPurchaseMapper.selectList(materialPurchaseWrapper);
System.out.println("开始初始化物料数据");
LambdaQueryWrapper<Stock> StockWrapper = new LambdaQueryWrapper<>();
StockWrapper.eq(Stock::getIsdeleted,0);
......
......@@ -38,13 +38,13 @@ public class PlanResultServiceTest {
// nsgaiiUtils.Test();
//planResultService.execute2("C5FB5EF2A7334A0A92F826F4937E1008");
// planResultService.execute2("726D4C1A712B4B1393175BD44B775B66");
planResultService.execute2("BCA6FA43FFA444D3952CF8F6E1EA291B");
planResultService.execute2("726D4C1A712B4B1393175BD44B775B66");
// planResultService.execute2("BCA6FA43FFA444D3952CF8F6E1EA291B");
// LocalDateTime t= LocalDateTime.of(2025, 11, 15, 6, 51, 11);
// List<Integer> opids=new ArrayList<>();
// opids.add(1);
// planResultService.Move("B571EF6682DB463AB2977B1055A74112",opids,t,3403L);
// planResultService.Redecode("12345679");
planResultService.Redecode("12345679");
// MaintenanceWindow maintenanceWindow=new MaintenanceWindow();
// maintenanceWindow.setStartTime(LocalDateTime.of(2025, 10, 21, 0, 0, 0));
// maintenanceWindow.setEndTime(LocalDateTime.of(2025, 10, 31, 0, 0, 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