Преглед на файлове

调度退火独立排程

fangpy преди 5 месеца
родител
ревизия
a28bae4a2f

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

@@ -1,8 +1,11 @@
 package com.rongwei.rwapsserver.aps.service;
 
+import com.rongwei.rwapsserver.aps.domain.ApsSolution;
 import com.rongwei.rwapsserver.aps.domain.ProductionProcesses;
+import com.rongwei.rwapsserver.aps.vo.ProductionScheduleVo;
 
 import java.util.List;
+import java.util.Map;
 
 public interface DdApsService {
 
@@ -11,4 +14,7 @@ public interface DdApsService {
     List<ProductionProcesses> thOtherMerge(List<ProductionProcesses> mergeprocesses, List<ProductionProcesses> otherThproces);
 
     List<ProductionProcesses> seriesLzBzMerge(List<ProductionProcesses> mergeprocesses, List<ProductionProcesses> otherSerProces);
+
+    void tuihuoApsSch(ApsSolution apsSolution, List<ProductionProcesses> otherThproces, List<ProductionProcesses> otherNotZzFirstProces
+            , ProductionScheduleVo productionScheduleVo, Map<String,List<String>> ordergrous);
 }

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

@@ -1,15 +1,33 @@
 package com.rongwei.rwapsserver.aps.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.StrUtil;
+import com.rongwei.rwapsserver.aps.domain.ApsOverallConfig;
+import com.rongwei.rwapsserver.aps.domain.ApsSolution;
 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.ApsUtils;
+import com.rongwei.rwapsserver.aps.vo.ProductionScheduleVo;
+import lombok.extern.slf4j.Slf4j;
+import org.optaplanner.core.api.score.ScoreExplanation;
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.optaplanner.core.api.solver.SolutionManager;
+import org.optaplanner.core.api.solver.Solver;
+import org.optaplanner.core.api.solver.SolverFactory;
+import org.optaplanner.core.config.solver.EnvironmentMode;
+import org.optaplanner.core.config.solver.SolverConfig;
+import org.optaplanner.core.config.solver.termination.TerminationConfig;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
 
+@Slf4j
 @Service
 public class DdApsServiceImpl implements DdApsService {
 
@@ -789,4 +807,115 @@ public class DdApsServiceImpl implements DdApsService {
         }
     }
 
+    /**
+     * 调度排程退火
+     * @param apsSolution
+     * @param otherThproces
+     * @param otherNotZzFirstProces
+     * @param productionScheduleVo
+     * @param ordergrous
+     */
+    @Override
+    public void tuihuoApsSch(ApsSolution apsSolution, List<ProductionProcesses> otherThproces, List<ProductionProcesses> otherNotZzFirstProces, ProductionScheduleVo productionScheduleVo, Map<String, List<String>> ordergrous) {
+        ApsSolution apsSolutionTh = new ApsSolution();
+        // 过滤所有待排程的退火工序
+        List<ProductionProcesses> tuihuos = new ArrayList<>();
+        for (ProductionProcesses process : apsSolution.getProcessesList()) {
+            if((process.getProcessType().equals("成退") || process.getProcessType().equals("中退") || process.getProcessType().equals("小卷成退")) && !process.getIfLock()){
+                tuihuos.add(process);
+            }
+        }
+        // 按照上道工序排程时间过滤
+        if(tuihuos != null && tuihuos.size()>0){
+            // 过滤出有前端工序结束时间的退火工序
+            List<ProductionProcesses> hasPreTimePps = tuihuos.stream().filter(v -> {
+                boolean hasPreTime = false;
+                if (v.getPreviousProcesses() != null && v.getPreviousProcesses().size() > 0) {
+                    for (ProductionProcesses previousProcess : v.getPreviousProcesses()) {
+                        if (previousProcess.getEndTime() != null) {
+                            hasPreTime = true;
+                            break;
+                        }
+                    }
+                }
+                return hasPreTime;
+            }).collect(Collectors.toList());
+            // 有上道工序结束时间的退火按照上道工序结束时间从晚到早排序
+            Collections.sort(hasPreTimePps,(v1,v2)->{
+                LocalDateTime presLatestEndTime1 = getPresLatestEndTime(v1);
+                LocalDateTime presLatestEndTime2 = getPresLatestEndTime(v2);
+                return presLatestEndTime2.compareTo(presLatestEndTime1);
+            });
+            // 剩下没有前道工序结束时间的任务
+            List<String> hasPreTimePpIds = hasPreTimePps.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+            List<ProductionProcesses> notPreTimes = tuihuos.stream().filter(v -> !hasPreTimePpIds.contains(v.getId())).collect(Collectors.toList());
+            if(notPreTimes != null && notPreTimes.size()>0){
+                hasPreTimePps.addAll(notPreTimes);
+            }
+            // 排程数据组装
+            apsSolutionTh.setProcessesList(hasPreTimePps);
+            apsSolutionTh.setEquipmentList(apsSolution.getEquipmentList());
+            // 开始排程
+            String cores = Runtime.getRuntime().availableProcessors() + "";
+            SolverFactory<ApsSolution> solverFactory = SolverFactory.create(new SolverConfig()
+                            .withEnvironmentMode(EnvironmentMode.REPRODUCIBLE)
+                            .withSolutionClass(ApsSolution.class)
+                            .withEntityClasses(ProductionProcesses.class)
+                            .withConstraintProviderClass(ApsConstraintProvider.class)
+//                .withTerminationSpentLimit(Duration.ofSeconds(runPlanSeconds1))
+                            .withTerminationConfig(new TerminationConfig().withUnimprovedSecondsSpentLimit(60L))
+                            .withMoveThreadCount(cores)
+            );
+            Solver<ApsSolution> solver = solverFactory.buildSolver();
+            ApsSolution solvedBalance = solver.solve(apsSolutionTh);
+            log.info("**************退火排程评分分析***************");
+            SolutionManager<ApsSolution, HardSoftScore> scoreManager = SolutionManager.create(solverFactory);
+            ScoreExplanation<ApsSolution, HardSoftScore> explain = scoreManager.explain(solvedBalance);
+            log.info(explain.toString());
+            log.info("**************退火排程评分分析***************");
+            ApsUtils apsUtils = new ApsUtils();
+            apsUtils.softExplain(explain,solvedBalance.getProcessesList());
+            // 排程结束数据锁定
+            for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
+                for (ProductionProcesses processes : apsSolution.getProcessesList()) {
+                    if(processes.getId().equals(productionProcesses.getId())){
+                        processes.setStartTime(productionProcesses.getStartTime());
+                        processes.setEndTime(productionProcesses.getEndTime());
+                        processes.setDelay(productionProcesses.getDelay());
+                        processes.setEquipment(productionProcesses.getEquipment());
+                        processes.setEquipmentId(productionProcesses.getEquipmentId());
+                        processes.setIfLock(true);
+                        processes.setHasConflict(productionProcesses.getHasConflict());
+                        processes.setConflictDes(productionProcesses.getConflictDes());
+                        processes.setSoftconflictdes(productionProcesses.getSoftconflictdes());
+                        processes.setConflictRoptions(productionProcesses.getConflictRoptions());
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 获取当前任务的前道任务最晚结束时间
+     * @param pps
+     * @return
+     */
+    private LocalDateTime getPresLatestEndTime(ProductionProcesses pps){
+        List<ProductionProcesses> previousProcesses = pps.getPreviousProcesses();
+        LocalDateTime endTime = null;
+        if(previousProcesses != null && previousProcesses.size()>0){
+            for (ProductionProcesses previousProcess : previousProcesses) {
+                if(endTime == null){
+                    endTime = previousProcess.getEndTime();
+                }else{
+                    if(previousProcess.getEndTime().compareTo(endTime)>0){
+                        endTime = previousProcess.getEndTime();
+                    }
+                }
+            }
+        }
+        return endTime;
+    }
+
 }

+ 83 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/util/ApsUtils.java

@@ -0,0 +1,83 @@
+package com.rongwei.rwapsserver.aps.util;
+
+import cn.hutool.core.util.StrUtil;
+import com.rongwei.rwapsserver.aps.domain.ApsSolution;
+import com.rongwei.rwapsserver.aps.domain.ProductionProcesses;
+import org.optaplanner.core.api.score.ScoreExplanation;
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.optaplanner.core.api.score.constraint.ConstraintMatch;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ApsUtils {
+
+    /**
+     * 最终得分分析
+     * @param explain
+     * @param processes
+     */
+    public void softExplain(ScoreExplanation<ApsSolution, HardSoftScore> explain, List<ProductionProcesses> processes){
+        if(explain != null && explain.getConstraintMatchTotalMap() != null && explain.getConstraintMatchTotalMap().size()>0){
+            explain.getConstraintMatchTotalMap().forEach((k,v)->{
+                String constraintName = v.getConstraintName();
+                if(constraintName != null){
+                    String desc = ApsConstants.constraintDesc.get(constraintName);
+                    String consLevel = ApsConstants.hardConstraint.contains(constraintName) ? "hard" : "soft";
+                    if(desc != null && v.getConstraintMatchSet() != null && v.getConstraintMatchSet().size()>0){
+                        for (ConstraintMatch<HardSoftScore> hardSoftScoreConstraintMatch : v.getConstraintMatchSet()) {
+                            if(hardSoftScoreConstraintMatch.getIndictedObjectList() != null && hardSoftScoreConstraintMatch.getIndictedObjectList().size() > 0){
+                                for (Object o : hardSoftScoreConstraintMatch.getIndictedObjectList()) {
+                                    if(o instanceof ProductionProcesses){
+                                        ProductionProcesses productionProcesses = (ProductionProcesses)o;
+                                        constraintDescInit(productionProcesses,desc,consLevel);
+                                    } else if (o instanceof ArrayList) {
+                                        List<ProductionProcesses> processesList = (ArrayList)o;
+                                        for (ProductionProcesses productionProcesses : processesList) {
+                                            constraintDescInit(productionProcesses,desc,consLevel);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * 冲突描述
+     * @param productionProcesses
+     * @param desc
+     * @param consLevel
+     */
+    private void constraintDescInit(ProductionProcesses productionProcesses,String desc,String consLevel){
+        if("y".equals(productionProcesses.getHasConflict())){
+            if("hard".equals(consLevel)){
+                if(StrUtil.isBlank(productionProcesses.getConflictDes())){
+                    productionProcesses.setConflictDes(desc);
+                }else{
+                    if(!productionProcesses.getConflictDes().contains(desc)){
+                        productionProcesses.setConflictDes(productionProcesses.getConflictDes()+";"+desc);
+                    }
+                }
+            }else{
+                if(StrUtil.isBlank(productionProcesses.getSoftconflictdes())){
+                    productionProcesses.setSoftconflictdes(desc);
+                }else{
+                    if(!productionProcesses.getSoftconflictdes().contains(desc)){
+                        productionProcesses.setSoftconflictdes(productionProcesses.getSoftconflictdes()+";"+desc);
+                    }
+                }
+            }
+        }else{
+            productionProcesses.setHasConflict("y");
+            if("hard".equals(consLevel)){
+                productionProcesses.setConflictDes(desc);
+            }else{
+                productionProcesses.setSoftconflictdes(desc);
+            }
+        }
+    }
+
+}