|
@@ -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;
|
|
|
+ }
|
|
|
+
|
|
|
}
|