Compare commits

...

2 Commits

Author SHA1 Message Date
lvjunjie 43b7c770ed perf(nmNum): 跳过 LM 形状阶段冻结参数的灵敏度试算
- 普通形状调整仅计算可调参数的灵敏度,跳过冻结的井储和表皮
- 保留井储表皮初调、回检及整体 LM 阶段的灵敏度重建逻辑
- 按当前子阶段所需参数列数显示重建结果,同步轨迹策略元数据和注释
2 weeks ago
lvjunjie 08de98335a refactor(nmNum): 分离 LM 三阶段拟合验收目标
- 渗透率预调整仅按上下误差验收,不再因总误差达标跳过预调整
- 移除形状阶段总误差上限、预测缩步及总误差达标提前退出
- 井储表皮回检仅按前期形状改善与整体形状容差验收
- 保留第三阶段按整体误差联合微调,同步阶段误差日志、轨迹元数据及中文翻译
2 weeks ago

Binary file not shown.

@ -1257,8 +1257,8 @@ Reason: %1</source>
<translation>井储试调:相对斜率匹配误差=%1,井储=%2 → %3</translation> <translation>井储试调:相对斜率匹配误差=%1,井储=%2 → %3</translation>
</message> </message>
<message> <message>
<source>Wellbore recheck: early error=%1, total limit=%2, shape limit=%3.</source> <source>Wellbore recheck: early shape error=%1, shape limit=%2.</source>
<translation>井储表皮回检:前期相对斜率匹配误差=%1,整体误差上限=%2,形状误差上限=%3。</translation> <translation>井储表皮回检:前期形状误差=%1,整体形状误差上限=%2。</translation>
</message> </message>
<message> <message>
<source>early relative-slope error restored within tolerance</source> <source>early relative-slope error restored within tolerance</source>
@ -1273,8 +1273,8 @@ Reason: %1</source>
<translation>井储表皮回检在灵敏度评价期间完成</translation> <translation>井储表皮回检在灵敏度评价期间完成</translation>
</message> </message>
<message> <message>
<source>total target reached during shape fitting</source> <source>Sensitivity probe accepted: shape error=%1</source>
<translation>形状调整期间已达到总误差目标</translation> <translation>接受灵敏度探针:形状误差=%1</translation>
</message> </message>
<message> <message>
<source>fresh sensitivity at joint shape entry</source> <source>fresh sensitivity at joint shape entry</source>

