Ver Fonte

排程算法优化

fangpy há 1 ano atrás
pai
commit
da7cdf10b5

+ 7 - 2
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/ApsBalancingApplication.java

@@ -126,13 +126,18 @@ public class ApsBalancingApplication {
         Integer a = 1;Integer b = 1;
         System.out.println(a+b);*/
 
-        LocalDateTime now = LocalDateTime.now();
+        /*LocalDateTime now = LocalDateTime.now();
         LocalDateTime nearestTenMinutes = now.minusSeconds(now.getSecond()) // 减去当前秒数
                 .minusNanos(now.getNano()) // 减去当前纳秒数
                 .plusMinutes(-now.getMinute() % 10) // 减去当前分钟数的余数,向下调整到最近的10的倍数
                 .plusMinutes(10); // 加上调整后的分钟数的余数
 
-        System.out.println(nearestTenMinutes);
+        System.out.println(nearestTenMinutes);*/
+        List<String> a = new ArrayList<>();
+        a.add("1");
+        List<String> b = a;
+        b.add("2");
+        System.out.println(a);
     }
 
     public static void constraintTest(){

+ 3 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/score/ApsConstraintProvider.java

@@ -385,6 +385,9 @@ public class ApsConstraintProvider implements ConstraintProvider {
     private Constraint hasOnePreGbAfterNow(ConstraintFactory constraintFactory) {
         return constraintFactory.forEach(ProductionProcesses.class)
                 .filter(productionProcesses -> {
+                    /*if(productionProcesses.getId().equals("2a231077b58844548c4a9d9e8f90f628")){
+                        int a = 1;
+                    }*/
                     boolean bln = false;
                     if(productionProcesses.getPreviousProcesses() != null && productionProcesses.getPreviousProcesses().size()>0){
                         // 此种情况简化为前道工序只有一个

+ 260 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/impl/ProductionScheduleServiceImpl.java

@@ -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();