@ -671,6 +671,30 @@ static bool buildTrustRegionFisherStep(
return projectAndPredict ( ) ;
}
// 为每个可调参数独立求解 LM 步,按边界投影后的预测下降量选择一个参数。
static bool buildBestSingleParameterStep ( const TrustRegionFisher & information ,
const QVector < int > & available , const QVector < double > & coordinates ,
double damping , double trustRadius , double minimumStep ,
QVector < int > * selected , QVector < double > * step , double * predictedReduction )
{
selected - > clear ( ) ;
step - > fill ( 0.0 , coordinates . size ( ) ) ;
* predictedReduction = 0.0 ;
for ( int i = 0 ; i < available . size ( ) ; + + i ) {
QVector < int > singleColumn ( 1 , available [ i ] ) ;
QVector < double > trialStep ;
double trialPrediction = 0.0 ;
if ( buildTrustRegionFisherStep ( information , singleColumn , coordinates ,
damping , trustRadius , minimumStep , & trialStep , & trialPrediction ) & &
trialPrediction > * predictedReduction ) {
* selected = singleColumn ;
* step = trialStep ;
* predictedReduction = trialPrediction ;
}
}
return ! selected - > isEmpty ( ) ;
}
// 前期每次只调一个参数:间距锁定符号,形状 LM 提供幅度和后续验收依据。
static bool buildEarlyGapGuidedStep ( const TrustRegionFisher & shapeInformation ,
const QVector < int > & selected , const QVector < double > & coordinates , double direction ,
@ -691,7 +715,7 @@ static bool buildEarlyGapGuidedStep(const TrustRegionFisher& shapeInformation,
}
// 放大当前方向,仍受传入的最大半径和参数边界限制。
// 普通形状步要求预测下降; 前期初始探路可跨过预测上坡区,最终仍按真实形状验收。
// 前期初始探路可跨过预测上坡区,最终仍按真实形状验收。
static bool buildExpandedTrustRegionStep ( const TrustRegionFisher & information ,
const QVector < double > & coordinates , const QVector < double > & originalStep ,
double maximumRadius , QVector < double > * expandedStep , double * prediction ,
@ -1123,7 +1147,7 @@ void nmCalculationAutoFitLM::writeTraceMetaFile()
QTextStream out ( & metaFile ) ;
out < < " { \n " ;
out < < " \" schema_version \" : 3 6 ,\n " ;
out < < " \" schema_version \" : 3 9 ,\n " ;
out < < " \" strategy \" : \" permeability_height_then_shape_then_joint_lm \" , \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 " ;
@ -1138,11 +1162,12 @@ void nmCalculationAutoFitLM::writeTraceMetaFile()
out < < " \" early_wellbore_total_constraint \" : false, \n " ;
out < < " \" shape_stage_total_constraint \" : false, \n " ;
out < < " \" shape_wellbore_parameters_frozen \" : true, \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 accepted shape direction, up to 2x with predicted descent and parameter bounds; no_rho_gate; retain ordinary step on failure \" , \n " ;
out < < " \" shape_global_parameter_selection \" : \" all_valid_non_wellbore_columns_with_positive_response_at_every_shape_step; no_window_selection \" , \n " ;
out < < " \" stage2_budget \" : \" adaptive, no fixed iteration or evaluation quota; 2 ineffective shape attempts then one fresh-J global confirmation \" , \n " ;
out < < " \" shape_step_improvement_threshold \" : \" max(0.0001, 10% of last effective shape loss); accumulate small improvements \" , \n " ;
out < < " \" shape_sensitivity_refresh \" : \" non_wellbore_columns_once_at_sweep_entry; secant updates during sweep; full Jacobian rebuilt at total-stage entry \" , \n " ;
out < < " \" shape_expansion_policy \" : \" lock parameter and direction; after each strict shape decrease double next coordinate step from accepted point; otherwise retain point and halve step \" , \n " ;
out < < " \" shape_radius_policy \" : \" initial LM step capped at 0.24; subsequent coordinate steps capped at 0.60; no prediction-ratio gate \" , \n " ;
out < < " \" shape_global_parameter_selection \" : \" largest predicted reduction among unvisited non-wellbore parameters; finish current parameter before selecting next; each parameter visited once \" , \n " ;
out < < " \" stage2_budget \" : \" one parameter sweep; each parameter stops after 3 consecutive non-improving trials, a bound, or minimum step; existing solver failure limit retained \" , \n " ;
out < < " \" shape_step_improvement_threshold \" : \" any strict shape loss decrease; no cumulative improvement threshold \" , \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 shape limit max(0.0001, 5%); no_total_loss_constraint \" , \n " ;
@ -1924,6 +1949,9 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
const double minimumCoordinateStep = 1.0e-5 ;
const double minimumTrustRadius = 2.0e-3 ;
const double maximumTrustRadius = 0.30 ;
// 第二阶段整体形状允许更大步幅;第三阶段继续使用原来的半径和预测验收规则。
const double initialShapeTrustRadius = 0.24 ;
const double maximumShapeTrustRadius = 0.60 ;
// 误差下降至少达到绝对 1e-5 且相对当前有效基准 0.2% 才算有效改善。
// 更小的下降仍保留为最佳解,但不能反复清除停滞状态、延长拟合时间。
const double effectiveRelativeImprovement = 2.0e-3 ;
@ -2120,14 +2148,16 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if ( m_shouldStop ) return LM_USER_STOPPED ;
// 第二阶段 不按迭代比例截断;连续两次改善不足后,刷新灵敏度并仅做一次全局联合确认 。
// 第二阶段 先测灵敏度,再逐个调完非井筒参数;每个参数只访问一次 。
// 普通形状调整冻结井储、表皮,只按形状验收;总误差达标只在第三阶段判断。
bool shapeStage = true ;
bool jointShapeStarted = false ;
double shapeImprovementBaseline = current . breakdown . shapeLoss ;
bool singleShapeStarted = false ;
int shapeStepCount = 0 ;
int ineffectiveShapeSteps = 0 ;
bool shapeConfirmationRequested = false ;
QVector < bool > shapeParameterFinished ( dimensions , false ) ;
int activeShapeColumn = - 1 ;
double shapeCoordinateStep = 0.0 ;
int consecutiveShapeRejections = 0 ;
const int maximumShapeRejections = 3 ;
const int storageColumn = m_enabledParamIndices . indexOf ( 2 ) ;
const int skinColumn = m_enabledParamIndices . indexOf ( 1 ) ;
bool hasRemainingShapeParameters = false ;
@ -2193,7 +2223,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
restoreEvaluationState ( current ) ;
} ;
emit logMessageGenerated ( shapeStage
? tr ( " LM stage 2: joint shape search; after 2 ineffective steps, refresh sensitivity and confirm with one global step ." )
? tr ( " LM stage 2: adjust each shape parameter once; double the step after improvement, halve it after rejection, and switch after 3 consecutive rejections ." )
: tr ( " LM stage 3: original LM fitting; accept by total error only. " ) ) ;
if ( earlyShapeStage ) {
emit logMessageGenerated ( earlyShapeParameter = = 2
@ -2267,7 +2297,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
consecutiveSolverFailures = 0 ;
stagnationConfirmationRequested = false ;
globalFallbackAttempted = false ;
trustRadius = 0.12 ;
trustRadius = shapeStage & & ! earlyShapeStage ? initialShapeTrustRadius : 0.12 ;
damping = 0.01 ;
} ;
auto enterTotalStage = [ & ] ( const QString & reason ) {
@ -2362,38 +2392,37 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
true , 0 , " early_wellbore_to_shape " , & current . breakdown ) ;
} ;
auto completeShapeSearchStep = [ & ] ( ) {
if ( ! shapeStage | | earlyShapeStage | | m_shouldStop ) return ;
// 改善相对上一次有效改善累计,避免单次小步被立即否定;不再等待完整窗口轮次。
const double required = qMax ( 1.0e-4 , 0.10 * shapeImprovementBaseline ) ;
const double improvement = shapeImprovementBaseline - current . breakdown . shapeLoss ;
const bool improved = improvement > = required ;
+ + shapeStepCount ;
writeTraceRow ( m_currentIteration , - 1 , " shape_step_end " , current . parameters , current . fitness ,
true , 0 , QString ( improved ? " improved_step_%1 " : " ineffective_step_%1 " ) . arg ( shapeStepCount ) , & current . breakdown ) ;
emit logMessageGenerated ( tr ( " Shape search step %1: shape error=%2, accumulated improvement=%3, required=%4. " )
. arg ( shapeStepCount ) . arg ( current . breakdown . shapeLoss , 0 , ' g ' , 6 )
. arg ( improvement , 0 , ' g ' , 6 ) . arg ( required , 0 , ' g ' , 6 ) ) ;
// 每次形状调整都是全局联合步,结束后清除本次尝试标记。
globalFallbackAttempted = false ;
if ( improved ) {
shapeImprovementBaseline = current . breakdown . shapeLoss ;
ineffectiveShapeSteps = 0 ;
shapeConfirmationRequested = false ;
return ;
}
+ + ineffectiveShapeSteps ;
if ( shapeConfirmationRequested ) {
finishShapeStage ( tr ( " no significant shape improvement after fresh sensitivity and one global step " ) ) ;
return ;
auto finishShapeParameter = [ & ] ( const QString & reason ) {
// 已完成的参数不再参与后续选优,保证所有可调参数只扫一遍。
if ( activeShapeColumn > = 0 ) {
shapeParameterFinished [ activeShapeColumn ] = true ;
writeTraceRow ( m_currentIteration , activeShapeColumn , " shape_parameter_end " ,
current . parameters , current . fitness , true , 0 , reason , & current . breakdown ) ;
}
if ( ineffectiveShapeSteps > = 2 ) {
jacobian . clear ( ) ;
reuseSensitivityForNextStage ( ) ;
rebuildRequested = true ;
rebuildReason = QT_TR_NOOP ( " confirm shape stagnation after 2 ineffective steps " ) ;
shapeConfirmationRequested = true ;
activeShapeColumn = - 1 ;
shapeCoordinateStep = 0.0 ;
consecutiveShapeRejections = 0 ;
for ( int column = 0 ; column < dimensions ; + + column ) {
if ( parameterAllowedInStage ( column ) & & ! shapeParameterFinished [ column ] ) return ;
}
finishShapeStage ( tr ( " all shape parameters visited once " ) ) ;
} ;
auto completeShapeSearchStep = [ & ] ( bool accepted ) {
if ( ! shapeStage | | earlyShapeStage | | m_shouldStop ) return ;
// 只按本次真实下降控制实际步长;不再使用累计 10% 门槛提前结束整轮。
+ + shapeStepCount ;
consecutiveShapeRejections = accepted ? 0 : consecutiveShapeRejections + 1 ;
shapeCoordinateStep = qBound ( - maximumShapeTrustRadius ,
shapeCoordinateStep * ( accepted ? 2.0 : 0.5 ) , maximumShapeTrustRadius ) ;
writeTraceRow ( m_currentIteration , activeShapeColumn , " shape_step_end " , current . parameters ,
current . fitness , true , 0 ,
QString ( " %1_step_%2_rejections_%3_next_delta_%4 " )
. arg ( accepted ? " improved " : " rejected " ) . arg ( shapeStepCount )
. arg ( consecutiveShapeRejections ) . arg ( shapeCoordinateStep , 0 , ' g ' , 12 ) , & current . breakdown ) ;
if ( consecutiveShapeRejections > = maximumShapeRejections )
finishShapeParameter ( " 3_consecutive_non_improving_trials " ) ;
else if ( qAbs ( shapeCoordinateStep ) < minimumCoordinateStep )
finishShapeParameter ( " minimum_coordinate_step " ) ;
} ;
auto registerEffectiveImprovement = [ & ] ( double fitness ) - > bool {
@ -2415,11 +2444,11 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
return true ;
} ;
// 普通形状 按连续尝试判断停滞,并用新灵敏度下的全局联合步确认 ;
// 普通形状 的失败试算缩步并累计当前参数的拒绝次数 ;
// 前期井储、表皮与整体 LM 沿用各自的无效次数处理。
auto recordIneffectiveStep = [ & ] ( ) - > bool {
if ( shapeStage & & ! earlyShapeStage ) {
completeShapeSearchStep ( ) ;
completeShapeSearchStep ( false ) ;
return false ;
}
+ + consecutiveIneffectiveSteps ;
@ -2587,9 +2616,11 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
jacobianColumnValid [ column ] = true ;
columnBuilt = true ;
// 后半段形状探针仅用于灵敏度,正式调整必须经过单参数 LM 预测选优。
// 前期同时测井储和表皮,但缓存探针不能绕过当前子阶段的选参限制。
// 前期首次正式调整必须从小步开始,测形状灵敏度的大探针不能提前成为工作点。
if ( ( ! earlyShapeStage | | earlyShapeHasImproved ) & &
if ( ( ! shapeStage | | earlyShapeStage ) & &
( ! earlyShapeStage | | earlyShapeHasImproved ) & &
parameterAllowedInStage ( column ) & & acceptable ( probe , base ) & &
( ! bestProbe . valid | | stageError ( probe ) < stageError ( bestProbe ) ) ) {
bestProbe = probe ;
@ -2609,14 +2640,14 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if ( parameterAllowedInStage ( i ) ) hasActiveSensitivity = true ;
}
}
// 冻结列成功不能掩盖所有可调形状列的求解失败;有效零梯度 仍由停滞逻辑 处理。
// 冻结列成功不能掩盖所有可调形状列的求解失败;有效零梯度 交给逐参数选步 处理。
if ( validColumnCount = = 0 | | ( shapeStage & & ! earlyShapeStage & & ! hasActiveSensitivity ) | | m_shouldStop ) {
restoreEvaluationState ( base ) ;
return false ;
}
// 灵敏度试算本身若找到更优真实解也应保留。所有列先基于同一个 base
// 建完,再用该已知割线把 Jacobian 平移到新工作点 ,避免边算边移动基点。
// 前期井储/表皮和整体阶段仍可接受更优缓存探针;后半段形状只由 LM 选步。
// 所有列先基于同一个 base 建完,再用已知割线平移 Jacobian ,避免边算边移动基点。
if ( bestProbe . valid & & bestProbeColumn > = 0 ) {
QVector < double > acceptedStep ( dimensions , 0.0 ) ;
acceptedStep [ bestProbeColumn ] = bestProbeDelta ;
@ -2676,14 +2707,13 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if ( wellboreRecheck & & current . breakdown . earlyParallelLoss < =
earlyWellboreBaseline + qMax ( 1.0e-4 , 0.10 * earlyWellboreBaseline ) )
enterTotalStage ( tr ( " early shape error restored within tolerance " ) ) ;
if ( shapeStage & & ! earlyShapeStage & & ! jointShapeStarted ) {
jointShapeStarted = true ;
shapeImprovementBaseline = current . breakdown . shapeLoss ;
if ( shapeStage & & ! earlyShapeStage & & ! singleShapeStarted ) {
singleShapeStarted = true ;
// 初调已改变井储/表皮,普通形状必须在新的工作点重测其余可调参数的响应。
jacobian . clear ( ) ;
reuseSensitivityForNextStage ( ) ;
rebuildRequested = true ;
rebuildReason = QT_TR_NOOP ( " fresh sensitivity at joint shape entry" ) ;
rebuildReason = QT_TR_NOOP ( " fresh sensitivity at single-parameter shape entry" ) ;
}
if ( m_shouldStop ) break ;
if ( ! shapeStage & & ( totalIterations > = m_maxIterations | | m_totalEvaluations > = maximumEvaluations ) ) break ;
@ -2741,13 +2771,13 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
- - iteration ;
continue ;
}
// 单列探针没有改善不代表联合步无效;重建后继续真实候选 评价,再确认停滞。
// 差分探针不等于 LM 候选;重建后继续按当前阶段求步并真实 评价,再确认停滞。
registerEffectiveImprovement ( stageError ( current ) ) ;
}
// 第三阶段独立计数;方向不可行也消耗一次局部尝试,不能无限缩步循环。
if ( ! shapeStage ) + + totalIterations ;
// 每次从最新 J 和当前阶段残差重算 Fisher, 联合步使用全局信息 。
// 每次从最新 J 和当前阶段残差重算 全局信息,供单参数或联合 LM 求步 。
const QVector < double > objectiveResidual = earlyShapeStage
? current . breakdown . earlyParallelResiduals
: ( shapeStage ? current . breakdown . shapeResiduals : current . breakdown . residualVector ) ;
@ -2775,8 +2805,8 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
double predictedReduction = 0.0 ;
const int selectedWindow = earlyShapeStage ? 0 : - 1 ;
// 前期只开放当前井储或表皮; 普通形状和整体 LM 都联合求解全部有效自由列 。
// 保留弱敏感、相关及边界列 ,让参数相互配合 ;窗口只保留作误差诊断。
// 前期只开放当前井储或表皮; 后半段形状从有效自由列中选一个,整体 LM 仍联合求解 。
// 保留弱敏感、相关及边界列 供预测比较 ;窗口只保留作误差诊断。
for ( int column = 0 ; column < dimensions ; + + column ) {
if ( stageColumnValid [ column ] & & ( earlyShapeStage | | global . matrix [ column ] [ column ] > 0.0 ) )
selectedColumns . append ( column ) ;
@ -2800,8 +2830,54 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
damping , earlyStepRadius , minimumCoordinateStep , & coordinateStep , & predictedReduction ) ) {
selectedColumns . clear ( ) ;
}
} else if ( shapeStage ) {
// 首步由灵敏度选出尚未调过的参数;后续锁定方向,直接使用扩缩后的步长。
if ( activeShapeColumn < 0 ) {
QVector < int > availableColumns ;
for ( int i = 0 ; i < selectedColumns . size ( ) ; + + i ) {
if ( ! shapeParameterFinished [ selectedColumns [ i ] ] ) availableColumns . append ( selectedColumns [ i ] ) ;
}
buildBestSingleParameterStep ( global , availableColumns , current . coordinates ,
0.01 , initialShapeTrustRadius , minimumCoordinateStep ,
& selectedColumns , & coordinateStep , & predictedReduction ) ;
if ( ! selectedColumns . isEmpty ( ) ) {
activeShapeColumn = selectedColumns [ 0 ] ;
shapeCoordinateStep = coordinateStep [ activeShapeColumn ] ;
consecutiveShapeRejections = 0 ;
writeTraceRow ( m_currentIteration , activeShapeColumn , " shape_parameter_start " ,
current . parameters , current . fitness , true , 0 ,
" largest_predicted_reduction_unvisited " , & current . breakdown ) ;
} else {
// 剩余参数均无可行预测下降步时逐项记录,不能重复选择已完成参数。
for ( int column = 0 ; column < dimensions ; + + column ) {
if ( ! parameterAllowedInStage ( column ) | | shapeParameterFinished [ column ] ) continue ;
activeShapeColumn = column ;
finishShapeParameter ( jacobianColumnValid [ column ]
? " no_feasible_descent_step " : " invalid_sensitivity " ) ;
if ( ! shapeStage | | earlyShapeStage ) break ;
}
- - iteration ;
continue ;
}
} else {
selectedColumns . clear ( ) ;
selectedColumns . append ( activeShapeColumn ) ;
coordinateStep . fill ( 0.0 , dimensions ) ;
shapeCoordinateStep = qBound ( 0.0 ,
current . coordinates [ activeShapeColumn ] + shapeCoordinateStep , 1.0 )
- current . coordinates [ activeShapeColumn ] ;
if ( qAbs ( shapeCoordinateStep ) < minimumCoordinateStep ) {
finishShapeParameter ( " parameter_bound_or_minimum_step " ) ;
- - iteration ;
continue ;
}
coordinateStep [ activeShapeColumn ] = shapeCoordinateStep ;
predictedReduction = - global . gradient [ activeShapeColumn ] * shapeCoordinateStep
- 0.5 * global . matrix [ activeShapeColumn ] [ activeShapeColumn ]
* shapeCoordinateStep * shapeCoordinateStep ;
}
} else {
// 普通调整和停滞确认共用全局联合方向,不再遍历窗口或枚举三参数子集。
// 第三阶段保持全部有效自由参数的联合 LM 调整 。
globalFallbackAttempted = true ;
if ( selectedColumns . isEmpty ( ) | | ! buildTrustRegionFisherStep (
global , selectedColumns , current . coordinates , damping ,
@ -2818,11 +2894,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
- - iteration ;
continue ;
}
if ( shapeStage ) {
completeShapeSearchStep ( ) ;
- - iteration ;
continue ;
}
if ( trustRadius < = minimumTrustRadius * 1.01 & &
modelRebuiltAtMinimumRadius ) {
if ( promoteSampling ( false ) ) continue ;
@ -2933,7 +3004,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
" solver_invalid_ " + selectionName ,
nullptr ) ;
restoreEvaluationState ( current ) ;
if ( consecutiveSolverFailures > = 2 ) {
if ( consecutiveSolverFailures > = 2 & & ( ! shapeStage | | earlyShapeStage ) ) {
rebuildRequested = true ;
rebuildReason = QT_TR_NOOP ( " 2 consecutive solver failures " ) ;
}
@ -2941,8 +3012,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
stopReason = LM_CONSECUTIVE_FAILURES ;
break ;
}
// 确认步求解失败不代表形状已收敛,沿用有限重试后按求解失败退出。
if ( shapeStage & & ! earlyShapeStage & & shapeConfirmationRequested ) continue ;
if ( recordIneffectiveStep ( ) ) {
if ( promoteSampling ( false ) ) continue ;
stopReason = LM_LOCAL_OPTIMUM ;
@ -2951,37 +3020,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
continue ;
}
// 普通形状步真实改善后,沿同一联合方向最多扩步一次,不再用预测兑现比例拦截。
// 扩步只按整体形状验收,优于原步才替换,否则保留原候选。
if ( shapeStage & & ! earlyShapeStage & & acceptable ( candidate , current ) & & processPauseAndStop ( ) ) {
QVector < double > expandedStep ;
double expandedPrediction = 0.0 ;
if ( buildExpandedTrustRegionStep ( stepInformation , current . coordinates , coordinateStep ,
maximumTrustRadius , & expandedStep , & expandedPrediction ) ) {
writeTraceRow ( m_currentIteration , - 1 , " shape_step_base " , candidate . parameters ,
candidate . fitness , true , candidate . elapsedMs , " eligible_for_expansion " , & candidate . breakdown ) ;
TrustRegionEvaluation expanded ;
expanded . coordinates = current . coordinates ;
for ( int i = 0 ; i < dimensions ; + + i ) expanded . coordinates [ i ] + = expandedStep [ i ] ;
expanded . parameters = parametersFromCoordinates ( expanded . coordinates ) ;
expanded . valid = evaluateTrustRegionPoint ( expanded . parameters , & expanded . fitness ,
& expanded . breakdown , & expanded . curve , & expanded . elapsedMs ) ;
const bool useExpanded = acceptable ( expanded , current ) & & expanded . breakdown . shapeLoss < candidate . breakdown . shapeLoss ;
writeTraceRow ( m_currentIteration , - 1 , " shape_step_expanded " , expanded . parameters ,
expanded . fitness , expanded . valid , expanded . elapsedMs , useExpanded ? " selected_expanded " : " retain_ordinary " ,
expanded . valid ? & expanded . breakdown : nullptr ) ;
if ( useExpanded ) {
candidate = expanded ;
coordinateStep = expandedStep ;
predictedReduction = expandedPrediction ;
stepNorm = qSqrt ( trustRegionSquaredNorm ( coordinateStep ) ) ;
selectionName + = " _expanded " ;
}
// 两次真实调用已分别记录,下方候选行只记录最终决策,避免重复统计耗时。
candidate . elapsedMs = - 1 ;
restoreEvaluationState ( current ) ;
}
}
if ( m_shouldStop ) {
restoreEvaluationState ( current ) ;
stopReason = LM_USER_STOPPED ;
@ -3011,7 +3049,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
const bool poorPrediction = predictedReduction > predictionFloor & &
( ! isFiniteNumber ( reductionRatio ) | | reductionRatio < 0.25 ) ;
consecutivePoorPredictions = poorPrediction ? consecutivePoorPredictions + 1 : 0 ;
if ( consecutivePoorPredictions > = 2 ) {
if ( consecutivePoorPredictions > = 2 & & ( ! shapeStage | | earlyShapeStage ) ) {
rebuildRequested = true ;
rebuildReason = QT_TR_NOOP ( " 2 consecutive steps with actual improvement below 25% of prediction " ) ;
}
@ -3032,21 +3070,24 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
+ + acceptedSinceRebuild ;
consecutiveRejectedSteps = 0 ;
if ( reductionRatio > 0.75 ) {
damping = qMax ( 1.0e-8 , damping * 0.5 ) ;
if ( stepNorm > = trustRadius * 0.8 ) {
trustRadius = qMin (
maximumTrustRadius , trustRadius * 1.6 ) ;
// 井筒调整及第三阶段保留原 LM 控制;逐参数粗调在步末直接扩缩实际步长。
if ( ! shapeStage | | earlyShapeStage ) {
if ( reductionRatio > 0.75 ) {
damping = qMax ( 1.0e-8 , damping * 0.5 ) ;
if ( stepNorm > = trustRadius * 0.8 ) {
trustRadius = qMin (
maximumTrustRadius , trustRadius * 1.6 ) ;
}
} else if ( reductionRatio > 0.25 ) {
damping = qMax ( 1.0e-8 , damping * 0.8 ) ;
} else {
damping = qMin ( 1.0e8 , damping * 2.0 ) ;
trustRadius = qMax (
minimumTrustRadius , trustRadius * 0.75 ) ;
}
} else if ( reductionRatio > 0.25 ) {
damping = qMax ( 1.0e-8 , damping * 0.8 ) ;
} else {
damping = qMin ( 1.0e8 , damping * 2.0 ) ;
trustRadius = qMax (
minimumTrustRadius , trustRadius * 0.75 ) ;
}
if ( acceptedSinceRebuild > = 10 & & ! rebuildRequested ) {
if ( acceptedSinceRebuild > = 10 & & ! rebuildRequested & & ( ! shapeStage | | earlyShapeStage ) ) {
rebuildRequested = true ;
rebuildReason = QT_TR_NOOP ( " 10 accepted steps since last rebuild " ) ;
}
@ -3102,6 +3143,10 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
finishEarlyShapeStage ( tr ( " initial same-direction expansion reached the parameter bound without early shape improvement " ) ) ;
continue ;
}
if ( shapeStage & & ! earlyShapeStage ) {
completeShapeSearchStep ( accepted ) ;
continue ;
}
const bool effectiveImprovement = registerEffectiveImprovement ( stageError ( current ) ) ;
if ( ! effectiveImprovement & & recordIneffectiveStep ( ) ) stopReason = LM_LOCAL_OPTIMUM ;