Browse Source

APS平台生产排程平台规划算法

fangpy 1 year ago
parent
commit
4ae1657f97

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

@@ -29,7 +29,8 @@ public class ApsSchedulingController {
      */
     @PostMapping("/productionSchedule")
     public ProductionScheduleRetVo productionSchedule(@RequestBody ProductionScheduleVo productionScheduleVo) throws Exception{
-        return productionScheduleService.productionSchedule(productionScheduleVo);
+        ProductionScheduleRetVo productionScheduleRetVo = productionScheduleService.productionSchedule(productionScheduleVo);
+        return productionScheduleRetVo;
     }
 
     /**

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

@@ -29,7 +29,7 @@ public class ProductionProcesses extends ApsAbstractPersistable{
     /**
      * 业务表订单工序ID
      */
-    private String bsProcessesId;
+    private List<String> bsProcessesId;
 
     /**
      * 设备类型
@@ -332,11 +332,11 @@ public class ProductionProcesses extends ApsAbstractPersistable{
         this.nextProcessesIds = nextProcessesIds;
     }
 
-    public String getBsProcessesId() {
+    public List<String> getBsProcessesId() {
         return bsProcessesId;
     }
 
-    public void setBsProcessesId(String bsProcessesId) {
+    public void setBsProcessesId(List<String> bsProcessesId) {
         this.bsProcessesId = bsProcessesId;
     }
 

+ 64 - 2
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/score/ApsConstraintProvider.java

@@ -33,6 +33,8 @@ public class ApsConstraintProvider implements ConstraintProvider {
                 equipmentRunTime(constraintFactory),
 //                balancedEqUse(constraintFactory),
 //                mergeProcess(constraintFactory)
+
+//                mergeSame(constraintFactory),
         };
     }
 
@@ -50,6 +52,62 @@ public class ApsConstraintProvider implements ConstraintProvider {
                 .asConstraint("eqTypeSame");
     }
 
+    /**
+     * 硬约束:合并生产工序设备、开始时间、结束时间都一样
+     * @param constraintFactory
+     * @return
+     */
+    private Constraint mergeSame(ConstraintFactory constraintFactory) {
+        return constraintFactory.forEach(ProductionProcesses.class)
+                .groupBy(ProductionProcesses::getMergeProcessMark, ConstraintCollectors.toList())
+                .filter((mergeProcessMark,processes) -> {
+                    if(processes != null && processes.size()>1){
+                        boolean a = false;
+                        // 合并生产的设备、开始时间、结束时间要一致
+                        Equipment ep = null;
+                        LocalDateTime startTime = null;
+                        LocalDateTime endTime = null;
+                        for (ProductionProcesses process : processes) {
+                            if(process.getEquipment() != null){
+                                if(ep == null){
+                                    ep = process.getEquipment();
+                                }else{
+                                    if(!ep.getId().equals(process.getEquipment().getId())){
+                                        a = true;
+                                        break;
+                                    }
+                                }
+                            }
+                            if(process.getStartTime() != null){
+                                if(startTime == null){
+                                    startTime = process.getStartTime();
+                                }else{
+                                    if(startTime.compareTo(process.getStartTime()) != 0){
+                                        a = true;
+                                        break;
+                                    }
+                                }
+                            }
+                            if(process.getEndTime() != null){
+                                if(endTime == null){
+                                    endTime = process.getEndTime();
+                                }else{
+                                    if(endTime.compareTo(process.getEndTime()) != 0){
+                                        a = true;
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        return a;
+                    }else{
+                        return false;
+                    }
+                })
+                .penalize(HardSoftScore.ONE_HARD,(mergeProcessMark,processes) -> 100)
+                .asConstraint("mergeSame");
+    }
+
     /**
      * 硬约束:没有上一步工步的开始时间小于当前时间
      * @param constraintFactory
@@ -257,8 +315,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
                              * 后道工序批次生产时间大于等于前道工序批次生产时间
                              * 从第一批次开始往后排程
                              */
-                            System.out.println("log-开始时间:"+productionProcesses.getStartTime());
-                            System.out.println("log-正确的开始时间:"+startTime.plusMinutes(preProcess.getUnitProduceTime()).plusMinutes(lzTimes));
+
                             if(preProcess.getMaxWaitTime() != null){
                                 lastFirstMaxWaitTime = startTime.plusMinutes(preProcess.getMaxWaitTime());
                             }
@@ -293,6 +350,11 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                     }
                                 }
                             }
+
+                            if(bln){
+                                System.out.println("log-开始时间:"+productionProcesses.getStartTime());
+                                System.out.println("log-正确的开始时间:"+startTime.plusMinutes(preProcess.getUnitProduceTime()).plusMinutes(lzTimes));
+                            }
                         }
                     }
 

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

