Procházet zdrojové kódy

退火调度排程优化

fangpengyuan před 3 měsíci
rodič
revize
8aa9f694e5

+ 2 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/DdApsService.java

@@ -17,4 +17,6 @@ public interface DdApsService {
 
     void tuihuoApsSch(ApsSolution apsSolution, List<ProductionProcesses> otherThproces, List<ProductionProcesses> otherNotZzFirstProces
             , ProductionScheduleVo productionScheduleVo, Map<String,List<String>> ordergrous);
+
+    List<ProductionProcesses> thProcessMerge(ProductionScheduleVo productionScheduleVo,ApsSolution apsSolution,List<ProductionProcesses> otherThproces);
 }

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

@@ -9,6 +9,7 @@ import com.rongwei.rwapsserver.aps.domain.Equipment;
 import com.rongwei.rwapsserver.aps.domain.ProductionProcesses;
 import com.rongwei.rwapsserver.aps.score.ApsConstraintProvider;
 import com.rongwei.rwapsserver.aps.service.DdApsService;
+import com.rongwei.rwapsserver.aps.util.ApsException;
 import com.rongwei.rwapsserver.aps.util.ApsUtils;
 import com.rongwei.rwapsserver.aps.vo.ProductionScheduleVo;
 import lombok.extern.slf4j.Slf4j;
@@ -23,6 +24,7 @@ import org.optaplanner.core.config.solver.termination.TerminationConfig;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -1006,4 +1008,280 @@ public class DdApsServiceImpl implements DdApsService {
         return endTime;
     }
 
