Explorar o código

退火调度排程优化

fangpengyuan hai 3 meses
pai
achega
242ca8a2c3

+ 6 - 2
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/controller/ApsSchedulingController.java

@@ -45,7 +45,11 @@ public class ApsSchedulingController {
     public ProductionScheduleRetVo productionSchedule(@RequestBody ProductionScheduleVo productionScheduleVo) throws Exception{
         ProductionScheduleRetVo productionScheduleRetVo = null;
         try{
-            productionScheduleRetVo = productionScheduleService.productionSchedule(productionScheduleVo);
+            if("dd".equals(productionScheduleVo.getScheduleType().getScheduleType()) && "thMergeBf".equals(productionScheduleVo.getScheduleType().getThMergeMode())){
+                productionScheduleRetVo = productionScheduleService.tuiHuoSchedule(productionScheduleVo);
+            }else{
+                productionScheduleRetVo = productionScheduleService.productionSchedule(productionScheduleVo);
+            }
             productionScheduleRetVo.setCode("200");
         }catch(ApsException ae){
             productionScheduleRetVo = new ProductionScheduleRetVo();
@@ -95,7 +99,7 @@ public class ApsSchedulingController {
     public ProductionScheduleRetVo productionThSchedule(@RequestBody ProductionScheduleVo productionScheduleVo) throws Exception{
         ProductionScheduleRetVo productionScheduleRetVo = null;
         try{
-            productionScheduleRetVo = productionScheduleService.tuiHuoSchedule(productionScheduleVo,null);
+            productionScheduleRetVo = productionScheduleService.tuiHuoSchedule(productionScheduleVo);
             productionScheduleRetVo.setCode("200");
         }catch(ApsException ae){
             productionScheduleRetVo = new ProductionScheduleRetVo();

+ 1 - 1
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/ProductionScheduleService.java

@@ -8,6 +8,6 @@ public interface ProductionScheduleService {
 
     ProductionScheduleRetVo productionSchedule(ProductionScheduleVo productionScheduleVo) throws Exception;
 
-    ProductionScheduleRetVo tuiHuoSchedule(ProductionScheduleVo productionScheduleVo, ApsSolution apsSolution) throws Exception;
+    ProductionScheduleRetVo tuiHuoSchedule(ProductionScheduleVo productionScheduleVo) throws Exception;
 
 }

+ 41 - 13
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/impl/ApsServiceImpl.java

@@ -364,17 +364,43 @@ public class ApsServiceImpl implements ApsService {
         Solver<ApsSolution> solver1 = solverFactory1.buildSolver();
         // 按照宽度排序
 //        apsSolutionTh.getProcessesList().sort(Comparator.comparing(ProductionProcesses::getSeriesProduceMark));
-        Collections.sort(apsSolutionTh.getProcessesList(),(v1,v2)->{
-            int a = 0;
-            // 合金
-            String alloy1 = v1.getVolumeMetal();
-            String alloy2 = v2.getVolumeMetal();
-            // 合金状态
-            String alloystatus1 = v1.getVolumeMetalstate();
-            String alloystatus2 = v2.getVolumeMetalstate();
-            // 宽度
-            BigDecimal prowidth1 = v1.getVolumeWidth();
-            BigDecimal prowidth2 = v2.getVolumeWidth();
+        if("dd".equals(productionScheduleVo.getScheduleType().getScheduleType())){
+            List<ProductionProcesses> hapres = new ArrayList<>();
+            List<ProductionProcesses> nothapres = new ArrayList<>();
+            for (ProductionProcesses v : apsSolutionTh.getProcessesList()) {
+                if(v.getPreviousProcesses() != null && v.getPreviousProcesses().size() > 0 && v.getPreviousProcesses().get(0).getEndTime() != null){
+                    hapres.add(v);
+                }else {
+                    nothapres.add(v);
+                }
+            }
+
+            Collections.sort(hapres,(v1,v2)->{
+                int a = 0;
+                if(v1.getPreviousProcesses().get(0).getStartTime().compareTo(v2.getPreviousProcesses().get(0).getStartTime()) == 0){
+                    a = v2.getVolumeWidth().compareTo(v1.getVolumeWidth());
+                }else{
+                    a = v2.getPreviousProcesses().get(0).getStartTime().compareTo(v1.getPreviousProcesses().get(0).getStartTime());
+                }
+                return a;
+            });
+
+            if(nothapres != null && nothapres.size()>0){
+                hapres.addAll(nothapres);
+            }
+            apsSolutionTh.setProcessesList(hapres);
+        }else{
+            Collections.sort(apsSolutionTh.getProcessesList(),(v1,v2)->{
+                int a = 0;
+                // 合金
+                String alloy1 = v1.getVolumeMetal();
+                String alloy2 = v2.getVolumeMetal();
+                // 合金状态
+                String alloystatus1 = v1.getVolumeMetalstate();
+                String alloystatus2 = v2.getVolumeMetalstate();
+                // 宽度
+                BigDecimal prowidth1 = v1.getVolumeWidth();
+                BigDecimal prowidth2 = v2.getVolumeWidth();
 //            if(prowidth1.compareTo(prowidth2) == 0){
                 // 合金
                 if(alloy1.compareTo(alloy2) == 0){
@@ -395,8 +421,10 @@ public class ApsServiceImpl implements ApsService {
             /*}else{
                 a = prowidth2.compareTo(prowidth1);
             }*/
-            return a;
-        });
+                return a;
+            });
+        }
+
         ApsSolution solvedBalance1 = solver1.solve(apsSolutionTh);
         /*for (ProductionProcesses productionProcesses : solvedBalance1.getProcessesList()) {
             DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

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

@@ -53,15 +53,15 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
     @Override
     public ProductionScheduleRetVo productionSchedule(ProductionScheduleVo productionScheduleVo) throws Exception{
         List<String> blankids = new ArrayList<>();
-        blankids.add("055aa157de194440be75ad115d60054d");
-        blankids.add("9e8bbe425aa044a4af55d8daf7ebb4cb");
-        blankids.add("7efe679a8e3c4942b88758617cdbc312");
+        blankids.add("3917c2948ba446698afd93342757c6b9");
+        blankids.add("caec67974fd04302b37e2fd848815a68");
+//        blankids.add("7efe679a8e3c4942b88758617cdbc312");
 //        blankids.add("acf4460f9488459780c0dc7d8038f1f9");
 //        blankids.add("efeb1f8d01b04cdb9921c0d1711bb967");
-//        List<ProductionProcesses> collect = productionScheduleVo.getProcesses().stream().filter(v ->
-//                        blankids.contains(v.getProduceOrder().get(0).getId())
-//                ).collect(Collectors.toList());
-//        productionScheduleVo.setProcesses(collect);
+        /*List<ProductionProcesses> collect = productionScheduleVo.getProcesses().stream().filter(v ->
+                        blankids.contains(v.getProduceOrder().get(0).getId())
+                ).collect(Collectors.toList());
+        productionScheduleVo.setProcesses(collect);*/
 
         log.info("*************** 排程开始:"+productionScheduleVo.getProductionScheduleId()+" *******************");
         if(productionScheduleVo.getScheduleType().getScheduleType() == null){
@@ -1820,94 +1820,226 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
     }
 
     /**
-     * 退火提前合并排程
+     * 退火调度排程
      * @param productionScheduleVo
      * @return
      */
-    public ProductionScheduleRetVo tuiHuoSchedule(ProductionScheduleVo productionScheduleVo,ApsSolution apsSolution) throws Exception{
+    public ProductionScheduleRetVo tuiHuoSchedule(ProductionScheduleVo productionScheduleVo) throws Exception{
+        log.info("*************** 退火调度排程开始:"+productionScheduleVo.getProductionScheduleId()+" *******************");
+        if(productionScheduleVo.getScheduleType().getScheduleType() == null){
+            productionScheduleVo.getScheduleType().setScheduleType("default");
+        }
+
+        ApsUtils apsUtils = new ApsUtils();
         // 排程结果对象
         ProductionScheduleRetVo productionScheduleRetVo = new ProductionScheduleRetVo();
-        // 排程运行时长
-        Integer maxPlanSeconds = productionScheduleVo.getPlanSeconds();
-        Integer prospeed = 20;
-        if(productionScheduleVo.getPcspeed() != null && productionScheduleVo.getPcspeed()>0){
-            prospeed = productionScheduleVo.getPcspeed();
+        // 排程校验
+        if(productionScheduleVo.getRoamTime() == null || productionScheduleVo.getRoamTime().size() == 0){
+            throw new ApsException("缺少全局流转时间配置");
         }
-        int processNum = productionScheduleVo.getProcesses().size();
-        int runPlanSeconds = (processNum/prospeed + 1)*60;
-        if(maxPlanSeconds == null || maxPlanSeconds <= 0){
-            maxPlanSeconds = 1800;
+
+        // optaplanner 求解器数据装配
+        List<ProductionProcesses> otherThproces = new ArrayList<>();
+        List<ProductionProcesses> otherNotThproces = new ArrayList<>();
+        ApsSolution apsSolution = getPreApsSolution(productionScheduleVo,otherThproces);
+        // 判断是否有非锁定的工序
+        boolean hasSchedulePro = false;
+        for (ProductionProcesses productionProcesses : apsSolution.getProcessesList()) {
+            if(!productionProcesses.getIfLock()){
+                hasSchedulePro = true;
+                break;
+            }
         }
-        if(runPlanSeconds > maxPlanSeconds){
-            throw new ApsException("所选排程作业太多,预计排程时间太长,请分开排程");
+        if(!hasSchedulePro){
+            throw new ApsException("没有可排程的工序");
         }
-        EnvironmentMode mode = EnvironmentMode.REPRODUCIBLE;
-        if(productionScheduleVo.getEnvironmentMode() != null && productionScheduleVo.getEnvironmentMode() == 1){
-            mode = EnvironmentMode.FULL_ASSERT;
+
+        // 退火合并
+        List<ProductionProcesses> thList = ddsService.thProcessMerge(productionScheduleVo,apsSolution,otherThproces);
+        apsSolution.setProcessesList(thList);
+
+        // 去掉锁定工序
+        List<ProductionProcesses> notLocks = new ArrayList<>();
+        List<ProductionProcesses> hasLocks = new ArrayList<>();
+        if(apsSolution.getProcessesList() != null && apsSolution.getProcessesList().size()>0){
+            for (ProductionProcesses productionProcesses : apsSolution.getProcessesList()) {
+                if(!productionProcesses.getIfLock()){
+                    notLocks.add(productionProcesses);
+                }else{
+                    hasLocks.add(productionProcesses);
+                }
+            }
         }
-        List<ProductionProcesses> otherThproces = new ArrayList<>();
-//        ApsSolution apsSolution = getPreApsSolution(productionScheduleVo,otherThproces);
-        // 退火提前排序
+        apsSolution.setProcessesList(notLocks);
+
+        ApsSolution apsSolutionTh = null;
         Map<String,Map<String,List<ProductionProcesses>>> relPros = new HashMap<>();
-        ApsSolution apsSolutionTh = apsService.tuihuoAps(apsSolution,relPros);
-        if(apsSolutionTh.getProcessesList() != null && apsSolutionTh.getProcessesList().size()>0){
-            // 退火工序求解器运行
-            int processNum1 = apsSolutionTh.getProcessesList().size();
-            int runPlanSeconds1 = (processNum1/prospeed + 1)*60;
-            // CPU核数
-            String cores = Runtime.getRuntime().availableProcessors() + "";
-            SolverFactory<ApsSolution> solverFactory1 = SolverFactory.create(new SolverConfig()
-                    .withEnvironmentMode(mode)
-                    .withSolutionClass(ApsSolution.class)
-                    .withEntityClasses(ProductionProcesses.class)
-                    .withConstraintProviderClass(ApsConstraintProvider.class)
-                    .withTerminationSpentLimit(Duration.ofSeconds(runPlanSeconds1))
-                    .withMoveThreadCount(cores)
-            );
-            Solver<ApsSolution> solver1 = solverFactory1.buildSolver();
-            ApsSolution solvedBalance1 = solver1.solve(apsSolutionTh);
-            log.info("**************退火排程评分分析***************");
-            SolutionManager<ApsSolution, HardSoftScore> scoreManager1 = SolutionManager.create(solverFactory1);
-            ScoreExplanation<ApsSolution, HardSoftScore> explain1 = scoreManager1.explain(solvedBalance1);
-            log.info(explain1.toString());
-            log.info("**************退火排程评分分析***************");
-            softExplain(explain1,solvedBalance1.getProcessesList());
-            productionScheduleRetVo.setScoreResult(scoreManager1.explain(solvedBalance1).toString());
-            productionScheduleRetVo.setProcesses(solvedBalance1.getProcessesList());
-            // 循环引用ProductionProcesses置空
-            for (ProductionProcesses productionProcesses : solvedBalance1.getProcessesList()) {
-                productionProcesses.setPreviousProcesses(null);
-                productionProcesses.setNextProcesses(null);
-                productionProcesses.getEquipment().setProcessesList(null);
-                productionProcesses.getEquipment().setEquipmentRunTimes(null);
-                productionProcesses.setPreviousStep(null);
-                productionProcesses.setOptionalProviderEquipments(null);
-                // 冲突约束补充处理
-                if(productionProcesses.getConflictRoptions() != null && productionProcesses.getConflictRoptions().size()>0){
-                    productionProcesses.getConflictRoptions().forEach((k,v)->{
-                        if(StrUtil.isBlank(productionProcesses.getHasConflict())){
-                            productionProcesses.setHasConflict("y");
+        // 调度退火排程
+        apsSolutionTh = new ApsSolution();
+        List<ProductionProcesses> tuihuos = new ArrayList<>();
+        for (ProductionProcesses process : apsSolution.getProcessesList()) {
+            if((process.getProcessType().equals("成退") || process.getProcessType().equals("中退") || process.getProcessType().equals("小卷成退")) && !process.getIfLock()){
+                tuihuos.add(process);
+            }
+        }
+
+        apsSolutionTh.setProcessesList(tuihuos);
+        apsSolutionTh.setEquipmentList(apsSolution.getEquipmentList());
+
+        // 退火工序求解器运行
+        int processNum1 = apsSolutionTh.getProcessesList().size();
+        int runPlanSeconds1 = (processNum1)*30;
+        // CPU核数
+        String cores = Runtime.getRuntime().availableProcessors() + "";
+        SolverFactory<ApsSolution> solverFactory1 = SolverFactory.create(new SolverConfig()
+                        .withEnvironmentMode(EnvironmentMode.REPRODUCIBLE)
+                        .withSolutionClass(ApsSolution.class)
+                        .withEntityClasses(ProductionProcesses.class)
+                        .withConstraintProviderClass(ApsConstraintProvider.class)
+//                .withTerminationSpentLimit(Duration.ofSeconds(runPlanSeconds1))
+                        .withTerminationConfig(new TerminationConfig().withUnimprovedSecondsSpentLimit(60L))
+                        .withMoveThreadCount(cores)
+        );
+        Solver<ApsSolution> solver1 = solverFactory1.buildSolver();
+        // 退火调度排序
+        List<ProductionProcesses> hapres = new ArrayList<>();
+        List<ProductionProcesses> nothapres = new ArrayList<>();
+        for (ProductionProcesses v : apsSolutionTh.getProcessesList()) {
+            if(v.getPreviousProcesses() != null && v.getPreviousProcesses().size() > 0 && v.getPreviousProcesses().get(0).getEndTime() != null){
+                hapres.add(v);
+            }else {
+                nothapres.add(v);
+            }
+        }
+
+        Collections.sort(hapres,(v1,v2)->{
+            int a = 0;
+            if(v1.getPreviousProcesses().get(0).getStartTime().compareTo(v2.getPreviousProcesses().get(0).getStartTime()) == 0){
+                a = v2.getVolumeWidth().compareTo(v1.getVolumeWidth());
+            }else{
+                a = v2.getPreviousProcesses().get(0).getStartTime().compareTo(v1.getPreviousProcesses().get(0).getStartTime());
+            }
+            return a;
+        });
+
+        if(nothapres != null && nothapres.size()>0){
+            hapres.addAll(nothapres);
+        }
+        apsSolutionTh.setProcessesList(hapres);
+
+        ApsSolution solvedBalance = solver1.solve(apsSolutionTh);
+
+        log.info("**************退火排程评分分析***************");
+        SolutionManager<ApsSolution, HardSoftScore> scoreManager1 = SolutionManager.create(solverFactory1);
+        ScoreExplanation<ApsSolution, HardSoftScore> explain1 = scoreManager1.explain(solvedBalance);
+        log.info(explain1.toString());
+        log.info("**************退火排程评分分析***************");
+
+        solvedBalance.getProcessesList().addAll(hasLocks);
+        // 退火合并工序排程完拆分
+        if(otherThproces != null && otherThproces.size()>0){
+            List<ProductionProcesses> otherThproce1 = new ArrayList<>();
+            for (ProductionProcesses otherThproce : otherThproces) {
+                if(StrUtil.isNotBlank(otherThproce.getMergeThMainId())){
+                    ProductionProcesses thpro = null;
+                    for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
+                        if(productionProcesses.getId().equals(otherThproce.getMergeThMainId())){
+                            thpro = productionProcesses;
+                            break;
                         }
-                        // 强制约束
-                        if(k.indexOf("hard") == 0){
-                            if(StrUtil.isBlank(productionProcesses.getConflictDes())){
-                                productionProcesses.setConflictDes(v);
-                            }else{
-                                productionProcesses.setConflictDes(productionProcesses.getConflictDes()+";"+v);
+                    }
+                    if(thpro != null){
+                        otherThproce.setStartTime(thpro.getStartTime());
+                        otherThproce.setEndTime(thpro.getEndTime());
+                        otherThproce.setEquipmentId(thpro.getEquipmentId());
+                        otherThproce.setEquipment(thpro.getEquipment());
+                        otherThproce.setConflictRoptions(thpro.getConflictRoptions());
+
+                        thpro.setOpeProducePcNum(1);
+                        if(thpro.getProcessType().equals("小卷成退")){
+                            thpro.setMinThPcNum(thpro.getMinThPcNum()-otherThproce.getMinThPcNum());
+                        }
+                    }else{
+                        otherThproce1.add(otherThproce);
+                    }
+                }
+            }
+            if(otherThproce1 != null && otherThproce1.size()>0){
+                for (ProductionProcesses otherThproce : otherThproce1) {
+                    if(StrUtil.isNotBlank(otherThproce.getMergeThMainId())){
+                        ProductionProcesses thpro = null;
+                        for (ProductionProcesses productionProcesses : otherThproces) {
+                            if(productionProcesses.getId().equals(otherThproce.getMergeThMainId())){
+                                thpro = productionProcesses;
+                                break;
                             }
                         }
-                        // 非强制约束
-                        else if (k.indexOf("soft") == 0) {
-                            if(StrUtil.isBlank(productionProcesses.getSoftconflictdes())){
-                                productionProcesses.setSoftconflictdes(v);
-                            }else{
-                                productionProcesses.setSoftconflictdes(productionProcesses.getSoftconflictdes()+";"+v);
+                        if(thpro != null){
+                            otherThproce.setStartTime(thpro.getStartTime());
+                            otherThproce.setEndTime(thpro.getEndTime());
+                            otherThproce.setEquipmentId(thpro.getEquipmentId());
+                            otherThproce.setEquipment(thpro.getEquipment());
+                            otherThproce.setConflictRoptions(thpro.getConflictRoptions());
+
+                            thpro.setOpeProducePcNum(1);
+                            if(thpro.getProcessType().equals("小卷成退")){
+                                thpro.setMinThPcNum(thpro.getMinThPcNum()-otherThproce.getMinThPcNum());
                             }
                         }
-                    });
+                    }
                 }
             }
         }
+
+        for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
+            productionProcesses.setPreviousProcesses(null);
+            productionProcesses.setRooprocess(null);
+            productionProcesses.setNextProcesses(null);
+            productionProcesses.getEquipment().setProcessesList(null);
+            productionProcesses.getEquipment().setEquipmentRunTimes(null);
+            productionProcesses.setPreviousStep(null);
+            productionProcesses.setOptionalProviderEquipments(null);
+            productionProcesses.setEquass(null);
+            productionProcesses.setMergeRooprocess(null);
+            productionProcesses.setOpeProducePcNum(1);
+            if(productionProcesses.getApsOverallConfig() != null){
+                productionProcesses.getApsOverallConfig().setFurnaceInstallations(null);
+                productionProcesses.getApsOverallConfig().setMergeFurnaces(null);
+            }
+            if(productionProcesses.getOldNextProcessesIds() != null){
+                productionProcesses.setNextProcessesIds(productionProcesses.getOldNextProcessesIds());
+            }
+            if(productionProcesses.getOldPreviousProcessesIds() != null){
+                productionProcesses.setPreviousProcessesIds(productionProcesses.getOldPreviousProcessesIds());
+            }
+            // 冲突约束补充处理
+            if(productionProcesses.getConflictRoptions() != null && productionProcesses.getConflictRoptions().size()>0){
+                productionProcesses.getConflictRoptions().forEach((k,v)->{
+                    if(StrUtil.isBlank(productionProcesses.getHasConflict())){
+                        productionProcesses.setHasConflict("y");
+                    }
+                    // 强制约束
+                    if(k.indexOf("hard") == 0){
+                        if(StrUtil.isBlank(productionProcesses.getConflictDes())){
+                            productionProcesses.setConflictDes(v);
+                        }else{
+                            productionProcesses.setConflictDes(productionProcesses.getConflictDes()+";"+v);
+                        }
+                    }
+                    // 非强制约束
+                    else if (k.indexOf("soft") == 0) {
+                        if(StrUtil.isBlank(productionProcesses.getSoftconflictdes())){
+                            productionProcesses.setSoftconflictdes(v);
+                        }else{
+                            productionProcesses.setSoftconflictdes(productionProcesses.getSoftconflictdes()+";"+v);
+                        }
+                    }
+                });
+            }
+        }
+
+        productionScheduleRetVo.setProcesses(solvedBalance.getProcessesList());
+
         return productionScheduleRetVo;
     }
 }