Просмотр исходного кода

排程优化-退火合并优化

fangpy 8 месяцев назад
Родитель
Сommit
68c12b71d3

+ 6 - 3
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/listener/TaskStartTimeListener.java

@@ -403,6 +403,9 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
             if(equipmentRunTimes.size()>0){
                 for(int i = 0; i < equipmentRunTimes.size(); i++){
                     EquipmentRunTime equipmentRunTime = equipmentRunTimes.get(i);
+                    if(equipmentRunTime.getEndRunTime() == null){
+                        continue;
+                    }
                     // 退火工序
                     if(process.getProcessType().equals("成退") || process.getProcessType().equals("中退") || process.getProcessType().equals("小卷成退")){
                         // 没有交叉直接跳过
@@ -417,7 +420,7 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
                         if(equipmentRunTime.getStartRunTime().compareTo(proStartTime) >= 0 && equipmentRunTime.getStartRunTime().compareTo(proEndTime) <= 0){
                             boolean hasMergeTh = thMerge(process,equipmentRunTime);
                             if(!hasMergeTh){
-                                proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(60);
+//                                proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(60);
                                 proEndTime = proStartTime.plusMinutes(process.getProduceTime());
                             }else{
                                 proStartTime = equipmentRunTime.getStartRunTime();
@@ -430,14 +433,14 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
                                 if(proStartTime.compareTo(equipmentRunTime.getStartRunTime())<0){
                                     boolean hasMergeTh = thMerge(process,equipmentRunTime);
                                     if(!hasMergeTh){
-                                        proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(60);
+//                                        proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(60);
                                         proEndTime = proStartTime.plusMinutes(process.getProduceTime());
                                     }else {
                                         proStartTime = equipmentRunTime.getStartRunTime();
                                         proEndTime = proStartTime.plusMinutes(process.getProduceTime());
                                     }
                                 }else{
-                                    proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(60);
+//                                    proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(60);
                                     proEndTime = proStartTime.plusMinutes(process.getProduceTime());
                                 }
                             }

+ 96 - 25
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/score/ApsConstraintProvider.java

@@ -364,27 +364,28 @@ public class ApsConstraintProvider implements ConstraintProvider {
                     return !pro.getProcessType().equals("成退") && !pro.getProcessType().equals("中退") && !pro.getProcessType().equals("小卷成退");
                 })
                 .filter(productionProcesses -> {
-                    boolean bol = false;
-                    // 瓶颈工序合并生产规则,总宽度和总承重不超过最大值即可
-                    if(productionProcesses.getBottleneck() != null && productionProcesses.getBottleneck()){
-
+                    if(productionProcesses.getEquipment().getId().equals("0001be252874536843730b100017")){
+                        int a = 1;
                     }
-                    // 非瓶颈工序设备运行时间段,不可再排产
-                    else{
-                        if(productionProcesses.getEquipment() != null && productionProcesses.getEquipment().getEquipmentRunTimes() != null &&
-                                productionProcesses.getEquipment().getEquipmentRunTimes().size()>0){
-                            for (EquipmentRunTime equipmentRunTime : productionProcesses.getEquipment().getEquipmentRunTimes()) {
-                                if(equipmentRunTime.getStartRunTime() != null && equipmentRunTime.getEndRunTime() != null){
-                                    LocalDateTime startTime = equipmentRunTime.getStartRunTime();
-                                    LocalDateTime endRunTime = equipmentRunTime.getEndRunTime();
-                                    if(productionProcesses.getStartTime() == null || productionProcesses.getEndTime() == null){
-                                        bol = false;
-                                        break;
-                                    }
-                                    if(productionProcesses.getStartTime().compareTo(endRunTime)>=0 || productionProcesses.getEndTime().compareTo(startTime)<=0){
-                                        continue;
-                                    }else{
+                    boolean bol = false;
+                    if(productionProcesses.getEquipment() != null && productionProcesses.getEquipment().getEquipmentRunTimes() != null &&
+                                productionProcesses.getEquipment().getEquipmentRunTimes().size()>0
+                                && productionProcesses.getStartTime() != null && productionProcesses.getEndTime() != null){
+                        for (EquipmentRunTime equipmentRunTime : productionProcesses.getEquipment().getEquipmentRunTimes()) {
+                            LocalDateTime startTime = equipmentRunTime.getStartRunTime();
+                            LocalDateTime endRunTime = equipmentRunTime.getEndRunTime();
+                            if(equipmentRunTime.getStartRunTime() != null && equipmentRunTime.getEndRunTime() != null){
+                                if(productionProcesses.getStartTime().compareTo(endRunTime)>=0 || productionProcesses.getEndTime().compareTo(startTime)<=0){
+                                    continue;
+                                }else{
+                                    bol = true;
+                                    break;
+                                }
+                            }else{
+                                if(startTime != null && endRunTime == null){
+                                    if(productionProcesses.getEndTime().compareTo(startTime)>0){
                                         bol = true;
+                                        break;
                                     }
                                 }
                             }
@@ -675,7 +676,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
             pp.setLastSerialLbWeight(equipment.getLastSerialLbWeight());
             hasStartTimeProcess.add(0,pp);
         }
-        if(equipment.getId().equals("0001be252874536843730b100052")){
+        if(equipment.getId().equals("0001be252874536843730b100050")){
             int aa = 2;
         }
         // 周期立板已连续生产吨数
@@ -688,6 +689,10 @@ public class ApsConstraintProvider implements ConstraintProvider {
             if(hasStartTimeProcess.get(i).getSeriesProduceMark() != null && hasStartTimeProcess.get(i+1).getSeriesProduceMark() != null){
                 String[] serspre = hasStartTimeProcess.get(i).getSeriesProduceMark().split("\\^_\\^");
                 String[] sersafter = hasStartTimeProcess.get(i+1).getSeriesProduceMark().split("\\^_\\^");
+                // 获取产品类型二级
+                String bfcplx = serspre[1].split("-")[0];
+                // 获取产品类型二级
+                String afcplx = sersafter[1].split("-")[0];
                 // 换辊时长(分钟)
                 int jgtime = hasStartTimeProcess.get(i).getCutfinishmin() + hasStartTimeProcess.get(i+1).getPrepressworkmin();
                 // 立板时长(分钟)
@@ -723,7 +728,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
                     if(!zzSeriesJr(hasStartTimeProcess.get(i),hasStartTimeProcess.get(i+1),apsNochangeRollerDos)){
                         if(syLb.compareTo(new BigDecimal("0"))>0 && hasStartTimeProcess.get(i).getEndTime().plusMinutes(maxTime).plusMinutes(syLbTime).compareTo(hasStartTimeProcess.get(i+1).getStartTime())>0){
                             // 只有存在当前排程的作业才会记录扣分数
-                            if(nextPro.getId() != null){
+                            if(nextPro.getId() != null || prePro.getId() != null){
                                 b++;
                                 conflictRoptions2.put("soft-seriesZzLb","和上道工序没有预留足够的周期立板时间");
                             }
@@ -741,7 +746,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
                             BigDecimal i2 = new BigDecimal(s2);
                             if(i1.compareTo(i2)<0){
                                 if(syLb.compareTo(new BigDecimal("0"))>0 && hasStartTimeProcess.get(i).getEndTime().plusMinutes(maxTime).plusMinutes(syLbTime).compareTo(hasStartTimeProcess.get(i+1).getStartTime())>0){
-                                    if(nextPro.getId() != null){
+                                    if(nextPro.getId() != null || prePro.getId() != null){
                                         b++;
                                         conflictRoptions2.put("soft-seriesZzLb","和上道工序没有预留足够的周期立板时间");
                                     }
@@ -750,13 +755,25 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                 lbserice = false;
                             }else if(i1.compareTo(i2)>0){
                                 if(syLb.compareTo(new BigDecimal("0"))>0 && hasStartTimeProcess.get(i).getEndTime().plusMinutes(standingtime).plusMinutes(syLbTime).compareTo(hasStartTimeProcess.get(i+1).getStartTime())>0){
-                                    if(nextPro.getId() != null){
+                                    if(nextPro.getId() != null || prePro.getId() != null){
                                         b++;
                                         conflictRoptions2.put("soft-seriesZzLb","和上道工序没有预留足够的周期立板时间");
                                     }
                                 }
                                 zqlb = new BigDecimal("0");
                                 lbserice = false;
+                            }else{
+                                // 二级产品类型不一样的也需要立板
+                                if(!bfcplx.equals(afcplx)){
+                                    if(syLb.compareTo(new BigDecimal("0"))>0 && hasStartTimeProcess.get(i).getEndTime().plusMinutes(standingtime).plusMinutes(syLbTime).compareTo(hasStartTimeProcess.get(i+1).getStartTime())>0){
+                                        if(nextPro.getId() != null || prePro.getId() != null){
+                                            b++;
+                                            conflictRoptions2.put("soft-seriesZzLb","和上道工序没有预留足够的周期立板时间");
+                                        }
+                                    }
+                                    zqlb = new BigDecimal("0");
+                                    lbserice = false;
+                                }
                             }
                         }catch (Exception e){
                             e.printStackTrace();
@@ -1855,9 +1872,9 @@ public class ApsConstraintProvider implements ConstraintProvider {
             equipment = processes.get(0).getEquipment();
             apsNochangeRollerDos = processes.get(0).getApsOverallConfig().getApsNochangeRollerDos();
         }
-        if(equipment.getId().equals("0001be252874536843730b100056")){
+        if(equipment.getId().equals("0001be252874536843730b100021")){
             int abc = 1;
-            if(processes.get(0).getDelay() == 100){
+            if(processes.get(0).getDelay() == 2000){
                 int abcd = 1;
             }
         }
@@ -1874,6 +1891,8 @@ public class ApsConstraintProvider implements ConstraintProvider {
                         pp.setStartTime(equipmentRunTime.getStartRunTime());
                         pp.setSeriesProduceMark(equipmentRunTime.getSeriesProduceMark());
                         pp.setProcessType(equipmentRunTime.getProcessType());
+                        pp.setSinglerollweight(equipmentRunTime.getTotalSinglerollweight());
+                        pp.setLastSerialLbWeight(equipmentRunTime.getLastSerialLbWeight());
                         pp.setBsProcessesId(Arrays.asList(new String[]{"haspcprocess"}));
                         pp.setConflictRoptions(new HashMap<>());
                         hasStartTimeProcess.add(pp);
@@ -1887,6 +1906,8 @@ public class ApsConstraintProvider implements ConstraintProvider {
                 ProductionProcesses pp = new ProductionProcesses();
                 pp.setSeriesProduceMark(equipment.getLastSeriesProduceMark());
                 pp.setProcessType(equipment.getLastProcessType());
+                pp.setSinglerollweight(equipment.getLastSinglerollweight());
+                pp.setLastSerialLbWeight(equipment.getLastSerialLbWeight());
                 pp.setBsProcessesId(Arrays.asList(new String[]{"lastprocess"}));
                 pp.setConflictRoptions(new HashMap<>());
                 hasStartTimeProcess.add(0,pp);
@@ -1895,6 +1916,8 @@ public class ApsConstraintProvider implements ConstraintProvider {
                     b = b+2;
                 }
             }
+            // 周期铸轧立板已连续生产吨数
+            BigDecimal zqlb = new BigDecimal("0");
             for(int i=0;i<hasStartTimeProcess.size();i++){
                 if(i == hasStartTimeProcess.size()-1){
                     if(hasStartTimeProcess.get(i).getId() == null){
@@ -1917,12 +1940,27 @@ public class ApsConstraintProvider implements ConstraintProvider {
                         Map<String, String> conflictRoptions1 = hasStartTimeProcess.get(i).getConflictRoptions();
                         Map<String, String> conflictRoptions2 = hasStartTimeProcess.get(i+1).getConflictRoptions();
                         if("铸轧".equals(hasStartTimeProcess.get(i).getProcessType())){
+                            if(hasStartTimeProcess.get(i+1).getId() == null){
+                                continue;
+                            }
                             String[] serspre = hasStartTimeProcess.get(i).getSeriesProduceMark().split("\\^_\\^");
                             String[] sersafter = hasStartTimeProcess.get(i+1).getSeriesProduceMark().split("\\^_\\^");
                             // 获取产品类型二级
                             String bfcplx = serspre[1].split("-")[0];
                             // 获取产品类型二级
                             String afcplx = sersafter[1].split("-")[0];
+                            // 周期立板总重量统计
+                            if(zqlb.compareTo(new BigDecimal("0")) == 0){
+                                if(hasStartTimeProcess.get(i).getLastSerialLbWeight() != null){
+                                    zqlb = hasStartTimeProcess.get(i).getLastSerialLbWeight();
+                                }else{
+                                    zqlb = hasStartTimeProcess.get(i).getSinglerollweight();
+                                }
+                            }else{
+                                zqlb = zqlb.add(hasStartTimeProcess.get(i).getSinglerollweight());
+                            }
+                            // 铸轧立板是否连续
+                            boolean lbserice = true;
                             if(serspre.length == 5 && sersafter.length == 5){
                                 // 铸轧换辊兼容规则
                                 if(!zzSeriesJr(hasStartTimeProcess.get(i),hasStartTimeProcess.get(i+1),apsNochangeRollerDos)){
@@ -1932,6 +1970,8 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                     }else{
                                         conflictRoptions2.put("soft-seriesProduceZz","和前一道工序违反换辊和立板的连续约束");
                                     }
+                                    zqlb = new BigDecimal("0");
+                                    lbserice = false;
                                 }else{
                                     // 合金相同情况下后面的宽度大于前面的宽度需要换辊和立板
                                     // 合金相同情况下后面的宽度小于前面的宽度需要立板
@@ -1948,6 +1988,8 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                             }else{
                                                 conflictRoptions2.put("soft-seriesProduceZz","和前一道工序违反换辊和立板的连续约束");
                                             }
+                                            zqlb = new BigDecimal("0");
+                                            lbserice = false;
                                         }else if(i1.compareTo(i2)>0){
                                             b = b+8;
                                             if(hasStartTimeProcess.get(i).getId() != null){
@@ -1955,6 +1997,8 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                             }else{
                                                 conflictRoptions2.put("soft-seriesProduceZz","和前一道工序违反立板的连续约束");
                                             }
+                                            zqlb = new BigDecimal("0");
+                                            lbserice = false;
                                         }else{
                                             // 二级产品类型不一样的也需要立板
                                             if(!bfcplx.equals(afcplx)){
@@ -1964,6 +2008,8 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                                 }else{
                                                     conflictRoptions2.put("soft-seriesProduceZz","和前一道工序违反立板的连续约束");
                                                 }
+                                                zqlb = new BigDecimal("0");
+                                                lbserice = false;
                                             }
                                         }
                                     }catch (Exception e){
@@ -2501,6 +2547,31 @@ public class ApsConstraintProvider implements ConstraintProvider {
                 .asConstraint("mergeTuihuo");
     }
 
+    /**
+     * 退火工序碎片化时间约束
+     * @param constraintFactory
+     * @return
+     */
+    private Constraint tuihuoSp(ConstraintFactory constraintFactory){
+        return constraintFactory.forEach(ProductionProcesses.class)
+                .filter(pro->{
+                    return pro.getProcessType().equals("成退") || pro.getProcessType().equals("中退") || pro.getProcessType().equals("小卷成退");
+                })
+                .groupBy(ProductionProcesses::getEquipmentId,ConstraintCollectors.toList())
+                .filter((equipmentId,processes) -> {
+                    if(processes != null && processes.size()>0){
+                        return true;
+                    }else{
+                        return false;
+                    }
+                })
+                .penalize(HardMediumSoftScore.ONE_MEDIUM,(equipmentId,processes)->{
+
+                    return 1000;
+                })
+                .asConstraint("tuihuoSp");
+    }
+
     /**
      * 相同作业放在同一设备上加工
      * @param constraintFactory

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

@@ -1908,9 +1908,25 @@ public class ApsServiceImpl implements ApsService {
             apsSolutionZz.setProcessesList(zzprocesList);
             // 铸轧合并工序
             List<ProductionProcesses> mergeZzs = new ArrayList<>();
-            Map<String, List<ProductionProcesses>> bsPros = zzprocesList.stream().collect(Collectors.groupingBy(ProductionProcesses::getUniqueBsProcessesId));
+//            Map<String, List<ProductionProcesses>> bsPros = zzprocesList.stream().collect(Collectors.groupingBy(ProductionProcesses::getUniqueBsProcessesId));
+            // 相同客户订单,相同合金,相同产品类型,相同宽度合并一个作业排程
+            Map<String, List<ProductionProcesses>> bsPros = new HashMap<>();
+            for (ProductionProcesses productionProcesses : zzprocesList) {
+                String cplx = productionProcesses.getProducttype().split("-")[0];
+                // 客户订单ID+合金+产品类型+宽度 作为合并的key
+                String keystr = productionProcesses.getProduceOrder().get(0).getCustomerOrderId()+productionProcesses.getVolumeMetal()+cplx+productionProcesses.getVolumeWidth();
+                if(bsPros.containsKey(keystr)){
+                    bsPros.get(keystr).add(productionProcesses);
+                }else{
+                    List<ProductionProcesses> pps = new ArrayList<>();
+                    pps.add(productionProcesses);
+                    bsPros.put(keystr,pps);
+                }
+            }
+
             bsPros.forEach((k,v)->{
                 if(v.size()>1){
+                    Collections.sort(v, Comparator.comparing(ProductionProcesses::getUniqueBsProcessesId));
                     if("铸轧".equals(v.get(0).getProcessType())){
                         ProductionProcesses productionProcesses = v.get(0);
                         List<String> mergeProOrders = new ArrayList<>();
@@ -1918,10 +1934,37 @@ public class ApsServiceImpl implements ApsService {
                         productionProcesses.setMergeProOrders(mergeProOrders);
                         for (int i = 0; i < v.size(); i++) {
                             if(i>0){
-                                productionProcesses.getMergeProOrders().add(v.get(i).getId());
-                                productionProcesses.setProduceTime(productionProcesses.getProduceTime()+v.get(i).getProduceTime());
-                                productionProcesses.setSinglerollweight(productionProcesses.getSinglerollweight().add(v.get(i).getSinglerollweight()));
-                                productionProcesses.setOpeProducePcNum(v.size());
+                                if(v.get(i).getUniqueBsProcessesId().equals(productionProcesses.getUniqueBsProcessesId())){
+                                    productionProcesses.getMergeProOrders().add(v.get(i).getId());
+                                    productionProcesses.setProduceTime(productionProcesses.getProduceTime()+v.get(i).getProduceTime());
+                                    productionProcesses.setSinglerollweight(productionProcesses.getSinglerollweight().add(v.get(i).getSinglerollweight()));
+                                    productionProcesses.setOpeProducePcNum(v.size());
+                                }else{
+                                    List<Equipment> bases = productionProcesses.getOptionalProviderEquipments();
+                                    List<Equipment> eq1 = v.get(i).getOptionalProviderEquipments();
+                                    if(bases != null && bases.size()>0 && eq1 != null && eq1.size()>0){
+                                        List<Equipment> eqjj = new ArrayList<>();
+                                        for (Equipment basis : bases) {
+                                            for (Equipment equipment : eq1) {
+                                                if(basis.getId().equals(equipment.getId())){
+                                                    eqjj.add(basis);
+                                                    break;
+                                                }
+                                            }
+                                        }
+                                        if(eqjj.size() > 0){
+                                            productionProcesses.getMergeProOrders().add(v.get(i).getId());
+                                            productionProcesses.setProduceTime(productionProcesses.getProduceTime()+v.get(i).getProduceTime());
+                                            productionProcesses.setSinglerollweight(productionProcesses.getSinglerollweight().add(v.get(i).getSinglerollweight()));
+                                            productionProcesses.setOpeProducePcNum(v.size());
+                                            productionProcesses.setOptionalProviderEquipments(eqjj);
+                                        }else{
+                                            mergeZzs.add(v.get(i));
+                                        }
+                                    }else{
+                                        throw new ApsException("可选设备不能为空");
+                                    }
+                                }
                             }
                         }
                         mergeZzs.add(productionProcesses);