diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm index 13ec7e77..5fba4952 100644 Binary files a/Bin/Config/Lang/cn/nmNum_cn.qm and b/Bin/Config/Lang/cn/nmNum_cn.qm differ diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts index 28acd643..104dcbea 100644 --- a/Bin/Config/Lang/cn/nmNum_cn.ts +++ b/Bin/Config/Lang/cn/nmNum_cn.ts @@ -1257,8 +1257,8 @@ Reason: %1 井储试调:相对斜率匹配误差=%1,井储=%2 → %3 - Wellbore recheck: early error=%1, total limit=%2, shape limit=%3. - 井储表皮回检:前期相对斜率匹配误差=%1,整体误差上限=%2,形状误差上限=%3。 + Wellbore recheck: early shape error=%1, shape limit=%2. + 井储表皮回检:前期形状误差=%1,整体形状误差上限=%2。 early relative-slope error restored within tolerance @@ -1273,8 +1273,8 @@ Reason: %1 井储表皮回检在灵敏度评价期间完成 - total target reached during shape fitting - 形状调整期间已达到总误差目标 + Sensitivity probe accepted: shape error=%1 + 接受灵敏度探针:形状误差=%1 fresh sensitivity at joint shape entry diff --git a/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp b/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp index 1aeccba9..378e7276 100644 --- a/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp @@ -1212,9 +1212,9 @@ void nmCalculationAutoFitLM::writeTraceMetaFile() QTextStream out(&metaFile); out << "{\n"; - out << " \"schema_version\": 29,\n"; + out << " \"schema_version\": 30,\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_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"; @@ -1225,7 +1225,7 @@ 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_wellbore_acceptance\": \"locked_gap_direction_and_early_shape_decrease\",\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_sensitivity_refresh\": \"full Jacobian at joint shape entry and stagnation confirmation\",\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"; @@ -1234,7 +1234,7 @@ void nmCalculationAutoFitLM::writeTraceMetaFile() 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 << " \"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 << " \"total_stage_shape_constraint\": false,\n"; out << " \"total_parameter_selection\": \"all_valid_free_columns\",\n"; @@ -2154,7 +2154,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() int heightStagnation = 0; double heightScale = 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).") .arg(heightBudget)); for(int trial = 0; trial < heightBudget && processPauseAndStop(); ++trial) { @@ -2211,9 +2211,8 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() if(m_shouldStop) return LM_USER_STOPPED; // 第二阶段不按迭代比例截断;普通形状按完整搜索轮次判断是否仍有显著改善。 - // 井储、表皮保持冻结,总误差上限仍固定于普通形状阶段入口。 - bool shapeStage = current.fitness >= m_targetError; - double shapeValueLimit = current.fitness + qMax(0.02, 0.25 * current.fitness); + // 普通形状调整冻结井储、表皮,只按形状验收;总误差达标只在第三阶段判断。 + bool shapeStage = true; bool jointShapeStarted = false; double shapeRoundBaseline = current.breakdown.shapeLoss; int shapeRoundNumber = 0; @@ -2230,7 +2229,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() bool wellboreRecheck = false; bool wellboreRecheckDone = false; double earlyWellboreBaseline = current.breakdown.earlyParallelLoss; - double recheckTotalLimit = 0.0; double recheckShapeLimit = 0.0; // 先井储、再表皮;回检沿用相同顺序和前期指标,不回到形状阶段反复循环。 bool earlyShapeStage = shapeStage && wellboreParameterCount > 0; @@ -2270,11 +2268,10 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() const int column = m_enabledParamIndices.indexOf(earlyShapeParameter); return earlyGapDirection * (point.coordinates[column] - base.coordinates[column]) > 0.0 && point.breakdown.earlyParallelLoss < base.breakdown.earlyParallelLoss && - (!wellboreRecheck || (point.fitness <= recheckTotalLimit && - point.breakdown.shapeLoss <= recheckShapeLimit)); + (!wellboreRecheck || point.breakdown.shapeLoss <= recheckShapeLimit); } return shapeStage - ? point.breakdown.shapeLoss < base.breakdown.shapeLoss && point.fitness <= shapeValueLimit + ? point.breakdown.shapeLoss < base.breakdown.shapeLoss // 预调整结束后恢复原 LM:有效候选只按整体误差下降接受。 : point.fitness < base.fitness; }; @@ -2408,7 +2405,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() initialEarlyGapBias = trustRegionEarlyGapBias(current.breakdown); earlyGapDirection = trustRegionEarlyGapDirection(initialEarlyGapBias); 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); effectiveImprovementBaseline = current.breakdown.earlyParallelLoss; // 其他参数已改变,回检入口重测形状灵敏度,方向由本轮初始间距重新确定。 @@ -2416,9 +2413,9 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() reuseSensitivityForNextStage(); rebuildRequested = true; 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(recheckTotalLimit, 0, 'g', 6).arg(recheckShapeLimit, 0, 'g', 6)); + .arg(recheckShapeLimit, 0, 'g', 6)); writeTraceRow(m_currentIteration, -1, "stage_switch", current.parameters, current.fitness, true, 0, "shape_to_wellbore_recheck", ¤t.breakdown); announceEarlyGapDirection(); @@ -2451,8 +2448,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() return; } effectiveImprovementBaseline = current.breakdown.shapeLoss; - // 井储、表皮可使总误差上升;联合形状阶段从当前工作点建立固定上限。 - shapeValueLimit = current.fitness + qMax(0.02, 0.25 * current.fitness); reuseSensitivityForNextStage(); 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, @@ -2733,8 +2728,9 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() ¤t.breakdown); emit logMessageGenerated( (earlyShapeStage ? tr("Sensitivity probe accepted: early shape error=%1") - : tr("Sensitivity probe accepted: total error=%1")) - .arg(earlyShapeStage ? current.breakdown.earlyParallelLoss : current.fitness, 0, 'e', 4)); + : (shapeStage ? tr("Sensitivity probe accepted: shape error=%1") + : tr("Sensitivity probe accepted: total error=%1"))) + .arg(stageError(current), 0, 'e', 4)); } else { restoreEvaluationState(current); } @@ -2819,11 +2815,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() : LM_LOCAL_OPTIMUM; break; } - if(shapeStage && !earlyShapeStage && current.fitness < m_targetError) { - finishShapeStage(tr("total target reached during shape fitting")); - --iteration; - continue; - } if(!shapeStage && current.fitness < m_targetError) { promoteSampling(true); stopReason = LM_TARGET_ACHIEVED; @@ -2956,37 +2947,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() : buildTrustRegionFisherStep(stepInformation, columns, current.coordinates, damping, trustRadius, minimumCoordinateStep, &step, &reduction); 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); if(selectedColumns.isEmpty() || reduction > predictedReduction + tolerance || (qAbs(reduction - predictedReduction) <= tolerance && @@ -3141,7 +3101,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() } // 普通形状步真实表现可靠时,沿同一联合方向最多扩步试算一次,不区分参数类型。 - // 扩步仍须通过固定总误差上限且优于原步,否则保留原候选。 + // 扩步只按整体形状验收,优于原步才替换,否则保留原候选。 if(shapeStage && !earlyShapeStage && acceptable(candidate, current) && processPauseAndStop()) { const double ordinaryEnergy = 0.5 * trustRegionSquaredNorm(objectiveResidual); const double ordinaryReduction = ordinaryEnergy - 0.5 * trustRegionSquaredNorm(candidate.breakdown.shapeResiduals); @@ -3286,7 +3246,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() .arg(iteration + 1) .arg(componentDisplayName) .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"))); emit progressUpdated(shapeStage ? -1 : totalIterations, m_globalBestFitness); @@ -3306,9 +3266,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() 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) { promoteSampling(true); stopReason = LM_TARGET_ACHIEVED; @@ -3337,7 +3294,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting() return LM_USER_STOPPED; } if(samplingRefreshFailed) return LM_OPTIMIZATION_FAILED; - if(current.fitness < m_targetError) { + if(!shapeStage && current.fitness < m_targetError) { promoteSampling(true); return samplingRefreshFailed ? LM_OPTIMIZATION_FAILED : LM_TARGET_ACHIEVED; }