Commit 087659cf authored by Tong Li's avatar Tong Li

初始化优化

parent 08991d0b
...@@ -17,6 +17,9 @@ import java.util.stream.Collectors; ...@@ -17,6 +17,9 @@ import java.util.stream.Collectors;
public class SimulatedAnnealing { public class SimulatedAnnealing {
private final Random rnd = new Random(); private final Random rnd = new Random();
// ==================== 改进判断参数 ====================
private static final double SIGNIFICANT_IMPROVEMENT_THRESHOLD = 0.0001; // 显著改进阈值:只有改进超过这个值才重置无改进计数
private void log(String message) { private void log(String message) {
log(message, false); log(message, false);
} }
...@@ -124,6 +127,7 @@ public class SimulatedAnnealing { ...@@ -124,6 +127,7 @@ public class SimulatedAnnealing {
int acceptCount = 0; int acceptCount = 0;
int improveCount = 0; int improveCount = 0;
int significantImproveCount = 0;
int totalIterations = 0; int totalIterations = 0;
for (int i = 0; i < maxIterations; i++) { for (int i = 0; i < maxIterations; i++) {
...@@ -152,11 +156,16 @@ public class SimulatedAnnealing { ...@@ -152,11 +156,16 @@ public class SimulatedAnnealing {
writeKpi(best); writeKpi(best);
improved = true; improved = true;
improveCount++; improveCount++;
noImproveCount = 0; boolean isSignificant = isSignificantImprovement(current, best);
if (isSignificant) {
// 记录改进详情 noImproveCount = 0; // 只有显著改进才重置无改进计数
logImprovementDetails(best, initialFitnessLevel, initialFitness, totalIterations); significantImproveCount++;
log(String.format("模拟退火+爬山法 - 迭代%d:找到更优解,fitness=%.4f", totalIterations, best.getFitness()),true); logImprovementDetails(best, initialFitnessLevel, initialFitness, totalIterations);
log(String.format("模拟退火+爬山法 - 迭代%d:找到更优解(显著),fitness=%.4f", totalIterations, best.getFitness()),true);
} else {
// 微小改进也接受,但不重置计数
log(String.format("模拟退火+爬山法 - 迭代%d:找到更优解(微小),fitness=%.4f", totalIterations, best.getFitness()),true);
}
} }
} }
...@@ -201,7 +210,7 @@ public class SimulatedAnnealing { ...@@ -201,7 +210,7 @@ public class SimulatedAnnealing {
if (shouldStop) { if (shouldStop) {
log(String.format("模拟退火+爬山法 - 提前停止:%s,迭代%d次,最终温度=%.4f", log(String.format("模拟退火+爬山法 - 提前停止:%s,迭代%d次,最终温度=%.4f",
stopReason, totalIterations, temperature)); stopReason, totalIterations, temperature));
logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations); logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, significantImproveCount, totalIterations);
log("模拟退火+爬山法 - 切换到爬山法求精"); log("模拟退火+爬山法 - 切换到爬山法求精");
HillClimbing hillClimbing = new HillClimbing( allOperations,orders,materials,_entryRel,fitnessCalculator); HillClimbing hillClimbing = new HillClimbing( allOperations,orders,materials,_entryRel,fitnessCalculator);
...@@ -214,7 +223,7 @@ public class SimulatedAnnealing { ...@@ -214,7 +223,7 @@ public class SimulatedAnnealing {
log(String.format("模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f", log(String.format("模拟退火+爬山法 - 完成所有%d次迭代,最终fitness=%.4f",
maxIterations, best.getFitness()),true); maxIterations, best.getFitness()),true);
logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations); logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, significantImproveCount, totalIterations);
// 7. 输出全局最优排产 // 7. 输出全局最优排产
return best; return best;
...@@ -257,6 +266,7 @@ public class SimulatedAnnealing { ...@@ -257,6 +266,7 @@ public class SimulatedAnnealing {
int acceptCount = 0; int acceptCount = 0;
int improveCount = 0; int improveCount = 0;
int significantImproveCount = 0;
int totalIterations = 0; int totalIterations = 0;
for (int i = 0; i < maxIterations; i++) { for (int i = 0; i < maxIterations; i++) {
...@@ -294,11 +304,15 @@ public class SimulatedAnnealing { ...@@ -294,11 +304,15 @@ public class SimulatedAnnealing {
writeKpi(best); writeKpi(best);
improved = true; improved = true;
improveCount++; improveCount++;
noImproveCount = 0; boolean isSignificant = isSignificantImprovement(current, best);
if (isSignificant) {
// 记录改进详情 noImproveCount = 0;
logImprovementDetails(best, initialFitnessLevel, initialFitness, totalIterations); significantImproveCount++;
log(String.format("模拟退火 - 迭代%d:找到更优解,fitness=%.4f", totalIterations, best.getFitness())); logImprovementDetails(best, initialFitnessLevel, initialFitness, totalIterations);
log(String.format("模拟退火 - 迭代%d:找到更优解(显著),fitness=%.4f", totalIterations, best.getFitness()));
} else {
log(String.format("模拟退火 - 迭代%d:找到更优解(微小),fitness=%.4f", totalIterations, best.getFitness()));
}
} }
} }
...@@ -341,14 +355,14 @@ public class SimulatedAnnealing { ...@@ -341,14 +355,14 @@ public class SimulatedAnnealing {
if (shouldStop) { if (shouldStop) {
log(String.format("模拟退火 - 提前停止:%s,迭代%d次,最终温度=%.4f", log(String.format("模拟退火 - 提前停止:%s,迭代%d次,最终温度=%.4f",
stopReason, totalIterations, temperature)); stopReason, totalIterations, temperature));
logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations); logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, significantImproveCount, totalIterations);
return best; return best;
} }
} }
log(String.format("模拟退火 - 完成所有%d次迭代,最终fitness=%.4f", log(String.format("模拟退火 - 完成所有%d次迭代,最终fitness=%.4f",
maxIterations, best.getFitness()),true); maxIterations, best.getFitness()),true);
logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, totalIterations); logFinalSummary(best, initialFitnessLevel, initialFitness, improveCount, significantImproveCount, totalIterations);
// 7. 输出全局最优排产 // 7. 输出全局最优排产
return best; return best;
...@@ -392,12 +406,13 @@ public class SimulatedAnnealing { ...@@ -392,12 +406,13 @@ public class SimulatedAnnealing {
/** /**
* 记录最终总结 * 记录最终总结
*/ */
private void logFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness, int improveCount, int totalIterations) { private void logFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness, int improveCount, int significantImproveCount, int totalIterations) {
StringBuilder sb = new StringBuilder("模拟退火 - 最终总结: "); StringBuilder sb = new StringBuilder("模拟退火 - 最终总结: ");
double[] currentFitness = best.getFitnessLevel(); double[] currentFitness = best.getFitnessLevel();
sb.append(String.format("总迭代%d次, 成功改进%d次, 改进率%.2f%%. ", sb.append(String.format("总迭代%d次, 成功改进%d次(显著%d次), 改进率%.2f%%. ",
totalIterations, improveCount, totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0)); totalIterations, improveCount, significantImproveCount,
totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
// 处理null或空数组的情况 // 处理null或空数组的情况
if (currentFitness != null && currentFitness.length > 0 && if (currentFitness != null && currentFitness.length > 0 &&
...@@ -543,6 +558,18 @@ public class SimulatedAnnealing { ...@@ -543,6 +558,18 @@ public class SimulatedAnnealing {
private boolean isBetter(Chromosome c1, Chromosome c2) { private boolean isBetter(Chromosome c1, Chromosome c2) {
return fitnessCalculator.isBetter(c1,c2); return fitnessCalculator.isBetter(c1,c2);
} }
/**
* 判断是否为显著改进(只有超过阈值的改进才重置无改进计数)
*/
private boolean isSignificantImprovement(Chromosome newChromo, Chromosome oldChromo) {
if (!isBetter(newChromo, oldChromo)) {
return false;
}
double newFitness = newChromo.getFitness();
double oldFitness = oldChromo.getFitness();
return (newFitness - oldFitness) > SIGNIFICANT_IMPROVEMENT_THRESHOLD;
}
private int Getbest(List<Chromosome> candidates,Chromosome best) { private int Getbest(List<Chromosome> candidates,Chromosome best) {
// 找出最佳候选方案 // 找出最佳候选方案
......
...@@ -15,6 +15,9 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -15,6 +15,9 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/ */
public class TabuSearch { public class TabuSearch {
// ==================== 改进判断参数 ====================
private static final double SIGNIFICANT_IMPROVEMENT_THRESHOLD = 0.0001; // 显著改进阈值:只有改进超过这个值才重置无改进计数
private void log(String message) { private void log(String message) {
log(message, false); log(message, false);
...@@ -72,6 +75,7 @@ public class TabuSearch { ...@@ -72,6 +75,7 @@ public class TabuSearch {
int iterations = 0; int iterations = 0;
int improveCount = 0; int improveCount = 0;
int significantImproveCount = 0;
int noImprovementCount = 0; int noImprovementCount = 0;
int maxNoImprovement = 5; // 优化:5次无改进则停止 int maxNoImprovement = 5; // 优化:5次无改进则停止
int maxIterations = Math.min(cachedAllOperations.size(), 20); // 优化:最多20次迭代 int maxIterations = Math.min(cachedAllOperations.size(), 20); // 优化:最多20次迭代
...@@ -154,14 +158,23 @@ public class TabuSearch { ...@@ -154,14 +158,23 @@ public class TabuSearch {
best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class); best = ProductionDeepCopyUtil.deepCopy(current, Chromosome.class);
this.bestFitness = best.getFitnessLevel().clone(); this.bestFitness = best.getFitnessLevel().clone();
writeKpi(best); writeKpi(best);
noImprovementCount = 0;
improveCount++; improveCount++;
improvedThisIteration = true; improvedThisIteration = true;
logTabuImprovement(best, initialFitnessLevel, initialFitness, iterations); boolean isSignificant = isSignificantImprovement(best, chromosome);
log(String.format("禁忌搜索 - 找到更好解,迭代=%d", iterations),true); if (isSignificant) {
noImprovementCount = 0;
significantImproveCount++;
logTabuImprovement(best, initialFitnessLevel, initialFitness, iterations);
log(String.format("禁忌搜索 - 找到更好解(显著),迭代=%d", iterations),true);
} else {
log(String.format("禁忌搜索 - 找到更好解(微小),迭代=%d", iterations),true);
}
} else if (isBetterThanCurrent) { } else if (isBetterThanCurrent) {
// 比当前解好但没有比最优解好 // 比当前解好但没有比最优解好
noImprovementCount = 0; boolean isSignificant = isSignificantImprovement(current, chromosome);
if (isSignificant) {
noImprovementCount = 0;
}
improvedThisIteration = true; improvedThisIteration = true;
} else { } else {
// 没有改进 // 没有改进
...@@ -201,12 +214,12 @@ public class TabuSearch { ...@@ -201,12 +214,12 @@ public class TabuSearch {
if (shouldStop) { if (shouldStop) {
log(String.format("禁忌搜索 - 提前停止:%s", stopReason)); log(String.format("禁忌搜索 - 提前停止:%s", stopReason));
logTabuFinalSummary(best, initialFitnessLevel, initialFitness, iterations, improveCount); logTabuFinalSummary(best, initialFitnessLevel, initialFitness, iterations, improveCount, significantImproveCount);
break; break;
} }
} }
logTabuFinalSummary(best, initialFitnessLevel, initialFitness, iterations, improveCount); logTabuFinalSummary(best, initialFitnessLevel, initialFitness, iterations, improveCount, significantImproveCount);
log(String.format("禁忌搜索 - 结束,总迭代=%d", iterations),true); log(String.format("禁忌搜索 - 结束,总迭代=%d", iterations),true);
return best; return best;
} }
...@@ -263,12 +276,13 @@ public class TabuSearch { ...@@ -263,12 +276,13 @@ public class TabuSearch {
* 记录禁忌搜索最终总结 * 记录禁忌搜索最终总结
*/ */
private void logTabuFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness, private void logTabuFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness,
int totalIterations, int improveCount) { int totalIterations, int improveCount, int significantImproveCount) {
StringBuilder sb = new StringBuilder("禁忌搜索 - 最终总结: "); StringBuilder sb = new StringBuilder("禁忌搜索 - 最终总结: ");
double[] currentFitness = best.getFitnessLevel(); double[] currentFitness = best.getFitnessLevel();
sb.append(String.format("总迭代%d次, 成功改进%d次, 改进率%.2f%%. ", sb.append(String.format("总迭代%d次, 成功改进%d次(显著%d次), 改进率%.2f%%. ",
totalIterations, improveCount, totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0)); totalIterations, improveCount, significantImproveCount,
totalIterations > 0 ? (double)improveCount / totalIterations * 100 : 0));
// 处理null或空数组的情况 // 处理null或空数组的情况
if (currentFitness != null && currentFitness.length > 0 && if (currentFitness != null && currentFitness.length > 0 &&
...@@ -342,11 +356,15 @@ public class TabuSearch { ...@@ -342,11 +356,15 @@ public class TabuSearch {
return fitnessCalculator.isBetter(c1,c2); return fitnessCalculator.isBetter(c1,c2);
} }
/**
* 判断是否为显著改进(只有超过阈值的改进才重置无改进计数)
*/
private boolean isSignificantImprovement(Chromosome newChromo, Chromosome oldChromo) {
if (!isBetter(newChromo, oldChromo)) {
return false;
}
double newFitness = newChromo.getFitness();
double oldFitness = oldChromo.getFitness();
return (newFitness - oldFitness) > SIGNIFICANT_IMPROVEMENT_THRESHOLD;
}
} }
\ No newline at end of file
...@@ -61,6 +61,9 @@ public class VariableNeighborhoodSearch { ...@@ -61,6 +61,9 @@ public class VariableNeighborhoodSearch {
private static final int TOP_MACHINES_TO_LOG = 5; // 日志输出的设备数量 private static final int TOP_MACHINES_TO_LOG = 5; // 日志输出的设备数量
private static final int MIN_USE_COUNT_FOR_EXPLORATION_BONUS = 5; // 低使用次数判断的最小阈值 private static final int MIN_USE_COUNT_FOR_EXPLORATION_BONUS = 5; // 低使用次数判断的最小阈值
// ==================== 改进判断参数 ====================
private static final double SIGNIFICANT_IMPROVEMENT_THRESHOLD = 0.0001; // 显著改进阈值:只有改进超过这个值才重置无改进计数
// 日志级别 // 日志级别
private static final int LOG_LEVEL_DEBUG = 0; private static final int LOG_LEVEL_DEBUG = 0;
private static final int LOG_LEVEL_INFO = 1; private static final int LOG_LEVEL_INFO = 1;
...@@ -279,6 +282,18 @@ public class VariableNeighborhoodSearch { ...@@ -279,6 +282,18 @@ public class VariableNeighborhoodSearch {
return improvedPopulation; return improvedPopulation;
} }
/**
* 判断是否为显著改进(只有超过阈值的改进才重置无改进计数)
*/
private boolean isSignificantImprovement(Chromosome newChromo, Chromosome oldChromo) {
if (!isBetter(newChromo, oldChromo)) {
return false;
}
double newFitness = newChromo.getFitness();
double oldFitness = oldChromo.getFitness();
return (newFitness - oldFitness) > SIGNIFICANT_IMPROVEMENT_THRESHOLD;
}
/** /**
* 对单个个体进行变邻域搜索 * 对单个个体进行变邻域搜索
*/ */
...@@ -298,6 +313,7 @@ public class VariableNeighborhoodSearch { ...@@ -298,6 +313,7 @@ public class VariableNeighborhoodSearch {
int noImproveRoundCount = 0; // 无改进轮数计数 int noImproveRoundCount = 0; // 无改进轮数计数
int totalRounds = 0; // 总轮数 int totalRounds = 0; // 总轮数
int totalImprovements = 0; // 总改进次数 int totalImprovements = 0; // 总改进次数
int totalSignificantImprovements = 0; // 显著改进次数
int k = 0; int k = 0;
// 按成功率排序获取邻域结构(先获取一次) // 按成功率排序获取邻域结构(先获取一次)
...@@ -341,15 +357,22 @@ public class VariableNeighborhoodSearch { ...@@ -341,15 +357,22 @@ public class VariableNeighborhoodSearch {
// 邻域移动 // 邻域移动
boolean success = isBetter(localBest, best); boolean success = isBetter(localBest, best);
boolean isSignificant = isSignificantImprovement(localBest, best);
if (success) { if (success) {
best = localBest; best = localBest;
writeKpi(best); writeKpi(best);
current = localBest; current = localBest;
k = 0; // 重置邻域索引
noImproveRoundCount = 0; // 重置无改进计数
totalImprovements++; totalImprovements++;
logVNSImprovement(best, initialFitnessLevel, initialFitness, totalRounds, neighborhood.name); if (isSignificant) {
log(String.format("变邻域搜索 - 邻域成功: %s", neighborhood.name),true); k = 0; // 重置邻域索引
noImproveRoundCount = 0; // 只有显著改进才重置无改进计数
totalSignificantImprovements++;
logVNSImprovement(best, initialFitnessLevel, initialFitness, totalRounds, neighborhood.name);
log(String.format("变邻域搜索 - 邻域成功(显著): %s", neighborhood.name),true);
} else {
// 微小改进也接受,但不重置计数,继续尝试
log(String.format("变邻域搜索 - 邻域成功(微小): %s", neighborhood.name),true);
}
} else { } else {
k++; // 尝试下一个邻域 k++; // 尝试下一个邻域
// 检查是否完成一轮 // 检查是否完成一轮
...@@ -369,13 +392,13 @@ public class VariableNeighborhoodSearch { ...@@ -369,13 +392,13 @@ public class VariableNeighborhoodSearch {
// 检查提前结束条件 // 检查提前结束条件
if (noImproveRoundCount >= maxNoImproveRounds) { if (noImproveRoundCount >= maxNoImproveRounds) {
log(String.format("变邻域搜索 - 提前结束:连续%d轮无改进", maxNoImproveRounds)); log(String.format("变邻域搜索 - 提前结束:连续%d轮无改进", maxNoImproveRounds));
logVNSFinalSummary(best, initialFitnessLevel, initialFitness, totalRounds, totalImprovements); logVNSFinalSummary(best, initialFitnessLevel, initialFitness, totalRounds, totalImprovements, totalSignificantImprovements);
break; break;
} }
} }
if (noImproveRoundCount < maxNoImproveRounds) { if (noImproveRoundCount < maxNoImproveRounds) {
logVNSFinalSummary(best, initialFitnessLevel, initialFitness, totalRounds, totalImprovements); logVNSFinalSummary(best, initialFitnessLevel, initialFitness, totalRounds, totalImprovements, totalSignificantImprovements);
} }
return best; return best;
...@@ -410,12 +433,13 @@ public class VariableNeighborhoodSearch { ...@@ -410,12 +433,13 @@ public class VariableNeighborhoodSearch {
* 记录变邻域搜索最终总结 * 记录变邻域搜索最终总结
*/ */
private void logVNSFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness, private void logVNSFinalSummary(Chromosome best, double[] initialFitnessLevel, double initialFitness,
int totalRounds, int totalImprovements) { int totalRounds, int totalImprovements, int totalSignificantImprovements) {
StringBuilder sb = new StringBuilder("变邻域搜索 - 最终总结: "); StringBuilder sb = new StringBuilder("变邻域搜索 - 最终总结: ");
double[] currentFitness = best.getFitnessLevel(); double[] currentFitness = best.getFitnessLevel();
sb.append(String.format("总轮次%d次, 成功改进%d次, 改进率%.2f%%. ", sb.append(String.format("总轮次%d次, 成功改进%d次(显著%d次), 改进率%.2f%%. ",
totalRounds, totalImprovements, totalRounds > 0 ? (double)totalImprovements / totalRounds * 100 : 0)); totalRounds, totalImprovements, totalSignificantImprovements,
totalRounds > 0 ? (double)totalImprovements / totalRounds * 100 : 0));
// 记录各邻域结构的成功率 // 记录各邻域结构的成功率
sb.append("邻域成功率: "); sb.append("邻域成功率: ");
......
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