Skip to content

Commit 72f07b2

Browse files
authored
Introduce & and | for StoppingCriterion. (#56)
* Introduce & and | for StoppingCriterion. * bump version.
1 parent 00f1a09 commit 72f07b2

File tree

5 files changed

+75
-4
lines changed

5 files changed

+75
-4
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Manopt"
22
uuid = "0fc0a36d-df90-57f3-8f93-d78a9fc72bb5"
33
authors = ["Ronny Bergmann <manopt@ronnybergmann.net>"]
4-
version = "0.2.15"
4+
version = "0.2.16"
55

66
[deps]
77
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"

docs/src/solvers/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Order = [:type]
4747
as well as the functions
4848

4949
```@docs
50+
Base.:&(::StoppingCriterion, ::StoppingCriterion)
51+
Base.:|(::StoppingCriterion, ::StoppingCriterion)
5052
get_reason
5153
get_stopping_criteria
5254
get_active_stopping_criteria

src/Manopt.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ using Random: shuffle!
1212
using DataStructures: CircularBuffer, capacity, length, size, push!
1313
using StaticArrays
1414
import Random: rand, randperm
15-
import Base: copy, identity
15+
import Base: copy, identity, &, |
1616
import ManifoldsBase:
1717
ℝ,
1818
ℂ,
@@ -126,7 +126,7 @@ include("data/artificialDataFunctions.jl")
126126

127127
include("random.jl")
128128

129-
export ×, ^, ℝ, ℂ
129+
export ℝ, ℂ, &, |
130130

131131
export Problem,
132132
ProximalProblem,

src/plans/stopping_criterion.jl

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ mutable struct StopAfterIteration <: StoppingCriterion
3838
reason::String
3939
StopAfterIteration(mIter::Int) = new(mIter, "")
4040
end
41-
function (c::StopAfterIteration)(p::P, o::O, i::Int) where {P<:Problem,O<:Options}
41+
function (c::StopAfterIteration)(::P, ::O, i::Int) where {P<:Problem,O<:Options}
4242
if i > c.maxIter
4343
c.reason = "The algorithm reached its maximal number of iterations ($(c.maxIter)).\n"
4444
return true
@@ -124,6 +124,33 @@ function (c::StopWhenAll)(p::P, o::O, i::Int) where {P<:Problem,O<:Options}
124124
end
125125
get_stopping_criteria(c::StopWhenAll) = c.criteria
126126

127+
"""
128+
&(s1,s2)
129+
s1 & s2
130+
131+
Combine two [`StoppingCriterion`](@ref) within an [`StopWhenAll`](@ref).
132+
If either `s1` (or `s2`) is already an [`StopWhenAll`](@ref), then `s2` (or `s1`) is
133+
appended to the list of [`StoppingCriterion`](@ref) within `s1` (or `s2`).
134+
135+
# Example
136+
a = StopAfterIteration(200) & StopWhenChangeLess(1e-6)
137+
b = a & StopWhenGradientNormLess(1e-6)
138+
139+
Is the same as
140+
141+
a = StopWhenAll(StopAfterIteration(200), StopWhenChangeLess(1e-6))
142+
b = StopWhenAll(StopAfterIteration(200), StopWhenChangeLess(1e-6), StopWhenGradientNormLess(1e-6))
143+
"""
144+
function Base.:&(s1::S, s2::T) where {S<:StoppingCriterion,T<:StoppingCriterion}
145+
return StopWhenAll(s1, s2)
146+
end
147+
function Base.:&(s1::S, s2::StopWhenAll) where {S<:StoppingCriterion}
148+
return StopWhenAll(s1, s2.criteria...)
149+
end
150+
function Base.:&(s1::StopWhenAll, s2::T) where {T<:StoppingCriterion}
151+
return StopWhenAll(s1.criteria..., s2)
152+
end
153+
127154
@doc raw"""
128155
StopWhenAny <: StoppingCriterion
129156
@@ -149,6 +176,34 @@ function (c::StopWhenAny)(p::P, o::O, i::Int) where {P<:Problem,O<:Options}
149176
return false
150177
end
151178
get_stopping_criteria(c::StopWhenAny) = c.criteria
179+
180+
"""
181+
|(s1,s2)
182+
s1 | s2
183+
184+
Combine two [`StoppingCriterion`](@ref) within an [`StopWhenAny`](@ref).
185+
If either `s1` (or `s2`) is already an [`StopWhenAny`](@ref), then `s2` (or `s1`) is
186+
appended to the list of [`StoppingCriterion`](@ref) within `s1` (or `s2`)
187+
188+
# Example
189+
a = StopAfterIteration(200) | StopWhenChangeLess(1e-6)
190+
b = a | StopWhenGradientNormLess(1e-6)
191+
192+
Is the same as
193+
194+
a = StopWhenAny(StopAfterIteration(200), StopWhenChangeLess(1e-6))
195+
b = StopWhenAny(StopAfterIteration(200), StopWhenChangeLess(1e-6), StopWhenGradientNormLess(1e-6))
196+
"""
197+
function Base.:|(s1::S, s2::T) where {S<:StoppingCriterion,T<:StoppingCriterion}
198+
return StopWhenAny(s1, s2)
199+
end
200+
function Base.:|(s1::S, s2::StopWhenAny) where {S<:StoppingCriterion}
201+
return StopWhenAny(s1, s2.criteria...)
202+
end
203+
function Base.:|(s1::StopWhenAny, s2::T) where {T<:StoppingCriterion}
204+
return StopWhenAny(s1.criteria..., s2)
205+
end
206+
152207
"""
153208
StopWhenCostLess <: StoppingCriterion
154209

test/plans/test_stopping_criteria.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,17 @@ end
4646
@test s(p, o, 2) == true
4747
@test_throws ErrorException StopAfter(Second(-1))
4848
end
49+
50+
@testset "Stopping Criterion &/| operators" begin
51+
a = StopAfterIteration(200)
52+
b = StopWhenChangeLess(1e-6)
53+
c = StopWhenGradientNormLess(1e-6)
54+
d = StopWhenAll(a, b, c)
55+
@test typeof(d) === typeof(a & b & c)
56+
@test typeof(d) === typeof(a & (b & c))
57+
@test typeof(d) === typeof((a & b) & c)
58+
e = StopWhenAny(a, b, c)
59+
@test typeof(e) === typeof(a | b | c)
60+
@test typeof(e) === typeof(a | (b | c))
61+
@test typeof(e) === typeof((a | b) | c)
62+
end

0 commit comments

Comments
 (0)