Commit 6d63a60c authored by Tong Li's avatar Tong Li

Merge remote-tracking branch 'origin/tl'

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