Kaynağa Gözat

排程优化-退火合并优化

fangpy 7 ay önce
ebeveyn
işleme
8d1608ae0e

+ 21 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/domain/CommonJavaBean.java

@@ -0,0 +1,21 @@
+package com.rongwei.rwapsserver.aps.domain;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class CommonJavaBean {
+
+    /**
+     * 单卷宽度
+     */
+    private BigDecimal maxVolumeWidth;
+
+    /**
+     * 坯料计划ID
+     */
+    private List<String> orderids;
+
+}

+ 5 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/domain/Equipment.java

@@ -135,6 +135,11 @@ public class Equipment implements Serializable {
      */
     private String equassociated;
 
+    /**
+     * 当前设备最后工序的轧机使用辊ID
+     */
+    private String lastZjgid;
+
     /**
      * 设备上排产的工序
      */

+ 5 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/domain/EquipmentRunTime.java

@@ -121,4 +121,9 @@ public class EquipmentRunTime implements Serializable {
 
     private Set<String> minThGroupNames;
 
+    /**
+     * 轧机使用辊ID
+     */
+    private String zjgid;
+
 }

+ 30 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/domain/ProductionProcesses.java

@@ -86,6 +86,16 @@ public class ProductionProcesses implements Serializable {
      */
     private List<String> optionalEquipments;
 
+    /**
+     * 可选设备ID
+     */
+    private Map<String,String> optionalEquipmentZg;
+
+    /**
+     * 当前作业明细的轧机辊
+     */
+    private String proZg;
+
     /**
      * 可选设备ID
      */
@@ -484,6 +494,10 @@ public class ProductionProcesses implements Serializable {
             if(equipment != null){
                 this.equipmentId = equipment.getId();
                 this.equipmentEquassociated = equipment.getEquassociated();
+                // 同步设置当前作业的轧机辊
+                if(this.optionalEquipmentZg != null && this.optionalEquipmentZg.size()>0){
+                    this.proZg = this.optionalEquipmentZg.get(this.equipmentId);
+                }
             }
         }
     }
@@ -1050,6 +1064,22 @@ public class ProductionProcesses implements Serializable {
         this.processCategory = processCategory;
     }
 
+    public Map<String, String> getOptionalEquipmentZg() {
+        return optionalEquipmentZg;
+    }
+
+    public void setOptionalEquipmentZg(Map<String, String> optionalEquipmentZg) {
+        this.optionalEquipmentZg = optionalEquipmentZg;
+    }
+
+    public String getProZg() {
+        return proZg;
+    }
+
+    public void setProZg(String proZg) {
+        this.proZg = proZg;
+    }
+
     public String getSeriSort(){
         String sortStr = this.getId();
         if(this.getStartTime() != null){

+ 14 - 2
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/listener/TaskStartTimeListener.java

@@ -407,7 +407,7 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
                         continue;
                     }
                     // 退火工序
-                    if(process.getProcessType().equals("成退") || process.getProcessType().equals("中退") || process.getProcessType().equals("小卷成退")){
+                    if(process.getProcessType().equals("成退") || process.getProcessType().equals("中退")){
                         // 没有交叉直接跳过
                         /*if(equipmentRunTime.getEndRunTime().compareTo(proStartTime)<=0 || equipmentRunTime.getStartRunTime().compareTo(proEndTime)>=0){
                             continue;
@@ -511,6 +511,15 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
                             }
                         }
                     }*/
+                    else if (process.getProcessType().equals("小卷成退")) {
+                        if(proStartTime.compareTo(equipmentRunTime.getEndRunTime())>=0 || proEndTime.compareTo(equipmentRunTime.getStartRunTime())<=0
+                                || proStartTime.compareTo(equipmentRunTime.getStartRunTime())==0){
+                            break;
+                        }else{
+                            proStartTime = equipmentRunTime.getEndRunTime();
+                            proEndTime = proStartTime.plusMinutes(process.getProduceTime());
+                        }
+                    }
                     // 其它工序
                     else{
                         if(proStartTime.compareTo(equipmentRunTime.getEndRunTime())>=0 || proEndTime.compareTo(equipmentRunTime.getStartRunTime())<=0){
@@ -525,7 +534,10 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
 
             toUpdateStartTime = proStartTime;
         }
-        if(process.getId().equals("f5228d1b1ffa4c22a54ebb811a8a7950")){
+        if(process.getId().equals("0b55bfc2d80249699d52dc8b4d42113e") && process.getEquipmentId().equals("ea69835012de4f2cb9c52496df8be111") && process.getDelay() == 92){
+            int a = 0;
+        }
+        if(process.getId().equals("753e5d7bb985465b92f40e24abc6b91c") || process.getId().equals("24a272fad1dd4fe2ac475dac44803bfe") || process.getId().equals("77594aa518a945c6be28c1bbd38d9cd4")){
             int a = 0;
         }
         return toUpdateStartTime;

+ 76 - 33
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/score/ApsConstraintProvider.java

@@ -1193,6 +1193,10 @@ public class ApsConstraintProvider implements ConstraintProvider {
             ProductionProcesses nextPro = hasStartTimeProcess.get(i+1);
             Map<String, String> conflictRoptions1 = prePro.getConflictRoptions();
             Map<String, String> conflictRoptions2 = nextPro.getConflictRoptions();
+            // 没有本次待排程的退火作业不考虑合并问题
+            if(prePro.getId().indexOf("equipmentRunTime") == 0 && nextPro.getId().indexOf("equipmentRunTime") == 0){
+                continue;
+            }
             // 开始时间相等为合并工序
             if (prePro.getStartTime().compareTo(nextPro.getStartTime()) == 0){
                 if(prePro.getTaskType().equals("maintenance") || nextPro.getTaskType().equals("maintenance")){
@@ -1267,13 +1271,13 @@ public class ApsConstraintProvider implements ConstraintProvider {
                         if(furnaceInstallation.getAlloystatus() != null && (productionProcesses.getVolumeMetalstate() == null || !furnaceInstallation.getAlloystatus().contains(productionProcesses.getVolumeMetalstate()))){
                             a = false;
                         }
-                        if(furnaceInstallation.getStartthickness() != null && furnaceInstallation.getStartthickness().compareTo(productionProcesses.getVolumeThickness())>0){
+                        if(furnaceInstallation.getStartthickness() != null && furnaceInstallation.getStartthickness().compareTo(productionProcesses.getVolumeThickness())>=0){
                             a = false;
                         }
                         if(furnaceInstallation.getEndthickness() != null && furnaceInstallation.getEndthickness().compareTo(productionProcesses.getVolumeThickness())<0){
                             a = false;
                         }
-                        if(furnaceInstallation.getStartwidth() != null && new BigDecimal(furnaceInstallation.getStartwidth()).compareTo(productionProcesses.getVolumeWidth())>0){
+                        if(furnaceInstallation.getStartwidth() != null && new BigDecimal(furnaceInstallation.getStartwidth()).compareTo(productionProcesses.getVolumeWidth())>=0){
                             a = false;
                         }
                         if(furnaceInstallation.getEndwidth() != null && new BigDecimal(furnaceInstallation.getEndwidth()).compareTo(productionProcesses.getVolumeWidth())<0){
@@ -2013,6 +2017,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
                         pp.setLastSerialLbWeight(equipmentRunTime.getLastSerialLbWeight());
                         pp.setBsProcessesId(Arrays.asList(new String[]{"haspcprocess"}));
                         pp.setConflictRoptions(new HashMap<>());
+                        pp.setProZg(equipmentRunTime.getZjgid());
                         hasStartTimeProcess.add(pp);
                     }
                 }
@@ -2028,6 +2033,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
                 pp.setLastSerialLbWeight(equipment.getLastSerialLbWeight());
                 pp.setBsProcessesId(Arrays.asList(new String[]{"lastprocess"}));
                 pp.setConflictRoptions(new HashMap<>());
+                pp.setProZg(equipment.getLastZjgid());
                 hasStartTimeProcess.add(0,pp);
             }else{
                 if(equipment.getEquipmentRunTimes() == null || equipment.getEquipmentRunTimes().size() == 0){
@@ -2135,14 +2141,28 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                     }
                                 }
                             }
-                        } else if ("冷轧".equals(hasStartTimeProcess.get(i).getProcessType())) {
+                        } else if ("冷轧".equals(hasStartTimeProcess.get(i).getProcessType()) || "箔轧".equals(hasStartTimeProcess.get(i).getProcessType())) {
+                            ProductionProcesses prepro = hasStartTimeProcess.get(i);
+                            ProductionProcesses nextpro = hasStartTimeProcess.get(i+1);
                             String[] serspre = hasStartTimeProcess.get(i).getSeriesProduceMark().split("\\^_\\^");
                             String[] sersafter = hasStartTimeProcess.get(i+1).getSeriesProduceMark().split("\\^_\\^");
+                            // 前道工序宽度、输入物料厚度、输出物料厚度
+                            String s1 = serspre[2];
+                            BigDecimal t1 = new BigDecimal(serspre[3]);
+                            BigDecimal to1 = new BigDecimal(serspre[4]);
+                            // 后道工序宽度、输入物料厚度、输出物料厚度
+                            String s2 = sersafter[2];
+                            BigDecimal t2 = new BigDecimal(sersafter[3]);
+                            BigDecimal to2 = new BigDecimal(sersafter[4]);
+                            BigDecimal i1 = new BigDecimal(s1);
+                            BigDecimal i2 = new BigDecimal(s2);
                             // 前后道所属作业ID
                             String processId1 = hasStartTimeProcess.get(i).getBsProcessesId().get(0);
                             String processId2 = hasStartTimeProcess.get(i+1).getBsProcessesId().get(0);
-                            if(serspre.length == 5 && sersafter.length == 5){
-                                if(!serspre[0].equals(sersafter[0]) || !serspre[1].equals(sersafter[1])){
+                            if(StrUtil.isNotBlank(prepro.getProZg()) && StrUtil.isNotBlank(nextpro.getProZg())){
+                                String preZg = prepro.getProZg();
+                                String nextZg = nextpro.getProZg();
+                                if(!preZg.equals(nextZg)){
                                     b = b+10;
                                     if(hasStartTimeProcess.get(i).getId() != null){
                                         conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
@@ -2150,20 +2170,30 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                         conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
                                     }
                                 }else{
-                                    // 前道工序宽度、输入物料厚度、输出物料厚度
-                                    String s1 = serspre[2];
-                                    BigDecimal t1 = new BigDecimal(serspre[3]);
-                                    BigDecimal to1 = new BigDecimal(serspre[4]);
-                                    // 后道工序宽度、输入物料厚度、输出物料厚度
-                                    String s2 = sersafter[2];
-                                    BigDecimal t2 = new BigDecimal(sersafter[3]);
-                                    BigDecimal to2 = new BigDecimal(sersafter[4]);
+                                    if((i1.add(new BigDecimal("30"))).compareTo(i2)<0){
+                                        b = b+8;
+                                        if(hasStartTimeProcess.get(i).getId() != null){
+                                            conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
+                                        }else{
+                                            conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
+                                        }
+                                    }else if(i1.compareTo(i2)<0 && (i1.add(new BigDecimal("30"))).compareTo(i2)>=0){
+                                        b = b+7;
+                                        if(hasStartTimeProcess.get(i).getId() != null){
+                                            conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
+                                        }else{
+                                            conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
+                                        }
+                                    }else if(i1.compareTo(i2)>0){
+                                        b = b+3;
+                                    }
+                                }
+                            }else{
+                                if(serspre.length == 5 && sersafter.length == 5){
                                     try{
-                                        BigDecimal i1 = new BigDecimal(s1);
-                                        BigDecimal i2 = new BigDecimal(s2);
                                         // 后端工序大于前道工序,并且大于30mm
                                         if((i1.add(new BigDecimal("30"))).compareTo(i2)<0){
-                                            b = b+7;
+                                            b = b+10;
                                             if(hasStartTimeProcess.get(i).getId() != null){
                                                 conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
                                             }else{
@@ -2172,7 +2202,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                         }
                                         // 后端工序大于前道工序,并且小于30mm
                                         else if(i1.compareTo(i2)<0 && (i1.add(new BigDecimal("30"))).compareTo(i2)>=0){
-                                            b = b+6;
+                                            b = b+8;
                                             if(hasStartTimeProcess.get(i).getId() != null){
                                                 conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
                                             }else{
@@ -2180,32 +2210,45 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                             }
                                         }
                                         // 后端工序小于前道工序
-                                        else if(i1.compareTo(i2)>0){
-                                            b = b+5;
-                                        }
-                                        // 宽度相等的情况下
+                                    /*else if(i1.compareTo(i2)>0){
+                                        b = b+5;
+                                    }*/
+                                        // 后端工序小于等于前道工序的情况下
                                         else{
+                                            if(!serspre[1].equals(sersafter[1])){
+                                                b = b+5;
+                                                if(hasStartTimeProcess.get(i).getId() != null){
+                                                    conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
+                                                }else{
+                                                    conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
+                                                }
+                                            }else{
+                                                if(i1.compareTo(i2)>0){
+                                                    b = b+2;
+                                                }
+                                            }
                                             // 输入厚度不同
-                                            if(t1.compareTo(t2) != 0){
-                                                b = b+4;
+                                        /*if(t1.compareTo(t2) != 0){
+                                            b = b+4;
+                                        }else{
+                                            // 输出厚度不同
+                                            if(to1.compareTo(to2) != 0){
+                                                b = b+3;
                                             }else{
-                                                // 输出厚度不同
-                                                if(to1.compareTo(to2) != 0){
-                                                    b = b+3;
-                                                }else{
-                                                    // 不属于同一作业
-                                                    if(!processId1.equals(processId2)){
-                                                        b = b+1;
-                                                    }
+                                                // 不属于同一作业
+                                                if(!processId1.equals(processId2)){
+                                                    b = b+1;
                                                 }
                                             }
+                                        }*/
                                         }
                                     }catch (Exception e){
                                         e.printStackTrace();
                                     }
                                 }
                             }
-                        }else if ("箔轧".equals(hasStartTimeProcess.get(i).getProcessType())) {
+                        }
+                        /*else if ("箔轧".equals(hasStartTimeProcess.get(i).getProcessType())) {
                             // 宽度从大到小
                             String[] serspre = hasStartTimeProcess.get(i).getSeriesProduceMark().split("\\^_\\^");
                             String[] sersafter = hasStartTimeProcess.get(i+1).getSeriesProduceMark().split("\\^_\\^");
@@ -2229,7 +2272,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                     e.printStackTrace();
                                 }
                             }
-                        }
+                        }*/
                     }
                 }
             }

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

@@ -15,7 +15,8 @@ public interface ApsService {
 
     ApsSolution tuihuoAps(ApsSolution apsSolution,Map<String, Map<String,List<ProductionProcesses>>> relPros);
 
-    void tuihuoApsSch(ApsSolution apsSolution,List<ProductionProcesses> otherThproces,List<ProductionProcesses> otherNotZzFirstProces,ProductionScheduleVo productionScheduleVo);
+    void tuihuoApsSch(ApsSolution apsSolution,List<ProductionProcesses> otherThproces,List<ProductionProcesses> otherNotZzFirstProces
+            ,ProductionScheduleVo productionScheduleVo,Map<String,List<String>> ordergrous);
 
     SolverFactory<ApsSolution> solverInit(ProductionScheduleVo productionScheduleVo);
 

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

@@ -282,7 +282,8 @@ public class ApsServiceImpl implements ApsService {
      * @param apsSolution
      */
     @Override
-    public void tuihuoApsSch(ApsSolution apsSolution,List<ProductionProcesses> otherThproces,List<ProductionProcesses> otherNotZzFirstProces,ProductionScheduleVo productionScheduleVo){
+    public void tuihuoApsSch(ApsSolution apsSolution,List<ProductionProcesses> otherThproces,List<ProductionProcesses> otherNotZzFirstProces
+            ,ProductionScheduleVo productionScheduleVo,Map<String,List<String>> ordergrous){
         if(otherNotZzFirstProces != null && otherNotZzFirstProces.size()>0){
             otherNotZzFirstProces = new ArrayList<>();
 
@@ -322,7 +323,7 @@ public class ApsServiceImpl implements ApsService {
         // CPU核数
         String cores = Runtime.getRuntime().availableProcessors() + "";
         SolverFactory<ApsSolution> solverFactory1 = SolverFactory.create(new SolverConfig()
-                .withEnvironmentMode(EnvironmentMode.REPRODUCIBLE)
+                .withEnvironmentMode(EnvironmentMode.FULL_ASSERT)
                 .withSolutionClass(ApsSolution.class)
                 .withEntityClasses(ProductionProcesses.class)
                 .withConstraintProviderClass(ApsConstraintProvider.class)
@@ -390,7 +391,6 @@ public class ApsServiceImpl implements ApsService {
                 thGroup.put(thkey,thpros);
             }
         }
-
         thGroup.forEach((k,v)->{
             Set<String> orderids = new HashSet<>();
             for (ProductionProcesses productionProcesses : v) {
@@ -398,6 +398,9 @@ public class ApsServiceImpl implements ApsService {
                     orderids.add(produceOrder.getId());
                 }
             }
+            List<String> orderidlist = new ArrayList<>();
+            orderidlist.addAll(orderids);
+            ordergrous.put(k,orderidlist);
             if(orderids.size()>1){
                 /*List<EquipmentRunTime> equipmentRunTimes = new ArrayList<>();
                 for (ProductionProcesses process : v) {
@@ -468,15 +471,6 @@ public class ApsServiceImpl implements ApsService {
                 apsSolution.getProcessesList().sort(Comparator.comparing(ProductionProcesses::getOrderMark));
                 // 退火后一道工序如果是精整类别的则合并
                 List<ProductionProcesses> lastProMerge = new ArrayList<>();
-                /*for (ProductionProcesses hbThPro : hbThPros) {
-                    if(hbThPro.getNextProcesses() != null && hbThPro.getNextProcesses().size() == 1){
-                        ProductionProcesses productionProcesses = hbThPro.getNextProcesses().get(0);
-                        if(productionProcesses.getProcessCategory() != null && "40".equals(productionProcesses.getProcessCategory())
-                                && (productionProcesses.getNextProcesses() == null || productionProcesses.getNextProcesses().size() == 0)){
-                            lastProMerge.add(productionProcesses);
-                        }
-                    }
-                }*/
                 if(mainTh.getNextProcesses() != null && mainTh.getNextProcesses().size()>0){
                     for (ProductionProcesses productionProcesses : mainTh.getNextProcesses()) {
                         if(productionProcesses.getProcessCategory() != null && "40".equals(productionProcesses.getProcessCategory())
@@ -561,6 +555,8 @@ public class ApsServiceImpl implements ApsService {
                         }
                     });
                 }
+                // 退火前一道工序合并
+
             }else{
                 for (ProductionProcesses process : v) {
                     List<ProductionProcesses> collect = apsSolution.getProcessesList().stream().filter(vp -> vp.getId().equals(process.getId())).collect(Collectors.toList());
@@ -825,6 +821,23 @@ public class ApsServiceImpl implements ApsService {
         }*/
     }
 
+    /**
+     * 不同坯料计划组炉前一道工序合并
+     * @param mainTh
+     */
+    private void thPreMerge(ProductionProcesses mainTh,ApsSolution apsSolution){
+        if(mainTh != null && mainTh.getPreviousProcesses() != null && mainTh.getPreviousProcesses().size()>0){
+            List<ProductionProcesses> previousProcesses = mainTh.getPreviousProcesses();
+            if(previousProcesses != null && previousProcesses.size()>1){
+                Map<String, List<ProductionProcesses>> orderProcess = previousProcesses.stream().collect(Collectors.groupingBy(ProductionProcesses::getProcessType));
+
+                Collections.sort(previousProcesses, (pro1, pro2) -> {
+                    return pro2.getVolumeWidth().compareTo(pro1.getVolumeWidth());
+                });
+            }
+        }
+    }
+
     private void proMaxTimeSet(ProductionProcesses rootPro,ProductionProcesses prePro,Integer preMins){
         if(preMins>0){
             prePro.setMaxStartTime(rootPro.getStartTime().minusMinutes(preMins+prePro.getProduceTime()));

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

@@ -1,5 +1,6 @@
 package com.rongwei.rwapsserver.aps.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import com.rongwei.rwapsserver.aps.domain.*;
 import com.rongwei.rwapsserver.aps.score.ApsConstraintProvider;
@@ -188,7 +189,8 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
             }
         }
         // 退火提前排序
-        apsService.tuihuoApsSch(apsSolution,otherThproces,otherNotZzFirstProces,productionScheduleVo);
+        Map<String,List<String>> ordergrous = new HashMap<>();
+        apsService.tuihuoApsSch(apsSolution,otherThproces,otherNotZzFirstProces,productionScheduleVo,ordergrous);
 
         /*if(1 == 1){
             return null;
@@ -209,7 +211,76 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
 //
 //        }
         apsSolution.setProcessesList(notLocks);
-        ApsSolution solvedBalance = solver.solve(apsSolution);
+
+        SolutionManager<ApsSolution, HardSoftScore> scoreManager = SolutionManager.create(solverFactory);
+        // 按照退火组炉分批排程
+        List<CommonJavaBean> orderMerges = produceOrderMerge(ordergrous,apsSolution);
+        Collections.sort(orderMerges, (pro1, pro2) -> {return pro2.getMaxVolumeWidth().compareTo(pro1.getMaxVolumeWidth());});
+        ApsSolution solvedBalance = new ApsSolution();
+        solvedBalance.setProcessesList(new ArrayList<>());
+        List<String> thOrderids = new ArrayList<>();
+        if(ordergrous != null && ordergrous.size()>0){
+            for (CommonJavaBean cjb : orderMerges) {
+                List<String> v = cjb.getOrderids();
+                ApsSolution apsSolution1 = new ApsSolution();
+                apsSolution1.setStartTime(apsSolution.getStartTime());
+                List<ProductionProcesses> processesList1 = apsSolution.getProcessesList().stream().filter(m -> v.contains(m.getProduceOrder().get(0).getId())).collect(Collectors.toList());
+                apsSolution1.setProcessesList(processesList1);
+                apsSolution1.setEquipmentList(apsSolution.getEquipmentList());
+                ApsSolution solvedBalance1 = solver.solve(apsSolution1);
+                log.info("**************排程评分分析***************");
+                ScoreExplanation<ApsSolution, HardSoftScore> explain = scoreManager.explain(solvedBalance1);
+                log.info(explain.toString());
+                log.info("**************排程评分分析***************");
+                productionScheduleRetVo.setScoreResult(scoreManager.explain(solvedBalance1).toString());
+                // 得分分析
+                softExplain(explain,solvedBalance1.getProcessesList());
+
+                solvedBalance.getProcessesList().addAll(solvedBalance1.getProcessesList());
+                thOrderids.addAll(v);
+
+                // 排程结束的数据手动添加到设备占用列表中
+                setEqRunTimes(solvedBalance1.getProcessesList());
+            }
+        }
+        // 剩余数据按照坯料计划分组排程
+        List<ProductionProcesses> otherPros = apsSolution.getProcessesList().stream().filter(n -> !thOrderids.contains(n.getProduceOrder().get(0).getId())).collect(Collectors.toList());
+        if(otherPros != null && otherPros.size()>0){
+            Map<String, List<ProductionProcesses>> equass = new HashMap<>();
+            for (ProductionProcesses otherPro : otherPros) {
+                if(equass.containsKey(otherPro.getProduceOrder().get(0).getId())){
+                    equass.get(otherPro.getProduceOrder().get(0).getId()).add(otherPro);
+                }else {
+                    List<ProductionProcesses> p1 = new ArrayList<>();
+                    p1.add(otherPro);
+                    equass.put(otherPro.getProduceOrder().get(0).getId(),p1);
+                }
+            }
+            if(equass != null && equass.size()>0){
+                equass.forEach((k,processesList1)->{
+                    ApsSolution apsSolution1 = new ApsSolution();
+                    apsSolution1.setStartTime(apsSolution.getStartTime());
+                    apsSolution1.setProcessesList(processesList1);
+                    apsSolution1.setEquipmentList(apsSolution.getEquipmentList());
+                    ApsSolution solvedBalance1 = solver.solve(apsSolution1);
+                    log.info("**************排程评分分析***************");
+                    ScoreExplanation<ApsSolution, HardSoftScore> explain = scoreManager.explain(solvedBalance1);
+                    log.info(explain.toString());
+                    log.info("**************排程评分分析***************");
+                    productionScheduleRetVo.setScoreResult(scoreManager.explain(solvedBalance1).toString());
+                    // 得分分析
+                    softExplain(explain,solvedBalance1.getProcessesList());
+
+                    solvedBalance.getProcessesList().addAll(solvedBalance1.getProcessesList());
+
+                    // 排程结束的数据手动添加到设备占用列表中
+                    setEqRunTimes(solvedBalance1.getProcessesList());
+                });
+            }
+        }
+
+
+        /*ApsSolution solvedBalance = solver.solve(apsSolution);
         log.info("**************排程评分分析***************");
         SolutionManager<ApsSolution, HardSoftScore> scoreManager = SolutionManager.create(solverFactory);
         ScoreExplanation<ApsSolution, HardSoftScore> explain = scoreManager.explain(solvedBalance);
@@ -217,7 +288,8 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         log.info("**************排程评分分析***************");
         productionScheduleRetVo.setScoreResult(scoreManager.explain(solvedBalance).toString());
         // 得分分析
-        softExplain(explain,solvedBalance.getProcessesList());
+        softExplain(explain,solvedBalance.getProcessesList());*/
+
         // 最大等待时间冲突手动解决
         /*List<ProductionProcesses> maxSetPros = new ArrayList<>();
         for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
@@ -259,7 +331,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
             }
         }*/
 
-        log.info("**************排程最终评分分析***************");
+        /*log.info("**************排程最终评分分析***************");
         if(notLocks != null && notLocks.size()>0){
             for (ProductionProcesses notLock : notLocks) {
                 for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
@@ -288,7 +360,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         log.info(explain2.toString());
         log.info("**************排程最终评分分析***************");
         productionScheduleRetVo.setScoreResult(explain2.toString());
-        softExplain(explain2,solvedBalance.getProcessesList());
+        softExplain(explain2,solvedBalance.getProcessesList());*/
 
         productionScheduleRetVo.setProcesses(solvedBalance.getProcessesList());
         // 循环引用ProductionProcesses置空
@@ -474,6 +546,112 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         return productionScheduleRetVo;
     }
 
+    /**
+     * 根据退火组炉合并待排程的坯料计划
+     * @param ordergrous
+     * @return
+     */
+    private List<CommonJavaBean> produceOrderMerge(Map<String,List<String>> ordergrous,ApsSolution apsSolution){
+        List<CommonJavaBean> resetIds = new ArrayList<>();
+        if(ordergrous != null && ordergrous.size()>0){
+            List<List<String>> allIds = new ArrayList<>();
+            ordergrous.forEach((k,v)->{
+                allIds.add(v);
+            });
+            listSet(allIds,resetIds,apsSolution);
+        }
+        return resetIds;
+    }
+
+    private void listSet(List<List<String>> allIds,List<CommonJavaBean> resetIds,ApsSolution apsSolution){
+        if(allIds != null && allIds.size()>0){
+            CommonJavaBean cjb = new CommonJavaBean();
+            if(allIds.size()>1){
+                List<String> fids = allIds.get(0);
+                List<List<String>> syids = new ArrayList<>();
+                for (int i = 1; i < allIds.size(); i++) {
+                    List<String> iids = allIds.get(i);
+                    boolean bl = CollUtil.containsAny(fids, iids);
+                    if(bl){
+                        CollUtil.addAllIfNotContains(fids,iids);
+                    }else{
+                        syids.add(iids);
+                    }
+                }
+                cjb.setOrderids(fids);
+                BigDecimal maxVolumeWidth = null;
+                for (String orderid : cjb.getOrderids()) {
+                    List<ProductionProcesses> processes = apsSolution.getProcessesList().stream().filter(v ->
+                            v.getProduceOrder().get(0).getId().equals(orderid)).collect(Collectors.toList());
+                    ProductionProcesses productionProcesses = processes.get(0);
+                    if(maxVolumeWidth == null){
+                        maxVolumeWidth = productionProcesses.getVolumeWidth();
+                    }else{
+                        if(productionProcesses.getVolumeWidth().compareTo(maxVolumeWidth) > 0){
+                            maxVolumeWidth = productionProcesses.getVolumeWidth();
+                        }
+                    }
+                }
+                cjb.setMaxVolumeWidth(maxVolumeWidth);
+                resetIds.add(cjb);
+                listSet(syids,resetIds,apsSolution);
+            }else{
+                cjb.setOrderids(allIds.get(0));
+                BigDecimal maxVolumeWidth = null;
+                for (String orderid : cjb.getOrderids()) {
+                    List<ProductionProcesses> processes = apsSolution.getProcessesList().stream().filter(v ->
+                            v.getProduceOrder().get(0).getId().equals(orderid)).collect(Collectors.toList());
+                    ProductionProcesses productionProcesses = processes.get(0);
+                    if(maxVolumeWidth == null){
+                        maxVolumeWidth = productionProcesses.getVolumeWidth();
+                    }else{
+                        if(productionProcesses.getVolumeWidth().compareTo(maxVolumeWidth) > 0){
+                            maxVolumeWidth = productionProcesses.getVolumeWidth();
+                        }
+                    }
+                }
+                cjb.setMaxVolumeWidth(maxVolumeWidth);
+                resetIds.add(cjb);
+            }
+        }
+    }
+
+    /**
+     * 排程结束数据手动添加到设备占用列表中
+     * @param pps
+     */
+    private void setEqRunTimes(List<ProductionProcesses> pps){
+        if(pps != null && pps.size()>0){
+            for (ProductionProcesses productionProcesses : pps) {
+                // 添加锁定工序设备占用时间
+                List<EquipmentRunTime> equipmentRunTimes = new ArrayList<>();
+                EquipmentRunTime pper = new EquipmentRunTime();
+                pper.setStartRunTime(productionProcesses.getStartTime());
+                pper.setEndRunTime(productionProcesses.getEndTime());
+                pper.setSeriesProduceMark(productionProcesses.getSeriesProduceMark());
+                pper.setProcessType(productionProcesses.getProcessType());
+                pper.setVolumeMetal(productionProcesses.getVolumeMetal());
+                pper.setTotalVolumeWidth(productionProcesses.getVolumeWidth());
+                pper.setTotalSinglerollweight(productionProcesses.getSinglerollweight());
+                pper.setTotalThickness(productionProcesses.getVolumeThickness());
+                pper.setProducttype(productionProcesses.getProducttype());
+                pper.setOnceprocessmin(productionProcesses.getProduceTime());
+                pper.setPcNum(productionProcesses.getOpeProducePcNum());
+                pper.setOccupyType("process");
+                equipmentRunTimes.add(pper);
+
+                if(equipmentRunTimes.size()>0){
+                    if(productionProcesses.getEquipment().getEquipmentRunTimes() == null){
+                        productionProcesses.getEquipment().setEquipmentRunTimes(equipmentRunTimes);
+                    }else{
+                        productionProcesses.getEquipment().getEquipmentRunTimes().addAll(equipmentRunTimes);
+                    }
+                    apsService.equipmentRunTimeMerge(productionProcesses.getEquipment(),productionProcesses.getApsOverallConfig().getFurnaceInstallations());
+                }
+            }
+        }
+    }
+
     private ProductionProcesses maxWaitTimeCheck(ProductionProcesses process,List<ProductionProcesses> maxSetPros,List<ProductionProcesses> processes,List<Equipment> equipments){
         ProductionProcesses newPre = null;
         List<ProductionProcesses> previousProcesses = process.getPreviousProcesses();