Commit 111874b6 authored by Tong Li's avatar Tong Li

优化

parent 40085732
...@@ -45,6 +45,16 @@ public class RedisUtils { ...@@ -45,6 +45,16 @@ public class RedisUtils {
@Getter @Getter
public static String prefix = "aps:"; public static String prefix = "aps:";
/**
* 最大重试次数
*/
private static final int MAX_RETRY_TIMES = 3;
/**
* 重试间隔(毫秒)
*/
private static final long RETRY_DELAY_MS = 500;
/** /**
* 设置redis前缀进行操作 * 设置redis前缀进行操作
* *
...@@ -62,7 +72,7 @@ public class RedisUtils { ...@@ -62,7 +72,7 @@ public class RedisUtils {
* @return: boolean * @return: boolean
*/ */
public boolean exists(final String key) { public boolean exists(final String key) {
return redisTemplate.hasKey(prefix + key); return executeWithRetry(() -> redisTemplate.hasKey(prefix + key), "exists(" + key + ")");
} }
public Set<String> keys(final String pattern) { public Set<String> keys(final String pattern) {
...@@ -164,13 +174,15 @@ public class RedisUtils { ...@@ -164,13 +174,15 @@ public class RedisUtils {
* @param key 可以传一个值 或多个 * @param key 可以传一个值 或多个
*/ */
public void del(String... key) { public void del(String... key) {
if (key != null && key.length > 0) { executeWithRetry(() -> {
if (key.length == 1) { if (key != null && key.length > 0) {
redisTemplate.delete(prefix + key[0]); if (key.length == 1) {
} else { redisTemplate.delete(prefix + key[0]);
redisTemplate.delete(Arrays.asList(key).stream().map(e -> prefix + e).collect(Collectors.toList())); } else {
redisTemplate.delete(Arrays.asList(key).stream().map(e -> prefix + e).collect(Collectors.toList()));
}
} }
} }, "del(" + Arrays.toString(key) + ")");
} }
public void del(Collection<String> keys) { public void del(Collection<String> keys) {
...@@ -184,7 +196,7 @@ public class RedisUtils { ...@@ -184,7 +196,7 @@ public class RedisUtils {
* @return 值 * @return 值
*/ */
public Object get(String key) { public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(prefix + key); return executeWithRetry(() -> key == null ? null : redisTemplate.opsForValue().get(prefix + key), "get(" + key + ")");
} }
/** /**
...@@ -207,13 +219,15 @@ public class RedisUtils { ...@@ -207,13 +219,15 @@ public class RedisUtils {
* @return true成功 false失败 * @return true成功 false失败
*/ */
public Boolean set(String key, Object value) { public Boolean set(String key, Object value) {
try { return executeWithRetry(() -> {
redisTemplate.opsForValue().set(prefix + key, value); try {
return true; redisTemplate.opsForValue().set(prefix + key, value);
} catch (Exception e) { return true;
log.error("Exception: {}", e.getMessage()); } catch (Exception e) {
return false; log.error("Exception: {}", e.getMessage());
} return false;
}
}, "set(" + key + ")");
} }
/** /**
...@@ -814,4 +828,120 @@ public class RedisUtils { ...@@ -814,4 +828,120 @@ public class RedisUtils {
redisLockUtil.releaseLock(prefix + key, ""); redisLockUtil.releaseLock(prefix + key, "");
} }
/**
* 通用重试执行器:用于处理 Redis 连接异常
* @param operation Redis 操作函数
* @param operationName 操作名称(用于日志)
* @param <T> 返回值类型
* @return 操作结果
*/
private <T> T executeWithRetry(java.util.function.Supplier<T> operation, String operationName) {
Exception lastException = null;
for (int attempt = 1; attempt <= MAX_RETRY_TIMES; attempt++) {
try {
if (attempt > 1) {
log.warn("Redis 操作重试 {}/{}: {}", attempt, MAX_RETRY_TIMES, operationName);
}
return operation.get();
} catch (Exception e) {
lastException = e;
log.error("Redis 操作失败 {}/{}: {}, 错误: {}", attempt, MAX_RETRY_TIMES, operationName, e.getMessage());
if (attempt < MAX_RETRY_TIMES) {
try {
log.warn("等待 {}ms 后重试...", RETRY_DELAY_MS);
Thread.sleep(RETRY_DELAY_MS);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Redis 操作重试被中断", ie);
}
}
}
}
throw new RuntimeException("Redis 操作失败,已重试 " + MAX_RETRY_TIMES + " 次: " + operationName, lastException);
}
/**
* 无返回值的重试执行器
* @param operation Redis 操作函数
* @param operationName 操作名称(用于日志)
*/
private void executeWithRetry(Runnable operation, String operationName) {
executeWithRetry(() -> {
operation.run();
return null;
}, operationName);
}
// ==================== 以下是添加了重试机制的方法 ====================
/**
* 判断是否有这个缓存key(带重试)
* @param key 缓存key
* @return boolean
*/
public boolean existsWithRetry(final String key) {
return executeWithRetry(() -> exists(key), "exists(" + key + ")");
}
/**
* 普通缓存获取(带重试)
* @param key 键
* @return 值
*/
public Object getWithRetry(String key) {
return executeWithRetry(() -> get(key), "get(" + key + ")");
}
/**
* 普通缓存放入(带重试)
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public Boolean setWithRetry(String key, Object value) {
return executeWithRetry(() -> set(key, value), "set(" + key + ")");
}
/**
* 普通缓存放入并设置时间(带重试)
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return true成功 false失败
*/
public Boolean setWithRetry(String key, Object value, Long time) {
return executeWithRetry(() -> set(key, value, time), "set(" + key + ", " + time + "s)");
}
/**
* 删除缓存(带重试)
* @param key 可以传一个值 或多个
*/
public void delWithRetry(String... key) {
executeWithRetry(() -> del(key), "del(" + Arrays.toString(key) + ")");
}
/**
* HashGet(带重试)
* @param key 键 不能为 null
* @param item 项 不能为 null
* @return 值
*/
public Object hgetWithRetry(String key, String item) {
return executeWithRetry(() -> hget(key, item), "hget(" + key + ", " + item + ")");
}
/**
* HashSet(带重试)
* @param key 键
* @param map 对应多个键值
* @return true成功 false失败
*/
public Boolean hmsetWithRetry(String key, Map<String, Object> map) {
return executeWithRetry(() -> hmset(key, map), "hmset(" + key + ")");
}
} }
...@@ -116,53 +116,53 @@ public class Chromosome { ...@@ -116,53 +116,53 @@ public class Chromosome {
private List<GlobalOperationInfo> globalOpList; private List<GlobalOperationInfo> globalOpList = new ArrayList<>();
private CopyOnWriteArrayList<Entry> allOperations; private CopyOnWriteArrayList<Entry> allOperations = new CopyOnWriteArrayList<>();
private CopyOnWriteArrayList<Order> orders; private CopyOnWriteArrayList<Order> orders = new CopyOnWriteArrayList<>();
private List<Machine> InitMachines; private List<Machine> InitMachines = new ArrayList<>();
private List<OrderMaterialRequirement> orderMaterials; private List<OrderMaterialRequirement> orderMaterials = new ArrayList<>();
private CopyOnWriteArrayList<GroupResult> OperatRel; private CopyOnWriteArrayList<GroupResult> OperatRel = new CopyOnWriteArrayList<>();
private ObjectiveWeights objectiveWeights; private ObjectiveWeights objectiveWeights;
private List<Material> materials; private List<Material> materials = new ArrayList<>();
private List<String> materialIds; private List<String> materialIds = new ArrayList<>();
/* /*
* 最早完工时间(最小化) 最小化总加工时间 最小总换型时间 * 最早完工时间(最小化) 最小化总加工时间 最小总换型时间
*/ */
private double[] Objectives ; // 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay] private double[] Objectives = new double[0]; // 多目标值:[Makespan, TotalFlowTime, TotalChangeover, LoadStd, Delay]
private double[] MaxObjectives ; // private double[] MaxObjectives = new double[0]; //
private double[] MinObjectives ; // private double[] MinObjectives = new double[0]; //
private int Rank; // 非支配排序等级(1最优) private int Rank; // 非支配排序等级(1最优)
private double CrowdingDistance =0; // 拥挤距离 越小越优 private double CrowdingDistance =0; // 拥挤距离 越小越优
/* /*
*(Objectives - min) / (max - min); *(Objectives - min) / (max - min);
*/ */
private double[] WeightedObjectives;//越靠近1越优 private double[] WeightedObjectives = new double[0];//越靠近1越优
private double WeightedObjective =0; // 加权目标值(用于自定义权重) private double WeightedObjective =0; // 加权目标值(用于自定义权重)
/// <summary> /// <summary>
/// 适应度值 /// 适应度值
/// </summary> /// </summary>
private double[] fitnessLevel; private double[] fitnessLevel = new double[0];
/// <summary> /// <summary>
/// 适应度值 /// 适应度值
/// </summary> /// </summary>
private double Fitness; private double Fitness = 0.0;
/// <summary> /// <summary>
/// 机器 /// 机器
/// </summary> /// </summary>
private List<Machine> Machines; private List<Machine> Machines = new ArrayList<>();
/// <summary> /// <summary>
/// 解码后的调度结果 /// 解码后的调度结果
/// </summary> /// </summary>
private CopyOnWriteArrayList<GAScheduleResult> Result; private CopyOnWriteArrayList<GAScheduleResult> Result = new CopyOnWriteArrayList<>();
/// <summary> /// <summary>
/// 解码后的调度结果 /// 解码后的调度结果
...@@ -172,33 +172,33 @@ public class Chromosome { ...@@ -172,33 +172,33 @@ public class Chromosome {
/// <summary> /// <summary>
/// 最早完工时间 /// 最早完工时间
/// </summary> /// </summary>
private double Makespan; private double Makespan = 0.0;
/// <summary> /// <summary>
/// 总流程时间 /// 总流程时间
/// </summary> /// </summary>
private double TotalFlowTime; private double TotalFlowTime = 0.0;
/// <summary> /// <summary>
/// 总换型时间 /// 总换型时间
/// </summary> /// </summary>
private double TotalChangeoverTime; private double TotalChangeoverTime = 0.0;
/// <summary> /// <summary>
/// 机器负载标准差(越小越均衡) /// 机器负载标准差(越小越均衡)
/// </summary> /// </summary>
private double MachineLoadStd; private double MachineLoadStd = 0.0;
/// <summary> /// <summary>
/// 交付期延迟时间 /// 交付期延迟时间
/// </summary> /// </summary>
private double DelayTime; private double DelayTime = 0.0;
private String ScenarioID; private String ScenarioID = "";
private String ScenarioName; private String ScenarioName = "";
private LocalDateTime BaseTime ; // 当前基准时间 private LocalDateTime BaseTime; // 当前基准时间
private List<Integer> reOrderids=new ArrayList<>(); private List<Integer> reOrderids=new ArrayList<>();
......
...@@ -165,14 +165,29 @@ public class FitnessCalculator { ...@@ -165,14 +165,29 @@ public class FitnessCalculator {
* 比较两个染色体的优劣(基于fitnessLevel多层次比较) * 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/ */
public boolean isBetter(Chromosome c1, Chromosome c2) { public boolean isBetter(Chromosome c1, Chromosome c2) {
for (int i = 0; i < c1.getFitnessLevel().length; i++) { double[] fitness1 = c1.getFitnessLevel();
double[] Fitness1 = c1.getFitnessLevel(); double[] fitness2 = c2.getFitnessLevel();
double[] Fitness2 = c2.getFitnessLevel();
if (Fitness1[i] > Fitness2[i]) { // 处理null或空数组的情况
if (fitness1 == null || fitness1.length == 0) {
return false; // c1没有fitness,认为c2更优
}
if (fitness2 == null || fitness2.length == 0) {
return true; // c2没有fitness,认为c1更优
}
// 取两个数组中较小的长度进行比较
int minLength = Math.min(fitness1.length, fitness2.length);
for (int i = 0; i < minLength; i++) {
if (fitness1[i] > fitness2[i]) {
return true; return true;
} else if (fitness1[i] < fitness2[i]) {
return false;
} }
} }
return false;
// 如果前面都相等,长度更长的视为更优(有更多维度)
return fitness1.length > fitness2.length;
} }
......
...@@ -193,7 +193,8 @@ public class GeneticDecoder { ...@@ -193,7 +193,8 @@ public class GeneticDecoder {
// 缓存命中:复用缓存结果 // 缓存命中:复用缓存结果
// 赋值给染色体 // 赋值给染色体
// chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(cachedResult.getInitMachines(),Machine.class)); // chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(cachedResult.getInitMachines(),Machine.class));
chromosome.setFitnessLevel(cachedResult.getFitnessLevel());
chromosome.setFitness(cachedResult.getFitness());
chromosome.setObjectives(cachedResult.getObjectives()); chromosome.setObjectives(cachedResult.getObjectives());
chromosome.setMakespan(cachedResult.getMakespan()); chromosome.setMakespan(cachedResult.getMakespan());
chromosome.setTotalFlowTime(cachedResult.getTotalFlowTime()); chromosome.setTotalFlowTime(cachedResult.getTotalFlowTime());
......
...@@ -105,34 +105,69 @@ public class GeneticOperations { ...@@ -105,34 +105,69 @@ public class GeneticOperations {
/** /**
* 锦标赛选择 * 锦标赛选择
*/ */
public List<Chromosome> tournamentSelection1(List<Chromosome> population, int tournamentSize) { public List<Chromosome> tournamentSelection2(List<Chromosome> population, int tournamentSize) {
int populationSize = population.size(); // 前置边界校验(避免NPE和无效计算)
if (population == null || population.isEmpty()) {
List<Chromosome> selected = new ArrayList<>(); // 预初始化容量 return new ArrayList<>();
}
int populationSize = population.size()>100?((int)(population.size()*0.8)):population.size();
// 预计算需要选中的个体数量,避免动态判断
int needSelectCount = populationSize - Math.max(1, Math.min(tournamentSize, populationSize));
List<Chromosome> selected = new ArrayList<>(needSelectCount); // 预初始化容量
// 边界值处理:锦标赛规模不能超过种群规模,且至少为1 // 边界值处理:锦标赛规模不能超过种群规模,且至少为1
int effectiveTournamentSize = Math.max(1, Math.min(tournamentSize, populationSize)); int effectiveTournamentSize = Math.max(1, Math.min(tournamentSize, populationSize));
List<Chromosome> selectedtemp = new ArrayList<>(needSelectCount); // 预初始化容量
// 预生成随机索引,减少Random对象创建开销
Random random = this.rnd;
// 固定次数循环,替代动态终止条件
for (int selectIdx = 0; selectIdx < needSelectCount; selectIdx++) {
while (selected.size() < populationSize-tournamentSize) { // 优化1:Fisher-Yates抽样(无重复、无冲突,比HashSet高效)
// 优化1:不复制整个种群,直接随机抽取有效锦标赛规模的个体,避免大量内存拷贝和shuffle开销 List<Integer> indices = new ArrayList<>(populationSize);
for (int i = 0; i < populationSize; i++) {
indices.add(i);
}
// 仅打乱前effectiveTournamentSize个索引,减少计算量
for (int i = 0; i < effectiveTournamentSize; i++) {
int swapIdx = i + random.nextInt(populationSize - i);
Collections.swap(indices, i, swapIdx);
}
Chromosome bestCandidate=null;
Collections.shuffle(population, new Random());//随机排序 for (int i = 0; i < effectiveTournamentSize; i++) {
int endIndex = Math.min(effectiveTournamentSize, population.size()); int idx = indices.get(i);
Chromosome curr= population.get(idx);
if(bestCandidate!=null)
{
if(isBetter(curr,bestCandidate))
{
bestCandidate=curr;
}
}else {
bestCandidate=curr;
}
}
if (bestCandidate != null) {
selected.add(bestCandidate);
}
}
List<Chromosome> chromosomes=population.subList(0, endIndex);
chromosomes.sort((c1, c2) -> {
int rankCompare = Integer.compare(c1.getRank(), c2.getRank());
return rankCompare != 0 ? rankCompare : Double.compare(c1.getCrowdingDistance(), c2.getCrowdingDistance());
});
Chromosome bestCandidate = chromosomes.get(0); return selected;// ProductionDeepCopyUtil.deepCopyList(selected, Chromosome.class);
}
// 深拷贝最优个体并加入选中列表(确保线程安全和种群独立性) private boolean isBetter(Chromosome c1, Chromosome c2) {
if (bestCandidate != null) {
selected.add(ProductionDeepCopyUtil.deepCopy(bestCandidate, Chromosome.class)); for (int i = 0; i < c1.getFitnessLevel().length; i++) {
double[] Fitness1 = c1.getFitnessLevel();
double[] Fitness2 = c2.getFitnessLevel();
if (Fitness1[i] > Fitness2[i]) {
return true;
} }
} }
return selected; return false;
} }
...@@ -145,6 +180,15 @@ public class GeneticOperations { ...@@ -145,6 +180,15 @@ public class GeneticOperations {
return populationn; return populationn;
} }
// 重载,使用默认锦标赛大小3
public List<Chromosome> tournamentSelection2(List<Chromosome> population) {
// List<Chromosome> populationn= ProductionDeepCopyUtil.deepCopyList(tournamentSelection(population, param.getTournamentSize()),Chromosome.class);
List<Chromosome> populationn= tournamentSelection2(population, param.getTournamentSize());
// populationn.parallelStream().forEach(t->DelOrder(t));
return populationn;
}
/** /**
* 改进POX交叉(工序排序部分) * 改进POX交叉(工序排序部分)
...@@ -166,7 +210,7 @@ public class GeneticOperations { ...@@ -166,7 +210,7 @@ public class GeneticOperations {
maxAllowedCount.put(job, Math.max(count1, count2)); // 取父代中该工件的最大出现次数 maxAllowedCount.put(job, Math.max(count1, count2)); // 取父代中该工件的最大出现次数
} }
// 步骤1:随机划分工件集 // 步骤2:随机划分工件集
List<Integer> jobset1 = new ArrayList<>(); List<Integer> jobset1 = new ArrayList<>();
for (int i = 1; i <= orderCount; i++) { for (int i = 1; i <= orderCount; i++) {
jobset1.add(i); jobset1.add(i);
...@@ -184,20 +228,32 @@ public class GeneticOperations { ...@@ -184,20 +228,32 @@ public class GeneticOperations {
} }
} }
// 步骤3:生成子代1(控制工件出现次数不超过父代最大值) List<Integer> child1Os, child2Os;
List<Integer> child1Os = generateChildOsWithCountLimit(
parent1, parent2, jobset1Set, maxAllowedCount, seqLength // 根据是否允许打破优先级选择不同的生成策略
); if (_GlobalParam.isIsBreakPriority()) {
// 步骤4:生成子代2(控制工件出现次数不超过父代最大值) // 允许打破优先级,使用原来的方法
List<Integer> child2Os = generateChildOsWithCountLimit( child1Os = generateChildOsWithCountLimit(parent1, parent2, jobset1Set, maxAllowedCount, seqLength);
parent2, parent1, jobset1Set, maxAllowedCount, seqLength child2Os = generateChildOsWithCountLimit(parent2, parent1, jobset1Set, maxAllowedCount, seqLength);
); } else {
// 不允许打破优先级,使用优先级保护的方法
child1Os = generateChildOsWithPriorityProtection(parent1, parent2, jobset1Set, maxAllowedCount, seqLength);
child2Os = generateChildOsWithPriorityProtection(parent2, parent1, jobset1Set, maxAllowedCount, seqLength);
}
// 机器选择部分交叉 // 机器选择部分交叉
// 构建工序ID到机器选择的映射,避免因GlobalOpList顺序不同导致的问题
Map<Integer, Integer> parent1OpToMachine = buildOpToMachineMap(parent1);
Map<Integer, Integer> parent2OpToMachine = buildOpToMachineMap(parent2);
List<Integer> child1Ms = new ArrayList<>(); List<Integer> child1Ms = new ArrayList<>();
List<Integer> child2Ms = new ArrayList<>(); List<Integer> child2Ms = new ArrayList<>();
for (int i = 0; i < parent1.getMachineSelection().size(); i++) { // 使用parent1的globalOpList作为基准(因为child1和child2都继承自parent1的orders/machines等)
int m1 = parent1.getMachineSelection().get(i); for (GlobalOperationInfo opInfo : parent1.getGlobalOpList()) {
int m2 = parent2.getMachineSelection().get(i); int opId = opInfo.getOp().getId();
int m1 = parent1OpToMachine.getOrDefault(opId, 1);
int m2 = parent2OpToMachine.getOrDefault(opId, 1);
if (rnd.nextDouble() < 0.5) { if (rnd.nextDouble() < 0.5) {
child1Ms.add(m1); child1Ms.add(m1);
child2Ms.add(m2); child2Ms.add(m2);
...@@ -208,19 +264,131 @@ public class GeneticOperations { ...@@ -208,19 +264,131 @@ public class GeneticOperations {
} }
Chromosome child1 = new Chromosome(); Chromosome child1 = new Chromosome();
child1.setOrders(parent1.getOrders()); child1.setGlobalOpList(parent1.getGlobalOpList());
child1.setMachines(parent1.getMachines());
child1.setMachineSelection(child1Ms); child1.setMachineSelection(child1Ms);
child1.setOperationSequencing(child1Os); child1.setOperationSequencing(child1Os);
Chromosome child2 = new Chromosome(); Chromosome child2 = new Chromosome();
child2.setOrders(parent1.getOrders()); child2.setGlobalOpList(parent1.getGlobalOpList());
child2.setMachines(parent1.getMachines());
child2.setMachineSelection(child2Ms); child2.setMachineSelection(child2Ms);
child2.setOperationSequencing(child2Os); child2.setOperationSequencing(child2Os);
return new Pair<>(child1, child2); return new Pair<>(child1, child2);
} }
/**
* 核心方法:生成子代操作序列(遵循POX规则 + 工件出现次数限制 + 优先级保护)
* 当不允许打破优先级时,确保高优先级的工序始终在低优先级工序之前
* @param mainParent 主父代(优先取其基因)
* @param secondaryParent 次父代(备选基因)
* @param jobset1Set POX交叉的工件集判断依据
* @param maxAllowedCount 每个工件的最大允许出现次数
* @param seqLength 序列长度
* @return 符合规则的子代序列
*/
private List<Integer> generateChildOsWithPriorityProtection(
Chromosome mainParent, Chromosome secondaryParent,
Set<Integer> jobset1Set, Map<Integer, Integer> maxAllowedCount,
int seqLength
) {
List<Integer> mainSeq = mainParent.getOperationSequencing();
List<Integer> secondarySeq = secondaryParent.getOperationSequencing();
// 1. 首先按POX规则和次数限制收集候选序列
List<Integer> candidateSeq = new ArrayList<>();
Map<Integer, Integer> childJobCount = new HashMap<>();
for (int i = 0; i < seqLength; i++) {
int mainOp = mainSeq.get(i);
int secondaryOp = secondarySeq.get(i);
int selectedOp = mainOp;
// 遵循原POX交叉规则筛选候选工件
if (!(jobset1Set.contains(mainOp) || jobset1Set.contains(secondaryOp))) {
selectedOp = secondaryOp;
}
// 检查候选工件是否超过最大允许次数
int currentCount = childJobCount.getOrDefault(selectedOp, 0);
if (currentCount >= maxAllowedCount.get(selectedOp)) {
// 切换到另一个父代的工件
selectedOp = (selectedOp == mainOp) ? secondaryOp : mainOp;
// 极端情况:切换后仍超过次数,从所有工件中选一个未超次数的
if (childJobCount.getOrDefault(selectedOp, 0) >= maxAllowedCount.get(selectedOp)) {
selectedOp = findValidJob(maxAllowedCount, childJobCount);
}
}
childJobCount.put(selectedOp, childJobCount.getOrDefault(selectedOp, 0) + 1);
candidateSeq.add(selectedOp);
}
// 2. 按优先级重新排序,确保不打破优先级
List<IndexedOperation> indexedOps = new ArrayList<>();
for (int i = 0; i < candidateSeq.size(); i++) {
int groupId = candidateSeq.get(i);
Entry entry = allOperations.stream()
.filter(o -> o.getGroupId() == groupId)
.findFirst()
.orElse(null);
double priority = (entry != null) ? entry.getPriority() : 0;
indexedOps.add(new IndexedOperation(i, groupId, priority));
}
// 按优先级降序排序(高优先级在前),同时保持同一优先级内的相对顺序
indexedOps.sort((a, b) -> {
int priorityCompare = Double.compare(a.priority, b.priority);
if (priorityCompare != 0) {
return priorityCompare;
}
return Integer.compare(a.originalIndex, b.originalIndex);
});
// 构建最终的子序列
List<Integer> childOs = new ArrayList<>();
for (IndexedOperation io : indexedOps) {
childOs.add(io.groupId);
}
return childOs;
}
/**
* 辅助方法:构建工序ID到机器选择的映射
* @param chromosome 染色体
* @return 工序ID -> 机器选择索引的映射
*/
private Map<Integer, Integer> buildOpToMachineMap(Chromosome chromosome) {
Map<Integer, Integer> opToMachine = new HashMap<>();
List<GlobalOperationInfo> globalOpList = chromosome.getGlobalOpList();
List<Integer> machineSelection = chromosome.getMachineSelection();
if (globalOpList != null && machineSelection != null) {
for (int i = 0; i < Math.min(globalOpList.size(), machineSelection.size()); i++) {
GlobalOperationInfo opInfo = globalOpList.get(i);
if (opInfo != null && opInfo.getOp() != null) {
int opId = opInfo.getOp().getId();
opToMachine.put(opId, machineSelection.get(i));
}
}
}
return opToMachine;
}
/**
* 辅助类:用于保持原始索引和优先级的工序信息
*/
private static class IndexedOperation {
int originalIndex;
int groupId;
double priority;
IndexedOperation(int originalIndex, int groupId, double priority) {
this.originalIndex = originalIndex;
this.groupId = groupId;
this.priority = priority;
}
}
/** /**
* 核心方法:生成子代操作序列(遵循POX规则 + 工件出现次数限制) * 核心方法:生成子代操作序列(遵循POX规则 + 工件出现次数限制)
* @param mainParent 主父代(优先取其基因) * @param mainParent 主父代(优先取其基因)
......
...@@ -643,16 +643,29 @@ public class HillClimbing { ...@@ -643,16 +643,29 @@ public class HillClimbing {
/** /**
* 比较两个染色体的优劣 * 比较两个染色体的优劣
*/ */
private boolean isBetter(Chromosome c1, Chromosome c2) { public boolean isBetter(Chromosome c1, Chromosome c2) {
double[] fitness1 = c1.getFitnessLevel();
double[] fitness2 = c2.getFitnessLevel();
for (int i = 0; i < c1.getFitnessLevel().length; i++) { // 处理null或空数组的情况
double[] Fitness1 = c1.getFitnessLevel(); if (fitness1 == null || fitness1.length == 0) {
double[] Fitness2 = c2.getFitnessLevel(); return false; // c1没有fitness,认为c2更优
if (Fitness1[i] > Fitness2[i]) { }
if (fitness2 == null || fitness2.length == 0) {
return true; // c2没有fitness,认为c1更优
}
// 取两个数组中较小的长度进行比较
int minLength = Math.min(fitness1.length, fitness2.length);
for (int i = 0; i < minLength; i++) {
if (fitness1[i] > fitness2[i]) {
return true; return true;
} else if (fitness1[i] < fitness2[i]) {
return false;
} }
} }
return false;
// 如果前面都相等,长度更长的视为更优(有更多维度)
return fitness1.length > fitness2.length;
} }
} }
\ No newline at end of file
...@@ -104,7 +104,7 @@ public class HybridAlgorithm { ...@@ -104,7 +104,7 @@ public class HybridAlgorithm {
GeneticOperations geneticOps = new GeneticOperations(_GlobalParam,allOperations,param); GeneticOperations geneticOps = new GeneticOperations(_GlobalParam,allOperations,param);
int opcount=allOperations.size(); int opcount=allOperations.size();
// 预生成全局工序列表(所有初始化方法共享同一顺序) // 预生成全局工序列表(所有初始化方法共享同一顺序)
List<GlobalOperationInfo> globalOpList = initialization.generateGlobalOpList(); List<GlobalOperationInfo> globalOpList =new ArrayList<>();// initialization.generateGlobalOpList();
// 初始化变邻域搜索 // 初始化变邻域搜索
_vns = new VariableNeighborhoodSearch( allOperations,orders,materials,_entryRel, _fitnessCalculator ); _vns = new VariableNeighborhoodSearch( allOperations,orders,materials,_entryRel, _fitnessCalculator );
_hillClimbing = new HillClimbing(allOperations,orders,materials,_entryRel, _fitnessCalculator); _hillClimbing = new HillClimbing(allOperations,orders,materials,_entryRel, _fitnessCalculator);
...@@ -137,11 +137,13 @@ int opcount=allOperations.size(); ...@@ -137,11 +137,13 @@ int opcount=allOperations.size();
// return getBestChromosome(population.get(0), param.getBaseTime(), starttime); // return getBestChromosome(population.get(0), param.getBaseTime(), starttime);
// 步骤2:对初始种群进行爬山法局部优化 // 步骤2:对初始种群进行爬山法局部优化
if(opcount<20 ) { if(opcount<100 ) {
Chromosome best=population.get(0);
geneticOps.DelOrder(best);
FileHelper.writeLogFile("爬山法局部优化-----------开始-------"); FileHelper.writeLogFile("爬山法局部优化-----------开始-------");
GeneticDecoder hillClimbingDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId); GeneticDecoder hillClimbingDecoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler, materialRequirementService, sceneId);
Chromosome optimized = _hillClimbing.search(population.get(0), hillClimbingDecoder,machines); Chromosome optimized = _hillClimbing.searchAll(best,machines,hillClimbingDecoder);
FileHelper.writeLogFile("爬山法局部优化-----------结束-------"); FileHelper.writeLogFile("爬山法局部优化-----------结束-------");
return getBestChromosome(optimized, param.getBaseTime(), starttime); return getBestChromosome(optimized, param.getBaseTime(), starttime);
} }
...@@ -158,14 +160,17 @@ int opcount=allOperations.size(); ...@@ -158,14 +160,17 @@ int opcount=allOperations.size();
if(opcount<800 ) { if(opcount<800 ) {
Chromosome best=population.get(0);
geneticOps.DelOrder(best);
FileHelper.writeLogFile("模拟退火+爬山法优化-----------开始-------"); FileHelper.writeLogFile("模拟退火+爬山法优化-----------开始-------");
Chromosome saHcOptimized = _simulatedAnnealing.searchWithHillClimbing(population.get(0),_vns, saDecoder1, machines); Chromosome saHcOptimized = _simulatedAnnealing.searchWithHillClimbing(best,_vns, saDecoder1, machines);
FileHelper.writeLogFile("模拟退火+爬山法优化-----------结束-------"); FileHelper.writeLogFile("模拟退火+爬山法优化-----------结束-------");
return getBestChromosome(saHcOptimized, param.getBaseTime(), starttime); return getBestChromosome(saHcOptimized, param.getBaseTime(), starttime);
} }
if(opcount>=800 ) { if(opcount>=800 ) {
Chromosome best=population.get(0); Chromosome best=population.get(0);
geneticOps.DelOrder(best);
best = _simulatedAnnealing.search(best, _tabuSearch, _vns, saDecoder1, machines); best = _simulatedAnnealing.search(best, _tabuSearch, _vns, saDecoder1, machines);
best = _vns.search(best, vnsDecoder1, machines); best = _vns.search(best, vnsDecoder1, machines);
best = _tabuSearch.search(best, _vns, tabuDecoder1, machines); best = _tabuSearch.search(best, _vns, tabuDecoder1, machines);
...@@ -194,6 +199,7 @@ int opcount=allOperations.size(); ...@@ -194,6 +199,7 @@ int opcount=allOperations.size();
int maxNoImprove = 10; int maxNoImprove = 10;
// 步骤2:迭代进化 // 步骤2:迭代进化
FileHelper.writeLogFile("迭代进化-----------开始-------"+param.getMaxIterations()); FileHelper.writeLogFile("迭代进化-----------开始-------"+param.getMaxIterations());
for (int iter = 0; iter < param.getMaxIterations(); iter++) { for (int iter = 0; iter < param.getMaxIterations(); iter++) {
// 解码并计算适应度 // 解码并计算适应度
FileHelper.writeLogFile("迭代进化------"+iter+"-----开始-------"); FileHelper.writeLogFile("迭代进化------"+iter+"-----开始-------");
...@@ -212,7 +218,7 @@ int opcount=allOperations.size(); ...@@ -212,7 +218,7 @@ int opcount=allOperations.size();
FileHelper.writeLogFile("选择操作-----------开始-------"); FileHelper.writeLogFile("选择操作-----------开始-------");
// 选择操作 // 选择操作
List<Chromosome> selected = geneticOps.tournamentSelection(population); List<Chromosome> selected = geneticOps.tournamentSelection2(population);
FileHelper.writeLogFile("选择操作-----------结束-------"); FileHelper.writeLogFile("选择操作-----------结束-------");
...@@ -230,13 +236,13 @@ int opcount=allOperations.size(); ...@@ -230,13 +236,13 @@ int opcount=allOperations.size();
Chromosome parent2 = selected.get(rnd.nextInt(selected.size())); Chromosome parent2 = selected.get(rnd.nextInt(selected.size()));
// 交叉 // 交叉
Chromosome child = parent1; Chromosome child = parent1;
// if (rnd.nextDouble() < param.getCrossoverProb()) { if (rnd.nextDouble() < param.getCrossoverProb()) {
// // 假设PoxCrossover返回包含两个子染色体的数组 // 假设PoxCrossover返回包含两个子染色体的数组
// Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount); Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
// child=children.getFirst(); child=children.getFirst();
// initDataToChromosome(child,param, allOperations,globalOpList); // initDataToChromosome(child,param, allOperations,globalOpList);
// child.setID(UUID.randomUUID().toString()); child.setID(UUID.randomUUID().toString());
// } }
// // 变异 // // 变异
// if (rnd.nextDouble() < param.getMutationProb()) { // if (rnd.nextDouble() < param.getMutationProb()) {
// geneticOps.mutate(child, globalOpList); // geneticOps.mutate(child, globalOpList);
...@@ -249,7 +255,7 @@ int opcount=allOperations.size(); ...@@ -249,7 +255,7 @@ int opcount=allOperations.size();
newPopulation.add(child); newPopulation.add(child);
FileHelper.writeLogFile("交叉-----------结束-------"+n); FileHelper.writeLogFile("交叉-----------结束-------"+n);
n++;
} }
population= chromosomeDistinctByObjectives(newPopulation);; population= chromosomeDistinctByObjectives(newPopulation);;
...@@ -375,14 +381,7 @@ int opcount=allOperations.size(); ...@@ -375,14 +381,7 @@ int opcount=allOperations.size();
* 比较两个染色体的优劣(基于fitnessLevel多层次比较) * 比较两个染色体的优劣(基于fitnessLevel多层次比较)
*/ */
private boolean isBetter(Chromosome c1, Chromosome c2) { private boolean isBetter(Chromosome c1, Chromosome c2) {
for (int i = 0; i < c1.getFitnessLevel().length; i++) { return _fitnessCalculator.isBetter(c1,c2);
double[] Fitness1 = c1.getFitnessLevel();
double[] Fitness2 = c2.getFitnessLevel();
if (Fitness1[i] > Fitness2[i]) {
return true;
}
}
return false;
} }
......
...@@ -149,10 +149,13 @@ public class MaterialRequirementService { ...@@ -149,10 +149,13 @@ public class MaterialRequirementService {
if(MaterialRequirements!=null) if(MaterialRequirements!=null)
{ {
List<Entry> Operations= _allOperations.stream() List<Entry> Operations= _allOperations.stream().filter(t -> t.getOrderId() != null)
.filter(t->t.getOrderId().equals(orderId)) .filter(t->t.getOrderId().equals(orderId))
.collect(Collectors.toList()); .collect(Collectors.toList());
if(Operations==null)
{
int i=1;
}
for (Entry operation : Operations) { for (Entry operation : Operations) {
List<Routingsupporting> MaterialRequirement_entrys = routingsupportings.stream() List<Routingsupporting> MaterialRequirement_entrys = routingsupportings.stream()
.filter(t -> t.getRoutingDetailId().equals(operation.getRoutingDetailId())) .filter(t -> t.getRoutingDetailId().equals(operation.getRoutingDetailId()))
...@@ -524,7 +527,10 @@ public class MaterialRequirementService { ...@@ -524,7 +527,10 @@ public class MaterialRequirementService {
for (Integer groupId : operationSequencing) for (Integer groupId : operationSequencing)
{ {
Order demand=orders.stream().filter(t->t.getId()==groupId).findFirst().orElse(null); Order demand=orders.stream().filter(t->t.getId()==groupId).findFirst().orElse(null);
if(demand==null)
{
continue;
}
if (demand.getFinishOrderId() != null && !demand.getFinishOrderId().isEmpty()) { if (demand.getFinishOrderId() != null && !demand.getFinishOrderId().isEmpty()) {
continue; continue;
} }
...@@ -606,7 +612,7 @@ public class MaterialRequirementService { ...@@ -606,7 +612,7 @@ public class MaterialRequirementService {
List<Entry> _allOperations= chromosome.getAllOperations(); List<Entry> _allOperations= chromosome.getAllOperations();
List<Entry> Operations= _allOperations.stream() List<Entry> Operations= _allOperations.stream().filter(t -> t.getOrderId() != null)
.filter(t->t.getOrderId().equals(childorderId)) .filter(t->t.getOrderId().equals(childorderId))
.collect(Collectors.toList()); .collect(Collectors.toList());
......
...@@ -232,6 +232,7 @@ public class RoutingDataService { ...@@ -232,6 +232,7 @@ public class RoutingDataService {
entry.setProductCode(order.getMaterialCode()); entry.setProductCode(order.getMaterialCode());
entry.setProductName(order.getMaterialName()); entry.setProductName(order.getMaterialName());
entry.setPriority(order.getActualPriority()); entry.setPriority(order.getActualPriority());
order.setId(entry.getGroupId()); order.setId(entry.getGroupId());
} }
List<ProdEquipment> Equipments = ProdEquipments.stream() List<ProdEquipment> Equipments = ProdEquipments.stream()
......
...@@ -106,13 +106,13 @@ public class SimulatedAnnealing { ...@@ -106,13 +106,13 @@ public class SimulatedAnnealing {
// log("模拟退火+爬山法 - 初始化解码完成"); // log("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度 // 初始化温度(优化:更快收敛)
double temperature = 100.0; double temperature = 100.0;
double coolingRate = 0.95; double coolingRate = 0.90; // 优化:降温更快
double temperatureThreshold = 1.0; double temperatureThreshold = 5.0; // 优化:温度阈值更高
int maxIterations = 300; int maxIterations = 100; // 优化:从300减少到100次
int noImproveCount = 0; int noImproveCount = 0;
int maxNoImprove = 30; // 降低最大无改进次数 int maxNoImprove = 15; // 优化:从30减少到15次
// 新增:改进率监控参数 // 新增:改进率监控参数
int stagnantWindow = 15; // 观察窗口大小 int stagnantWindow = 15; // 观察窗口大小
...@@ -239,13 +239,13 @@ public class SimulatedAnnealing { ...@@ -239,13 +239,13 @@ public class SimulatedAnnealing {
// log("模拟退火+爬山法 - 初始化解码完成"); // log("模拟退火+爬山法 - 初始化解码完成");
// 初始化温度 // 初始化温度(优化:更快收敛)
double temperature = 100.0; double temperature = 100.0;
double coolingRate = 0.95; double coolingRate = 0.90; // 优化:降温更快
double temperatureThreshold = 1.0; double temperatureThreshold = 5.0; // 优化:温度阈值更高
int maxIterations = 300; int maxIterations = 80; // 优化:从300减少到80次
int noImproveCount = 0; int noImproveCount = 0;
int maxNoImprove = 20; // 降低最大无改进次数,更快提前结束 int maxNoImprove = 10; // 优化:从20减少到10次
// 新增:改进率监控参数 // 新增:改进率监控参数
int stagnantWindow = 10; // 观察窗口大小 int stagnantWindow = 10; // 观察窗口大小
...@@ -361,9 +361,16 @@ public class SimulatedAnnealing { ...@@ -361,9 +361,16 @@ public class SimulatedAnnealing {
StringBuilder sb = new StringBuilder("模拟退火 - 改进详情: 迭代" + iteration + ", "); StringBuilder sb = new StringBuilder("模拟退火 - 改进详情: 迭代" + iteration + ", ");
double[] currentFitness = best.getFitnessLevel(); double[] currentFitness = best.getFitnessLevel();
for (int i = 0; i < currentFitness.length; i++) { // 处理null或空数组的情况
double improvement = currentFitness[i] - initialFitnessLevel[i]; if (currentFitness != null && currentFitness.length > 0 &&
sb.append(String.format("KPI%d: %.4f→%.4f(+%.4f) ", i+1, initialFitnessLevel[i], currentFitness[i], improvement)); initialFitnessLevel != null && initialFitnessLevel.length > 0) {
int minLength = Math.min(currentFitness.length, initialFitnessLevel.length);
for (int i = 0; i < minLength; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(+%.4f) ", i+1, initialFitnessLevel[i], currentFitness[i], improvement));
}
} else {
sb.append("(KPI数据不可用) ");
} }
double totalImprovement = best.getFitness() - initialFitness; double totalImprovement = best.getFitness() - initialFitness;
...@@ -392,10 +399,17 @@ public class SimulatedAnnealing { ...@@ -392,10 +399,17 @@ public class SimulatedAnnealing {
sb.append(String.format("总迭代%d次, 成功改进%d次, 改进率%.2f%%. ", sb.append(String.format("总迭代%d次, 成功改进%d次, 改进率%.2f%%. ",
totalIterations, improveCount, totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0)); totalIterations, improveCount, totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
for (int i = 0; i < currentFitness.length; i++) { // 处理null或空数组的情况
double improvement = currentFitness[i] - initialFitnessLevel[i]; if (currentFitness != null && currentFitness.length > 0 &&
sb.append(String.format("KPI%d: %.4f→%.4f(%.2f%%) ", i+1, initialFitnessLevel[i], currentFitness[i], initialFitnessLevel != null && initialFitnessLevel.length > 0) {
initialFitnessLevel[i] > 0 ? improvement / initialFitnessLevel[i] * 100 : 0)); int minLength = Math.min(currentFitness.length, initialFitnessLevel.length);
for (int i = 0; i < minLength; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(%.2f%%) ", i+1, initialFitnessLevel[i], currentFitness[i],
initialFitnessLevel[i] > 0 ? improvement / initialFitnessLevel[i] * 100 : 0));
}
} else {
sb.append("(KPI数据不可用) ");
} }
double totalImprovement = best.getFitness() - initialFitness; double totalImprovement = best.getFitness() - initialFitness;
...@@ -408,9 +422,12 @@ public class SimulatedAnnealing { ...@@ -408,9 +422,12 @@ public class SimulatedAnnealing {
private void writeKpi(Chromosome chromosome) { private void writeKpi(Chromosome chromosome) {
String fitness = ""; String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel(); double[] fitness1 = chromosome.getFitnessLevel();
for (int i = 0; i < fitness1.length; i++) { if (fitness1 != null) {
for (int i = 0; i < fitness1.length; i++) {
fitness += fitness1[i] + ","; fitness += fitness1[i] + ",";
}
} else {
fitness = "null (未计算)";
} }
log(String.format("模拟退火 - kpi:%s", fitness),true); log(String.format("模拟退火 - kpi:%s", fitness),true);
......
...@@ -65,7 +65,7 @@ public class TabuSearch { ...@@ -65,7 +65,7 @@ public class TabuSearch {
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);
this.bestFitness = best.getFitnessLevel().clone(); this.bestFitness = best.getFitnessLevel().clone();
writeKpi(best); writeKpi(best);
// 记录初始KPI用于计算改进率 // 记录初始KPI用于计算改进率
double[] initialFitnessLevel = best.getFitnessLevel().clone(); double[] initialFitnessLevel = best.getFitnessLevel().clone();
double initialFitness = best.getFitness(); double initialFitness = best.getFitness();
...@@ -73,8 +73,8 @@ writeKpi(best); ...@@ -73,8 +73,8 @@ writeKpi(best);
int iterations = 0; int iterations = 0;
int improveCount = 0; int improveCount = 0;
int noImprovementCount = 0; int noImprovementCount = 0;
int maxNoImprovement = 15; // 降低到15次无改进则停止 int maxNoImprovement = 5; // 优化:5次无改进则停止
int maxIterations = Math.min(cachedAllOperations.size(), 80); // 降低到最多80次 int maxIterations = Math.min(cachedAllOperations.size(), 20); // 优化:最多20次迭代
// 改进率监控 // 改进率监控
int stagnantWindow = 10; int stagnantWindow = 10;
...@@ -213,12 +213,15 @@ writeKpi(best); ...@@ -213,12 +213,15 @@ writeKpi(best);
private void writeKpi(Chromosome chromosome) { private void writeKpi(Chromosome chromosome) {
String fitness = ""; String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel(); double[] fitness1 = chromosome.getFitnessLevel();
for (int i = 0; i < fitness1.length; i++) { if (fitness1 != null) {
for (int i = 0; i < fitness1.length; i++) {
fitness += fitness1[i] + ","; fitness += fitness1[i] + ",";
}
} else {
fitness = "null (未计算)";
} }
log(String.format("变邻域搜索 - kpi:%s", fitness),true); log(String.format("禁忌搜索 - kpi:%s", fitness),true);
} }
/** /**
...@@ -228,9 +231,16 @@ writeKpi(best); ...@@ -228,9 +231,16 @@ writeKpi(best);
StringBuilder sb = new StringBuilder("禁忌搜索 - 改进详情: 迭代" + iteration + ", "); StringBuilder sb = new StringBuilder("禁忌搜索 - 改进详情: 迭代" + iteration + ", ");
double[] currentFitness = best.getFitnessLevel(); double[] currentFitness = best.getFitnessLevel();
for (int i = 0; i < currentFitness.length; i++) { // 处理null或空数组的情况
double improvement = currentFitness[i] - initialFitnessLevel[i]; if (currentFitness != null && currentFitness.length > 0 &&
sb.append(String.format("KPI%d: %.4f→%.4f(+%.4f) ", i+1, initialFitnessLevel[i], currentFitness[i], improvement)); initialFitnessLevel != null && initialFitnessLevel.length > 0) {
int minLength = Math.min(currentFitness.length, initialFitnessLevel.length);
for (int i = 0; i < minLength; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(+%.4f) ", i+1, initialFitnessLevel[i], currentFitness[i], improvement));
}
} else {
sb.append("(KPI数据不可用) ");
} }
double totalImprovement = best.getFitness() - initialFitness; double totalImprovement = best.getFitness() - initialFitness;
...@@ -260,10 +270,17 @@ writeKpi(best); ...@@ -260,10 +270,17 @@ writeKpi(best);
sb.append(String.format("总迭代%d次, 成功改进%d次, 改进率%.2f%%. ", sb.append(String.format("总迭代%d次, 成功改进%d次, 改进率%.2f%%. ",
totalIterations, improveCount, totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0)); totalIterations, improveCount, totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
for (int i = 0; i < currentFitness.length; i++) { // 处理null或空数组的情况
double improvement = currentFitness[i] - initialFitnessLevel[i]; if (currentFitness != null && currentFitness.length > 0 &&
sb.append(String.format("KPI%d: %.4f→%.4f(%.2f%%) ", i+1, initialFitnessLevel[i], currentFitness[i], initialFitnessLevel != null && initialFitnessLevel.length > 0) {
initialFitnessLevel[i] > 0 ? improvement / initialFitnessLevel[i] * 100 : 0)); int minLength = Math.min(currentFitness.length, initialFitnessLevel.length);
for (int i = 0; i < minLength; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(%.2f%%) ", i+1, initialFitnessLevel[i], currentFitness[i],
initialFitnessLevel[i] > 0 ? improvement / initialFitnessLevel[i] * 100 : 0));
}
} else {
sb.append("(KPI数据不可用) ");
} }
double totalImprovement = best.getFitness() - initialFitness; double totalImprovement = best.getFitness() - initialFitness;
......
...@@ -21,7 +21,7 @@ public class VariableNeighborhoodSearch { ...@@ -21,7 +21,7 @@ public class VariableNeighborhoodSearch {
// ==================== 常量定义 ==================== // ==================== 常量定义 ====================
private static final int MAX_CONSECUTIVE_SAME_STRATEGY = 3; private static final int MAX_CONSECUTIVE_SAME_STRATEGY = 3;
private static final int MAX_NEIGHBORHOODS = 7; private static final int MAX_NEIGHBORHOODS = 4; // 优化:从7减少到4个邻域
private static final double HIGH_PRIORITY_GROUP_PROBABILITY = 0.7; private static final double HIGH_PRIORITY_GROUP_PROBABILITY = 0.7;
private static final int MAX_ATTEMPTS = 50; private static final int MAX_ATTEMPTS = 50;
private static final int NEIGHBOR_SELECTION_TOP_K = 3; private static final int NEIGHBOR_SELECTION_TOP_K = 3;
...@@ -378,9 +378,16 @@ public class VariableNeighborhoodSearch { ...@@ -378,9 +378,16 @@ public class VariableNeighborhoodSearch {
StringBuilder sb = new StringBuilder("变邻域搜索 - 改进详情: 轮次" + round + ", 邻域=" + neighborhoodName + ", "); StringBuilder sb = new StringBuilder("变邻域搜索 - 改进详情: 轮次" + round + ", 邻域=" + neighborhoodName + ", ");
double[] currentFitness = best.getFitnessLevel(); double[] currentFitness = best.getFitnessLevel();
for (int i = 0; i < currentFitness.length; i++) { // 处理null或空数组的情况
double improvement = currentFitness[i] - initialFitnessLevel[i]; if (currentFitness != null && currentFitness.length > 0 &&
sb.append(String.format("KPI%d: %.4f→%.4f(+%.4f) ", i+1, initialFitnessLevel[i], currentFitness[i], improvement)); initialFitnessLevel != null && initialFitnessLevel.length > 0) {
int minLength = Math.min(currentFitness.length, initialFitnessLevel.length);
for (int i = 0; i < minLength; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(+%.4f) ", i+1, initialFitnessLevel[i], currentFitness[i], improvement));
}
} else {
sb.append("(KPI数据不可用) ");
} }
double totalImprovement = best.getFitness() - initialFitness; double totalImprovement = best.getFitness() - initialFitness;
...@@ -409,10 +416,16 @@ public class VariableNeighborhoodSearch { ...@@ -409,10 +416,16 @@ public class VariableNeighborhoodSearch {
sb.append("\n"); sb.append("\n");
// 记录KPI改进 // 记录KPI改进
for (int i = 0; i < currentFitness.length; i++) { if (currentFitness != null && currentFitness.length > 0 &&
double improvement = currentFitness[i] - initialFitnessLevel[i]; initialFitnessLevel != null && initialFitnessLevel.length > 0) {
sb.append(String.format("KPI%d: %.4f→%.4f(%.2f%%) ", i+1, initialFitnessLevel[i], currentFitness[i], int minLength = Math.min(currentFitness.length, initialFitnessLevel.length);
initialFitnessLevel[i] > 0 ? improvement / initialFitnessLevel[i] * 100 : 0)); for (int i = 0; i < minLength; i++) {
double improvement = currentFitness[i] - initialFitnessLevel[i];
sb.append(String.format("KPI%d: %.4f→%.4f(%.2f%%) ", i+1, initialFitnessLevel[i], currentFitness[i],
initialFitnessLevel[i] > 0 ? improvement / initialFitnessLevel[i] * 100 : 0));
}
} else {
sb.append("(KPI数据不可用) ");
} }
double totalImprovement = best.getFitness() - initialFitness; double totalImprovement = best.getFitness() - initialFitness;
...@@ -424,9 +437,12 @@ public class VariableNeighborhoodSearch { ...@@ -424,9 +437,12 @@ public class VariableNeighborhoodSearch {
private void writeKpi(Chromosome chromosome) { private void writeKpi(Chromosome chromosome) {
String fitness = ""; String fitness = "";
double[] fitness1 = chromosome.getFitnessLevel(); double[] fitness1 = chromosome.getFitnessLevel();
for (int i = 0; i < fitness1.length; i++) { if (fitness1 != null) {
for (int i = 0; i < fitness1.length; i++) {
fitness += fitness1[i] + ","; fitness += fitness1[i] + ",";
}
} else {
fitness = "null (未计算)";
} }
log(String.format("变邻域搜索 - kpi:%s", fitness),true); log(String.format("变邻域搜索 - kpi:%s", fitness),true);
...@@ -2024,6 +2040,7 @@ public class VariableNeighborhoodSearch { ...@@ -2024,6 +2040,7 @@ public class VariableNeighborhoodSearch {
} else { } else {
chromosome.setResultOld(new CopyOnWriteArrayList<>()); chromosome.setResultOld(new CopyOnWriteArrayList<>());
} }
//decoder.decodeChromosomeWithCache(chromosome,true);
}); });
log(String.format("变邻域搜索 -复制对象E")); log(String.format("变邻域搜索 -复制对象E"));
......
...@@ -39,10 +39,13 @@ public class PlanResultServiceTest { ...@@ -39,10 +39,13 @@ public class PlanResultServiceTest {
// TestSortService sortService=new TestSortService(); // TestSortService sortService=new TestSortService();
// sortService.test1(); // sortService.test1();
// nsgaiiUtils.Test(); // nsgaiiUtils.Test();
planResultService.execute2("08B1D87FE1B84ECDBAC2E546DDB6FB81");//2000
// planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//2000 planResultService.execute2("F6747C64865D4609989D943709939331");//2000
// planResultService.execute2("08B1D87FE1B84ECDBAC2E546DDB6FB81");//2000
// planResultService.execute2("0428340BB4F540938F1FB5599F03E8A4");//5000
// planResultService.execute2("C8B533BD8944405B9A2F8823C575C204");//500 // planResultService.execute2("C8B533BD8944405B9A2F8823C575C204");//500
// planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");//20 // planResultService.execute2("EFDD34E4B5BC434BAEAE6A84DFCD4E7B");//20
// planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D"); // planResultService.execute2("00E0C5D3E4AD4F36B56C39395906618D");
// planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2"); // planResultService.execute2("92BB773E1E2447C99D8176C991D5C9D2");
......
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