@@ -18,6 +18,7 @@ import java.time.Duration;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 public class ProductionScheduleServiceImpl implements ProductionScheduleService {
@@ -54,7 +55,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         // optaplanner 求解器运行
         ApsSolution solvedBalance = solver.solve(apsSolution);
         System.out.println("*****************************");
-        System.out.println(solvedBalance);
+//        System.out.println(solvedBalance);
         SolutionManager<ApsSolution, HardSoftScore> scoreManager = SolutionManager.create(solverFactory);
         System.out.println(scoreManager.explain(solvedBalance));
         System.out.println("*****************************");
@@ -74,7 +75,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
      * @param productionScheduleVo
      * @return
      */
-    private static ApsSolution getPreApsSolution(ProductionScheduleVo productionScheduleVo){
+    private ApsSolution getPreApsSolution(ProductionScheduleVo productionScheduleVo){
         ApsSolution unsolvedCloudBalance = new ApsSolution();
         // 排程全局配置
         ApsOverallConfig apsOverallConfig = new ApsOverallConfig();
@@ -89,7 +90,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         // 根据前道、后道工序ID,转换为前道、后道工序对象
         Map<String,ProductionProcesses> idMaps = new HashMap<>();
         for (ProductionProcesses process : productionScheduleVo.getProcesses()) {
-            idMaps.put(process.getId(),process);
+            idMaps.put(String.join(",",process.getBsProcessesId()),process);
         }
         for (ProductionProcesses process : productionScheduleVo.getProcesses()) {
             // 全局配置设置
@@ -98,7 +99,12 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
             if(process.getPreviousProcessesIds() != null && process.getPreviousProcessesIds().size()>0){
                 List<ProductionProcesses> pres = new ArrayList<>();
                 for (String previousProcessesId : process.getPreviousProcessesIds()) {
-                    pres.add(idMaps.get(previousProcessesId));
+                    for (ProductionProcesses productionScheduleVoProcess : productionScheduleVo.getProcesses()) {
+                        if(productionScheduleVoProcess.getBsProcessesId().contains(previousProcessesId)){
+                            pres.add(productionScheduleVoProcess);
+                        }
+                    }
+
                 }
                 if(pres != null && pres.size()>0){
                     process.setPreviousProcesses(pres);
@@ -125,8 +131,77 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         }
         // 设备列表初始化
         unsolvedCloudBalance.setEquipmentList(productionScheduleVo.getEquipmentList());
+
+        List<ProductionProcesses> productionProcesses = sortProcess(productionScheduleVo.getProcesses());
         // 工序任务初始化
-        unsolvedCloudBalance.setProcessesList(productionScheduleVo.getProcesses());
+        unsolvedCloudBalance.setProcessesList(productionProcesses);
         return unsolvedCloudBalance;
     }
+
+    private List<ProductionProcesses> sortProcess(List<ProductionProcesses> sources){
+        // 排序后的列表
+        List<ProductionProcesses> processes = new ArrayList<>();
+        // 任务的排序
+        List<ProductionProcesses> processesSort = sources;
+        // 已排序的数据
+//        List<String> bsIds = new ArrayList<>();
+        // 最开始任务
+        List<ProductionProcesses> roots = new ArrayList<>();
+        for (ProductionProcesses productionProcesses : processesSort) {
+            if(productionProcesses.getPreviousProcesses() == null || productionProcesses.getPreviousProcesses().size() == 0){
+                roots.add(productionProcesses);
+            }
+        }
+        for (ProductionProcesses root : roots) {
+            List<Integer> repeatPro = new ArrayList<>();
+            Map<Integer,Integer> repeatProMap = new HashMap<>();
+            List<ProductionProcesses> subprocesses = new ArrayList<>();
+            subprocesses.add(root);
+//            bsIds.add(root.getBsProcessesId());
+            getNextProcess(root,subprocesses,repeatPro,processes,repeatProMap);
+
+            if(repeatPro != null && repeatPro.size()>0){
+                Collections.sort(repeatPro);
+                int a = 0;
+                for (Integer integer : repeatPro) {
+                    for(int i=integer-1;i>=a;i--){
+                        int finalI = i;
+                        List<ProductionProcesses> ps = processes.stream().filter(v -> v.getId().equals(subprocesses.get(finalI).getId())).collect(Collectors.toList());
+                        if(ps == null || ps .size() == 0){
+                            processes.add(repeatProMap.get(integer),subprocesses.get(i));
+                        }
+                    }
+                    // 最后一个把所有后面的工序插入到总工序列表后面
+                    /*if(integer.equals(repeatPro.get(repeatPro.size() - 1))){
+                        for(int i=integer+1;i<subprocesses.size();i++){
+                            processes.add(subprocesses.get(i));
+                        }
+                    }*/
+                }
+            }else{
+                processes.addAll(subprocesses);
+            }
+        }
+        return processes;
+    }
+
+    private void getNextProcess(ProductionProcesses proces,List<ProductionProcesses> subprocesses,
+                                List<Integer> repeatPro,List<ProductionProcesses> processes,Map<Integer,Integer> repeatProMap){
+        if(proces.getNextProcesses() != null && proces.getNextProcesses().size()>0){
+            for (ProductionProcesses nextProcess : proces.getNextProcesses()) {
+                subprocesses.add(nextProcess);
+                // 重复的工序
+                if(processes != null && processes.size()>0){
+                    for (int i=0;i<processes.size();i++) {
+                        ProductionProcesses process = processes.get(i);
+                        if(nextProcess.getId().equals(process.getId())){
+                            repeatPro.add(subprocesses.size()-1);
+                            repeatProMap.put(subprocesses.size()-1,i);
+                        }
+                    }
+                }
+                getNextProcess(nextProcess,subprocesses,repeatPro,processes,repeatProMap);
+            }
+        }
+    }
 }