调整局部收敛判定

feature/MultiWellAutoFit-20260805
lvjunjie 5 days ago
parent e1a8610df4
commit 83a29152c9

Binary file not shown.

@ -49,6 +49,18 @@ Reason: %1</source>
</context> </context>
<context> <context>
<name>nmCalculationAutoFitPSO</name> <name>nmCalculationAutoFitPSO</name>
<message>
<source>Effective improvement threshold: max(%1, %2% of baseline error); %3 consecutive ineffective steps trigger convergence confirmation</source>
<translation> %1 %2% %3 </translation>
</message>
<message>
<source>No effective improvement for %1 consecutive steps; rebuilding sensitivity model for confirmation</source>
<translation> %1 </translation>
</message>
<message>
<source>Sensitivity rebuild produced no effective improvement; local convergence detected</source>
<translation></translation>
</message>
<message> <message>
<source>=== User Stop Request Received ===</source> <source>=== User Stop Request Received ===</source>
<translation>=== ===</translation> <translation>=== ===</translation>

@ -4235,6 +4235,11 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
const double maximumTrustRadius = 0.30; const double maximumTrustRadius = 0.30;
const double columnCorrelationLimit = 0.995; const double columnCorrelationLimit = 0.995;
const double diagnosisThreshold = 1.0e-5; const double diagnosisThreshold = 1.0e-5;
// 误差下降至少达到绝对 1e-5 且相对当前有效基准 0.2% 才算有效改善。
// 更小的下降仍保留为最佳解,但不能反复清除停滞状态、延长拟合时间。
const double effectiveRelativeImprovement = 2.0e-3;
const double effectiveAbsoluteImprovement = 1.0e-5;
const int maximumIneffectiveSteps = 3;
// damping 是 LM 阻尼;拒绝或预测失准时增大,真实下降与预测一致时减小。 // damping 是 LM 阻尼;拒绝或预测失准时增大,真实下降与预测一致时减小。
// 两组累计量控制 Jacobian 重建,避免长期使用已偏离当前工作点的局部模型。 // 两组累计量控制 Jacobian 重建,避免长期使用已偏离当前工作点的局部模型。
@ -4243,9 +4248,11 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
int consecutiveRejectedSteps = 0; int consecutiveRejectedSteps = 0;
int consecutiveSolverFailures = 0; int consecutiveSolverFailures = 0;
int acceptedSinceRebuild = 0; int acceptedSinceRebuild = 0;
int consecutiveIneffectiveSteps = 0;
double movementSinceRebuild = 0.0; double movementSinceRebuild = 0.0;
bool rebuildRequested = true; bool rebuildRequested = true;
bool modelRebuiltAtMinimumRadius = false; bool modelRebuiltAtMinimumRadius = false;
bool stagnationConfirmationRequested = false;
StopReasonPSO stopReason = PSO_MAX_ITERATIONS; StopReasonPSO stopReason = PSO_MAX_ITERATIONS;
// jacobian 的行对应固定 160 维残差,列对应用户勾选的参数。 // jacobian 的行对应固定 160 维残差,列对应用户勾选的参数。
@ -4367,6 +4374,54 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
.arg(current.fitness, 0, 'e', 4) .arg(current.fitness, 0, 'e', 4)
.arg(maximumEvaluations)); .arg(maximumEvaluations));
// 有效改善始终相对“上一次有效改善后的误差”累计判断,避免一连串微小
// 下降每次都清零计数;累计达到门槛后才开始新的有效改善基准。
double effectiveImprovementBaseline = current.fitness;
auto registerEffectiveImprovement = [&](double fitness) -> bool {
const double requiredImprovement = qMax(
effectiveAbsoluteImprovement,
qAbs(effectiveImprovementBaseline) *
effectiveRelativeImprovement);
const double improvement = effectiveImprovementBaseline - fitness;
if(improvement < requiredImprovement) {
return false;
}
effectiveImprovementBaseline = fitness;
consecutiveIneffectiveSteps = 0;
stagnationConfirmationRequested = false;
return true;
};
// 连续三次没有有效改善时只请求一次灵敏度重建。重建完成后由主循环
// 直接检查累计改善,仍达不到门槛就判定局部收敛,不再继续微小试探。
auto recordIneffectiveStep = [&]() -> bool {
++consecutiveIneffectiveSteps;
if(consecutiveIneffectiveSteps < maximumIneffectiveSteps) {
return false;
}
if(stagnationConfirmationRequested) {
return true;
}
consecutiveIneffectiveSteps = 0;
stagnationConfirmationRequested = true;
rebuildRequested = true;
emit logMessageGenerated(
tr("No effective improvement for %1 consecutive steps; "
"rebuilding sensitivity model for confirmation")
.arg(maximumIneffectiveSteps));
return false;
};
emit logMessageGenerated(
tr("Effective improvement threshold: max(%1, %2% of baseline error); "
"%3 consecutive ineffective steps trigger convergence confirmation")
.arg(effectiveAbsoluteImprovement, 0, 'e', 2)
.arg(effectiveRelativeImprovement * 100.0, 0, 'f', 2)
.arg(maximumIneffectiveSteps));
if(current.fitness < m_targetError) { if(current.fitness < m_targetError) {
return PSO_TARGET_ACHIEVED; return PSO_TARGET_ACHIEVED;
} }
@ -4603,6 +4658,8 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
break; break;
} }
if(rebuildRequested) { if(rebuildRequested) {
const bool confirmingStagnation =
stagnationConfirmationRequested;
if(!rebuildSensitivity()) { if(!rebuildSensitivity()) {
stopReason = m_shouldStop stopReason = m_shouldStop
? PSO_USER_STOPPED ? PSO_USER_STOPPED
@ -4617,6 +4674,15 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
stopReason = PSO_MAX_ITERATIONS; stopReason = PSO_MAX_ITERATIONS;
break; break;
} }
const bool rebuildEffective =
registerEffectiveImprovement(current.fitness);
if(confirmingStagnation && !rebuildEffective) {
emit logMessageGenerated(
tr("Sensitivity rebuild produced no effective improvement; "
"local convergence detected"));
stopReason = PSO_LOCAL_OPTIMUM;
break;
}
} }
// 先确定当前最突出的可靠诊断误差,用其梯度回答“哪些参数最能改善 // 先确定当前最突出的可靠诊断误差,用其梯度回答“哪些参数最能改善
@ -4748,6 +4814,10 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
trustRadius = qMax(minimumTrustRadius, trustRadius * 0.5); trustRadius = qMax(minimumTrustRadius, trustRadius * 0.5);
damping = qMin(1.0e8, damping * 4.0); damping = qMin(1.0e8, damping * 4.0);
rebuildRequested = true; rebuildRequested = true;
if(recordIneffectiveStep()) {
stopReason = PSO_LOCAL_OPTIMUM;
break;
}
continue; continue;
} }
@ -4865,6 +4935,10 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
} }
rebuildRequested = true; rebuildRequested = true;
} }
if(recordIneffectiveStep()) {
stopReason = PSO_LOCAL_OPTIMUM;
break;
}
continue; continue;
} }
@ -4905,6 +4979,10 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
stopReason = PSO_CONSECUTIVE_FAILURES; stopReason = PSO_CONSECUTIVE_FAILURES;
break; break;
} }
if(recordIneffectiveStep()) {
stopReason = PSO_LOCAL_OPTIMUM;
break;
}
continue; continue;
} }
@ -4994,6 +5072,14 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
} }
} }
// 候选只要更优就继续作为 current 保存;是否足以解除停滞,则统一
// 相对上一次有效改善基准判断。拒绝和微小改善都会累计无效次数。
const bool effectiveImprovement =
registerEffectiveImprovement(current.fitness);
if(!effectiveImprovement && recordIneffectiveStep()) {
stopReason = PSO_LOCAL_OPTIMUM;
}
writeTraceRow(m_currentIteration, writeTraceRow(m_currentIteration,
-1, -1,
"trust_region_candidate", "trust_region_candidate",
@ -5018,6 +5104,10 @@ StopReasonPSO nmCalculationAutoFitPSO::runTrustRegionFitting()
.arg(accepted ? tr("accepted") : tr("rejected"))); .arg(accepted ? tr("accepted") : tr("rejected")));
emit progressUpdated(iteration + 1, m_globalBestFitness); emit progressUpdated(iteration + 1, m_globalBestFitness);
if(stopReason == PSO_LOCAL_OPTIMUM) {
break;
}
if(current.fitness < m_targetError) { if(current.fitness < m_targetError) {
stopReason = PSO_TARGET_ACHIEVED; stopReason = PSO_TARGET_ACHIEVED;
break; break;

Loading…
Cancel
Save