@ -1212,9 +1212,9 @@ void nmCalculationAutoFitLM::writeTraceMetaFile()
QTextStream out(&metaFile); QTextStream out(&metaFile);
out << "{\n"; out << "{\n";
out << " \"schema_version\": 29,\n"; out << " \"schema_version\": 31,\n";
out << " \"strategy\": \"permeability_height_then_shape_then_joint_lm\",\n"; out << " \"strategy\": \"permeability_height_then_shape_then_joint_lm\",\n";
out << " \"height_acceptance\": \"reliable_vertical_loss_decrease; no_shape_loss_constraint\",\n"; out << " \"height_acceptance\": \"reliable_vertical_loss_decrease; no_shape_or_total_loss_constraint\",\n";
out << " \"shape_priority\": \"storage_then_skin_then_shape_without_wellbore_then_optional_wellbore_recheck\",\n"; out << " \"shape_priority\": \"storage_then_skin_then_shape_without_wellbore_then_optional_wellbore_recheck\",\n";
out << " \"shape_metric\": \"pressure_and_derivative_log_slopes_81_points_lag_8\",\n"; out << " \"shape_metric\": \"pressure_and_derivative_log_slopes_81_points_lag_8\",\n";
out << " \"early_parallel_metric\": \"pressure_and_derivative_log_slopes_first_window_81_points_lag_8\",\n"; out << " \"early_parallel_metric\": \"pressure_and_derivative_log_slopes_first_window_81_points_lag_8\",\n";
@ -1225,16 +1225,16 @@ void nmCalculationAutoFitLM::writeTraceMetaFile()
out << " \"early_initial_expansion_policy\": \"before_first_accepted_shape_improvement; if_shape_worsens_double_coordinate_step_from_unchanged_base_up_to_parameter_bound; retain_base_on_failure\",\n"; out << " \"early_initial_expansion_policy\": \"before_first_accepted_shape_improvement; if_shape_worsens_double_coordinate_step_from_unchanged_base_up_to_parameter_bound; retain_base_on_failure\",\n";
out << " \"early_wellbore_acceptance\": \"locked_gap_direction_and_early_shape_decrease\",\n"; out << " \"early_wellbore_acceptance\": \"locked_gap_direction_and_early_shape_decrease\",\n";
out << " \"early_wellbore_total_constraint\": false,\n"; out << " \"early_wellbore_total_constraint\": false,\n";
out << " \"shape_stage_total_tolerance\": \"max(0.02, 25% of stage entry total)\",\n"; out << " \"shape_stage_total_constraint\": false,\n";
out << " \"shape_wellbore_parameters_frozen\": true,\n"; out << " \"shape_wellbore_parameters_frozen\": true,\n";
out << " \"shape_sensitivity_refresh\": \"full Jacobian at joint shape entry and stagnation confirmation\",\n"; out << " \"shape_sensitivity_refresh\": \"non_wellbore_columns_only at joint shape entry and stagnation confirmation; full Jacobian rebuilt at total-stage entry\",\n";
out << " \"shape_expansion_policy\": \"one expansion per reliable shape direction, up to 2x when actual rho exceeds 0.75; retain ordinary step on failure\",\n"; out << " \"shape_expansion_policy\": \"one expansion per reliable shape direction, up to 2x when actual rho exceeds 0.75; retain ordinary step on failure\",\n";
out << " \"shape_global_parameter_selection\": \"all_valid_non_wellbore_columns_with_positive_response\",\n"; out << " \"shape_global_parameter_selection\": \"all_valid_non_wellbore_columns_with_positive_response\",\n";
out << " \"stage2_budget\": \"adaptive, no fixed iteration or evaluation quota; full window/global rounds, 2 ineffective rounds then fresh-J confirmation\",\n"; out << " \"stage2_budget\": \"adaptive, no fixed iteration or evaluation quota; full window/global rounds, 2 ineffective rounds then fresh-J confirmation\",\n";
out << " \"shape_round_improvement_threshold\": \"max(0.0001, 1% of round entry shape loss)\",\n"; out << " \"shape_round_improvement_threshold\": \"max(0.0001, 1% of round entry shape loss)\",\n";
out << " \"iteration_count_scope\": \"max_iterations applies to total-stage LM; trace iteration remains cumulative\",\n"; out << " \"iteration_count_scope\": \"max_iterations applies to total-stage LM; trace iteration remains cumulative\",\n";
out << " \"wellbore_recheck_trigger\": \"early loss exceeds initial early-stage exit by max(0.0001, 10%)\",\n"; out << " \"wellbore_recheck_trigger\": \"early loss exceeds initial early-stage exit by max(0.0001, 10%)\",\n";
out << " \"wellbore_recheck_acceptance\": \"early decrease with fixed entry total and shape limits, each max(0.0001, 5%)\",\n"; out << " \"wellbore_recheck_acceptance\": \"early decrease with fixed entry shape limit max(0.0001, 5%); no_total_loss_constraint\",\n";
out << " \"wellbore_recheck_budget\": \"once when early shape degrades; each wellbore parameter stops after 2 ineffective steps, independent of total-stage budget\",\n"; out << " \"wellbore_recheck_budget\": \"once when early shape degrades; each wellbore parameter stops after 2 ineffective steps, independent of total-stage budget\",\n";
out << " \"total_stage_shape_constraint\": false,\n"; out << " \"total_stage_shape_constraint\": false,\n";
out << " \"total_parameter_selection\": \"all_valid_free_columns\",\n"; out << " \"total_parameter_selection\": \"all_valid_free_columns\",\n";
@ -2038,7 +2038,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
StopReasonLM stopReason = LM_MAX_ITERATIONS; StopReasonLM stopReason = LM_MAX_ITERATIONS;
// jacobian 的行对应当前采样层的残差,列对应用户勾选的参数。 // jacobian 的行对应当前采样层的残差,列对应用户勾选的参数。
// Fisher 按当前阶段取数值或形状残差行,完整 Jacobian 在阶段之间复用。 // Fisher 按当前阶段取数值或形状残差行;冻结列不参与形状差分,整体阶段重建全部列。
QVector<QVector<double> > jacobian; QVector<QVector<double> > jacobian;
QVector<bool> jacobianColumnValid(dimensions, false); QVector<bool> jacobianColumnValid(dimensions, false);
@ -2154,7 +2154,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
int heightStagnation = 0; int heightStagnation = 0;
double heightScale = 1.0; double heightScale = 1.0;
double heightSlope = -1.0; double heightSlope = -1.0;
if(permeabilityColumn >= 0 && current.fitness >= m_targetError) { if(permeabilityColumn >= 0) {
emit logMessageGenerated(tr("LM stage 1: align curve height using permeability only (up to %1 evaluations).") emit logMessageGenerated(tr("LM stage 1: align curve height using permeability only (up to %1 evaluations).")
.arg(heightBudget)); .arg(heightBudget));
for(int trial = 0; trial < heightBudget && processPauseAndStop(); ++trial) { for(int trial = 0; trial < heightBudget && processPauseAndStop(); ++trial) {
@ -2211,9 +2211,8 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if(m_shouldStop) return LM_USER_STOPPED; if(m_shouldStop) return LM_USER_STOPPED;
// 第二阶段不按迭代比例截断;普通形状按完整搜索轮次判断是否仍有显著改善。 // 第二阶段不按迭代比例截断;普通形状按完整搜索轮次判断是否仍有显著改善。
// 井储、表皮保持冻结,总误差上限仍固定于普通形状阶段入口。 // 普通形状调整冻结井储、表皮,只按形状验收;总误差达标只在第三阶段判断。
bool shapeStage = current.fitness >= m_targetError; bool shapeStage = true;
double shapeValueLimit = current.fitness + qMax(0.02, 0.25 * current.fitness);
bool jointShapeStarted = false; bool jointShapeStarted = false;
double shapeRoundBaseline = current.breakdown.shapeLoss; double shapeRoundBaseline = current.breakdown.shapeLoss;
int shapeRoundNumber = 0; int shapeRoundNumber = 0;
@ -2230,7 +2229,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
bool wellboreRecheck = false; bool wellboreRecheck = false;
bool wellboreRecheckDone = false; bool wellboreRecheckDone = false;
double earlyWellboreBaseline = current.breakdown.earlyParallelLoss; double earlyWellboreBaseline = current.breakdown.earlyParallelLoss;
double recheckTotalLimit = 0.0;
double recheckShapeLimit = 0.0; double recheckShapeLimit = 0.0;
// 先井储、再表皮;回检沿用相同顺序和前期指标,不回到形状阶段反复循环。 // 先井储、再表皮;回检沿用相同顺序和前期指标,不回到形状阶段反复循环。
bool earlyShapeStage = shapeStage && wellboreParameterCount > 0; bool earlyShapeStage = shapeStage && wellboreParameterCount > 0;
@ -2270,11 +2268,10 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
const int column = m_enabledParamIndices.indexOf(earlyShapeParameter); const int column = m_enabledParamIndices.indexOf(earlyShapeParameter);
return earlyGapDirection * (point.coordinates[column] - base.coordinates[column]) > 0.0 && return earlyGapDirection * (point.coordinates[column] - base.coordinates[column]) > 0.0 &&
point.breakdown.earlyParallelLoss < base.breakdown.earlyParallelLoss && point.breakdown.earlyParallelLoss < base.breakdown.earlyParallelLoss &&
(!wellboreRecheck || (point.fitness <= recheckTotalLimit && (!wellboreRecheck || point.breakdown.shapeLoss <= recheckShapeLimit);
point.breakdown.shapeLoss <= recheckShapeLimit));
} }
return shapeStage return shapeStage
? point.breakdown.shapeLoss < base.breakdown.shapeLoss && point.fitness <= shapeValueLimit ? point.breakdown.shapeLoss < base.breakdown.shapeLoss
// 预调整结束后恢复原 LM:有效候选只按整体误差下降接受。 // 预调整结束后恢复原 LM:有效候选只按整体误差下降接受。
: point.fitness < base.fitness; : point.fitness < base.fitness;
}; };
@ -2374,7 +2371,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
wellboreRecheck = false; wellboreRecheck = false;
effectiveImprovementBaseline = current.fitness; effectiveImprovementBaseline = current.fitness;
reuseSensitivityForNextStage(); reuseSensitivityForNextStage();
// 初调、回检只测井储/表皮;所有出口都在当前点重建完整 J,不能把缺列模型带入整体 LM。 // 第二阶段只测各子阶段需要的列;所有出口都在当前点重建完整 J,不能把缺列模型带入整体 LM。
jacobian.clear(); jacobian.clear();
rebuildRequested = true; rebuildRequested = true;
rebuildReason = QT_TR_NOOP("full sensitivity at total-stage entry"); rebuildReason = QT_TR_NOOP("full sensitivity at total-stage entry");
@ -2408,7 +2405,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
initialEarlyGapBias = trustRegionEarlyGapBias(current.breakdown); initialEarlyGapBias = trustRegionEarlyGapBias(current.breakdown);
earlyGapDirection = trustRegionEarlyGapDirection(initialEarlyGapBias); earlyGapDirection = trustRegionEarlyGapDirection(initialEarlyGapBias);
earlyShapeHasImproved = false; earlyShapeHasImproved = false;
recheckTotalLimit = current.fitness + qMax(1.0e-4, 0.05 * current.fitness); // 回检只约束形状:允许总误差上升,但保护其他参数已调好的整体形状。
recheckShapeLimit = current.breakdown.shapeLoss + qMax(1.0e-4, 0.05 * current.breakdown.shapeLoss); recheckShapeLimit = current.breakdown.shapeLoss + qMax(1.0e-4, 0.05 * current.breakdown.shapeLoss);
effectiveImprovementBaseline = current.breakdown.earlyParallelLoss; effectiveImprovementBaseline = current.breakdown.earlyParallelLoss;
// 其他参数已改变,回检入口重测形状灵敏度,方向由本轮初始间距重新确定。 // 其他参数已改变,回检入口重测形状灵敏度,方向由本轮初始间距重新确定。
@ -2416,9 +2413,9 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
reuseSensitivityForNextStage(); reuseSensitivityForNextStage();
rebuildRequested = true; rebuildRequested = true;
rebuildReason = QT_TR_NOOP("new sensitivity for wellbore recheck"); rebuildReason = QT_TR_NOOP("new sensitivity for wellbore recheck");
emit logMessageGenerated(tr("Wellbore recheck: early error=%1, total limit=%2, shape limit=%3.") emit logMessageGenerated(tr("Wellbore recheck: early shape error=%1, shape limit=%2.")
.arg(current.breakdown.earlyParallelLoss, 0, 'g', 6) .arg(current.breakdown.earlyParallelLoss, 0, 'g', 6)
.arg(recheckTotalLimit, 0, 'g', 6).arg(recheckShapeLimit, 0, 'g', 6)); .arg(recheckShapeLimit, 0, 'g', 6));
writeTraceRow(m_currentIteration, -1, "stage_switch", current.parameters, current.fitness, writeTraceRow(m_currentIteration, -1, "stage_switch", current.parameters, current.fitness,
true, 0, "shape_to_wellbore_recheck", &current.breakdown); true, 0, "shape_to_wellbore_recheck", &current.breakdown);
announceEarlyGapDirection(); announceEarlyGapDirection();
@ -2451,8 +2448,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
return; return;
} }
effectiveImprovementBaseline = current.breakdown.shapeLoss; effectiveImprovementBaseline = current.breakdown.shapeLoss;
// 井储、表皮可使总误差上升;联合形状阶段从当前工作点建立固定上限。
shapeValueLimit = current.fitness + qMax(0.02, 0.25 * current.fitness);
reuseSensitivityForNextStage(); reuseSensitivityForNextStage();
emit logMessageGenerated(tr("Shape fitting continues with storage and skin fixed; a conditional wellbore recheck follows.")); emit logMessageGenerated(tr("Shape fitting continues with storage and skin fixed; a conditional wellbore recheck follows."));
writeTraceRow(m_currentIteration, -1, "stage_switch", current.parameters, current.fitness, writeTraceRow(m_currentIteration, -1, "stage_switch", current.parameters, current.fitness,
@ -2567,6 +2562,8 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
auto rebuildSensitivity = [&]() -> bool { auto rebuildSensitivity = [&]() -> bool {
// 第二阶段差分不受第三阶段额度限制;每列仍只有有限的缩步和反向重试。 // 第二阶段差分不受第三阶段额度限制;每列仍只有有限的缩步和反向重试。
const int evaluationLimit = shapeStage ? (std::numeric_limits<int>::max)() : maximumEvaluations; const int evaluationLimit = shapeStage ? (std::numeric_limits<int>::max)() : maximumEvaluations;
const int sensitivityColumnCount = shapeStage
? (earlyShapeStage ? wellboreParameterCount : dimensions - wellboreParameterCount) : dimensions;
const TrustRegionEvaluation base = current; const TrustRegionEvaluation base = current;
const QVector<double> baseResidual = trustRegionFullResidual(base.breakdown); const QVector<double> baseResidual = trustRegionFullResidual(base.breakdown);
const int residualCount = baseResidual.size(); const int residualCount = baseResidual.size();
@ -2594,6 +2591,8 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
++column) { ++column) {
const int parameterIndex = m_enabledParamIndices[column]; const int parameterIndex = m_enabledParamIndices[column];
if(earlyShapeStage && parameterIndex != 1 && parameterIndex != 2) continue; if(earlyShapeStage && parameterIndex != 1 && parameterIndex != 2) continue;
// 普通形状阶段跳过冻结的井储、表皮,避免无用正演;回检和整体阶段会重新差分。
if(shapeStage && !earlyShapeStage && !parameterAllowedInStage(column)) continue;
const double lower = m_parameterLower[parameterIndex]; const double lower = m_parameterLower[parameterIndex];
const double upper = m_parameterUpper[parameterIndex]; const double upper = m_parameterUpper[parameterIndex];
if(upper <= lower) continue; if(upper <= lower) continue;
@ -2681,7 +2680,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
jacobianColumnValid[column] = true; jacobianColumnValid[column] = true;
columnBuilt = true; columnBuilt = true;
// 其他参数仍建立灵敏度供后续复用,但不能绕过当前子阶段的选参限制。 // 前期同时测井储和表皮,但缓存探针不能绕过当前子阶段的选参限制。
// 前期首次正式调整必须从小步开始,测形状灵敏度的大探针不能提前成为工作点。 // 前期首次正式调整必须从小步开始,测形状灵敏度的大探针不能提前成为工作点。
if((!earlyShapeStage || earlyShapeHasImproved) && if((!earlyShapeStage || earlyShapeHasImproved) &&
parameterAllowedInStage(column) && acceptable(probe, base) && parameterAllowedInStage(column) && acceptable(probe, base) &&
@ -2733,8 +2732,9 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
&current.breakdown); &current.breakdown);
emit logMessageGenerated( emit logMessageGenerated(
(earlyShapeStage ? tr("Sensitivity probe accepted: early shape error=%1") (earlyShapeStage ? tr("Sensitivity probe accepted: early shape error=%1")
: tr("Sensitivity probe accepted: total error=%1")) : (shapeStage ? tr("Sensitivity probe accepted: shape error=%1")
.arg(earlyShapeStage ? current.breakdown.earlyParallelLoss : current.fitness, 0, 'e', 4)); : tr("Sensitivity probe accepted: total error=%1")))
.arg(stageError(current), 0, 'e', 4));
} else { } else {
restoreEvaluationState(current); restoreEvaluationState(current);
} }
@ -2751,7 +2751,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
emit logMessageGenerated( emit logMessageGenerated(
tr("Sensitivity model rebuilt: %1/%2 parameter columns valid") tr("Sensitivity model rebuilt: %1/%2 parameter columns valid")
.arg(validColumnCount) .arg(validColumnCount)
.arg(dimensions)); .arg(sensitivityColumnCount));
return true; return true;
}; };
@ -2772,7 +2772,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if(shapeStage && !earlyShapeStage && !jointShapeStarted) { if(shapeStage && !earlyShapeStage && !jointShapeStarted) {
jointShapeStarted = true; jointShapeStarted = true;
shapeRoundBaseline = current.breakdown.shapeLoss; shapeRoundBaseline = current.breakdown.shapeLoss;
// 初调已改变井储/表皮,普通形状必须在新的工作点测完整响应。 // 初调已改变井储/表皮,普通形状必须在新的工作点重测其余可调参数的响应。
jacobian.clear(); jacobian.clear();
reuseSensitivityForNextStage(); reuseSensitivityForNextStage();
rebuildRequested = true; rebuildRequested = true;
@ -2819,11 +2819,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
: LM_LOCAL_OPTIMUM; : LM_LOCAL_OPTIMUM;
break; break;
} }
if(shapeStage && !earlyShapeStage && current.fitness < m_targetError) {
finishShapeStage(tr("total target reached during shape fitting"));
--iteration;
continue;
}
if(!shapeStage && current.fitness < m_targetError) { if(!shapeStage && current.fitness < m_targetError) {
promoteSampling(true); promoteSampling(true);
stopReason = LM_TARGET_ACHIEVED; stopReason = LM_TARGET_ACHIEVED;
@ -2956,37 +2951,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
: buildTrustRegionFisherStep(stepInformation, columns, current.coordinates, : buildTrustRegionFisherStep(stepInformation, columns, current.coordinates,
damping, trustRadius, minimumCoordinateStep, &step, &reduction); damping, trustRadius, minimumCoordinateStep, &step, &reduction);
if(!stepBuilt) continue; if(!stepBuilt) continue;
// 仅联合形状阶段预测总误差上限;井储、表皮步长不受总误差裁剪。
if(shapeStage && !earlyShapeStage) {
auto predictedGuard = [&](double scale) -> double {
double energy = 0.0;
for(int row = 0; row < current.breakdown.residualVector.size(); ++row) {
double value = current.breakdown.residualVector[row];
for(int column = 0; column < dimensions; ++column)
value += scale * jacobian[row][column] * step[column];
energy += value * value;
}
return qSqrt(energy);
};
const double currentGuard = predictedGuard(0.0);
const double predictedLimit = currentGuard + 0.9 * qMax(0.0, shapeValueLimit - currentGuard);
if(predictedGuard(1.0) > predictedLimit) {
double low = 0.0, high = 1.0;
for(int search = 0; search < 32; ++search) {
const double middle = 0.5 * (low + high);
if(predictedGuard(middle) <= predictedLimit) low = middle;
else high = middle;
}
const double stepScale = low;
for(int column = 0; column < dimensions; ++column) step[column] *= stepScale;
if(qSqrt(trustRegionSquaredNorm(step)) < minimumCoordinateStep) continue;
reduction = -trustRegionDotProduct(stepInformation.gradient, step);
for(int a = 0; a < dimensions; ++a)
for(int b = 0; b < dimensions; ++b)
reduction -= 0.5 * step[a] * stepInformation.matrix[a][b] * step[b];
if(!isFiniteNumber(reduction) || reduction <= 1.0e-14) continue;
}
}
const double tolerance = 1.0e-12 * qMax(predictedReduction, reduction); const double tolerance = 1.0e-12 * qMax(predictedReduction, reduction);
if(selectedColumns.isEmpty() || reduction > predictedReduction + tolerance || if(selectedColumns.isEmpty() || reduction > predictedReduction + tolerance ||
(qAbs(reduction - predictedReduction) <= tolerance && (qAbs(reduction - predictedReduction) <= tolerance &&
@ -3141,7 +3105,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
} }
// 普通形状步真实表现可靠时,沿同一联合方向最多扩步试算一次,不区分参数类型。 // 普通形状步真实表现可靠时,沿同一联合方向最多扩步试算一次,不区分参数类型。
// 扩步仍须通过固定总误差上限且优于原步,否则保留原候选。 // 扩步只按整体形状验收,优于原步才替换,否则保留原候选。
if(shapeStage && !earlyShapeStage && acceptable(candidate, current) && processPauseAndStop()) { if(shapeStage && !earlyShapeStage && acceptable(candidate, current) && processPauseAndStop()) {
const double ordinaryEnergy = 0.5 * trustRegionSquaredNorm(objectiveResidual); const double ordinaryEnergy = 0.5 * trustRegionSquaredNorm(objectiveResidual);
const double ordinaryReduction = ordinaryEnergy - 0.5 * trustRegionSquaredNorm(candidate.breakdown.shapeResiduals); const double ordinaryReduction = ordinaryEnergy - 0.5 * trustRegionSquaredNorm(candidate.breakdown.shapeResiduals);
@ -3286,7 +3250,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
.arg(iteration + 1) .arg(iteration + 1)
.arg(componentDisplayName) .arg(componentDisplayName)
.arg(selectedColumns.size()) .arg(selectedColumns.size())
.arg(earlyShapeStage ? candidate.breakdown.earlyParallelLoss : candidate.fitness, 0, 'e', 4) .arg(stageError(candidate), 0, 'e', 4)
.arg(accepted ? tr("accepted") : tr("rejected"))); .arg(accepted ? tr("accepted") : tr("rejected")));
emit progressUpdated(shapeStage ? -1 : totalIterations, m_globalBestFitness); emit progressUpdated(shapeStage ? -1 : totalIterations, m_globalBestFitness);
@ -3306,9 +3270,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if(stopReason == LM_LOCAL_OPTIMUM || samplingRefreshFailed) break; if(stopReason == LM_LOCAL_OPTIMUM || samplingRefreshFailed) break;
} }
if(shapeStage && !earlyShapeStage && current.fitness < m_targetError) {
finishShapeStage(tr("total target reached during shape fitting"));
}
if(!shapeStage && current.fitness < m_targetError) { if(!shapeStage && current.fitness < m_targetError) {
promoteSampling(true); promoteSampling(true);
stopReason = LM_TARGET_ACHIEVED; stopReason = LM_TARGET_ACHIEVED;
@ -3337,7 +3298,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
return LM_USER_STOPPED; return LM_USER_STOPPED;
} }
if(samplingRefreshFailed) return LM_OPTIMIZATION_FAILED; if(samplingRefreshFailed) return LM_OPTIMIZATION_FAILED;
if(current.fitness < m_targetError) { if(!shapeStage && current.fitness < m_targetError) {
promoteSampling(true); promoteSampling(true);
return samplingRefreshFailed ? LM_OPTIMIZATION_FAILED : LM_TARGET_ACHIEVED; return samplingRefreshFailed ? LM_OPTIMIZATION_FAILED : LM_TARGET_ACHIEVED;
} }

Loading…
Cancel
Save