11@doc """
22 StoppingCriterion
33
4- An abstract type to represent a stopping criterion of an solver .
4+ An abstract type to represent a stopping criterion.
55
6- Any concrete stopping criterion should be implemented as a functor,
7- that takes the “usual tuple” `(p, a, s)` of a [`Problem`](@ref) `p`,
8- an [`Algorithm`](@ref) and a [`State`](@ref) as input, where this criterion
9- should usually be part of the [`State`](@ref) itself.
10-
11- ## Methods
6+ A concrete [`StoppingCriterion`](@ref) `sc` should also implement a
7+ [`initialize(sc::StoppingCriterion)`](@ref) function to create its accompaying
8+ [`StoppingCriterionState`](@ref).
9+ It should usually implement
1210
13- A concrete `StoppingCriterion` `sc` should provide the following functions
14- besides the above-mentioned functor is it itself
15-
16- * `get_reason(sc)` a human readable text of about one line of length providing a reason
17- why this stopping criterion indicated to stop. An empty string if it did not indicate to stop
18- * `get_summary(sc)` a short summary of this stopping criterion, and whether it was reached,
19- e.g. a short string like `"Max Iterations (15): reached"`
2011* `indicates_convergence(sc)` a boolean whether or not this stopping criterion would indicate
2112 that the algorithm has converged, if it indicates to stop.
22- * `show(io::IO, sc )` to display its constructor and the `get_summary`
13+ * `show(io::IO, scs )` for use in REPL and display within an [`Algorithm`](@ref).
2314"""
2415abstract type StoppingCriterion end
2516
17+ @doc """
18+ StoppingCriterionState
19+
20+ An abstract type to represent a stopping criterion state withinn a [`State`](@ref).
21+
22+ Any concrete stopping criterion should be implemented as a functor,
23+ that takes the “usual tuple” `(problem, algorithm, state, stopping_criterion)`
24+ of a [`Problem`](@ref) `p`, an [`Algorithm`](@ref) and a [`State`](@ref) as input,
25+ as well as the corresponding [`StoppingCriterion`](@ref). Though this is usually stored¨
26+ in the [`Algorithm`](@ref) `algorithm`, the extra parameter allows both for more flexibility and
27+ for multiple dispatch.
28+ The concrete [`StoppingCriterionState`](@ref) should be part of the [`State`](@ref) `state`.
29+
30+ The functor might modify the stopping criterion state.
31+ """
32+ abstract type StoppingCriterionState end
33+
2634function get_reason end
2735@doc """
28- get_reason(sc::StoppingCriterion)
36+ get_reason(sc::StoppingCriterion, scs::StoppingCriterionState )
2937
30- Provide a reason in human readable text as to why a [`StoppingCriterion`](@ref) indicated
31- to stop. If it does not indicate to stop, this should return an empty string.
38+ Provide a reason in human readable text as to why a [`StoppingCriterion`](@ref) `sc
39+ with [`StoppingCriterionState`](@ref) `scs` indicated to stop.
40+ If it does not indicate to stop, this should return an empty string.
3241
33- Providing the iteration at which this indicated to stop would be preferrable .
42+ Providing the iteration at which this indicated to stop in the reason would be preferable .
3443"""
35- get_reason (:: StoppingCriterion )
44+ get_reason (:: StoppingCriterion , :: StoppingCriterionState )
3645
3746function indicates_convergence end
3847@doc """
3948 indicates_convergence(sc::StoppingCriterion)
4049
41- Return whether or not a [`StoppingCriterion`](@ref) indicates convergence of an algorithm
42- if it would indicate to stop.
50+ Return whether or not a [`StoppingCriterion`](@ref) `sc` indicates convergence.
4351"""
44- indicates_convergence (:: StoppingCriterion )
52+ indicates_convergence (sc:: StoppingCriterion )
53+
54+ @doc """
55+ indicates_convergence(sc::StoppingCriterion, ::StoppingCriterionState)
4556
57+ Return whether or not a [`StoppingCriterion`](@ref) `sc` indicates convergence
58+ when it is in [`StoppingCriterionState`](@ref)
59+
60+ By default this checks whether the [`StoppingCriterion`](@ref) has actually stopped.
61+ If so it returns whether `sc` itself indicates convergence, otherwise it returns `false`,
62+ since the algorithm has then not yet stopped.
63+ """
64+ function indicates_convergence (sc:: StoppingCriterion , scs:: StoppingCriterionState )
65+ return length (get_reason (sc, scs)) > 0 ? indicates_convergence (sc) : false
66+ end
4667
4768function get_summary end
4869@doc """
49- get_summary(sc::StoppingCriterion)
70+ get_summary(sc::StoppingCriterion, scs::StoppingCriterionState )
5071
5172Provide a summary of the status of a stopping criterion – its parameters and whether
5273it currently indicates to stop. It should not be longer than one line
@@ -59,42 +80,60 @@ For the [`StopAfterIteration`](@ref) criterion, the summary looks like
5980Max Iterations (15): not reached
6081```
6182"""
62- get_summary (sc:: StoppingCriterion )
83+ get_summary (sc:: StoppingCriterion , scs :: StoppingCriterionState )
6384
6485@doc raw """
6586 StopAfterIteration <: StoppingCriterion
6687
67- A functor for a stopping criterion to stop after a maximal number of iterations.
88+ A simple stopping criterion to stop after a maximal number of iterations.
6889
6990# Fields
7091
7192* `max_iterations` stores the maximal iteration number where to stop at
72- * `at_iteration` indicates at which iteration (including `i=0`) the stopping criterion
73- was fulfilled and is `-1` while it is not fulfilled.
7493
7594# Constructor
7695
7796 StopAfterIteration(maxIter)
7897
7998initialize the functor to indicate to stop after `maxIter` iterations.
8099"""
81- mutable struct StopAfterIteration <: StoppingCriterion
82- max_iterations:: Int
100+ struct StopAfterIteration <: StoppingCriterion
101+ max_iterations:: Int
102+ end
103+
104+ """
105+ DefaultStoppingCriterionState <: StoppingCriterionState
106+
107+ A [`StoppingCriterionState`](@ref) that does not require any information besides
108+ storing the iteration number when it (last) indicated to stop).
109+
110+ # Field
111+ * `at_iteration::Int` store the iteration number this state
112+ indicated to stop.
113+ * `0` means already at the start it indicated to stop
114+ * any negative number means that it did not yet indicate to stop.
115+ """
116+ mutable struct DefaultStoppingCriterionState
83117 at_iteration:: Int
84- StopAfterIteration (k:: Int ) = new (k, - 1 )
118+ DefaultStoppingCriterionState () = new (- 1 )
119+ end
120+
121+ initialize (:: Problem , :: Algorithm , :: State , :: StopAfterIteration ) = DefaultStoppingCriterionState ()
122+ function initialize! (scs:: DefaultStoppingCriterionState , :: Problem , :: Algorithm , :: State , :: StopAfterIteration )
123+ scs. indicated_convergence_at = - 1
124+ return scs
85125end
86- function (sc:: StopAfterIteration )(:: Problem , :: Algorithm , s:: State )
126+
127+ function (sc:: DefaultStoppingCriterionState )(:: Problem , :: Algorithm , s:: State , sc:: StopAfterIteration )
87128 k = get_iteration (s)
88- if k == 0 # reset on init
89- sc. at_iteration = - 1
90- end
129+ (k == 0 ) && (sc. at_iteration = - 1 )
91130 if k >= sc. max_iterations
92131 sc. at_iteration = k
93132 return true
94133 end
95134 return false
96135end
97- function get_reason (c:: StopAfterIteration )
136+ function get_reason (c:: StopAfterIteration , scs :: DefaultStoppingCriterionState )
98137 if c. at_iteration >= c. max_iterations
99138 return " At iteration $(c. at_iteration) the algorithm reached its maximal number of iterations ($(c. max_iterations) ).\n "
100139 end
0 commit comments