Commit eb9004a2 authored by Tong Li's avatar Tong Li

换型,拖动

parent 18420541
...@@ -142,7 +142,9 @@ public class Entry { ...@@ -142,7 +142,9 @@ public class Entry {
private BigDecimal runtime;//持续时间 private BigDecimal runtime;//持续时间
private BigDecimal singleOut;//单件产出 private BigDecimal singleOut;//单件产出
private double changeLineTime;//换模时间 private double changeLineTime;//换模时间
private BigDecimal setupTime; private BigDecimal setupTime;//准备时间
private int teardownTime; // 收尾时间(后处理时间)
//常数时间
private int constTime; private int constTime;
private String equipCode;//设备编码 private String equipCode;//设备编码
private String equipName;//设备编码 private String equipName;//设备编码
......
...@@ -38,5 +38,9 @@ public class GlobalParam { ...@@ -38,5 +38,9 @@ public class GlobalParam {
/// </summary> /// </summary>
private boolean IsOverlap = false; private boolean IsOverlap = false;
private boolean _smoothSetup = false; // 默认true,不占用设备时长 private boolean _smoothSetup = false; // 设置时间平滑 工序的前处理是否提前
private boolean _smoothChangeOver = true; // 默认true,设置时间 是否考虑换型时间
private boolean _smoothChangeOverInWeek = true; // 默认true,后台任务设置 休息时间是否换型
} }
...@@ -13,10 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -13,10 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -361,29 +358,33 @@ return population; ...@@ -361,29 +358,33 @@ return population;
FileHelper.writeLogFile(String.format(" KPI---%f-------",d)); FileHelper.writeLogFile(String.format(" KPI---%f-------",d));
} }
} }
private ExecutorService decodeExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2); //private ExecutorService decodeExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
private final ExecutorService decodeExecutor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors() - 1, // 核心线程数=CPU-1,无切换开销
Runtime.getRuntime().availableProcessors() - 1, // 最大线程数=核心数
0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(200), // 有界队列,避免内存溢出
new ThreadPoolExecutor.CallerRunsPolicy() // 任务满了主线程执行,不丢失任务
);
private void Chromosomedecode(ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList,List<Chromosome> population) private void Chromosomedecode(ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList,List<Chromosome> population)
{ {
FileHelper.writeLogFile("解码---------------"+population.size() ); FileHelper.writeLogFile("解码---------------"+population.size() );
GeneticDecoder decoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler,orderMaterials); GeneticDecoder decoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler,orderMaterials);
boolean ismore=true;
if(ismore) {
CompletableFuture.allOf(population.stream() CompletableFuture.allOf(population.stream()
.map(chromosome -> CompletableFuture.runAsync(() -> decode(decoder, chromosome, param, allOperations, globalOpList), decodeExecutor)) .map(chromosome -> CompletableFuture.runAsync(() -> decode(decoder, chromosome, param, allOperations, globalOpList), decodeExecutor))
.toArray(CompletableFuture[]::new)) .toArray(CompletableFuture[]::new))
.join(); .join();
} else {
if(1==2) {
if (population != null && population.size() > 0) { if (population != null && population.size() > 0) {
population.parallelStream().forEach(chromosome -> { population.parallelStream().forEach(chromosome -> {
decode(decoder, chromosome, param, allOperations, globalOpList); decode(decoder, chromosome, param, allOperations, globalOpList);
}); });
} }
} }
......
...@@ -329,7 +329,8 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -329,7 +329,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
.orElse(null); .orElse(null);
int prevtime = 0; int prevtime = 0;
//后处理时间
int teardownTime = currentOp.getTeardownTime();
if (!currentOp.getPrevEntryIds().isEmpty()) { if (!currentOp.getPrevEntryIds().isEmpty()) {
// 处理多个前工序 // 处理多个前工序
prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine); prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine);
...@@ -363,9 +364,16 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -363,9 +364,16 @@ if(finishedOrder==null||finishedOrder.size()==0)
private int processWithSingleMachine(Entry operation, Machine machine, double processingTime, private int processWithSingleMachine(Entry operation, Machine machine, double processingTime,
int prevOperationEndTime, Chromosome chromosome) {
int processingTimeTotal =(int)(processingTime * operation.getQuantity()); int prevOperationEndTime, Chromosome chromosome) {
int processingTimeTotal=0;
int earliestStartTime = prevOperationEndTime;
if(operation.getConstTime()==1)//常数时间
{
processingTimeTotal=(int)Math.ceil (processingTime);
}else {
processingTimeTotal =(int)Math.ceil (processingTime * operation.getQuantity());
}
if(machine==null||operation.getMachineOptions()==null) if(machine==null||operation.getMachineOptions()==null)
{ {
...@@ -380,21 +388,75 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -380,21 +388,75 @@ if(finishedOrder==null||finishedOrder.size()==0)
operation.setEquipCode(machine.getCode()); operation.setEquipCode(machine.getCode());
operation.setEquipName(machine.getName()); operation.setEquipName(machine.getName());
int teardownTime = machineOption.getTeardownTime(); if(setTime>0)
{
processingTimeTotal+=setTime;//加上准备工时
}
//后处理时间
int teardownTime = operation.getTeardownTime();
//前处理时间
int preTime = machineOption.getPreTime(); int preTime = machineOption.getPreTime();
//设置时间平滑 是 不考虑设置时间
//前处理,是否可以在相同任务前序未完工就开始设置时间,
// 就是 最早开工时间是否+前处理时间,总的加工工时不考虑前处理
if (!_globalParam.is_smoothSetup()) {
// 工序的前处理不能提前,则要在前处理完成后才能开工,所以要在前一工序的结束时间基础上+前处理
earliestStartTime+=preTime;
}
int setupTime=0;
CopyOnWriteArrayList<GAScheduleResult> machineTasks =chromosome.getResult().stream()
.filter(t -> t.getMachineId() == machine.getId())
.sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
// _globalParam.set_smoothChangeOver(false);
CopyOnWriteArrayList<ScheduleResultDetail> geneDetails=new CopyOnWriteArrayList<>();
if (_globalParam.is_smoothChangeOver()) {
//是否考虑换型时间
Map<Integer,Object> reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime,processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(),"",null);
setupTime=(int)reslte.get(1);//换型时间
int setupStartTime=(int)reslte.get(2);//换型开始时间
//earliestStartTime=(int)reslte.get(3);//上个任务的结束时间
earliestStartTime=(int)reslte.get(4);//最早开工时间
processingTimeTotal=(int)reslte.get(5);//processingTimeTotal
if(setupTime==0)
{
geneDetails = machineCalculator.getNextAvailableTime(machine, earliestStartTime, -1,
processingTimeTotal, chromosome.getResult(), operation.IsInterrupt!=1, true,processingTime, operation.getQuantity(), true);
}else {
CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = (CopyOnWriteArrayList<TimeSegment>) reslte.get(6);
int setupTime = calculateSetupTime(chromosome.getResult(), operation, machine, machineOption); GAScheduleResult existingResult = chromosome.getResultOld().stream().filter(r-> r.getOperationId() == operation.getId()).findFirst().orElse(null);
if(existingResult!=null)
{
earliestStartTime = Math.max(earliestStartTime,existingResult.getDesignatedStartTime());
}
//准备工时
int setTime = operation.getSetupTime().intValue();
Map<Integer,Object> result = machineCalculator.CreateScheduleResult(machine, processingTimeTotal, earliestStartTime,
AvailableTimeSegment, processingTime, operation.getQuantity(), operation.IsInterrupt != 1, setupTime, _globalParam.is_smoothChangeOverInWeek(), setupStartTime);
geneDetails = machineCalculator.getNextAvailableTime(machine, earliestStartTime, -1,
processingTimeTotal, chromosome.getResult(), operation.IsInterrupt!=1, true,processingTime, operation.getQuantity(), true);
// FileHelper.writeLogFile(" 开始 "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime + }
setupTime=(int)result.get(1);
operation.setChangeLineTime(setupTime);
geneDetails=(CopyOnWriteArrayList<ScheduleResultDetail>) result.get(2);
}
}else {
// FileHelper.writeLogFile(" 开始 "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
// ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt()); // ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt());
// 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理) // 确定任务的最早开始时间(基于前一道工序的完整结束时间,包含后处理)
int earliestStartTime = prevOperationEndTime;
// System.out.println(" 最终最早开始时间: " + earliestStartTime + // System.out.println(" 最终最早开始时间: " + earliestStartTime +
...@@ -402,28 +464,10 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -402,28 +464,10 @@ if(finishedOrder==null||finishedOrder.size()==0)
// (lastGeneOnMachine != null ? lastGeneOnMachine.getEndTime() : 0) + // (lastGeneOnMachine != null ? lastGeneOnMachine.getEndTime() : 0) +
// ", 换型: " + setupTime + ")"); // ", 换型: " + setupTime + ")");
// 根据换型模式调整处理时间
// int processingTimeForScheduling;
if (_globalParam.is_smoothSetup()) {
// 平滑模式:只需要安排主处理时间
// processingTimeForScheduling = processingTimeTotal;
// System.out.println(" 平滑模式:安排主处理时间 " + processingTime + " 分钟");
} else {
// 标准模式:需要安排主处理时间+换型时间
processingTimeTotal = processingTimeTotal + setupTime;
// System.out.println(" 标准模式:安排主处理+" + setupTime + "分钟换型=" + processingTimeTotal + "分钟");
}
GAScheduleResult existingResult = chromosome.getResultOld().stream().filter(r-> r.getOperationId() == operation.getId()).findFirst().orElse(null);
if(existingResult!=null)
{
earliestStartTime = Math.max(earliestStartTime,existingResult.getDesignatedStartTime());
}
CopyOnWriteArrayList<ScheduleResultDetail> geneDetails = machineCalculator.getNextAvailableTime(machine, earliestStartTime, -1,
processingTimeTotal, chromosome.getResult(), operation.IsInterrupt!=1, true,processingTime, operation.getQuantity(), true);
...@@ -436,52 +480,17 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -436,52 +480,17 @@ if(finishedOrder==null||finishedOrder.size()==0)
.mapToInt(ScheduleResultDetail::getEndTime) .mapToInt(ScheduleResultDetail::getEndTime)
.max() .max()
.orElse(0); .orElse(0);
//换型时间是否占用设备加工时间 //换型时间是否占用设备加工时间
//10:00 开始上班 前面的任务:24:00 结束 开始换型 休息时间 10小时 //10:00 开始上班 前面的任务:24:00 结束 开始换型 休息时间 10小时
// 换型时间 12小时 // 换型时间 12小时
// 换型时间 - 中间休息时间 =2小时 // 换型时间 - 中间休息时间 =2小时
//开工时间需往后延 2小时 //开工时间需往后延 2小时
//设置时间平滑
//前处理,准备工时 是否可以在前序未完工就开始时间, 就是 // 准备工时 加入到加工时间里
// 冲突检测和解决 // 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
final int finalStartTime = startTime;//10:00 12
final int finalEndTime = endTime;//15:00
// 7:00-9:00 1
//7:00-11:00 2
// 10<9&&15>7 1
// 10<11&&15>7 2 有任务
GAScheduleResult conflictingGene = chromosome.getResult().stream()
.filter(g -> g.getMachineId() == machine.getId())
.filter(g -> (finalStartTime < g.getEndTime() && finalEndTime > g.getStartTime()))
.findFirst()
.orElse(null);
if (conflictingGene != null) {
// System.out.println(" ⚠️ 检测到时间冲突,重新调度");
int conflictSetupStartTime = conflictingGene.getEndTime(); //11:00
int conflictSetupTime = calculateSetupTimeForConflict(chromosome.getResult(),operation , machine, machineOption, conflictingGene);
int conflictEarliestStartTime = conflictSetupStartTime + conflictSetupTime;
machineCalculator.AddMachineAvailable(machine,geneDetails);
/// 时间安排
geneDetails = machineCalculator.getNextAvailableTime(machine, conflictEarliestStartTime, -1,
processingTimeTotal, chromosome.getResult(), false, true,processingTime, operation.getQuantity(), true);
if (!geneDetails.isEmpty()) {
startTime = geneDetails.stream()
.mapToInt(ScheduleResultDetail::getStartTime)
.min()
.orElse(0);
endTime = geneDetails.stream()
.mapToInt(ScheduleResultDetail::getEndTime)
.max()
.orElse(0);
// System.out.println(" 重新安排时间: " + ConvertTime(startTime) + " - " + ConvertTime(endTime));
}
}
GAScheduleResult result=new GAScheduleResult(); GAScheduleResult result=new GAScheduleResult();
...@@ -541,7 +550,8 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -541,7 +550,8 @@ if(finishedOrder==null||finishedOrder.size()==0)
.filter(t -> t.getGroupId() == currentOp.GroupId && t.getOperationId() == opid.getPrevOperationId()) .filter(t -> t.getGroupId() == currentOp.GroupId && t.getOperationId() == opid.getPrevOperationId())
.collect(Collectors.toList());//多台 .collect(Collectors.toList());//多台
for (GAScheduleResult prevOp : prevOperations) { for (GAScheduleResult prevOp : prevOperations) {
prevtime = Math.max(prevtime, prevOp.getEndTime() + prevOp.getTeardownTime()); //加上后处理时间
prevtime = Math.max(prevtime, prevOp.getEndTime() + currentOp.getTeardownTime());
} }
} }
} }
...@@ -560,9 +570,6 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -560,9 +570,6 @@ if(finishedOrder==null||finishedOrder.size()==0)
for (GAScheduleResult prevOp : prevOperations) { for (GAScheduleResult prevOp : prevOperations) {
newScheduleResult.add(prevOp); newScheduleResult.add(prevOp);
newScheduleResultDetails.addAll(prevOp.getGeneDetails()); newScheduleResultDetails.addAll(prevOp.getGeneDetails());
} }
} }
...@@ -832,19 +839,71 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -832,19 +839,71 @@ if(finishedOrder==null||finishedOrder.size()==0)
private String ConvertTime(int minute) { private String ConvertTime(int minute) {
return baseTime.plusSeconds(minute).format(java.time.format.DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm")); return baseTime.plusSeconds(minute).format(java.time.format.DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm"));
} }
private int calculateSetupTime(List<GAScheduleResult> existingGenes, Entry operation, Machine machine, MachineOption machineOption) { private Map<Integer,Object> calculateSetupTime(CopyOnWriteArrayList<GAScheduleResult> machineTasks, Entry operation, Machine machine, int earliestStartTime,int processingTimeTotal,boolean changeOverInWeek,String lastExecId,Map<Integer,Object> lastsetupTime) {
Map<Integer,Object> reslte=new HashMap<>();
reslte.put(1,0);//换型时间
reslte.put(2,0);//换型开始时间
reslte.put(3,0);//上个任务的结束时间
reslte.put(4,earliestStartTime);//最早开工时间
reslte.put(5,processingTimeTotal);//总加工时长
if(machineTasks==null||machineTasks.size()==0)
{
return reslte;
}
// LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);
GAScheduleResult lastGeneOnMachine=machineTasks.get(machineTasks.size()-1);
if(lastGeneOnMachine.getEndTime()>earliestStartTime)
{
CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = machineCalculator.getMachineAvailableTime(machine, earliestStartTime,
processingTimeTotal, machineTasks, operation.IsInterrupt!=1);
if(AvailableTimeSegment!=null) {
reslte.put(6,AvailableTimeSegment);
int start= (int) ChronoUnit.SECONDS.between(baseTime, AvailableTimeSegment.get(0).getStart());
earliestStartTime= earliestStartTime>start ?earliestStartTime:start;
int earliestStartTime1=earliestStartTime;
reslte.put(4,earliestStartTime);//最早开工时间
CopyOnWriteArrayList<GAScheduleResult> machineTasks1= machineTasks.stream()
.filter(t->t.getEndTime()<=earliestStartTime1)
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
if(machineTasks1!=null&&machineTasks1.size()>0)
{
lastGeneOnMachine=machineTasks1.get(machineTasks1.size()-1);
}else {
GAScheduleResult lastGeneOnMachine = existingGenes.stream() return reslte;
.filter(g -> g.getMachineId() == machine.getId()) }
.max(Comparator.comparingInt(GAScheduleResult::getEndTime)) }
.orElse(null); }else {
CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = machineCalculator.getMachineAvailableTime(machine, earliestStartTime,
processingTimeTotal, machineTasks, operation.IsInterrupt!=1);
if(AvailableTimeSegment!=null) {
reslte.put(6, AvailableTimeSegment);
int start = (int) ChronoUnit.SECONDS.between(baseTime, AvailableTimeSegment.get(0).getStart());
earliestStartTime = earliestStartTime > start ? earliestStartTime : start;
if (lastGeneOnMachine == null) { reslte.put(4,earliestStartTime);//最早开工时间
// System.out.println("设备 " + machine.getId() + " 上无历史任务,换型时间为0"); }
return 0;
} }
reslte.put(3,lastGeneOnMachine.getEndTime());//换型开始时间
String ExecId=lastGeneOnMachine.getExecId();
if(lastExecId.equals(ExecId)) {
reslte.put(1, lastsetupTime.get(1));//换型时间
if(changeOverInWeek) {
reslte.put(2, earliestStartTime - (int) lastsetupTime.get(1)-1);
}
return reslte;
}
Entry prev= _allOperations.stream(). Entry prev= _allOperations.stream().
filter(t->t.getExecId().equals(lastGeneOnMachine.getExecId())) filter(t->t.getExecId().equals(ExecId))
.findFirst().orElse(null); .findFirst().orElse(null);
int setupTime=0; int setupTime=0;
if(prev!=null) if(prev!=null)
...@@ -869,11 +928,45 @@ if(finishedOrder==null||finishedOrder.size()==0) ...@@ -869,11 +928,45 @@ if(finishedOrder==null||finishedOrder.size()==0)
} }
// setupTime=20*3600;
operation.setChangeLineTime(setupTime); operation.setChangeLineTime(setupTime);
if(setupTime==0)
{
return reslte;
}
reslte.put(1,setupTime);//换型时间
if(changeOverInWeek)//可以放到休息时间
{
//01 16:00 +20 -01 16:00 02 12:00 08:00 -18:00 01 16:18 02 08:00-12:00
//01 16:00 +10 -01 16:00 换型10:00 08:00
//01 18:00 +10 -02 08:00<0 换型 休息时间满足
//01 18:00 +20 -02 08:00>0
//01 18:00 +10 -02 00:00>0
int cha=(lastGeneOnMachine.getEndTime()+setupTime)-earliestStartTime;
if(cha>0)
{
cha=cha+1;//加1是工序开始加工时间
reslte.put(2,lastGeneOnMachine.getEndTime());//换型开始时间
reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime+cha,processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), ExecId,reslte);
}
else {
reslte.put(2,earliestStartTime-setupTime);//换型开始时间
//如果空余时间足够
//可能会往前或后暂用设备时间
return reslte;
}
}else {
//开始时间加上设置时间重新算
//如果是前提供任务是相同的则跳出
reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime,processingTimeTotal+setupTime, _globalParam.is_smoothChangeOverInWeek(),ExecId,reslte);
}
// System.out.println("换型时间111"+setupTime); // System.out.println("换型时间111"+setupTime);
return setupTime; return reslte;
} }
private int calculateSetupTimeForConflict(List<GAScheduleResult> existingGenes, Entry operation, Machine machine, private int calculateSetupTimeForConflict(List<GAScheduleResult> existingGenes, Entry operation, Machine machine,
......
...@@ -37,7 +37,7 @@ public class GeneticOperations { ...@@ -37,7 +37,7 @@ public class GeneticOperations {
if (population == null || population.isEmpty()) { if (population == null || population.isEmpty()) {
return new ArrayList<>(); return new ArrayList<>();
} }
int populationSize = population.size(); int populationSize = population.size()>100?((int)(population.size()*0.8)):population.size();
// 预计算需要选中的个体数量,避免动态判断 // 预计算需要选中的个体数量,避免动态判断
int needSelectCount = populationSize - Math.max(1, Math.min(tournamentSize, populationSize)); int needSelectCount = populationSize - Math.max(1, Math.min(tournamentSize, populationSize));
List<Chromosome> selected = new ArrayList<>(needSelectCount); // 预初始化容量 List<Chromosome> selected = new ArrayList<>(needSelectCount); // 预初始化容量
......
...@@ -59,6 +59,194 @@ public class MachineCalculator { ...@@ -59,6 +59,194 @@ public class MachineCalculator {
existingTasks, oneTime, quantity, istask, islockMachineTime,isInterrupt); existingTasks, oneTime, quantity, istask, islockMachineTime,isInterrupt);
} }
public CopyOnWriteArrayList<TimeSegment> getMachineAvailableTime(Machine machine, int proposedStartTime,
int processingTime,
CopyOnWriteArrayList<GAScheduleResult> existingTasks,
boolean isInterrupt) {
LocalDateTime startTime = baseTime.plus(proposedStartTime, ChronoUnit.SECONDS);
// 查找合适的班次窗口
return findAvailableSegments(machine, startTime, existingTasks, processingTime, isInterrupt);
}
public Map<Integer,Object> CreateScheduleResult(
Machine machine, int processingTime, int proposedStartTime,CopyOnWriteArrayList<TimeSegment> timeSegments,
double oneTime,double quantity
,boolean isInterrupt,int changeOvertTime,boolean changeOverInWeek,int setupStartTime) {
LocalDateTime startTime = baseTime.plus(proposedStartTime, ChronoUnit.SECONDS);
Map<Integer,Object> result=new HashMap<>(2);
CopyOnWriteArrayList<ScheduleResultDetail> times = new CopyOnWriteArrayList<>();
int ChangeOverTimenew=0;
CopyOnWriteArrayList<TimeSegment> usedSegments=new CopyOnWriteArrayList<>();
if(changeOverInWeek)
{
// 换型时间完全在休息时间
LocalDateTime setupStartTime1 = baseTime.plusSeconds(setupStartTime);
ChangeOverTimenew=changeOvertTime;
int changeOvertTime_end=setupStartTime+changeOvertTime;
LocalDateTime setupendTime1 = baseTime.plusSeconds(changeOvertTime_end);
List<TimeSegment> setuptime= machine.getAvailability()
.stream()
.filter(t->((t.getStart().compareTo(setupStartTime1)>=0)
&&t.getEnd().compareTo(setupendTime1)<=0)||((t.getStart().compareTo(setupStartTime1)<=0)
&&t.getEnd().compareTo(setupStartTime1)>0))
.sorted(Comparator.comparing(TimeSegment::getStart))
.collect(Collectors.toList());
if(setuptime!=null&&setuptime.size()>0)
{
TimeSegment shift1 = setuptime.get(0);
LocalDateTime shiftStart1 = shift1.getStart();
//判断换型开始时间是否在工作时间段内,要占用工作时间,分割工作时间
if(setupStartTime1.compareTo(shiftStart1)>0)
{
ScheduleResultDetail time =new ScheduleResultDetail();
time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, setupStartTime1));
time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, shift1.getEnd()));
CopyOnWriteArrayList<TimeSegment> usedSegments1= RemoveMachineAvailable(machine, time,shift1);
if (usedSegments1 != null && usedSegments1.size() > 0) {
usedSegments.addAll(usedSegments1);
}
for (int i = 1; i <setuptime.size() ; i++) {
TimeSegment se = setuptime.get(i);
se.setUsed(true);
}
}else {
for (TimeSegment se:setuptime) {
se.setUsed(true);
}
}
// int i = 0;
// while (changeOvertTime > 0) {
// TimeSegment shift = setuptime.get(i);
// LocalDateTime shiftStart = shift.getStart();
// LocalDateTime shiftEnd = shift.getEnd();
// long availableSeconds = ChronoUnit.SECONDS.between(shiftStart, shiftEnd);
// int processable = Math.min(changeOvertTime, (int) availableSeconds);
//
// changeOvertTime-=processable;
// if(changeOvertTime>0)
// {
// shift.setUsed(true);
// }else {
// ScheduleResultDetail time =new ScheduleResultDetail();
// time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, shiftEnd.plusSeconds(-processable)));
// time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, shiftEnd));
//
// CopyOnWriteArrayList<TimeSegment> usedSegments1= RemoveMachineAvailable(machine, time,shift);
// if (usedSegments1 != null && usedSegments1.size() > 0) {
// usedSegments.addAll(usedSegments1);
// }
// }
// if(i!=setuptime.size()-1)
// {
// TimeSegment shift2 = setuptime.get(i+1);
// LocalDateTime shiftEnd2 = shift2.getEnd();
// long availableSeconds2 = ChronoUnit.SECONDS.between(shiftEnd2, shiftStart);
//
// changeOvertTime-=availableSeconds2;
// }
// i++;
// }
}
if (usedSegments != null && usedSegments.size() > 0) {
machine.getAvailability().addAll(usedSegments);
machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
}
times= CaldScheduleResult(
machine, processingTime, startTime,
timeSegments, oneTime, quantity
);
}else {
//换型时间在工作时间
int i = 0;
//要先把换型时间占用的工作时间占用
LocalDateTime ChangeOverstartTime=startTime;
LocalDateTime ChangeOverendTime=startTime;
int changeOvertTimeold=changeOvertTime;
while (changeOvertTime > 0) {
TimeSegment shift = timeSegments.get(i);
LocalDateTime shiftStart = shift.getStart();
LocalDateTime shiftEnd = shift.getEnd();
// 计算有效时间
LocalDateTime effectiveStart = startTime.isAfter(shiftStart) ? startTime : shiftStart;
long availableSeconds = ChronoUnit.SECONDS.between(effectiveStart, shiftEnd);
// 处理当前班次
int processable = Math.min(changeOvertTime, (int) availableSeconds);
changeOvertTime -= processable;
startTime = effectiveStart.plusSeconds(processable);
ChangeOverendTime=startTime;
ScheduleResultDetail time =new ScheduleResultDetail();
time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, effectiveStart));
time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, startTime));
CopyOnWriteArrayList<TimeSegment> usedSegments1= RemoveMachineAvailable(machine, time,shift);
if (usedSegments1 != null && usedSegments1.size() > 0) {
usedSegments.addAll(usedSegments1);
}
if(processable>=availableSeconds)
{
i++;
}
}
ChangeOverTimenew =(int)ChronoUnit.SECONDS.between(ChangeOverstartTime, ChangeOverendTime);
processingTime= processingTime-changeOvertTimeold;
TimeSegment slot = timeSegments.get(i);
LocalDateTime startCandidate = slot.getStart().isAfter(startTime)
? slot.getStart()
: startTime;
LocalDateTime endCandidate = startCandidate.plusSeconds(processingTime);
if (endCandidate.isAfter(slot.getEnd())) {
CopyOnWriteArrayList<TimeSegment> timeSegments1= timeSegments.stream()
.filter(t->t.getStart().compareTo(startCandidate)>=0)
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
times= CaldScheduleResult(
machine, processingTime, startTime,
timeSegments1, oneTime, quantity);
} else {
ScheduleResultDetail time = new ScheduleResultDetail();
time.setKey(slot.getKey());
time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, startCandidate));
time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, endCandidate));
time.setOneTime(oneTime);
time.setQuantity(quantity);
times.add(time);
CopyOnWriteArrayList<TimeSegment> usedSegments1= RemoveMachineAvailable(machine, time,slot);
if (usedSegments1 != null && usedSegments1.size() > 0) {
usedSegments.addAll(usedSegments1);
}
}
if (usedSegments != null && usedSegments.size() > 0) {
machine.getAvailability().addAll(usedSegments);
machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
}
}
result.put(1,ChangeOverTimenew);
result.put(2,times);
return result;
}
// 查找最早可用开始时间 // 查找最早可用开始时间
...@@ -80,6 +268,10 @@ public class MachineCalculator { ...@@ -80,6 +268,10 @@ public class MachineCalculator {
LocalDateTime startCandidate = slot.getStart().isAfter(prevTimeDateTime != null ? prevTimeDateTime : currentTime) LocalDateTime startCandidate = slot.getStart().isAfter(prevTimeDateTime != null ? prevTimeDateTime : currentTime)
? slot.getStart() ? slot.getStart()
: (prevTimeDateTime != null ? prevTimeDateTime : currentTime); : (prevTimeDateTime != null ? prevTimeDateTime : currentTime);
if(slot.getStart().isBefore(startCandidate))
{
int i=0;
}
LocalDateTime endCandidate = startCandidate.plusSeconds(processingTime); LocalDateTime endCandidate = startCandidate.plusSeconds(processingTime);
if (endCandidate.isAfter(slot.getEnd())) { if (endCandidate.isAfter(slot.getEnd())) {
...@@ -92,8 +284,11 @@ public class MachineCalculator { ...@@ -92,8 +284,11 @@ public class MachineCalculator {
time.setOneTime(oneTime); time.setOneTime(oneTime);
time.setQuantity(quantity); time.setQuantity(quantity);
times.add(time); times.add(time);
if(islockMachineTime) {
RemoveMachineAvailable(machine, time,slot); CopyOnWriteArrayList<TimeSegment> usedSegments = RemoveMachineAvailable(machine, time, slot);
if (usedSegments != null && usedSegments.size() > 0) {
machine.getAvailability().addAll(usedSegments);
machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
} }
return times; return times;
} }
...@@ -183,28 +378,89 @@ public class MachineCalculator { ...@@ -183,28 +378,89 @@ public class MachineCalculator {
CopyOnWriteArrayList<ScheduleResultDetail> times = new CopyOnWriteArrayList<>(); CopyOnWriteArrayList<ScheduleResultDetail> times = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<TimeSegment> timeSegments= findAvailableSegments(machine, currentTime, machineTasks, remainingTime, isInterrupt); CopyOnWriteArrayList<TimeSegment> timeSegments= findAvailableSegments(machine, currentTime, machineTasks, remainingTime, isInterrupt);
times= CaldScheduleResult(
machine, processingTime, currentTime,
timeSegments, oneTime, quantity
);
// int estimateIndex= (int) Math.ceil(remainingTime / (double) ONE_DAY_MINUTES);
// CopyOnWriteArrayList<TimeSegment> timeSegments1=null;
// if(estimateIndex>10)
// {
// timeSegments1= getEnoughSegmentsByEstimateIndex(timeSegments,currentTime,remainingTime);
// }
//
// if(timeSegments1==null) {
// int i = 0;
// CopyOnWriteArrayList<TimeSegment> usedSegments =new CopyOnWriteArrayList<>();
// while (remainingTime > 0) {
// 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);
// // 还原未使用的时间段
// CopyOnWriteArrayList<TimeSegment> usedSegments1= RemoveMachineAvailable(machine, time,shift);
// if(usedSegments1!=null&&usedSegments1.size()>0)
// {
// usedSegments.addAll(usedSegments1);
// }
// i++;
// }
//
// if (usedSegments != null && usedSegments.size() > 0) {
// machine.getAvailability().addAll(usedSegments);
// machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
// }
// }else {
// times= CaldScheduleResultDetail(timeSegments1,machine,st,remainingTime,oneTime);
// }
return times;
}
private CopyOnWriteArrayList<ScheduleResultDetail> CaldScheduleResult(
Machine machine, int processingTime, LocalDateTime currentTime,
CopyOnWriteArrayList<TimeSegment> timeSegments,double oneTime,double quantity
) {
int remainingTime = processingTime;
CopyOnWriteArrayList<ScheduleResultDetail> times = new CopyOnWriteArrayList<>();
int estimateIndex= (int) Math.ceil(remainingTime / (double) ONE_DAY_MINUTES); int estimateIndex= (int) Math.ceil(remainingTime / (double) ONE_DAY_MINUTES);
CopyOnWriteArrayList<TimeSegment> timeSegments1=null; CopyOnWriteArrayList<TimeSegment> timeSegments1=null;
if(estimateIndex>10) if(estimateIndex>10)
{ {
timeSegments1= getEnoughSegmentsByEstimateIndex(timeSegments,currentTime,remainingTime); timeSegments1= getEnoughSegmentsByEstimateIndex(timeSegments,currentTime,remainingTime);
} }
if(timeSegments1==null) { if(timeSegments1==null) {
int i = 0; int i = 0;
CopyOnWriteArrayList<TimeSegment> usedSegments =new CopyOnWriteArrayList<>();
while (remainingTime > 0) { while (remainingTime > 0) {
TimeSegment shift = timeSegments.get(i); TimeSegment shift = timeSegments.get(i);
Map<Integer, Object> outMap = CreateScheduleResultDetail(shift, st, remainingTime, oneTime); Map<Integer, Object> outMap = CreateScheduleResultDetail(shift, currentTime, remainingTime, oneTime);
remainingTime = (int) outMap.get(1); remainingTime = (int) outMap.get(1);
ScheduleResultDetail time = (ScheduleResultDetail) outMap.get(2); ScheduleResultDetail time = (ScheduleResultDetail) outMap.get(2);
times.add(time); times.add(time);
// 还原未使用的时间段 // 还原未使用的时间段
RemoveMachineAvailable(machine, time,shift); CopyOnWriteArrayList<TimeSegment> usedSegments1= RemoveMachineAvailable(machine, time,shift);
if(usedSegments1!=null&&usedSegments1.size()>0)
{
usedSegments.addAll(usedSegments1);
}
i++; i++;
} }
if (usedSegments != null && usedSegments.size() > 0) {
machine.getAvailability().addAll(usedSegments);
machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
}
}else { }else {
times= CaldScheduleResultDetail(timeSegments1,machine,st,remainingTime,oneTime); times= CaldScheduleResultDetail(timeSegments1,machine,currentTime,remainingTime,oneTime);
} }
return times; return times;
...@@ -214,6 +470,7 @@ public class MachineCalculator { ...@@ -214,6 +470,7 @@ public class MachineCalculator {
{ {
int processable1 =(int)calculateTotalAvailableSecond(timeSegments, st); int processable1 =(int)calculateTotalAvailableSecond(timeSegments, st);
CopyOnWriteArrayList<TimeSegment> usedSegments =new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<ScheduleResultDetail> times = new CopyOnWriteArrayList<>(); CopyOnWriteArrayList<ScheduleResultDetail> times = new CopyOnWriteArrayList<>();
...@@ -224,8 +481,10 @@ public class MachineCalculator { ...@@ -224,8 +481,10 @@ public class MachineCalculator {
remainingTime=(int)outMap.get(1); remainingTime=(int)outMap.get(1);
ScheduleResultDetail time1=(ScheduleResultDetail)outMap.get(2); ScheduleResultDetail time1=(ScheduleResultDetail)outMap.get(2);
times.add(time1); times.add(time1);
RemoveMachineAvailable(machine, time1,shiftfrist); CopyOnWriteArrayList<TimeSegment> usedSegments1 = RemoveMachineAvailable(machine, time1,shiftfrist);
if (usedSegments1 != null && usedSegments1.size() > 0) {
usedSegments.addAll(usedSegments1);
}
// 计算有效时间 // 计算有效时间
CopyOnWriteArrayList<TimeSegment> timeSegments2= new CopyOnWriteArrayList<>(timeSegments.subList(1,timeSegments.size()-1)); CopyOnWriteArrayList<TimeSegment> timeSegments2= new CopyOnWriteArrayList<>(timeSegments.subList(1,timeSegments.size()-1));
...@@ -252,7 +511,14 @@ public class MachineCalculator { ...@@ -252,7 +511,14 @@ public class MachineCalculator {
remainingTime=(int)outMaplast.get(1); remainingTime=(int)outMaplast.get(1);
ScheduleResultDetail timelast=(ScheduleResultDetail)outMaplast.get(2); ScheduleResultDetail timelast=(ScheduleResultDetail)outMaplast.get(2);
times.add(timelast); times.add(timelast);
RemoveMachineAvailable(machine, timelast,shiftlast); CopyOnWriteArrayList<TimeSegment> usedSegments2 = RemoveMachineAvailable(machine, timelast,shiftlast);
if (usedSegments2 != null && usedSegments2.size() > 0) {
usedSegments.addAll(usedSegments2);
}
if (usedSegments != null && usedSegments.size() > 0) {
machine.getAvailability().addAll(usedSegments);
machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
}
return times; return times;
} }
...@@ -978,42 +1244,73 @@ public class MachineCalculator { ...@@ -978,42 +1244,73 @@ public class MachineCalculator {
return times; return times;
} }
private void RemoveMachineAvailable(Machine machine, ScheduleResultDetail geneDetails,TimeSegment targetSegment) { private CopyOnWriteArrayList<TimeSegment> RemoveMachineAvailable(Machine machine, ScheduleResultDetail geneDetails,TimeSegment targetSegment) {
// 关键修复2:加锁(若多线程访问),避免并发修改
LocalDateTime geneStartTime = baseTime.plusSeconds(geneDetails.getStartTime());
LocalDateTime geneEndTime = baseTime.plusSeconds(geneDetails.getEndTime());
CopyOnWriteArrayList<TimeSegment> usedSegments=new CopyOnWriteArrayList<>();
if (targetSegment.getStart().isBefore(geneStartTime)&&targetSegment.getEnd().isAfter(geneEndTime)) {
TimeSegment usedSegment=new TimeSegment();
usedSegment.setStart(targetSegment.getStart());
usedSegment.setEnd(geneStartTime);
usedSegment.setHoliday(false);
usedSegment.setKey(UUID.randomUUID().toString());
usedSegment.setType(SegmentType.REGULAR);
usedSegment.setUsed(false);
usedSegment.setKey(UUID.randomUUID().toString());
usedSegments.add(usedSegment);
TimeSegment usedSegment2=new TimeSegment();
usedSegment2.setStart(geneStartTime);
usedSegment2.setEnd(geneEndTime);
usedSegment2.setHoliday(false);
usedSegment2.setKey(UUID.randomUUID().toString());
usedSegment2.setType(SegmentType.REGULAR);
usedSegment2.setUsed(true);
usedSegments.add(usedSegment2);
LocalDateTime geneEndTime = baseTime.plusSeconds(geneDetails.getEndTime()); geneDetails.setKey(usedSegment2.getKey());
TimeSegment usedSegment = null; targetSegment.setStart(geneEndTime);
if (targetSegment.getEnd().isAfter(geneEndTime)) {
usedSegment=new TimeSegment(); }
else if (targetSegment.getEnd().isAfter(geneEndTime)) {
TimeSegment usedSegment=new TimeSegment();
usedSegment.setStart(baseTime.plusSeconds(geneDetails.getStartTime())); usedSegment.setStart(baseTime.plusSeconds(geneDetails.getStartTime()));
usedSegment.setEnd(geneEndTime); usedSegment.setEnd(geneEndTime);
usedSegment.setHoliday(false); usedSegment.setHoliday(false);
usedSegment.setKey(UUID.randomUUID().toString()); usedSegment.setKey(UUID.randomUUID().toString());
usedSegment.setType(SegmentType.REGULAR); usedSegment.setType(SegmentType.REGULAR);
usedSegment.setUsed(true); usedSegment.setUsed(true);
usedSegments.add(usedSegment);
geneDetails.setKey(usedSegment.getKey()); geneDetails.setKey(usedSegment.getKey());
targetSegment.setStart(geneEndTime); targetSegment.setStart(geneEndTime);
} else { }else if (targetSegment.getStart().isBefore(geneStartTime)) {
//换型时可能需要把前面的时间分割处理
TimeSegment usedSegment=new TimeSegment();
usedSegment.setStart(targetSegment.getStart());
usedSegment.setEnd(geneStartTime);
usedSegment.setHoliday(false);
usedSegment.setKey(UUID.randomUUID().toString());
usedSegment.setType(SegmentType.REGULAR);
usedSegment.setUsed(false);
usedSegment.setKey(UUID.randomUUID().toString());
usedSegments.add(usedSegment);
geneDetails.setKey(targetSegment.getKey());
targetSegment.setStart(geneStartTime);
targetSegment.setUsed(true);
}else {
targetSegment.setUsed(true); targetSegment.setUsed(true);
} }
return usedSegments;
if(usedSegment!=null) // if(usedSegments!=null&&usedSegments.size()>0)
{ // {
// machine.getAvailability().addAll(usedSegments);
// machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
machine.getAvailability().add(usedSegment); // }
machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
}
} }
private void RemoveMachineAvailable1(Machine machine, ScheduleResultDetail geneDetails,TimeSegment targetSegment1) { private void RemoveMachineAvailable1(Machine machine, ScheduleResultDetail geneDetails,TimeSegment targetSegment1) {
......
package com.aps.service.Algorithm; package com.aps.service.Algorithm;
import com.aps.common.util.FileHelper;
import com.aps.entity.Algorithm.Chromosome; import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.ObjectiveWeights; import com.aps.entity.Algorithm.ObjectiveWeights;
...@@ -48,7 +49,10 @@ public class NSGAIIUtils { ...@@ -48,7 +49,10 @@ public class NSGAIIUtils {
* 并行快速非支配排序(大规模种群提速50%+) * 并行快速非支配排序(大规模种群提速50%+)
*/ */
public List<List<Chromosome>> parallelFastNonDominatedSort(List<Chromosome> population) { public List<List<Chromosome>> parallelFastNonDominatedSort(List<Chromosome> population) {
int popSize = population.size(); int popSize = population.size();
FileHelper.writeLogFile("非支配排序---------------"+popSize );
List<List<Chromosome>> fronts = new ArrayList<>(); List<List<Chromosome>> fronts = new ArrayList<>();
// 步骤1:预处理 - 计算归一化目标值和加权目标值 // 步骤1:预处理 - 计算归一化目标值和加权目标值
......
...@@ -213,7 +213,10 @@ public class RoutingDataService { ...@@ -213,7 +213,10 @@ public class RoutingDataService {
entry.setEquipTypeCode(op.getEquipTypeCode()); entry.setEquipTypeCode(op.getEquipTypeCode());
entry.setRuntime(op.getRuntime()); entry.setRuntime(op.getRuntime());
entry.setSingleOut(op.getSingleOut()); entry.setSingleOut(op.getSingleOut());
//生产准备
entry.setSetupTime(op.getSetupTime()); entry.setSetupTime(op.getSetupTime());
//后处理
entry.setTeardownTime(op.getPostprocessingTime());
entry.setConstTime(op.getConstTime()); entry.setConstTime(op.getConstTime());
entry.setOrderId(op.getOrderId()); entry.setOrderId(op.getOrderId());
entry.setOrderCode(op.getOrderCode()); entry.setOrderCode(op.getOrderCode());
...@@ -248,6 +251,7 @@ public class RoutingDataService { ...@@ -248,6 +251,7 @@ public class RoutingDataService {
machineIds.replace(e.getEquipId(),totalprocessTime); machineIds.replace(e.getEquipId(),totalprocessTime);
} }
}else { }else {
//大概记录要用到的设备的加工时间,用于生成设备日历
machineIds.put(e.getEquipId(),totalprocessTime); machineIds.put(e.getEquipId(),totalprocessTime);
} }
......
...@@ -23,6 +23,183 @@ import java.util.stream.IntStream; ...@@ -23,6 +23,183 @@ import java.util.stream.IntStream;
*/ */
public class ScheduleOperationService { public class ScheduleOperationService {
/**
* 移动工序方法
* @param chromosome 染色体对象
* @param opIds 工序ID
* @param targetopId 目标工序ID
* @param isfront 目标工序ID的前面
* @param newMachineId 新设备ID
*/
public void dragOperation(Chromosome chromosome, List<Integer> opIds, int targetopId,Boolean isfront,
Long newMachineId, GlobalParam globalParam) {
List<Entry> allOperations = chromosome.getAllOperations();
int newStartTime=0;
List<Integer> ordersIds=new ArrayList<>();
List<Integer> opsIndexs=new ArrayList<>();
Map<Integer, Integer> opTimeMap = chromosome.getResult().stream()
.collect(Collectors.toMap(
GAScheduleResult::getOperationId,
r -> r.getStartTime()
));
List<OperationSort> opGroupMap = allOperations.stream()
.map(data -> new OperationSort(data.getId(), 0,data.getGroupId(),data.getSequence())) // 再提取字段
.collect(Collectors.toList());
Integer newMachineId1=newMachineId.intValue();
List<Integer> OperationSequencing= chromosome.getOperationSequencing();
GAScheduleResult targetResult1=null;
Entry targetOp1=null;
int targetopIndex1=0;
if(targetopId!=0) {
targetResult1 = chromosome.getResult().stream()
.filter(r -> r.getOperationId() == targetopId)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("Operation not found: " + targetopId));
targetOp1 = allOperations.stream()
.filter(o -> o.getId() == targetopId)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("Operation not found: " + targetopId));
int GroupId=targetOp1.GroupId;
OptionalInt OperationIndex = IntStream.range(0, OperationSequencing.size())
.filter(i -> OperationSequencing.get(i).equals(GroupId)) // 过滤出值为1的索引
.skip(targetOp1.Sequence-1) // 跳过第一个匹配项
.findFirst(); // 取第二个匹配项
targetopIndex1=OperationIndex.getAsInt();
if(isfront)
{
newStartTime=targetResult1.getStartTime();
}else {
newStartTime=targetResult1.getEndTime();
}
}
for (Integer opId:opIds) {
// 获取目标结果和工序
GAScheduleResult targetResult = chromosome.getResult().stream()
.filter(r -> r.getOperationId() == opId)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("Operation not found: " + targetopId));
Entry targetOp = allOperations.stream()
.filter(o -> o.getId() == opId)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("Operation not found: " + opId));
if (targetOp.getSequence() > 1) {
Entry targetOp2 = allOperations.stream()
.filter(o -> o.getGroupId() == targetOp.getGroupId()
&& o.getSequence() == targetOp.getSequence() - 1)
.findFirst()
.orElseThrow(() -> new NoSuchElementException("Operation not found: " + opId));
GAScheduleResult targetResult2 = chromosome.getResult().stream()
.filter(r -> r.getOperationId() == targetOp2.getId())
.findFirst()
.orElseThrow(() -> new NoSuchElementException("Operation not found: " + opId));
if (targetResult2.getEndTime() < newStartTime) {
throw new RuntimeException("不能早于前一工序的结束时间");
}
}
if(targetopId!=0) {
OptionalInt OperationIndex = IntStream.range(0, OperationSequencing.size())
.filter(i -> OperationSequencing.get(i).equals(targetOp.GroupId)) // 过滤出值为1的索引
.skip(targetOp.Sequence - 1) // 跳过第一个匹配项
.findFirst(); // 取第二个匹配项
int targetOpIndex = OperationIndex.getAsInt();
opsIndexs.add(targetOpIndex);
ordersIds.add(targetOp.GroupId);
List<Entry> targetOp2s = allOperations.stream()
.filter(o -> o.getGroupId() == targetOp.getGroupId()
&& o.getSequence() > targetOp.getSequence()).collect(Collectors.toList());
if(targetOp2s!=null&&targetOp2s.size()>0)
{
for (Entry targetOp4:targetOp2s) {
OptionalInt OperationIndex1 = IntStream.range(0, OperationSequencing.size())
.filter(i -> OperationSequencing.get(i).equals(targetOp.GroupId)) // 过滤出值为1的索引
.skip(targetOp4.Sequence - 1) // 跳过第一个匹配项
.findFirst(); // 取第二个匹配项
int targetOpIndex2 = OperationIndex1.getAsInt();
if(targetOpIndex2<targetopIndex1)//后面的工序位置比目标位置靠前
{//后面的工序也要往后挪
opsIndexs.add(targetOpIndex2);
ordersIds.add(targetOp.GroupId);
}
}
}
}
if(newMachineId1!=0) {
int machineOptionIndex = targetOp.getMachineOptions().stream()
.map(MachineOption::getMachineId)
.collect(Collectors.toList())
.indexOf(newMachineId) + 1;
if (machineOptionIndex == 0) {
throw new NoSuchElementException("Machine not found: " + newMachineId);
}
// 更新设备选择序列
int globalOpIndex = chromosome.getGlobalOpList().stream()
.filter(g -> g.getOp().getId() == opId)
.findFirst()
.map(GlobalOperationInfo::getGlobalOpId)
.orElseThrow(() -> new NoSuchElementException("Global operation not found: " + opId));
chromosome.getMachineSelection().set(globalOpIndex, machineOptionIndex);
targetResult.setForcedMachineId(newMachineId);
}else {
newMachineId1=(int)targetResult.getMachineId();
}
}
if(targetopId!=0) {
opsIndexs.sort(Comparator.reverseOrder());
for (int i = 0; i < opsIndexs.size(); i++) {
Integer in = opsIndexs.get(i);
// 安全校验:防止索引越界
if (in >= 0 && in < OperationSequencing.size()) {
OperationSequencing.remove((int)in);
}
}
int GroupId=targetOp1.GroupId;
OptionalInt OperationIndex = IntStream.range(0, OperationSequencing.size())
.filter(i -> OperationSequencing.get(i).equals(GroupId)) // 过滤出值为1的索引
.skip(targetOp1.Sequence-1) // 跳过第一个匹配项
.findFirst(); // 取第二个匹配项
int targetOpIndex= OperationIndex.getAsInt();
if(!isfront)
{
targetOpIndex+=1;
}
for (Integer orderid:ordersIds) {
OperationSequencing.add(targetOpIndex, orderid);
targetOpIndex++;
}
}
chromosome.setOperationSequencing(OperationSequencing);
// 重新解码
redecode(chromosome, chromosome.getBaseTime(), globalParam);
}
/** /**
...@@ -317,7 +494,7 @@ if(targetOp.getSequence()>1) { ...@@ -317,7 +494,7 @@ if(targetOp.getSequence()>1) {
.findFirst(); .findFirst();
if (index.isPresent()) { if (index.isPresent()) {
machine.getMaintenanceWindows().remove(index.getAsInt()); machine.getMaintenanceWindows().remove((int)index.getAsInt());
MachineSchedulerService machineScheduler = new MachineSchedulerService( MachineSchedulerService machineScheduler = new MachineSchedulerService(
chromosome.getBaseTime()); chromosome.getBaseTime());
machineScheduler.ClearMachineCache(machineId); machineScheduler.ClearMachineCache(machineId);
...@@ -746,27 +923,27 @@ if(targetOp.getSequence()>1) { ...@@ -746,27 +923,27 @@ if(targetOp.getSequence()>1) {
OptionalInt index = IntStream.range(0, allOperations.size()) OptionalInt index = IntStream.range(0, allOperations.size())
.filter(h -> entry.getId()==allOperations.get(h).getId()) .filter(h -> entry.getId()==allOperations.get(h).getId())
.findFirst(); .findFirst();
allOperations.remove(index.orElse(0)); allOperations.remove((int)index.orElse(0));
OptionalInt index1 = IntStream.range(0, globalOpList.size()) OptionalInt index1 = IntStream.range(0, globalOpList.size())
.filter(h -> entry.getId()==globalOpList.get(h).getOp().getId()) .filter(h -> entry.getId()==globalOpList.get(h).getOp().getId())
.findFirst(); .findFirst();
globalOpList.remove(index1.orElse(0)); globalOpList.remove((int)index1.orElse(0));
chromosome.getMachineSelection().remove(index1.orElse(0)); chromosome.getMachineSelection().remove((int)index1.orElse(0));
OptionalInt OperationIndex = IntStream.range(0, OperationSequencing.size()) OptionalInt OperationIndex = IntStream.range(0, OperationSequencing.size())
.filter(i -> OperationSequencing.get(i).equals(entry.GroupId)) // 过滤出值为1的索引 .filter(i -> OperationSequencing.get(i).equals(entry.GroupId)) // 过滤出值为1的索引
.findFirst(); .findFirst();
int targetOpIndex= OperationIndex.getAsInt(); int targetOpIndex= OperationIndex.getAsInt();
OperationSequencing.remove(targetOpIndex); OperationSequencing.remove((int)targetOpIndex);
OptionalInt OperationIndex1 = IntStream.range(0, ScheduleResults.size()) OptionalInt OperationIndex1 = IntStream.range(0, ScheduleResults.size())
.filter(i -> ScheduleResults.get(i).getOperationId()==entry.getId()) // 过滤出值为1的索引 .filter(i -> ScheduleResults.get(i).getOperationId()==entry.getId()) // 过滤出值为1的索引
.findFirst(); .findFirst();
//锁定需要删除 //锁定需要删除
ScheduleResults.remove(OperationIndex1.getAsInt()); ScheduleResults.remove((int)OperationIndex1.getAsInt());
} }
AtomicInteger globalOpId = new AtomicInteger(0); AtomicInteger globalOpId = new AtomicInteger(0);
...@@ -892,7 +1069,7 @@ if(targetOp.getSequence()>1) { ...@@ -892,7 +1069,7 @@ if(targetOp.getSequence()>1) {
.filter(i -> OperationSequencing.get(i).equals(targetOp.GroupId)) // 过滤出值为1的索引 .filter(i -> OperationSequencing.get(i).equals(targetOp.GroupId)) // 过滤出值为1的索引
.skip(targetOp.Sequence-1) // 跳过第一个匹配项 .skip(targetOp.Sequence-1) // 跳过第一个匹配项
.findFirst(); .findFirst();
chromosome.getOperationSequencing().remove(OperationIndex.getAsInt()); chromosome.getOperationSequencing().remove((int)OperationIndex.getAsInt());
...@@ -902,8 +1079,8 @@ if(targetOp.getSequence()>1) { ...@@ -902,8 +1079,8 @@ if(targetOp.getSequence()>1) {
.orElseThrow(() -> new NoSuchElementException("Global operation not found: " + opId)); .orElseThrow(() -> new NoSuchElementException("Global operation not found: " + opId));
chromosome.getMachineSelection().remove(globalOpIndex); chromosome.getMachineSelection().add((int)globalOpIndex);
globalOpList.remove(globalOpIndex); globalOpList.remove((int)globalOpIndex);
AtomicInteger globalOpId = new AtomicInteger(0); AtomicInteger globalOpId = new AtomicInteger(0);
...@@ -953,27 +1130,27 @@ if(targetOp.getSequence()>1) { ...@@ -953,27 +1130,27 @@ if(targetOp.getSequence()>1) {
OptionalInt index = IntStream.range(0, allOperations.size()) OptionalInt index = IntStream.range(0, allOperations.size())
.filter(h -> entry.getId()==allOperations.get(h).getId()) .filter(h -> entry.getId()==allOperations.get(h).getId())
.findFirst(); .findFirst();
allOperations.remove(index.orElse(0)); allOperations.remove((int)index.orElse(0));
OptionalInt index1 = IntStream.range(0, globalOpList.size()) OptionalInt index1 = IntStream.range(0, globalOpList.size())
.filter(h -> entry.getId()==globalOpList.get(h).getOp().getId()) .filter(h -> entry.getId()==globalOpList.get(h).getOp().getId())
.findFirst(); .findFirst();
globalOpList.remove(index1.orElse(0)); globalOpList.remove((int)index1.orElse(0));
chromosome.getMachineSelection().remove(index1.orElse(0)); chromosome.getMachineSelection().remove((int)index1.orElse(0));
OptionalInt OperationIndex = IntStream.range(0, OperationSequencing.size()) OptionalInt OperationIndex = IntStream.range(0, OperationSequencing.size())
.filter(i -> OperationSequencing.get(i).equals(entry.GroupId)) // 过滤出值为1的索引 .filter(i -> OperationSequencing.get(i).equals(entry.GroupId)) // 过滤出值为1的索引
.findFirst(); .findFirst();
int targetOpIndex= OperationIndex.getAsInt(); int targetOpIndex= OperationIndex.getAsInt();
OperationSequencing.remove(targetOpIndex); OperationSequencing.remove((int)targetOpIndex);
OptionalInt OperationIndex1 = IntStream.range(0, ScheduleResults.size()) OptionalInt OperationIndex1 = IntStream.range(0, ScheduleResults.size())
.filter(i -> ScheduleResults.get(i).getOperationId()==entry.getId()) // 过滤出值为1的索引 .filter(i -> ScheduleResults.get(i).getOperationId()==entry.getId()) // 过滤出值为1的索引
.findFirst(); .findFirst();
//锁定需要删除 //锁定需要删除
ScheduleResults.remove(OperationIndex1.getAsInt()); ScheduleResults.remove((int)OperationIndex1.getAsInt());
} }
......
...@@ -540,6 +540,23 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0)); ...@@ -540,6 +540,23 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
return chromosome; return chromosome;
} }
public Chromosome Drag(String SceneId,List<Integer> opId, int targetopId,Boolean isfront,
Long newMachineId) {
GlobalParam globalParam=new GlobalParam();
Chromosome chromosome= _sceneService.loadChromosomeFromFile(SceneId);
// WriteScheduleSummary(chromosome);
ScheduleOperationService ScheduleOperation=new ScheduleOperationService();
// WriteScheduleSummary(chromosome);
ScheduleOperation.dragOperation(chromosome,opId,targetopId,isfront,newMachineId, globalParam);
// WriteScheduleSummary(chromosome);
_sceneService.saveChromosomeToFile(chromosome, SceneId);
return chromosome;
}
public Chromosome Move(String SceneId,List<Integer> opId, LocalDateTime newStartTime, public Chromosome Move(String SceneId,List<Integer> opId, LocalDateTime newStartTime,
Long newMachineId,int lockStartTime) { Long newMachineId,int lockStartTime) {
...@@ -583,11 +600,11 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0)); ...@@ -583,11 +600,11 @@ order.setDueDate(LocalDateTime.of(2025, 12, 1,0,0,0));
{ {
Chromosome chromosome= _sceneService.loadChromosomeFromFile(SceneId); Chromosome chromosome= _sceneService.loadChromosomeFromFile(SceneId);
ScheduleOperationService ScheduleOperation=new ScheduleOperationService(); ScheduleOperationService ScheduleOperation=new ScheduleOperationService();
WriteScheduleSummary(chromosome); // WriteScheduleSummary(chromosome);
GlobalParam globalParam=new GlobalParam(); GlobalParam globalParam=new GlobalParam();
ScheduleOperation.redecode(chromosome, chromosome.getBaseTime(), globalParam); ScheduleOperation.redecode(chromosome, chromosome.getBaseTime(), globalParam);
WriteScheduleSummary(chromosome); // WriteScheduleSummary(chromosome);
} }
......
...@@ -37,14 +37,16 @@ public class PlanResultServiceTest { ...@@ -37,14 +37,16 @@ public class PlanResultServiceTest {
// NSGAIIUtils nsgaiiUtils=new NSGAIIUtils(); // NSGAIIUtils nsgaiiUtils=new NSGAIIUtils();
// nsgaiiUtils.Test(); // nsgaiiUtils.Test();
planResultService.execute2("C5FB5EF2A7334A0A92F826F4937E1008"); // planResultService.execute2("FFAC5AA2E0B943D292933B28BDAB9068");
// planResultService.execute2("726D4C1A712B4B1393175BD44B775B66"); // planResultService.execute2("726D4C1A712B4B1393175BD44B775B66");
// 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
// opids.add(9); opids.add(7);
// planResultService.Move("27065EA0ECD14A81B7FAAFEF52273F93",opids,t,1265l,0); // planResultService.Move("27065EA0ECD14A81B7FAAFEF52273F93",opids,t,1265l,0);
// planResultService.Redecode("27065EA0ECD14A81B7FAAFEF52273F93"); // planResultService.Redecode("27065EA0ECD14A81B7FAAFEF52273F93");
// planResultService.Redecode("CA71321FE55B4437A3900315692F9220");
planResultService.Drag("27065EA0ECD14A81B7FAAFEF52273F93",opids,6,false,0l);
// MaintenanceWindow maintenanceWindow=new MaintenanceWindow(); // MaintenanceWindow maintenanceWindow=new MaintenanceWindow();
// maintenanceWindow.setStartTime(LocalDateTime.of(2025, 10, 21, 0, 0, 0)); // maintenanceWindow.setStartTime(LocalDateTime.of(2025, 10, 21, 0, 0, 0));
// maintenanceWindow.setEndTime(LocalDateTime.of(2025, 10, 31, 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