Commit 41cab0d7 authored by Tong Li's avatar Tong Li

优化

parent 7c25b0fe
...@@ -10,6 +10,32 @@ public class FileHelper { ...@@ -10,6 +10,32 @@ public class FileHelper {
private static final String LOG_FILE = "schedule_log.txt"; private static final String LOG_FILE = "schedule_log.txt";
private static final String LOG_FILE_PATH = "log/"; private static final String LOG_FILE_PATH = "log/";
// 日志级别
private static final int LOG_LEVEL_DEBUG = 0;
private static final int LOG_LEVEL_INFO = 1;
private static final int LOG_LEVEL_WARN = 2;
private static int currentLogLevel = LOG_LEVEL_INFO;
// 局部搜索优化
public static void log(String message) {
log(message, LOG_LEVEL_INFO, true);
}
public static void log(String message, boolean enableLogging) {
log(message, LOG_LEVEL_INFO, enableLogging);
}
public static void log(String message, int level) {
log(message, level, false);
}
public static void log(String message, int level, boolean enableLogging) {
if (enableLogging && level >= currentLogLevel) {
writeLogFile(message);
}
}
public static void writeLogFile(String message) { public static void writeLogFile(String message) {
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))+"-"; String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))+"-";
......
...@@ -142,6 +142,12 @@ public class Chromosome { ...@@ -142,6 +142,12 @@ public class Chromosome {
private double[] Objectives = new double[0]; // 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay] private double[] Objectives = new double[0]; // 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay]
private double[] MaxObjectives = new double[0]; // private double[] MaxObjectives = new double[0]; //
private double[] MinObjectives = new double[0]; // private double[] MinObjectives = new double[0]; //
private double[] weights = new double[0];
/**
* 各目标维度的理论下界(用于计算 Gap = (current - lowerBound) / lowerBound)。
* 由 KpiLowerBoundCalculator 在 decode 后计算并填入。
*/
private double[] LowerBoundObjectives = new double[0];
private int Rank; // 非支配排序等级(1最优) private int Rank; // 非支配排序等级(1最优)
private double CrowdingDistance =0; // 拥挤距离 越小越优 private double CrowdingDistance =0; // 拥挤距离 越小越优
/* /*
...@@ -255,7 +261,7 @@ public class Chromosome { ...@@ -255,7 +261,7 @@ public class Chromosome {
* *
* @return 不在 allOperations 中的 GAScheduleResult 列表;若均存在则返回空列表 * @return 不在 allOperations 中的 GAScheduleResult 列表;若均存在则返回空列表
*/ */
public List<GAScheduleResult> getResultsNotInAllOperations() { public List<GAScheduleResult> checkResultsNotInAllOperations1() {
if (Result == null || Result.isEmpty()) { if (Result == null || Result.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
...@@ -281,8 +287,52 @@ public class Chromosome { ...@@ -281,8 +287,52 @@ public class Chromosome {
* *
* @return 存在则返回 true,否则返回 false * @return 存在则返回 true,否则返回 false
*/ */
public boolean hasResultNotInAllOperations() { // public boolean hasResultNotInAllOperations1() {
return !getResultsNotInAllOperations().isEmpty(); // / return !getResultsNotInAllOperations1().isEmpty();
// }
/**
* LNS 需要:创建染色体的深拷贝(machineSelection 和 operationSequencing 独立副本)
* 大对象(globalOpList / allOperations / orders / materials)共享引用
*/
public Chromosome deepCopy() {
Chromosome copy = new Chromosome();
if (machineSelection != null) {
copy.machineSelection = new CopyOnWriteArrayList<>(machineSelection);
copy.machineStrDirty = true;
}
if (operationSequencing != null) {
copy.operationSequencing = new CopyOnWriteArrayList<>(operationSequencing);
copy.operationStrDirty = true;
}
copy.geneStrDirty = true;
if (Objectives != null) copy.Objectives = Arrays.copyOf(Objectives, Objectives.length);
if (WeightedObjectives != null) copy.WeightedObjectives = Arrays.copyOf(WeightedObjectives, WeightedObjectives.length);
if (fitnessLevel != null) copy.fitnessLevel = Arrays.copyOf(fitnessLevel, fitnessLevel.length);
if (LowerBoundObjectives != null) copy.LowerBoundObjectives = Arrays.copyOf(LowerBoundObjectives, LowerBoundObjectives.length);
copy.WeightedObjective = WeightedObjective;
copy.Makespan = Makespan;
copy.TotalFlowTime = TotalFlowTime;
copy.TotalChangeoverTime = TotalChangeoverTime;
copy.MachineLoadStd = MachineLoadStd;
copy.Fitness = Fitness;
copy.Rank = Rank;
copy.CrowdingDistance = CrowdingDistance;
copy.gsOrls = gsOrls;
copy.generateType = generateType + "_copy";
copy.globalParamSnapshot = globalParamSnapshot;
copy.objectiveWeights = objectiveWeights;
copy.globalOpList = globalOpList;
copy.allOperations = allOperations;
copy.orders = orders;
copy.InitMachines = InitMachines;
copy.materials = materials;
copy.materialIds = materialIds;
copy.OperatRel = OperatRel;
copy.orderMaterials = orderMaterials;
copy.Machines = Machines;
if (Result != null) copy.Result = new CopyOnWriteArrayList<>(Result);
return copy;
} }
} }
...@@ -85,6 +85,9 @@ public class Entry { ...@@ -85,6 +85,9 @@ public class Entry {
* 工序顺序 * 工序顺序
*/ */
private int sequence; private int sequence;
private double minProcessingTime; // 加工时间 (秒)
/** /**
* 可选设备列表 * 可选设备列表
*/ */
......
package com.aps.service.Algorithm; package com.aps.service.Algorithm;
import com.aps.common.util.FileHelper;
import com.aps.entity.Algorithm.Chromosome; import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GlobalOperationInfo; import com.aps.entity.Algorithm.GlobalOperationInfo;
import com.aps.entity.basic.Entry; import com.aps.entity.basic.Entry;
import com.aps.entity.basic.Machine; import com.aps.entity.basic.Machine;
import com.aps.entity.basic.MachineOption; import com.aps.entity.basic.MachineOption;
import com.aps.entity.basic.Order;
import com.google.ortools.Loader; import com.google.ortools.Loader;
import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpModel;
import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolver;
...@@ -16,6 +18,7 @@ import com.google.ortools.sat.LinearExpr; ...@@ -16,6 +18,7 @@ import com.google.ortools.sat.LinearExpr;
import com.google.ortools.sat.Literal; import com.google.ortools.sat.Literal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
...@@ -48,6 +51,9 @@ public class CpSatFjspModel { ...@@ -48,6 +51,9 @@ public class CpSatFjspModel {
private final List<Machine> machines; private final List<Machine> machines;
private final List<GlobalOperationInfo> globalOpList; private final List<GlobalOperationInfo> globalOpList;
private final List<Entry> allOperations; private final List<Entry> allOperations;
private final LocalDateTime baseTime;
private final List<Order> orders;
private final int operationCount; private final int operationCount;
private CpModel model; private CpModel model;
...@@ -61,11 +67,14 @@ public class CpSatFjspModel { ...@@ -61,11 +67,14 @@ public class CpSatFjspModel {
public CpSatFjspModel(List<GlobalOperationInfo> globalOpList, public CpSatFjspModel(List<GlobalOperationInfo> globalOpList,
List<Entry> allOperations, List<Entry> allOperations,
List<Machine> machines, List<Machine> machines,
List<Order> orders,
LocalDateTime baseTime) { LocalDateTime baseTime) {
this.globalOpList = globalOpList; this.globalOpList = globalOpList;
this.allOperations = allOperations; this.allOperations = allOperations;
this.machines = machines; this.machines = machines;
this.operationCount = globalOpList.size(); this.operationCount = globalOpList.size();
this.orders=orders;
this.baseTime=baseTime;
} }
private int estimateHorizon() { private int estimateHorizon() {
...@@ -221,28 +230,90 @@ public class CpSatFjspModel { ...@@ -221,28 +230,90 @@ public class CpSatFjspModel {
globalOpList.get(i).getOp().getPriority()); globalOpList.get(i).getOp().getPriority());
} }
int priorityTerms = 0; List<LinearArgument> objTerms = new ArrayList<>();
for (int i = 0; i < operationCount; i++) { List<Long> objWeights = new ArrayList<>();
if (globalOpList.get(i).getOp().getPriority() > 0) priorityTerms++;
}
LinearArgument[] objVars = new LinearArgument[1 + priorityTerms]; objTerms.add(makespanVar);
long[] objCoeffs = new long[1 + priorityTerms]; objWeights.add(100L);
objVars[0] = makespanVar;
objCoeffs[0] = 100;
int t = 1;
for (int i = 0; i < operationCount; i++) { for (int i = 0; i < operationCount; i++) {
double priority = globalOpList.get(i).getOp().getPriority(); double priority = globalOpList.get(i).getOp().getPriority();
if (priority > 0) { if (priority > 0) {
objVars[t] = endVars.get(i); objTerms.add(endVars.get(i));
objCoeffs[t] = (long)(maxPriority - priority + 1); objWeights.add((long)(maxPriority - priority + 1));
t++;
} }
} }
model.minimize(LinearExpr.weightedSum(objVars, objCoeffs));
// ==================== 新增目标1:Tardiness(延迟时间) ====================
// 按订单分组,找到每个订单最后一道工序的end_time
Map<Integer, List<Integer>> groupOps = new LinkedHashMap<>();
Map<Integer, Long> groupDueDates = new HashMap<>();
for (int i = 0; i < operationCount; i++) {
GlobalOperationInfo info = globalOpList.get(i);
int groupId = info.getGroupId();
groupOps.computeIfAbsent(groupId, k -> new ArrayList<>()).add(i);
if (!groupDueDates.containsKey(groupId)) {
Order order = orders.stream()
.filter(o -> info.getOp().getOrderId().equals(o.getOrderId()))
.findFirst().orElse(null);
if (order != null && order.getDueDate() != null) {
long dueMin = ChronoUnit.MINUTES.between(baseTime, order.getDueDate());
groupDueDates.put(groupId, dueMin * 60);
} }
}
}
long totalTardinessWeight = 80L;
for (Map.Entry<Integer, List<Integer>> entry : groupOps.entrySet()) {
int groupId = entry.getKey();
List<Integer> opIndices = entry.getValue();
// 找到该订单最后完成的工序
IntVar lastEnd = model.newIntVar(0, horizonSeconds, "lastEnd_g" + groupId);
List<LinearArgument> endCandidates = new ArrayList<>();
for (int idx : opIndices) {
endCandidates.add(endVars.get(idx));
}
model.addMaxEquality(lastEnd, endCandidates.toArray(new LinearArgument[0]));
Long dueDateSec = groupDueDates.get(groupId);
if (dueDateSec != null) {
IntVar tardiness = model.newIntVar(0, horizonSeconds, "tardiness_g" + groupId);
LinearArgument diff = LinearExpr.sum(new LinearArgument[]{
lastEnd, LinearExpr.constant(-dueDateSec)});
model.addMaxEquality(tardiness, new LinearArgument[]{diff, LinearExpr.constant(0)});
objTerms.add(tardiness);
objWeights.add(totalTardinessWeight);
}
}
// ==================== 新增目标2:Machine Load Balance(负载均衡) ====================
// 简化版本:取每台机器上所有工序的最大end_time,加入目标函数
// 这样 CP-SAT 会倾向于让各机器的完工时间更均匀
Map<Long, List<LinearArgument>> machineEndTimes = new HashMap<>();
for (int i = 0; i < operationCount; i++) {
GlobalOperationInfo info = globalOpList.get(i);
List<MachineOption> options = info.getOp().getMachineOptions();
if (options == null || options.isEmpty()) continue;
for (MachineOption mo : options) {
machineEndTimes.computeIfAbsent(mo.getMachineId(), k -> new ArrayList<>()).add(endVars.get(i));
}
}
long loadBalanceWeight = 30L;
for (Map.Entry<Long, List<LinearArgument>> entry : machineEndTimes.entrySet()) {
IntVar machineMakespan = model.newIntVar(0, horizonSeconds, "mk_m" + entry.getKey());
model.addMaxEquality(machineMakespan, entry.getValue().toArray(new LinearArgument[0]));
objTerms.add(machineMakespan);
objWeights.add(loadBalanceWeight);
}
model.minimize(LinearExpr.weightedSum(
objTerms.toArray(new LinearArgument[0]),
objWeights.stream().mapToLong(Long::longValue).toArray()));
}
private boolean enableLogging=true;
/** /**
* 单次求解,返回一个 Chromosome * 单次求解,返回一个 Chromosome
*/ */
...@@ -258,8 +329,13 @@ public class CpSatFjspModel { ...@@ -258,8 +329,13 @@ public class CpSatFjspModel {
CpSolverStatus status = solver.solve(model); CpSolverStatus status = solver.solve(model);
if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) { if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) {
long makespanSec = (long) solver.value(makespanVar);
FileHelper.log("[CpSatFjsp] 单次求解 状态=" + status
+ " CP-SAT目标值=" + String.format("%,d", (long) solver.objectiveValue())
+ " makespan=" + String.format("%,d秒 (%.1f小时)", makespanSec, makespanSec / 3600.0),enableLogging);
return extractChromosome(solver); return extractChromosome(solver);
} }
FileHelper.log("[CpSatFjsp] 单次求解 状态=" + status + "(无解)",enableLogging);
return null; return null;
} }
...@@ -328,15 +404,22 @@ public class CpSatFjspModel { ...@@ -328,15 +404,22 @@ public class CpSatFjspModel {
CpSolverStatus status = solver.solve(model); CpSolverStatus status = solver.solve(model);
if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) { if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) {
long msSec = (long) solver.value(makespanVar);
FileHelper.log("[CpSatFjsp] 第" + (round + 1) + "轮 状态=" + status
+ " CP-SAT目标=" + String.format("%,d", (long) solver.objectiveValue())
+ " makespan=" + String.format("%,d秒(%.1f小时)", msSec, msSec / 3600.0),enableLogging);
Chromosome chromo = extractChromosome(solver); Chromosome chromo = extractChromosome(solver);
if (chromo != null && !containsDuplicate(results, chromo)) { if (chromo != null && !containsDuplicate(results, chromo)) {
chromo.setGsOrls(4); chromo.setGsOrls(4);
chromo.setGenerateType("CP-SAT"); chromo.setGenerateType("CP-SAT");
results.add(chromo); results.add(chromo);
} }
} else {
FileHelper.log("[CpSatFjsp] 第" + (round + 1) + "轮 状态=" + status + "(无解)",enableLogging);
} }
} }
FileHelper.log("[CpSatFjsp] 多样性解生成完成,共" + results.size() + "个解",enableLogging);
return results; return results;
} }
......
...@@ -93,7 +93,7 @@ public class CpSatInitializer { ...@@ -93,7 +93,7 @@ public class CpSatInitializer {
*/ */
private List<Chromosome> smallScaleSolve(List<GlobalOperationInfo> globalOpList, private List<Chromosome> smallScaleSolve(List<GlobalOperationInfo> globalOpList,
int targetCount, int timeBudgetSec) { int targetCount, int timeBudgetSec) {
CpSatFjspModel model = new CpSatFjspModel(globalOpList, allOperations, machines, baseTime); CpSatFjspModel model = new CpSatFjspModel(globalOpList, allOperations, machines,orders, baseTime);
return model.generateDiverseSolutions( return model.generateDiverseSolutions(
Math.min(targetCount, 8), timeBudgetSec, true); Math.min(targetCount, 8), timeBudgetSec, true);
} }
...@@ -103,7 +103,7 @@ public class CpSatInitializer { ...@@ -103,7 +103,7 @@ public class CpSatInitializer {
*/ */
private List<Chromosome> mediumScaleSolve(List<GlobalOperationInfo> globalOpList, private List<Chromosome> mediumScaleSolve(List<GlobalOperationInfo> globalOpList,
int targetCount, int timeBudgetSec) { int targetCount, int timeBudgetSec) {
CpSatFjspModel model = new CpSatFjspModel(globalOpList, allOperations, machines, baseTime); CpSatFjspModel model = new CpSatFjspModel(globalOpList, allOperations, machines,orders, baseTime);
int effectiveTarget = Math.min(targetCount, 5); int effectiveTarget = Math.min(targetCount, 5);
int perSolveTime = Math.max(timeBudgetSec, 15); int perSolveTime = Math.max(timeBudgetSec, 15);
return model.generateDiverseSolutions(effectiveTarget, perSolveTime, true); return model.generateDiverseSolutions(effectiveTarget, perSolveTime, true);
...@@ -158,7 +158,7 @@ public class CpSatInitializer { ...@@ -158,7 +158,7 @@ public class CpSatInitializer {
} }
CpSatFjspModel model = new CpSatFjspModel( CpSatFjspModel model = new CpSatFjspModel(
bottleneckOps, allOperations, bottleneckMachines, baseTime); bottleneckOps, allOperations, bottleneckMachines,orders, baseTime);
List<Chromosome> cpSatResults = model.generateDiverseSolutions( List<Chromosome> cpSatResults = model.generateDiverseSolutions(
effectiveTarget, timeBudgetSec, true); effectiveTarget, timeBudgetSec, true);
......
...@@ -695,11 +695,6 @@ public class GeneticDecoder { ...@@ -695,11 +695,6 @@ public class GeneticDecoder {
int scheduledCount = orderProcessCounter.get(groupId); int scheduledCount = orderProcessCounter.get(groupId);
if(groupId==7)
{
int k=0;
}
List<Entry> orderOps=new ArrayList<>(); List<Entry> orderOps=new ArrayList<>();
boolean orderIsJit=orderDueDate.get(groupId)>0; boolean orderIsJit=orderDueDate.get(groupId)>0;
...@@ -743,7 +738,7 @@ public class GeneticDecoder { ...@@ -743,7 +738,7 @@ public class GeneticDecoder {
} else { } else {
orderAnchor = bom.computeSemiFinishedAnchor(this, groupId, entrysBygroupId, orderAnchor = bom.computeSemiFinishedAnchor(this, groupId, entrysBygroupId,
opMachineKeyMap, chromosome, opMachineKeyMap, chromosome,
scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,_globalParam.isIsCheckMp()); scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,_globalParam.isIsCheckMp(),null);
if (orderAnchor < 0) { if (orderAnchor < 0) {
orderIsJit = false; orderIsJit = false;
orderSchedulingInfo.put(groupId, orderSchedulingInfo.put(groupId,
...@@ -3524,6 +3519,7 @@ if(geneDetails!=null&&geneDetails.size()>0) ...@@ -3524,6 +3519,7 @@ if(geneDetails!=null&&geneDetails.size()>0)
private void calculateScheduleResult(Chromosome chromosome) { private void calculateScheduleResult(Chromosome chromosome) {
double[] Objectives = new double[_globalParam.getObjectiveWeights().size()]; double[] Objectives = new double[_globalParam.getObjectiveWeights().size()];
double[] weights = new double[_globalParam.getObjectiveWeights().size()];
int i = 0; int i = 0;
for (ObjectiveConfig config : _globalParam.getObjectiveConfigs()) { for (ObjectiveConfig config : _globalParam.getObjectiveConfigs()) {
...@@ -3535,7 +3531,9 @@ if(geneDetails!=null&&geneDetails.size()>0) ...@@ -3535,7 +3531,9 @@ if(geneDetails!=null&&geneDetails.size()>0)
.max() .max()
.orElse(0); .orElse(0);
Objectives[i] = makespan; Objectives[i] = makespan;
weights[i] = config.getWeight();
chromosome.setMakespan(makespan); chromosome.setMakespan(makespan);
} }
if (GlobalParam.OBJECTIVE_TARDINESS.equals(config.getName())) { if (GlobalParam.OBJECTIVE_TARDINESS.equals(config.getName())) {
// 2. 交付期满足情况(最小化延迟) // 2. 交付期满足情况(最小化延迟)
...@@ -3604,6 +3602,16 @@ if(geneDetails!=null&&geneDetails.size()>0) ...@@ -3604,6 +3602,16 @@ if(geneDetails!=null&&geneDetails.size()>0)
} }
chromosome.setObjectives(Objectives); chromosome.setObjectives(Objectives);
// 计算各 KPI 的理论下界(用于计算 Gap = (current - lowerBound) / lowerBound)
try {
KpiLowerBoundCalculator.computeAndSetLowerBounds(chromosome, _globalParam);
} catch (Exception e) {
// 下界计算异常不应影响主流程
com.aps.common.util.FileHelper.writeLogFile(
"KPI 下界计算异常: " + e.getClass().getSimpleName() + " - " + e.getMessage());
}
FitnessCalculator fitnessCalculator = new FitnessCalculator(); FitnessCalculator fitnessCalculator = new FitnessCalculator();
chromosome.setFitnessLevel(fitnessCalculator.calculateFitness(chromosome, _globalParam)); chromosome.setFitnessLevel(fitnessCalculator.calculateFitness(chromosome, _globalParam));
......
...@@ -76,7 +76,7 @@ public class HillClimbing { ...@@ -76,7 +76,7 @@ public class HillClimbing {
Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class); Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
decoder.DelOrder(current);
// 构建位置索引映射:groupId_sequence -> position // 构建位置索引映射:groupId_sequence -> position
Map<String, Integer> positionIndex = buildPositionIndex(current); Map<String, Integer> positionIndex = buildPositionIndex(current);
...@@ -119,7 +119,7 @@ public class HillClimbing { ...@@ -119,7 +119,7 @@ public class HillClimbing {
positionIndex = buildPositionIndex(current); positionIndex = buildPositionIndex(current);
entryIndex = buildEntryIndex(current, entrys); entryIndex = buildEntryIndex(current, entrys);
MachinePositionIndex = buildEntryMachinePositionIndex(current); MachinePositionIndex = buildEntryMachinePositionIndex(current);
decoder.DelOrder(current); // decoder.DelOrder(current);
break; break;
} }
} }
......
...@@ -49,6 +49,8 @@ public class HybridAlgorithm { ...@@ -49,6 +49,8 @@ public class HybridAlgorithm {
private String sceneId; private String sceneId;
private VariableNeighborhoodSearch _vns; private VariableNeighborhoodSearch _vns;
private AdaptiveLargeNeighborhoodSearch _ALNS;
// 初始化算法实例 // 初始化算法实例
private HillClimbing _hillClimbing; private HillClimbing _hillClimbing;
private SimulatedAnnealing _simulatedAnnealing; private SimulatedAnnealing _simulatedAnnealing;
...@@ -116,6 +118,7 @@ public class HybridAlgorithm { ...@@ -116,6 +118,7 @@ public class HybridAlgorithm {
// 初始化变邻域搜索 // 初始化变邻域搜索
_vns = new VariableNeighborhoodSearch( allOperations,orders,materials,_entryRel, _fitnessCalculator ); _vns = new VariableNeighborhoodSearch( allOperations,orders,materials,_entryRel, _fitnessCalculator );
_vns.initMachineSelectFrequency(); _vns.initMachineSelectFrequency();
_ALNS = new AdaptiveLargeNeighborhoodSearch( allOperations,orders,materials,_entryRel, _fitnessCalculator );
_hillClimbing = new HillClimbing(allOperations,orders,materials,_entryRel, _fitnessCalculator); _hillClimbing = new HillClimbing(allOperations,orders,materials,_entryRel, _fitnessCalculator);
_simulatedAnnealing = new SimulatedAnnealing( allOperations,orders,materials,_entryRel, _fitnessCalculator); _simulatedAnnealing = new SimulatedAnnealing( allOperations,orders,materials,_entryRel, _fitnessCalculator);
_tabuSearch = new TabuSearch(allOperations,orders,materials,_entryRel, _fitnessCalculator); _tabuSearch = new TabuSearch(allOperations,orders,materials,_entryRel, _fitnessCalculator);
...@@ -148,6 +151,26 @@ public class HybridAlgorithm { ...@@ -148,6 +151,26 @@ public class HybridAlgorithm {
if (population == null || population.isEmpty()) { if (population == null || population.isEmpty()) {
throw new RuntimeException("初始种群为空,请检查 populationSize、种群初始化和解码结果"); throw new RuntimeException("初始种群为空,请检查 populationSize、种群初始化和解码结果");
} }
if (_GlobalParam.isOptimizer()) {
FileHelper.writeLogFile("LNS-CPSAT 邻域重优化-----------开始-------种群=" + population.size());
try {
CpSatLnsNeighborhood lns = new CpSatLnsNeighborhood(
allOperations, machines,orders,materials,_entryRel,_fitnessCalculator);
List<Chromosome> lnsResult = lns.runLnsOnParetoFront(population, sharedDecoder);
if (lnsResult != null && !lnsResult.isEmpty()) {
// Chromosomedecode(sharedDecoder, param, allOperations, globalOpList, lnsResult);
population = chromosomeDistinctByObjectives(lnsResult);
if (population == null || population.isEmpty()) {
population = lnsResult;
}
}
} catch (Throwable t) {
FileHelper.writeLogFile("LNS-CPSAT 失败,跳过:" + t.getMessage());
}
FileHelper.writeLogFile("LNS-CPSAT 邻域重优化-----------结束-------种群="
+ (population == null ? 0 : population.size()));
}
// if(1==1) // if(1==1)
// return getBestChromosome(population.get(0), param.getBaseTime(), starttime); // return getBestChromosome(population.get(0), param.getBaseTime(), starttime);
// 步骤2:对初始种群进行爬山法局部优化 // 步骤2:对初始种群进行爬山法局部优化
...@@ -178,9 +201,9 @@ public class HybridAlgorithm { ...@@ -178,9 +201,9 @@ public class HybridAlgorithm {
return getBestChromosome(saHcOptimized, param.getBaseTime(), starttime); return getBestChromosome(saHcOptimized, param.getBaseTime(), starttime);
} }
if(opcount>=800 ) { if(opcount>800&&opcount<2000 ) {
Chromosome best=population.get(0); Chromosome best=population.get(0);
best = _ALNS.search(best,_tabuSearch,_vns, sharedDecoder, machines);
best = _simulatedAnnealing.search(best, _tabuSearch, _vns, sharedDecoder, machines); best = _simulatedAnnealing.search(best, _tabuSearch, _vns, sharedDecoder, machines);
best = _vns.search(best,_tabuSearch, sharedDecoder, machines); best = _vns.search(best,_tabuSearch, sharedDecoder, machines);
...@@ -189,6 +212,29 @@ public class HybridAlgorithm { ...@@ -189,6 +212,29 @@ public class HybridAlgorithm {
return getBestChromosome(best, param.getBaseTime(), starttime); return getBestChromosome(best, param.getBaseTime(), starttime);
}else {
Chromosome best=population.get(0);
int topN = Math.min(3, population.size());
for (int iter = 0; iter < topN; iter++) {
FileHelper.writeLogFile("迭代进化------"+iter+"-----开始-------");
System.gc();
Chromosome chromosome=population.get(iter);
chromosome = _ALNS.search(chromosome,_tabuSearch,_vns, sharedDecoder, machines);
chromosome = _simulatedAnnealing.search(chromosome, _tabuSearch, _vns, sharedDecoder, machines);
chromosome = _vns.search(chromosome,_tabuSearch, sharedDecoder, machines);
if(_fitnessCalculator.isBetter(chromosome,best)) {
FileHelper.writeLogFile("迭代进化------发现更优解-----------");
writeKpi(chromosome);
best= chromosome;
}
FileHelper.writeLogFile("迭代进化------"+iter+"-----结束-------");
// 周期性 GC 释放内存
System.gc();
}
} }
...@@ -514,7 +560,47 @@ public class HybridAlgorithm { ...@@ -514,7 +560,47 @@ public class HybridAlgorithm {
// } // }
} }
private void writeKpi(Chromosome chromosome) {
String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel();
if (fitness1 != null) {
for (int i = 0; i < fitness1.length; i++) {
fitness += fitness1[i] + ",";
}
} else {
fitness = "null (未计算)";
}
log(String.format("变邻域搜索 - kpi:%s", fitness),true);
if(chromosome.getMakespan()!=0) {
log(String.format("变邻域搜索 - kpi-Makespan: %f", chromosome.getMakespan()));
}
if(chromosome.getDelayTime()!=0) {
log(String.format("变邻域搜索 - kpi-DelayTime: %f", chromosome.getDelayTime()));
}
if(chromosome.getTotalChangeoverTime()!=0) {
log(String.format("变邻域搜索 - kpi-ChangeoverTime: %f", chromosome.getTotalChangeoverTime()));
}
if(chromosome.getMachineLoadStd()!=0) {
log(String.format("变邻域搜索 - kpi-MachineLoad: %f", chromosome.getMachineLoadStd()));
}
if(chromosome.getTotalFlowTime()!=0) {
log(String.format("变邻域搜索 - kpi-FlowTime: %f",chromosome.getTotalFlowTime()));
}
// ==================== 打印各 KPI 的 Gap ====================
log(KpiLowerBoundCalculator.generateGapReport(chromosome));
}
private void log(String message) {
log( message, true);
}
private void log(String message, boolean enableLogging) {
if (enableLogging ) {
FileHelper.writeLogFile(message);
}
}
} }
...@@ -1137,9 +1137,15 @@ public class Initialization { ...@@ -1137,9 +1137,15 @@ public class Initialization {
List<Chromosome> heuristicPopulation = List<Chromosome> heuristicPopulation =
generateHeuristicInitialPopulation(subParam,remaining); generateHeuristicInitialPopulation(subParam,remaining);
for (Chromosome chromo : heuristicPopulation) { for (Chromosome chromo : heuristicPopulation) {
if(chromo!=null)
{
chromo.setOrders(new CopyOnWriteArrayList<>(orders)); chromo.setOrders(new CopyOnWriteArrayList<>(orders));
population.add(chromo);
}
} }
population.addAll(heuristicPopulation);
} }
long cpSatCount = population.stream() long cpSatCount = population.stream()
......
...@@ -265,6 +265,7 @@ public class RoutingDataService { ...@@ -265,6 +265,7 @@ public class RoutingDataService {
List<ProdEquipment> Equipments = ProdEquipments.stream() List<ProdEquipment> Equipments = ProdEquipments.stream()
.filter(t -> t.getExecId().equals(op.getExecId())) .filter(t -> t.getExecId().equals(op.getExecId()))
.collect(Collectors.toList()); .collect(Collectors.toList());
double minProcessingTime=999999999;
if (Equipments != null && Equipments.size() > 0) { if (Equipments != null && Equipments.size() > 0) {
List<MachineOption> mos = new ArrayList<>(); List<MachineOption> mos = new ArrayList<>();
for (ProdEquipment e : Equipments) { for (ProdEquipment e : Equipments) {
...@@ -277,7 +278,7 @@ public class RoutingDataService { ...@@ -277,7 +278,7 @@ public class RoutingDataService {
totalprocessTime=e.getSpeed()/e.getSingleOut().doubleValue()*entry.getQuantity(); totalprocessTime=e.getSpeed()/e.getSingleOut().doubleValue()*entry.getQuantity();
} }
minProcessingTime=Math.min(minProcessingTime,totalprocessTime);
if(machineIds.containsKey(e.getEquipId())) if(machineIds.containsKey(e.getEquipId()))
{ {
if( machineIds.get(e.getEquipId())<totalprocessTime) if( machineIds.get(e.getEquipId())<totalprocessTime)
...@@ -307,6 +308,7 @@ public class RoutingDataService { ...@@ -307,6 +308,7 @@ public class RoutingDataService {
mos.add(mo); mos.add(mo);
} }
entry.setMinProcessingTime(minProcessingTime);
entry.setMachineOptions(mos); entry.setMachineOptions(mos);
} }
} }
......
...@@ -43,8 +43,8 @@ public class PlanResultServiceTest { ...@@ -43,8 +43,8 @@ public class PlanResultServiceTest {
// planResultService.execute2("64E64F6B68094AF38CEDC418630C3CC2");//2000 // planResultService.execute2("64E64F6B68094AF38CEDC418630C3CC2");//2000
// planResultService.execute2("E1448B3C9C8743DEAB39708F2CFE348A");//倒排bomces // planResultService.execute2("E1448B3C9C8743DEAB39708F2CFE348A");//倒排bomces
// planResultService.execute2("197083D0D26A449EB179AC103C753FD3"); planResultService.execute2("85DA28EC5F4643449E65A51253D5F127");
planResultService.execute2("F8F147BD627C47B1A190399DD7A697F6"); // planResultService.execute2("F8F147BD627C47B1A190399DD7A697F6");
// planResultService.execute2("9FEDFD92BB6A4675BF9B1CC64505D1AB"); // planResultService.execute2("9FEDFD92BB6A4675BF9B1CC64505D1AB");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment