|
@@ -53,15 +53,15 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
|
|
|
@Override
|
|
|
public ProductionScheduleRetVo productionSchedule(ProductionScheduleVo productionScheduleVo) throws Exception{
|
|
|
List<String> blankids = new ArrayList<>();
|
|
|
- blankids.add("055aa157de194440be75ad115d60054d");
|
|
|
- blankids.add("9e8bbe425aa044a4af55d8daf7ebb4cb");
|
|
|
- blankids.add("7efe679a8e3c4942b88758617cdbc312");
|
|
|
+ blankids.add("3917c2948ba446698afd93342757c6b9");
|
|
|
+ blankids.add("caec67974fd04302b37e2fd848815a68");
|
|
|
+// blankids.add("7efe679a8e3c4942b88758617cdbc312");
|
|
|
// blankids.add("acf4460f9488459780c0dc7d8038f1f9");
|
|
|
// blankids.add("efeb1f8d01b04cdb9921c0d1711bb967");
|
|
|
-// List<ProductionProcesses> collect = productionScheduleVo.getProcesses().stream().filter(v ->
|
|
|
-// blankids.contains(v.getProduceOrder().get(0).getId())
|
|
|
-// ).collect(Collectors.toList());
|
|
|
-// productionScheduleVo.setProcesses(collect);
|
|
|
+ /*List<ProductionProcesses> collect = productionScheduleVo.getProcesses().stream().filter(v ->
|
|
|
+ blankids.contains(v.getProduceOrder().get(0).getId())
|
|
|
+ ).collect(Collectors.toList());
|
|
|
+ productionScheduleVo.setProcesses(collect);*/
|
|
|
|
|
|
log.info("*************** 排程开始:"+productionScheduleVo.getProductionScheduleId()+" *******************");
|
|
|
if(productionScheduleVo.getScheduleType().getScheduleType() == null){
|
|
@@ -1820,94 +1820,226 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 退火提前合并排程
|
|
|
+ * 退火调度排程
|
|
|
* @param productionScheduleVo
|
|
|
* @return
|
|
|
*/
|
|
|
- public ProductionScheduleRetVo tuiHuoSchedule(ProductionScheduleVo productionScheduleVo,ApsSolution apsSolution) throws Exception{
|
|
|
+ public ProductionScheduleRetVo tuiHuoSchedule(ProductionScheduleVo productionScheduleVo) throws Exception{
|
|
|
+ log.info("*************** 退火调度排程开始:"+productionScheduleVo.getProductionScheduleId()+" *******************");
|
|
|
+ if(productionScheduleVo.getScheduleType().getScheduleType() == null){
|
|
|
+ productionScheduleVo.getScheduleType().setScheduleType("default");
|
|
|
+ }
|
|
|
+
|
|
|
+ ApsUtils apsUtils = new ApsUtils();
|
|
|
// 排程结果对象
|
|
|
ProductionScheduleRetVo productionScheduleRetVo = new ProductionScheduleRetVo();
|
|
|
- // 排程运行时长
|
|
|
- Integer maxPlanSeconds = productionScheduleVo.getPlanSeconds();
|
|
|
- Integer prospeed = 20;
|
|
|
- if(productionScheduleVo.getPcspeed() != null && productionScheduleVo.getPcspeed()>0){
|
|
|
- prospeed = productionScheduleVo.getPcspeed();
|
|
|
+ // 排程校验
|
|
|
+ if(productionScheduleVo.getRoamTime() == null || productionScheduleVo.getRoamTime().size() == 0){
|
|
|
+ throw new ApsException("缺少全局流转时间配置");
|
|
|
}
|
|
|
- int processNum = productionScheduleVo.getProcesses().size();
|
|
|
- int runPlanSeconds = (processNum/prospeed + 1)*60;
|
|
|
- if(maxPlanSeconds == null || maxPlanSeconds <= 0){
|
|
|
- maxPlanSeconds = 1800;
|
|
|
+
|
|
|
+ // optaplanner 求解器数据装配
|
|
|
+ List<ProductionProcesses> otherThproces = new ArrayList<>();
|
|
|
+ List<ProductionProcesses> otherNotThproces = new ArrayList<>();
|
|
|
+ ApsSolution apsSolution = getPreApsSolution(productionScheduleVo,otherThproces);
|
|
|
+ // 判断是否有非锁定的工序
|
|
|
+ boolean hasSchedulePro = false;
|
|
|
+ for (ProductionProcesses productionProcesses : apsSolution.getProcessesList()) {
|
|
|
+ if(!productionProcesses.getIfLock()){
|
|
|
+ hasSchedulePro = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- if(runPlanSeconds > maxPlanSeconds){
|
|
|
- throw new ApsException("所选排程作业太多,预计排程时间太长,请分开排程");
|
|
|
+ if(!hasSchedulePro){
|
|
|
+ throw new ApsException("没有可排程的工序");
|
|
|
}
|
|
|
- EnvironmentMode mode = EnvironmentMode.REPRODUCIBLE;
|
|
|
- if(productionScheduleVo.getEnvironmentMode() != null && productionScheduleVo.getEnvironmentMode() == 1){
|
|
|
- mode = EnvironmentMode.FULL_ASSERT;
|
|
|
+
|
|
|
+ // 退火合并
|
|
|
+ List<ProductionProcesses> thList = ddsService.thProcessMerge(productionScheduleVo,apsSolution,otherThproces);
|
|
|
+ apsSolution.setProcessesList(thList);
|
|
|
+
|
|
|
+ // 去掉锁定工序
|
|
|
+ List<ProductionProcesses> notLocks = new ArrayList<>();
|
|
|
+ List<ProductionProcesses> hasLocks = new ArrayList<>();
|
|
|
+ if(apsSolution.getProcessesList() != null && apsSolution.getProcessesList().size()>0){
|
|
|
+ for (ProductionProcesses productionProcesses : apsSolution.getProcessesList()) {
|
|
|
+ if(!productionProcesses.getIfLock()){
|
|
|
+ notLocks.add(productionProcesses);
|
|
|
+ }else{
|
|
|
+ hasLocks.add(productionProcesses);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- List<ProductionProcesses> otherThproces = new ArrayList<>();
|
|
|
-// ApsSolution apsSolution = getPreApsSolution(productionScheduleVo,otherThproces);
|
|
|
- // 退火提前排序
|
|
|
+ apsSolution.setProcessesList(notLocks);
|
|
|
+
|
|
|
+ ApsSolution apsSolutionTh = null;
|
|
|
Map<String,Map<String,List<ProductionProcesses>>> relPros = new HashMap<>();
|
|
|
- ApsSolution apsSolutionTh = apsService.tuihuoAps(apsSolution,relPros);
|
|
|
- if(apsSolutionTh.getProcessesList() != null && apsSolutionTh.getProcessesList().size()>0){
|
|
|
- // 退火工序求解器运行
|
|
|
- int processNum1 = apsSolutionTh.getProcessesList().size();
|
|
|
- int runPlanSeconds1 = (processNum1/prospeed + 1)*60;
|
|
|
- // CPU核数
|
|
|
- String cores = Runtime.getRuntime().availableProcessors() + "";
|
|
|
- SolverFactory<ApsSolution> solverFactory1 = SolverFactory.create(new SolverConfig()
|
|
|
- .withEnvironmentMode(mode)
|
|
|
- .withSolutionClass(ApsSolution.class)
|
|
|
- .withEntityClasses(ProductionProcesses.class)
|
|
|
- .withConstraintProviderClass(ApsConstraintProvider.class)
|
|
|
- .withTerminationSpentLimit(Duration.ofSeconds(runPlanSeconds1))
|
|
|
- .withMoveThreadCount(cores)
|
|
|
- );
|
|
|
- Solver<ApsSolution> solver1 = solverFactory1.buildSolver();
|
|
|
- ApsSolution solvedBalance1 = solver1.solve(apsSolutionTh);
|
|
|
- log.info("**************退火排程评分分析***************");
|
|
|
- SolutionManager<ApsSolution, HardSoftScore> scoreManager1 = SolutionManager.create(solverFactory1);
|
|
|
- ScoreExplanation<ApsSolution, HardSoftScore> explain1 = scoreManager1.explain(solvedBalance1);
|
|
|
- log.info(explain1.toString());
|
|
|
- log.info("**************退火排程评分分析***************");
|
|
|
- softExplain(explain1,solvedBalance1.getProcessesList());
|
|
|
- productionScheduleRetVo.setScoreResult(scoreManager1.explain(solvedBalance1).toString());
|
|
|
- productionScheduleRetVo.setProcesses(solvedBalance1.getProcessesList());
|
|
|
- // 循环引用ProductionProcesses置空
|
|
|
- for (ProductionProcesses productionProcesses : solvedBalance1.getProcessesList()) {
|
|
|
- productionProcesses.setPreviousProcesses(null);
|
|
|
- productionProcesses.setNextProcesses(null);
|
|
|
- productionProcesses.getEquipment().setProcessesList(null);
|
|
|
- productionProcesses.getEquipment().setEquipmentRunTimes(null);
|
|
|
- productionProcesses.setPreviousStep(null);
|
|
|
- productionProcesses.setOptionalProviderEquipments(null);
|
|
|
- // 冲突约束补充处理
|
|
|
- if(productionProcesses.getConflictRoptions() != null && productionProcesses.getConflictRoptions().size()>0){
|
|
|
- productionProcesses.getConflictRoptions().forEach((k,v)->{
|
|
|
- if(StrUtil.isBlank(productionProcesses.getHasConflict())){
|
|
|
- productionProcesses.setHasConflict("y");
|
|
|
+ // 调度退火排程
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ apsSolutionTh.setProcessesList(tuihuos);
|
|
|
+ apsSolutionTh.setEquipmentList(apsSolution.getEquipmentList());
|
|
|
+
|
|
|
+ // 退火工序求解器运行
|
|
|
+ int processNum1 = apsSolutionTh.getProcessesList().size();
|
|
|
+ int runPlanSeconds1 = (processNum1)*30;
|
|
|
+ // CPU核数
|
|
|
+ String cores = Runtime.getRuntime().availableProcessors() + "";
|
|
|
+ SolverFactory<ApsSolution> solverFactory1 = 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> solver1 = solverFactory1.buildSolver();
|
|
|
+ // 退火调度排序
|
|
|
+ List<ProductionProcesses> hapres = new ArrayList<>();
|
|
|
+ List<ProductionProcesses> nothapres = new ArrayList<>();
|
|
|
+ for (ProductionProcesses v : apsSolutionTh.getProcessesList()) {
|
|
|
+ if(v.getPreviousProcesses() != null && v.getPreviousProcesses().size() > 0 && v.getPreviousProcesses().get(0).getEndTime() != null){
|
|
|
+ hapres.add(v);
|
|
|
+ }else {
|
|
|
+ nothapres.add(v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Collections.sort(hapres,(v1,v2)->{
|
|
|
+ int a = 0;
|
|
|
+ if(v1.getPreviousProcesses().get(0).getStartTime().compareTo(v2.getPreviousProcesses().get(0).getStartTime()) == 0){
|
|
|
+ a = v2.getVolumeWidth().compareTo(v1.getVolumeWidth());
|
|
|
+ }else{
|
|
|
+ a = v2.getPreviousProcesses().get(0).getStartTime().compareTo(v1.getPreviousProcesses().get(0).getStartTime());
|
|
|
+ }
|
|
|
+ return a;
|
|
|
+ });
|
|
|
+
|
|
|
+ if(nothapres != null && nothapres.size()>0){
|
|
|
+ hapres.addAll(nothapres);
|
|
|
+ }
|
|
|
+ apsSolutionTh.setProcessesList(hapres);
|
|
|
+
|
|
|
+ ApsSolution solvedBalance = solver1.solve(apsSolutionTh);
|
|
|
+
|
|
|
+ log.info("**************退火排程评分分析***************");
|
|
|
+ SolutionManager<ApsSolution, HardSoftScore> scoreManager1 = SolutionManager.create(solverFactory1);
|
|
|
+ ScoreExplanation<ApsSolution, HardSoftScore> explain1 = scoreManager1.explain(solvedBalance);
|
|
|
+ log.info(explain1.toString());
|
|
|
+ log.info("**************退火排程评分分析***************");
|
|
|
+
|
|
|
+ solvedBalance.getProcessesList().addAll(hasLocks);
|
|
|
+ // 退火合并工序排程完拆分
|
|
|
+ if(otherThproces != null && otherThproces.size()>0){
|
|
|
+ List<ProductionProcesses> otherThproce1 = new ArrayList<>();
|
|
|
+ for (ProductionProcesses otherThproce : otherThproces) {
|
|
|
+ if(StrUtil.isNotBlank(otherThproce.getMergeThMainId())){
|
|
|
+ ProductionProcesses thpro = null;
|
|
|
+ for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
|
|
|
+ if(productionProcesses.getId().equals(otherThproce.getMergeThMainId())){
|
|
|
+ thpro = productionProcesses;
|
|
|
+ break;
|
|
|
}
|
|
|
- // 强制约束
|
|
|
- if(k.indexOf("hard") == 0){
|
|
|
- if(StrUtil.isBlank(productionProcesses.getConflictDes())){
|
|
|
- productionProcesses.setConflictDes(v);
|
|
|
- }else{
|
|
|
- productionProcesses.setConflictDes(productionProcesses.getConflictDes()+";"+v);
|
|
|
+ }
|
|
|
+ if(thpro != null){
|
|
|
+ otherThproce.setStartTime(thpro.getStartTime());
|
|
|
+ otherThproce.setEndTime(thpro.getEndTime());
|
|
|
+ otherThproce.setEquipmentId(thpro.getEquipmentId());
|
|
|
+ otherThproce.setEquipment(thpro.getEquipment());
|
|
|
+ otherThproce.setConflictRoptions(thpro.getConflictRoptions());
|
|
|
+
|
|
|
+ thpro.setOpeProducePcNum(1);
|
|
|
+ if(thpro.getProcessType().equals("小卷成退")){
|
|
|
+ thpro.setMinThPcNum(thpro.getMinThPcNum()-otherThproce.getMinThPcNum());
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ otherThproce1.add(otherThproce);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(otherThproce1 != null && otherThproce1.size()>0){
|
|
|
+ for (ProductionProcesses otherThproce : otherThproce1) {
|
|
|
+ if(StrUtil.isNotBlank(otherThproce.getMergeThMainId())){
|
|
|
+ ProductionProcesses thpro = null;
|
|
|
+ for (ProductionProcesses productionProcesses : otherThproces) {
|
|
|
+ if(productionProcesses.getId().equals(otherThproce.getMergeThMainId())){
|
|
|
+ thpro = productionProcesses;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
- // 非强制约束
|
|
|
- else if (k.indexOf("soft") == 0) {
|
|
|
- if(StrUtil.isBlank(productionProcesses.getSoftconflictdes())){
|
|
|
- productionProcesses.setSoftconflictdes(v);
|
|
|
- }else{
|
|
|
- productionProcesses.setSoftconflictdes(productionProcesses.getSoftconflictdes()+";"+v);
|
|
|
+ if(thpro != null){
|
|
|
+ otherThproce.setStartTime(thpro.getStartTime());
|
|
|
+ otherThproce.setEndTime(thpro.getEndTime());
|
|
|
+ otherThproce.setEquipmentId(thpro.getEquipmentId());
|
|
|
+ otherThproce.setEquipment(thpro.getEquipment());
|
|
|
+ otherThproce.setConflictRoptions(thpro.getConflictRoptions());
|
|
|
+
|
|
|
+ thpro.setOpeProducePcNum(1);
|
|
|
+ if(thpro.getProcessType().equals("小卷成退")){
|
|
|
+ thpro.setMinThPcNum(thpro.getMinThPcNum()-otherThproce.getMinThPcNum());
|
|
|
}
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
|
|
|
+ productionProcesses.setPreviousProcesses(null);
|
|
|
+ productionProcesses.setRooprocess(null);
|
|
|
+ productionProcesses.setNextProcesses(null);
|
|
|
+ productionProcesses.getEquipment().setProcessesList(null);
|
|
|
+ productionProcesses.getEquipment().setEquipmentRunTimes(null);
|
|
|
+ productionProcesses.setPreviousStep(null);
|
|
|
+ productionProcesses.setOptionalProviderEquipments(null);
|
|
|
+ productionProcesses.setEquass(null);
|
|
|
+ productionProcesses.setMergeRooprocess(null);
|
|
|
+ productionProcesses.setOpeProducePcNum(1);
|
|
|
+ if(productionProcesses.getApsOverallConfig() != null){
|
|
|
+ productionProcesses.getApsOverallConfig().setFurnaceInstallations(null);
|
|
|
+ productionProcesses.getApsOverallConfig().setMergeFurnaces(null);
|
|
|
+ }
|
|
|
+ if(productionProcesses.getOldNextProcessesIds() != null){
|
|
|
+ productionProcesses.setNextProcessesIds(productionProcesses.getOldNextProcessesIds());
|
|
|
+ }
|
|
|
+ if(productionProcesses.getOldPreviousProcessesIds() != null){
|
|
|
+ productionProcesses.setPreviousProcessesIds(productionProcesses.getOldPreviousProcessesIds());
|
|
|
+ }
|
|
|
+ // 冲突约束补充处理
|
|
|
+ if(productionProcesses.getConflictRoptions() != null && productionProcesses.getConflictRoptions().size()>0){
|
|
|
+ productionProcesses.getConflictRoptions().forEach((k,v)->{
|
|
|
+ if(StrUtil.isBlank(productionProcesses.getHasConflict())){
|
|
|
+ productionProcesses.setHasConflict("y");
|
|
|
+ }
|
|
|
+ // 强制约束
|
|
|
+ if(k.indexOf("hard") == 0){
|
|
|
+ if(StrUtil.isBlank(productionProcesses.getConflictDes())){
|
|
|
+ productionProcesses.setConflictDes(v);
|
|
|
+ }else{
|
|
|
+ productionProcesses.setConflictDes(productionProcesses.getConflictDes()+";"+v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 非强制约束
|
|
|
+ else if (k.indexOf("soft") == 0) {
|
|
|
+ if(StrUtil.isBlank(productionProcesses.getSoftconflictdes())){
|
|
|
+ productionProcesses.setSoftconflictdes(v);
|
|
|
+ }else{
|
|
|
+ productionProcesses.setSoftconflictdes(productionProcesses.getSoftconflictdes()+";"+v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ productionScheduleRetVo.setProcesses(solvedBalance.getProcessesList());
|
|
|
+
|
|
|
return productionScheduleRetVo;
|
|
|
}
|
|
|
}
|