+    /**
+     * 调度退火提前合并
+     * @param productionScheduleVo
+     * @param apsSolution
+     * @param otherThproces
+     * @return
+     */
+    public List<ProductionProcesses> thProcessMerge(ProductionScheduleVo productionScheduleVo,ApsSolution apsSolution,List<ProductionProcesses> otherThproces){
+        List<ProductionProcesses> processes = apsSolution.getProcessesList();
+        // 设备集合
+        List<Equipment> equipmentList = apsSolution.getEquipmentList();
+        List<ProductionProcesses> mergeprocesses = new ArrayList<>();
+        // 所有作业集合
+        Map<String,ProductionProcesses> allProMap = new HashMap<>();
+
+        // 其它作业集合
+        Map<String,List<ProductionProcesses>> notthproMap = new HashMap<>();
+        // 按订单分组
+        Map<String, List<ProductionProcesses>> orderProcess = processes.stream().collect(Collectors.groupingBy(ProductionProcesses::getOrderId));
+        orderProcess.forEach((orderId,orderpss)->{
+            if("6639310eb2204f77ac9d36a2f289039c".equals(orderId)){
+                int a = 1;
+            }
+            // 退火作业集合
+            Map<String,List<ProductionProcesses>> thproMap = new HashMap<>();
+            for (ProductionProcesses process : orderpss) {
+                if("成退".equals(process.getProcessType()) || "中退".equals(process.getProcessType()) || "小卷成退".equals(process.getProcessType())){
+                    // 锁定的不参与合并
+                    /*if(process.getIfLock()){
+                        mergeprocesses.add(process);
+                    }else{*/
+                    String bsproid = process.getBsProcessesId().get(0);
+                    List<ProductionProcesses> bsprocess = thproMap.get(bsproid);
+                    if(bsprocess == null){
+                        bsprocess = new ArrayList<>();
+                    }
+                    bsprocess.add(process);
+                    thproMap.put(bsproid,bsprocess);
+//                    }
+                }else{
+                    mergeprocesses.add(process);
+
+                    String bsproid = process.getBsProcessesId().get(0);
+                    List<ProductionProcesses> bsprocess = thproMap.get(bsproid);
+                    if(bsprocess == null){
+                        bsprocess = new ArrayList<>();
+                    }
+                    bsprocess.add(process);
+                    notthproMap.put(bsproid,bsprocess);
+                }
+                allProMap.put(process.getId(),process);
+            }
+            // 退火合并
+            if(thproMap != null && thproMap.size()>0){
+                thproMap.forEach((k,v)->{
+                    // 未锁定的退火合并
+                    if(v.size()>1){
+                        // 作业卷数大于1,合并退火
+                        List<Equipment> equipments = equipmentList.stream().filter(eq -> eq.getId().equals(v.get(0).getOptionalEquipments().get(0))).collect(Collectors.toList());
+                        if(equipments != null && equipments.size()>0){
+                            Equipment equipment = equipments.get(0);
+                            // 根据承重计算最大几卷
+                            int a = equipment.getEquipmentParameter().getEquipmentBearing().divide(v.get(0).getSinglerollweight(), 2, RoundingMode.HALF_UP).intValue();
+                            // 根据宽度计算最大几卷
+                            if("成退".equals(v.get(0).getProcessType()) || "中退".equals(v.get(0).getProcessType())){
+                                int b = equipment.getEquipmentParameter().getEquipmentWidth().divide(v.get(0).getVolumeWidth().add(equipment.getEquipmentParameter().getFurnace()), 2, RoundingMode.HALF_UP).intValue();
+                                if(b<a){
+                                    a = b;
+                                }
+
+                                // 最大装炉卷数
+                                Integer maxheatroll = v.get(0).getProduceOrder().get(0).getMaxheatroll();
+                                if(maxheatroll != null && maxheatroll < a){
+                                    a = maxheatroll;
+                                }
+                                if(equipment.getEquipmentParameter() != null && equipment.getEquipmentParameter().getMaxfurance() != null && equipment.getEquipmentParameter().getMaxfurance()>0){
+                                    if(equipment.getEquipmentParameter().getMaxfurance() < a){
+                                        a = equipment.getEquipmentParameter().getMaxfurance();
+                                    }
+                                }
+                            }
+
+                            // 作业计划加工卷数是否大于一炉最大卷数
+                            if(v.get(0).getPreviousProcesses() != null && v.get(0).getPreviousProcesses().size()>0){
+                                Collections.sort(v,(p1,p2)->{
+                                    return p1.getPreviousProcesses().get(0).getEndTime().compareTo(p2.getPreviousProcesses().get(0).getEndTime());
+                                });
+                            }else{
+                                if(v.get(0).getRooprocess() != null && v.get(0).getRooprocess().getStartTime() != null){
+                                    Collections.sort(v,(p1,p2)->{
+                                        if(p1.getRooprocess() == null || p1.getRooprocess().getStartTime() == null){
+                                            return 1;
+                                        } else if (p2.getRooprocess() == null || p2.getRooprocess().getStartTime() == null) {
+                                            return -1;
+                                        }else{
+                                            return p1.getRooprocess().getStartTime().compareTo(p2.getRooprocess().getStartTime());
+                                        }
+                                    });
+                                }
+                            }
+
+                            if(a == 0){
+                                throw new ApsException(v.get(0).getUniqueBsProcessesId()+"作业单卷重超过设备承重或最大装炉卷数设置为0");
+                            }
+
+                            List<List<ProductionProcesses>> chunks = new ArrayList<>();
+
+                            List<ProductionProcesses> lockpps = v.stream().filter(m -> m.getIfLock()).collect(Collectors.toList());
+                            List<ProductionProcesses> notlockpps = v.stream().filter(m -> !m.getIfLock()).collect(Collectors.toList());
+                            if(lockpps != null && lockpps.size()>0){
+                                /*Collections.sort(lockpps,(p1,p2)->{
+                                    return p1.getStartTime().compareTo(p2.getStartTime());
+                                });
+                                Map<String, List<ProductionProcesses>> map = new TreeMap<>();
+                                for (ProductionProcesses productionProcesses : lockpps) {
+                                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                                    String startStr = productionProcesses.getStartTime().format(formatter);
+                                    if(map.containsKey(startStr)){
+                                        map.get(startStr).add(productionProcesses);
+                                    }else{
+                                        List<ProductionProcesses> b = new ArrayList<>();
+                                        b.add(productionProcesses);
+                                        map.put(startStr,b);
+                                    }
+                                }
+                                if(map != null && map.size()>0){
+                                    for (Map.Entry<String, List<ProductionProcesses>> entry : map.entrySet()) {
+                                        chunks.add(entry.getValue());
+                                    }
+                                }*/
+                                mergeprocesses.addAll(lockpps);
+                            }
+                            if(notlockpps != null && notlockpps.size()>0) {
+                                int listSize = notlockpps.size();
+                                /*for (int i = 0; i < listSize; i += a) {
+                                    chunks.add(notlockpps.subList(i, Math.min(i + a, listSize)));
+                                }*/
+                                // 根据最大装炉卷数以及最大等待时间来判断是否合并
+                                LocalDateTime minpreendTime = null;
+                                for (int i = 0; i < listSize; i++) {
+                                    ProductionProcesses processes1 = notlockpps.get(i);
+                                    // 是否新组炉
+                                    boolean newList = true;
+                                    if(!chunks.isEmpty()){
+                                        int lastsize = chunks.get(chunks.size() - 1).size();
+                                        // 最大装炉卷数限制
+                                        if(lastsize<a){
+                                            // 有最大等待时间则判断前道工序时间差是否小于最大等待时间
+                                            if(processes1.getMaxWaitTime() != null && processes1.getMaxWaitTime()>0){
+                                                if(processes1.getPreviousProcesses() != null && processes1.getPreviousProcesses().size()>0){
+                                                    // 待合并的退火前道工序结束时间最大差不能大于最大等待时间
+                                                    if(processes1.getPreviousProcesses().get(0).getEndTime().compareTo(minpreendTime.plusMinutes(processes1.getMaxWaitTime()))<0){
+                                                        newList = false;
+                                                    }
+                                                }else {
+                                                    newList = false;
+                                                }
+                                            }else{
+                                                newList = false;
+                                            }
+                                        }
+                                    }
+                                    if(newList){
+                                        minpreendTime = processes1.getPreviousProcesses().get(0).getEndTime();
+                                        List<ProductionProcesses> thps = new ArrayList<>();
+                                        thps.add(processes1);
+                                        chunks.add(thps);
+                                    }else{
+                                        chunks.get(chunks.size() - 1).add(processes1);
+                                    }
+                                }
+                            }
+                            // 合并退火作业
+                            for(int j = 0;j < chunks.size();j++){
+                                List<ProductionProcesses> thps = chunks.get(j);
+                                for (int i = 0; i < thps.size(); i++) {
+                                    if(i>0){
+                                        // 设置待合并退火的主ID
+                                        thps.get(i).setMergeThMainId(thps.get(0).getId());
+                                        // 设置合并作业的根节点
+                                        thps.get(0).getMergeRooprocess().add(thps.get(i).getRooprocess());
+                                        otherThproces.add(thps.get(i));
+                                        // 退火前一道作业设置下一作业ID
+                                        if(thps.get(i).getPreviousProcessesIds() == null){
+                                            int a12 = 111;
+                                        }
+                                        if(thps.get(i).getPreviousProcessesIds() != null && thps.get(i).getPreviousProcessesIds().size()>0){
+                                            ProductionProcesses prepro = allProMap.get(thps.get(i).getPreviousProcessesIds().get(0));
+                                            // 历史关联关系备份
+                                            List<String> oldNextProcessesIds = new ArrayList<>();
+                                            oldNextProcessesIds.addAll(prepro.getNextProcessesIds());
+//                                        prepro.setOldNextProcessesIds(oldNextProcessesIds);
+                                            // 合并后关联关系重置
+                                            if(!prepro.getNextProcessesIds().contains(thps.get(0).getId())){
+                                                int i1 = prepro.getNextProcessesIds().indexOf(thps.get(i).getId());
+                                                prepro.getNextProcessesIds().set(i1,thps.get(0).getId());
+                                            }
+                                            List<String> list = new ArrayList<>();
+                                            Set<String> set = new LinkedHashSet<>();
+                                            for (String nextProcessesId : prepro.getNextProcessesIds()) {
+                                                set.add(nextProcessesId);
+                                            }
+                                            list.addAll(set);
+                                            prepro.setNextProcessesIds(list);
+                                            List<ProductionProcesses> nextpros = new ArrayList<>();
+                                            for (String nextProcessesId : prepro.getNextProcessesIds()) {
+                                                nextpros.add(allProMap.get(nextProcessesId));
+                                            }
+                                            prepro.setNextProcesses(nextpros);
+                                            // 当前合并退火作业设置前一道作业
+                                            if(!thps.get(0).getPreviousProcessesIds().contains(prepro.getId())){
+                                                thps.get(0).getPreviousProcessesIds().add(prepro.getId());
+                                            }
+                                            List<ProductionProcesses> previousProces = new ArrayList<>();
+                                            for (String pid : thps.get(0).getPreviousProcessesIds()) {
+                                                previousProces.add(allProMap.get(pid));
+                                            }
+                                            thps.get(0).setPreviousProcesses(previousProces);
+                                        }
+                                        // 退火后一道作业设置上一道作业ID
+                                        if(thps.get(i).getNextProcessesIds() != null && thps.get(i).getNextProcessesIds().size()>0){
+                                            for (String nextProcessesId : thps.get(i).getNextProcessesIds()) {
+                                                ProductionProcesses nextpro = allProMap.get(nextProcessesId);
+                                                // 历史关联关系备份
+                                                List<String> oldpreids = new ArrayList<>();
+                                                if(nextpro == null){
+                                                    int aaa = 11;
+                                                }
+                                                oldpreids.addAll(nextpro.getPreviousProcessesIds());
+//                                                nextpro.setOldPreviousProcessesIds(oldpreids);
+                                                // 合并后关联关系重置
+                                                List<String> preids = new ArrayList<>();
+                                                preids.add(thps.get(0).getId());
+                                                nextpro.setPreviousProcessesIds(preids);
+
+                                                List<ProductionProcesses> nextprepros = new ArrayList<>();
+                                                for (String pid : nextpro.getPreviousProcessesIds()) {
+                                                    nextprepros.add(allProMap.get(pid));
+                                                }
+                                                nextpro.setPreviousProcesses(nextprepros);
+                                            }
+                                            // 设置合并退火作业下一道工序
+                                            thps.get(0).getNextProcessesIds().addAll(thps.get(i).getNextProcessesIds());
+                                            List<ProductionProcesses> thnexts = new ArrayList<>();
+                                            for (String pid : thps.get(0).getNextProcessesIds()) {
+                                                thnexts.add(allProMap.get(pid));
+                                            }
+                                            thps.get(0).setNextProcesses(thnexts);
+                                        }
+                                        // 小卷退火卷数合并
+                                        if(thps.get(i).getProcessType().equals("小卷成退")){
+                                            thps.get(0).setMinThPcNum(thps.get(0).getMinThPcNum()+thps.get(i).getMinThPcNum());
+                                        }
+                                    }
+                                }
+                                // 取第一个作业作为合并作业
+                                ProductionProcesses mergePro = thps.get(0);
+                                mergePro.setTotalVolumeWidth(mergePro.getVolumeWidth().multiply(new BigDecimal(thps.size())));
+                                mergePro.setTotalSinglerollweight(mergePro.getTotalSinglerollweight().multiply(new BigDecimal(thps.size())));
+                                mergePro.setOpeProducePcNum(thps.size());
+                                // 设置是否满炉
+                                if(thps.size() == a){
+                                    mergePro.setIffullth("y");
+                                }
+                                mergeprocesses.add(mergePro);
+                            }
+                        }
+                    }else{
+                        mergeprocesses.addAll(v);
+                    }
+                });
+            }
+        });
+        return mergeprocesses;
+    }
+
 }

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

@@ -53,7 +53,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
     @Override
     public ProductionScheduleRetVo productionSchedule(ProductionScheduleVo productionScheduleVo) throws Exception{
         List<String> blankids = new ArrayList<>();
-        blankids.add("85e8e1938b7445939713f70f00401333");
+        blankids.add("055aa157de194440be75ad115d60054d");
         blankids.add("9e8bbe425aa044a4af55d8daf7ebb4cb");
         blankids.add("7efe679a8e3c4942b88758617cdbc312");
 //        blankids.add("acf4460f9488459780c0dc7d8038f1f9");
@@ -143,7 +143,11 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         // 退火合并
         List<ProductionProcesses> thList = null;
         if("dd".equals(productionScheduleVo.getScheduleType().getScheduleType())){
-            thList = apsSolution.getProcessesList();
+            if("thMergeBf".equals(productionScheduleVo.getScheduleType().getThMergeMode())){
+                thList = ddsService.thProcessMerge(productionScheduleVo,apsSolution,otherThproces);
+            }else {
+                thList = apsSolution.getProcessesList();
+            }
         }else{
             thList = apsService.thProcessMerge(productionScheduleVo,apsSolution,otherThproces);
         }