Skip to content

BUG: Honor StopOptimization from IterationEvent in v4 optimizers#6328

Merged
blowekamp merged 1 commit into
InsightSoftwareConsortium:mainfrom
blowekamp:stop-optimizerv4-from-iteration-event
May 22, 2026
Merged

BUG: Honor StopOptimization from IterationEvent in v4 optimizers#6328
blowekamp merged 1 commit into
InsightSoftwareConsortium:mainfrom
blowekamp:stop-optimizerv4-from-iteration-event

Conversation

@blowekamp
Copy link
Copy Markdown
Member

Summary

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 #6196 (commit cf929f2) which added the same pattern to the GradientDescentOptimizerv4 family.

Behavior Table

After this PR, all v4 optimizers that support stopping now behave consistently when StopOptimization() is called from an IterationEvent observer:

Optimizer Stop Method Stops Before Next Step GetCurrentIteration() at stop
ConjugateGradientLineSearch StopOptimization() ✓ (via #6196) iteration where stop was called
GradientDescent StopOptimization() ✓ (via #6196) iteration where stop was called
GradientDescentLineSearch StopOptimization() ✓ (via #6196) iteration where stop was called
RegularStepGradientDescent StopOptimization() ✓ (via #6196) iteration where stop was called
ExhaustiveOptimizerv4 StopWalking() (this PR) iteration where stop was called
PowellOptimizerv4 StopOptimization() (this PR) iteration where stop was called
OnePlusOneEvolutionaryOptimizerv4 StopOptimization() (this PR) iteration where stop was called

References

@github-actions github-actions Bot added type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances area:Numerics Issues affecting the Numerics module labels May 22, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 22, 2026

Greptile Summary

This PR ports the m_Stop-after-IterationEvent pattern (introduced for the gradient descent optimizer family in #6196) to ExhaustiveOptimizerv4, PowellOptimizerv4, and OnePlusOneEvolutionaryOptimizerv4, making it possible to halt these optimizers from an IterationEvent observer.

  • PowellOptimizerv4 and OnePlusOneEvolutionaryOptimizerv4: the new stop checks are correct and consistent with how those classes fire EndEvent on all other exit paths.
  • ExhaustiveOptimizerv4: the new check calls StopWalking(), but StopWalking() unconditionally fires EndEvent itself. When an observer calls StopWalking() during IterationEvent, EndEvent fires once inside the observer and then a second time from the new check — duplicating the event. The fix is to replace this->StopWalking() with a plain break.

Confidence Score: 3/5

Two of the three changed optimizers are correct, but ExhaustiveOptimizerv4 introduces a double EndEvent emission that will affect any observer registered on EndEvent when the user stops via StopWalking().

The ExhaustiveOptimizerv4 change calls StopWalking() after the observer may have already called it, causing EndEvent to fire twice. This is a present behavioural regression on the primary user-facing stop path for that optimizer and should be fixed before merging.

itkExhaustiveOptimizerv4.hxx — the new stop check needs to use a bare break instead of calling StopWalking() to avoid the duplicate EndEvent.

Important Files Changed

Filename Overview
Modules/Numerics/Optimizersv4/include/itkExhaustiveOptimizerv4.hxx Adds m_Stop check after IterationEvent, but calls StopWalking() (which fires EndEvent) even though an observer that called StopWalking() already fired it — resulting in a double EndEvent.
Modules/Numerics/Optimizersv4/include/itkOnePlusOneEvolutionaryOptimizerv4.hxx Adds correct m_Stop guard after IterationEvent; breaks to the single EndEvent call at the bottom of StartOptimization, so EndEvent fires exactly once.
Modules/Numerics/Optimizersv4/include/itkPowellOptimizerv4.hxx Adds correct m_Stop guard after IterationEvent; explicitly fires EndEvent once and returns, consistent with the other early-exit paths in StartOptimization.

Sequence Diagram

sequenceDiagram
    participant Observer
    participant ResumeWalking
    participant StopWalking

    ResumeWalking->>ResumeWalking: InvokeEvent(IterationEvent())
    Note over ResumeWalking: observer is notified
    ResumeWalking->>Observer: IterationEvent callback
    Observer->>StopWalking: "StopWalking() [sets m_Stop=true]"
    StopWalking-->>Observer: "InvokeEvent(EndEvent()) fires #1"
    Observer-->>ResumeWalking: returns

    ResumeWalking->>ResumeWalking: if (m_Stop) — true
    ResumeWalking->>StopWalking: StopWalking() [m_Stop already true]
    StopWalking-->>ResumeWalking: "InvokeEvent(EndEvent()) fires #2 (bug)"
    ResumeWalking->>ResumeWalking: break
Loading

Reviews (1): Last reviewed commit: "BUG: Honor StopOptimization from Iterati..." | Re-trigger Greptile

Comment thread Modules/Numerics/Optimizersv4/include/itkExhaustiveOptimizerv4.hxx
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 cf929f2 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.
@blowekamp blowekamp force-pushed the stop-optimizerv4-from-iteration-event branch from 4faefbe to ddaffa1 Compare May 22, 2026 17:23
Copy link
Copy Markdown
Member

@dzenanz dzenanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good on a glance.

Copy link
Copy Markdown
Member

@hjmjohnson hjmjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @blowekamp . I don't see any issues.

@hjmjohnson
Copy link
Copy Markdown
Member

hjmjohnson commented May 22, 2026

ITK.Pixi / Pixi-Cxx (windows-2022) failures are un-related to this PR.
Fixes in should resolve the failure.

Additional improvements inspired by reviewing MSVC cache missins in

should provide additional improvements in both disk space allocation and .obj file size.

@blowekamp blowekamp merged commit b3342c8 into InsightSoftwareConsortium:main May 22, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Numerics Issues affecting the Numerics module type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants