From ddaffa10fa8ae07d05867a729c5de12008e3ffea Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Fri, 22 May 2026 17:04:36 +0000 Subject: [PATCH] BUG: Honor StopOptimization from IterationEvent in v4 optimizers Add an immediate m_Stop check after InvokeEvent(IterationEvent()) in ExhaustiveOptimizerv4, PowellOptimizerv4, and OnePlusOneEvolutionaryOptimizerv4. Previously these optimizers would continue advancing after an observer called StopOptimization() (or StopWalking()) during IterationEvent, making it impossible to halt from a callback. This is the companion change to cf929f2ca7 which added the same pattern to the GradientDescentOptimizerv4 family. All v4 optimizers now consistently stop before taking another step when Stop is requested from an IterationEvent observer. --- .../Optimizersv4/include/itkExhaustiveOptimizerv4.hxx | 4 ++++ .../include/itkOnePlusOneEvolutionaryOptimizerv4.hxx | 7 +++++++ .../Numerics/Optimizersv4/include/itkPowellOptimizerv4.hxx | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/Modules/Numerics/Optimizersv4/include/itkExhaustiveOptimizerv4.hxx b/Modules/Numerics/Optimizersv4/include/itkExhaustiveOptimizerv4.hxx index e7a1c84abce..3b1f32b3f0b 100644 --- a/Modules/Numerics/Optimizersv4/include/itkExhaustiveOptimizerv4.hxx +++ b/Modules/Numerics/Optimizersv4/include/itkExhaustiveOptimizerv4.hxx @@ -134,6 +134,10 @@ ExhaustiveOptimizerv4::ResumeWalking() << "@ index " << this->GetCurrentIndex() << " value is " << m_CurrentValue; this->InvokeEvent(IterationEvent()); + if (m_Stop) + { + break; + } this->AdvanceOneStep(); this->m_CurrentIteration++; } diff --git a/Modules/Numerics/Optimizersv4/include/itkOnePlusOneEvolutionaryOptimizerv4.hxx b/Modules/Numerics/Optimizersv4/include/itkOnePlusOneEvolutionaryOptimizerv4.hxx index 7d464af752b..bc12b7e7951 100644 --- a/Modules/Numerics/Optimizersv4/include/itkOnePlusOneEvolutionaryOptimizerv4.hxx +++ b/Modules/Numerics/Optimizersv4/include/itkOnePlusOneEvolutionaryOptimizerv4.hxx @@ -257,6 +257,13 @@ OnePlusOneEvolutionaryOptimizerv4::StartOptimizat } this->InvokeEvent(IterationEvent()); + if (m_Stop) + { + m_StopConditionDescription.str(""); + m_StopConditionDescription << this->GetNameOfClass() << ": " + << "StopOptimization() called"; + break; + } itkDebugMacro("Current position: " << this->GetCurrentPosition()); } if (this->m_CurrentIteration >= m_MaximumIteration) diff --git a/Modules/Numerics/Optimizersv4/include/itkPowellOptimizerv4.hxx b/Modules/Numerics/Optimizersv4/include/itkPowellOptimizerv4.hxx index a511067cf84..9804b4be4ff 100644 --- a/Modules/Numerics/Optimizersv4/include/itkPowellOptimizerv4.hxx +++ b/Modules/Numerics/Optimizersv4/include/itkPowellOptimizerv4.hxx @@ -498,6 +498,12 @@ PowellOptimizerv4::StartOptimization(bool /* doOn } this->InvokeEvent(IterationEvent()); + if (m_Stop) + { + m_StopConditionDescription << "StopOptimization() called"; + this->InvokeEvent(EndEvent()); + return; + } } m_StopConditionDescription << "Maximum number of iterations exceeded. "