|
@@ -3,6 +3,7 @@ package com.rongwei.rwapsserver.aps.service.impl;
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.nacos.common.utils.StringUtils;
|
|
|
import com.baomidou.mybatisplus.extension.api.R;
|
|
|
import com.rongwei.rwapsserver.aps.domain.*;
|
|
|
import com.rongwei.rwapsserver.aps.score.ApsConstraintProvider;
|
|
@@ -24,6 +25,8 @@ import org.optaplanner.core.config.solver.EnvironmentMode;
|
|
|
import org.optaplanner.core.config.solver.SolverConfig;
|
|
|
import org.optaplanner.core.config.solver.termination.TerminationConfig;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.time.Duration;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.ZoneId;
|
|
@@ -115,6 +118,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
|
|
|
ApsSolution solvedBalance = solver.solve(apsSolution);
|
|
|
/*List<ProductionProcesses> apsProcess = solvedBalance.getProcessesList();
|
|
|
solvedBalance.setProcessesList(solvedBalance.getStepBestProcessesList());*/
|
|
|
+
|
|
|
log.info("**************排程评分分析***************");
|
|
|
SolutionManager<ApsSolution, HardSoftScore> scoreManager = SolutionManager.create(solverFactory);
|
|
|
ScoreExplanation<ApsSolution, HardSoftScore> explain = scoreManager.explain(solvedBalance);
|
|
@@ -127,6 +131,45 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
|
|
|
// 得分分析
|
|
|
softExplain(explain,solvedBalance.getProcessesList());
|
|
|
productionScheduleRetVo.setProcesses(solvedBalance.getProcessesList());
|
|
|
+ // 最大等待时间冲突手动解决
|
|
|
+ List<ProductionProcesses> maxSetPros = new ArrayList<>();
|
|
|
+ for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
|
|
|
+ if(productionProcesses.getConflictDes() != null && "开工时间超出上道工序作业最大等待时间限制".equals(productionProcesses.getConflictDes())){
|
|
|
+ ProductionProcesses newPre = maxWaitTimeCheck(productionProcesses, maxSetPros,solvedBalance.getProcessesList());
|
|
|
+ if(newPre != null){
|
|
|
+ /*ProductionProcesses preProcess = productionProcesses.getPreviousProcesses().get(0);
|
|
|
+ EquipmentRunTime copy = new EquipmentRunTime();
|
|
|
+ copy.setStartRunTime(preProcess.getStartTime());
|
|
|
+ copy.setEndRunTime(preProcess.getEndTime());
|
|
|
+ copy.setOccupyType("temporaryProcess");
|
|
|
+ copy.setLocked(true);
|
|
|
+ copy.setSeriesProduceMark(preProcess.getSeriesProduceMark());
|
|
|
+ copy.setCutfinishmin(preProcess.getCutfinishmin() == null ? 0 : preProcess.getCutfinishmin());
|
|
|
+ copy.setPrepressworkmin(preProcess.getPrepressworkmin() == null ? 0 : preProcess.getPrepressworkmin());
|
|
|
+ productionProcesses.getPreviousProcesses().get(0).getEquipment().getEquipmentRunTimes().add(copy);*/
|
|
|
+ // 冲突信息处理
|
|
|
+ productionProcesses.setConflictDes(productionProcesses.getConflictDes().replaceAll("开工时间超出上道工序作业最大等待时间限制",""));
|
|
|
+ if(StrUtil.isBlank(productionProcesses.getConflictDes()) && StrUtil.isBlank(productionProcesses.getSoftconflictdes())){
|
|
|
+ productionProcesses.setHasConflict(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ productionProcesses.setIfLock(true);
|
|
|
+ }
|
|
|
+ if(maxSetPros != null && maxSetPros.size()>0){
|
|
|
+ for (ProductionProcesses maxSetPro : maxSetPros) {
|
|
|
+ for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
|
|
|
+ if(productionProcesses.getId().equals(maxSetPro.getId())){
|
|
|
+ productionProcesses.setStartTime(maxSetPro.getStartTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("**************排程最终评分分析***************");
|
|
|
+ ScoreExplanation<ApsSolution, HardSoftScore> explain1 = scoreManager.explain(solvedBalance);
|
|
|
+ log.info(explain1.toString());
|
|
|
+ log.info("**************排程最终评分分析***************");
|
|
|
+
|
|
|
// 循环引用ProductionProcesses置空
|
|
|
for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
|
|
|
productionProcesses.setPreviousProcesses(null);
|
|
@@ -163,6 +206,223 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
|
|
|
return productionScheduleRetVo;
|
|
|
}
|
|
|
|
|
|
+ private ProductionProcesses maxWaitTimeCheck(ProductionProcesses process,List<ProductionProcesses> maxSetPros,List<ProductionProcesses> processes){
|
|
|
+ ProductionProcesses newPre = null;
|
|
|
+ List<ProductionProcesses> previousProcesses = process.getPreviousProcesses();
|
|
|
+ if(previousProcesses != null){
|
|
|
+ ProductionProcesses preProcess = previousProcesses.get(0);
|
|
|
+ // 当前工序设备已占用时间
|
|
|
+ List<EquipmentRunTime> equipmentRunTimes = new ArrayList<>();
|
|
|
+ List<EquipmentRunTime> equipmentRunTimesAll = new ArrayList<>();
|
|
|
+ if(preProcess.getEquipment().getEquipmentRunTimes() != null && preProcess.getEquipment().getEquipmentRunTimes().size()>0){
|
|
|
+ // 过滤最大等待时间范围内的占用时间段
|
|
|
+ List<EquipmentRunTime> maxWaitRunTimes = new ArrayList<>();
|
|
|
+ for (int i = 0;i<preProcess.getEquipment().getEquipmentRunTimes().size();i++) {
|
|
|
+ EquipmentRunTime equipmentRunTime = preProcess.getEquipment().getEquipmentRunTimes().get(i);
|
|
|
+ EquipmentRunTime copy = new EquipmentRunTime();
|
|
|
+ copy.setStartRunTime(equipmentRunTime.getStartRunTime());
|
|
|
+ copy.setEndRunTime(equipmentRunTime.getEndRunTime());
|
|
|
+ copy.setTotalVolumeWidth(equipmentRunTime.getTotalVolumeWidth());
|
|
|
+ copy.setTotalSinglerollweight(equipmentRunTime.getTotalSinglerollweight());
|
|
|
+ copy.setOccupyType("temporaryProcess");
|
|
|
+ copy.setLocked(true);
|
|
|
+ copy.setSeriesProduceMark(equipmentRunTime.getSeriesProduceMark());
|
|
|
+ copy.setCutfinishmin(equipmentRunTime.getCutfinishmin() == null ? 0 : equipmentRunTime.getCutfinishmin());
|
|
|
+ copy.setPrepressworkmin(equipmentRunTime.getPrepressworkmin() == null ? 0 : equipmentRunTime.getPrepressworkmin());
|
|
|
+ equipmentRunTimesAll.add(copy);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 过滤当前排序的作业占用时间段
|
|
|
+ if(processes != null && processes.size()>0){
|
|
|
+ for (int i = 0;i<processes.size();i++) {
|
|
|
+ ProductionProcesses productionProcesses = processes.get(i);
|
|
|
+ if(productionProcesses.getEquipmentId().equals(preProcess.getEquipmentId())){
|
|
|
+ EquipmentRunTime copy = new EquipmentRunTime();
|
|
|
+ copy.setStartRunTime(productionProcesses.getStartTime());
|
|
|
+ copy.setEndRunTime(productionProcesses.getEndTime());
|
|
|
+ copy.setTotalVolumeWidth(productionProcesses.getVolumeWidth());
|
|
|
+ copy.setTotalSinglerollweight(productionProcesses.getSinglerollweight());
|
|
|
+ copy.setOccupyType("temporaryProcess");
|
|
|
+ copy.setLocked(true);
|
|
|
+ copy.setSeriesProduceMark(productionProcesses.getSeriesProduceMark());
|
|
|
+ copy.setCutfinishmin(productionProcesses.getCutfinishmin() == null ? 0 : productionProcesses.getCutfinishmin());
|
|
|
+ copy.setPrepressworkmin(productionProcesses.getPrepressworkmin() == null ? 0 : productionProcesses.getPrepressworkmin());
|
|
|
+ equipmentRunTimesAll.add(copy);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 按照开始时间排序
|
|
|
+ equipmentRunTimesAll.sort(Comparator.comparing(EquipmentRunTime::getStartRunTime));
|
|
|
+ EquipmentRunTime minRunTime = null;
|
|
|
+ EquipmentRunTime maxRunTime = null;
|
|
|
+ for (EquipmentRunTime equipmentRunTime : equipmentRunTimesAll) {
|
|
|
+ if(equipmentRunTime.getEndRunTime().compareTo(process.getStartTime())<=0
|
|
|
+ && equipmentRunTime.getStartRunTime().compareTo(process.getStartTime().plusMinutes(-preProcess.getMaxWaitTime()))>=0){
|
|
|
+ equipmentRunTimes.add(equipmentRunTime);
|
|
|
+ }else{
|
|
|
+ if(equipmentRunTime.getStartRunTime().compareTo(process.getStartTime().plusMinutes(-preProcess.getMaxWaitTime()))<0){
|
|
|
+ if(minRunTime == null){
|
|
|
+ minRunTime = equipmentRunTime;
|
|
|
+ }else{
|
|
|
+ if(equipmentRunTime.getStartRunTime().compareTo(minRunTime.getStartRunTime())>0){
|
|
|
+ minRunTime = equipmentRunTime;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(maxRunTime == null){
|
|
|
+ maxRunTime = equipmentRunTime;
|
|
|
+ }else{
|
|
|
+ if(equipmentRunTime.getStartRunTime().compareTo(maxRunTime.getStartRunTime())<0){
|
|
|
+ maxRunTime = equipmentRunTime;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 按照开始时间排序
|
|
|
+ equipmentRunTimes.sort(Comparator.comparing(EquipmentRunTime::getStartRunTime));
|
|
|
+ equipmentRunTimes.add(0,minRunTime);
|
|
|
+ // 当前工序最小开始时间、结束时间
|
|
|
+ LocalDateTime proStartTime = preProcess.getStartTime();
|
|
|
+ LocalDateTime proEndTime = preProcess.getEndTime();
|
|
|
+ // 前一道工序尝试往后挪
|
|
|
+ for(int i = 0; i < equipmentRunTimes.size(); i++){
|
|
|
+ EquipmentRunTime equipmentRunTime = equipmentRunTimes.get(i);
|
|
|
+ if (preProcess.getProcessType().equals("冷轧")) {
|
|
|
+ // 首个占用时间
|
|
|
+ if(i == 0){
|
|
|
+ EquipmentRunTime nextEquipmentRunTime = equipmentRunTimes.get(i+1);
|
|
|
+ boolean preseries = seriesLz(nextEquipmentRunTime, preProcess, 1);
|
|
|
+ LocalDateTime proEndTime1 = nextEquipmentRunTime.getStartRunTime().plusMinutes(-1);
|
|
|
+ // 连续
|
|
|
+ if(!preseries){
|
|
|
+ proEndTime1 = proEndTime1.plusMinutes(-preProcess.getCutfinishmin()).plusMinutes(-nextEquipmentRunTime.getPrepressworkmin());
|
|
|
+ }
|
|
|
+ LocalDateTime proStartTime1 = proEndTime1.plusMinutes(-preProcess.getProduceTime());
|
|
|
+ if(proStartTime1.compareTo(process.getStartTime().plusMinutes(preProcess.getMaxWaitTime()))>0){
|
|
|
+ LocalDateTime minproStartTime = proStartTime1;
|
|
|
+ boolean nextseries = seriesLz(equipmentRunTime, preProcess, -1);
|
|
|
+ if(!nextseries){
|
|
|
+ minproStartTime = minproStartTime.plusMinutes(-equipmentRunTime.getCutfinishmin()).plusMinutes(-preProcess.getPrepressworkmin());
|
|
|
+ }
|
|
|
+ if(minproStartTime.compareTo(equipmentRunTime.getEndRunTime())>0){
|
|
|
+ proStartTime = proStartTime1;
|
|
|
+ proEndTime = proEndTime1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 最后一个占用时间
|
|
|
+ else if (i == equipmentRunTimes.size()-1) {
|
|
|
+ LocalDateTime a = proStartTime;
|
|
|
+ if(equipmentRunTime.getEndRunTime().compareTo(a)>0){
|
|
|
+ a = equipmentRunTime.getEndRunTime().plusMinutes(1);
|
|
|
+ }
|
|
|
+ boolean preseries = seriesLz(equipmentRunTime, preProcess, -1);
|
|
|
+ if(!preseries){
|
|
|
+ a = a.plusMinutes(equipmentRunTime.getCutfinishmin()).plusMinutes(preProcess.getPrepressworkmin());
|
|
|
+// preProcess.getConflictRoptions().put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+// preProcess.getConflictRoptions().remove("soft-seriesProduceLz");
|
|
|
+ }
|
|
|
+ LocalDateTime b = a.plusMinutes(preProcess.getProduceTime());
|
|
|
+ if(b.compareTo(process.getStartTime())<0){
|
|
|
+ proStartTime = a;
|
|
|
+ proEndTime = proStartTime.plusMinutes(preProcess.getProduceTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 其它情况
|
|
|
+ else{
|
|
|
+ EquipmentRunTime nextEquipmentRunTime = equipmentRunTimes.get(i+1);
|
|
|
+ if(nextEquipmentRunTime.getStartRunTime().compareTo(proEndTime)>0){
|
|
|
+ boolean preseries = seriesLz(equipmentRunTime, preProcess, -1);
|
|
|
+ boolean nextseries = seriesLz(nextEquipmentRunTime, preProcess, 1);
|
|
|
+ LocalDateTime preEndTime = equipmentRunTime.getEndRunTime().plusMinutes(1);
|
|
|
+ if(!preseries){
|
|
|
+ preEndTime = preEndTime.plusMinutes(equipmentRunTime.getCutfinishmin()).plusMinutes(preProcess.getPrepressworkmin());
|
|
|
+// preProcess.getConflictRoptions().put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+// preProcess.getConflictRoptions().remove("soft-seriesProduceLz");
|
|
|
+ }
|
|
|
+ LocalDateTime nextEndTime = preEndTime.plusMinutes(preProcess.getProduceTime());
|
|
|
+ if(!nextseries){
|
|
|
+ nextEndTime = nextEndTime.plusMinutes(preProcess.getCutfinishmin()).plusMinutes(nextEquipmentRunTime.getPrepressworkmin());
|
|
|
+// preProcess.getConflictRoptions().put("soft-seriesProduceLz","和后一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+// preProcess.getConflictRoptions().remove("soft-seriesProduceLz");
|
|
|
+ }
|
|
|
+ if(nextEndTime.compareTo(nextEquipmentRunTime.getStartRunTime())<0){
|
|
|
+ proStartTime = preEndTime;
|
|
|
+ proEndTime = proStartTime.plusMinutes(preProcess.getProduceTime());
|
|
|
+ break;
|
|
|
+ }else{
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 其它工序
|
|
|
+ else{
|
|
|
+ if(proStartTime.compareTo(equipmentRunTime.getEndRunTime())>0 || proEndTime.compareTo(equipmentRunTime.getStartRunTime())<0){
|
|
|
+ continue;
|
|
|
+ }else{
|
|
|
+ proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(1);
|
|
|
+ proEndTime = proStartTime.plusMinutes(preProcess.getProduceTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(proStartTime.compareTo(preProcess.getStartTime()) > 0){
|
|
|
+ preProcess.setStartTime(proStartTime);
|
|
|
+ newPre = new ProductionProcesses();
|
|
|
+ newPre.setId(preProcess.getId());
|
|
|
+ newPre.setStartTime(proStartTime);
|
|
|
+ newPre.setEndTime(proEndTime);
|
|
|
+ maxSetPros.add(newPre);
|
|
|
+ System.out.println(preProcess.getId() + ":" + proStartTime);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return newPre;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param equipmentRunTime
|
|
|
+ * @param process
|
|
|
+ * @param isBefore -1:equipmentRunTime在process之前,1:equipmentRunTime在process之后
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private boolean seriesLz(EquipmentRunTime equipmentRunTime,ProductionProcesses process,Integer isBefore){
|
|
|
+ boolean isSeriesLz = true;
|
|
|
+ String[] serspre = null;String[] sersafter = null;
|
|
|
+ if(isBefore == -1){
|
|
|
+ serspre = equipmentRunTime.getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ sersafter = process.getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ }else {
|
|
|
+ serspre = process.getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ sersafter = equipmentRunTime.getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ }
|
|
|
+ if(serspre.length == 5 && sersafter.length == 5){
|
|
|
+ if(!serspre[0].equals(sersafter[0]) || !serspre[1].equals(sersafter[1])){
|
|
|
+ isSeriesLz = false;
|
|
|
+ }else{
|
|
|
+ String s1 = serspre[2];
|
|
|
+ String s2 = sersafter[2];
|
|
|
+ try{
|
|
|
+ BigDecimal i1 = new BigDecimal(s1);
|
|
|
+ BigDecimal i2 = new BigDecimal(s2);
|
|
|
+ if(i1.compareTo(i2)<0){
|
|
|
+ isSeriesLz = false;
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return isSeriesLz;
|
|
|
+ }
|
|
|
+
|
|
|
private void testOne(ApsSolution solvedBalance){
|
|
|
List<ProductionProcesses> processesList = solvedBalance.getProcessesList();
|
|
|
List<ProductionProcesses> stepBestProcessesList = solvedBalance.getStepBestProcessesList();
|