Skip to content

Commit 1496457

Browse files
authored
Add a function enum to enumerate parameter values (#70)
* Add a function `enum` to enumerate parameter values
1 parent 47f2286 commit 1496457

File tree

7 files changed

+93
-3
lines changed

7 files changed

+93
-3
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
with:
2424
version: ${{ matrix.version }}
2525
arch: ${{ matrix.arch }}
26-
- uses: actions/cache@v1
26+
- uses: actions/cache@v3
2727
env:
2828
cache-name: cache-artifacts
2929
with:

src/SolverParameters.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Base.values
99
import Base.names
1010
import Base.convert
1111

12+
export enum
13+
1214
include("default-parameter.jl")
1315
include("domains.jl")
1416
include("parameters.jl")

src/domains.jl

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ See [`RealInterval`](@ref), [`IntegerRange`](@ref), [`IntegerSet`](@ref), [`Bina
2424
"""
2525
abstract type AbstractDomain{T} end
2626

27+
"""
28+
enum(::AbstractDomain{T}; step, kwargs...)
29+
30+
Return an iterable object of values in the domain `d` with step `step`.
31+
"""
32+
function enum end
33+
2734
(::T, ::AbstractDomain{T}) where {T} = false
2835
lower(::AbstractDomain{T}) where {T} =
2936
throw(DomainError("Lower bound is undefined for this domain."))
@@ -94,6 +101,29 @@ function Base.rand(rng::Random.AbstractRNG, d::RealInterval{T}) where {T <: Inte
94101
return r * (upp - low) + low
95102
end
96103

104+
function enum(d::RealInterval{T}; step = sqrt(eps(T)), kwargs...) where {T <: AbstractFloat}
105+
bnd = 1 / sqrt(eps(T))
106+
low = if lower(d) == -Inf || !d.lower_open
107+
lower(d)
108+
else
109+
lower(d) + eps(T)
110+
end
111+
low = max(low, -bnd)
112+
upp = if upper(d) == -Inf || !d.lower_open
113+
upper(d)
114+
else
115+
upper(d) - eps(T)
116+
end
117+
upp = min(upp, bnd)
118+
return range(low, upp, step = step)
119+
end
120+
121+
function enum(d::RealInterval{T}; step = 1, kwargs...) where {T <: Integer}
122+
low = d.lower_open ? lower(d) + 1 : lower(d)
123+
upp = d.upper_open ? upper(d) - 1 : upper(d)
124+
return range(low, upp, step = step)
125+
end
126+
97127
"""
98128
Integer domain for discrete variables:
99129
- Integer range;
@@ -129,6 +159,7 @@ upper(D::IntegerRange) = D.upper
129159
(x::T, D::IntegerRange{T}) where {T <: Integer} = lower(D) x upper(D)
130160

131161
Base.rand(rng::Random.AbstractRNG, d::IntegerRange) = rand(rng, (d.lower):(d.upper))
162+
enum(d::IntegerRange; step = 1) = range(d.lower, d.upper, step = step)
132163

133164
"""
134165
BinaryRange{T <: Bool} <: IntegerDomain{T}
@@ -150,6 +181,7 @@ lower(D::BinaryRange{Bool}) = false
150181
upper(D::BinaryRange{Bool}) = true
151182
(x::T, D::BinaryRange{T}) where {T <: Bool} = true
152183
Base.rand(rng::Random.AbstractRNG, ::BinaryRange) = rand(rng, Bool)
184+
enum(::BinaryRange; kwargs...) = (false, true)
153185

154186
"""
155187
IntegerSet{T} <: IntegerDomain{T}
@@ -175,7 +207,8 @@ end
175207
lower(D::IntegerSet{T}) where {T <: Integer} = min(D.set...)
176208
upper(D::IntegerSet{T}) where {T <: Integer} = max(D.set...)
177209

178-
Base.rand(rng::Random.AbstractRNG, d::IntegerSet) = rand(rng, d.set)
210+
Base.rand(rng::Random.AbstractRNG, D::IntegerSet) = rand(rng, D.set)
211+
enum(D::IntegerSet; kwargs...) = D.set
179212

180213
"""
181214
Categorical domain for categorical variables.
@@ -209,3 +242,4 @@ end
209242
CategoricalSet() = CategoricalSet(Vector{String}())
210243
(x::T, D::CategoricalSet{T}) where {T} = x in D.categories
211244
Base.rand(rng::Random.AbstractRNG, d::CategoricalSet) = rand(rng, Set(d.categories))
245+
enum(d::CategoricalSet) = d.categories

src/parameters.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,12 @@ function set_value!(parameter::Parameter{T}, new_value::T) where {T}
143143
check_value(domain(parameter), new_value)
144144
parameter.value = new_value
145145
end
146+
147+
"""
148+
enum(::Parameter{T}; step, kwargs...)
149+
150+
Return an iterable object of values in the domain `d` with step `step`.
151+
"""
152+
function enum(parameter::Parameter{T}; kwargs...) where {T}
153+
return enum(domain(parameter); kwargs...)
154+
end

src/parameterset.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,25 @@ function Base.rand(
7373
return values
7474
end
7575

76+
"""
77+
enum(::AbstractParameterSet; step, kwargs...)
78+
enum(subset::NTuple{N, Symbol}, ::AbstractParameterSet; step, kwargs...)
79+
80+
Return an iterable object of values in the AbstractParameterSet with step `step`.
81+
"""
82+
function enum(subset::NTuple{N, Symbol}, param_set::AbstractParameterSet; kwargs...) where {N}
83+
vec = Vector{Any}(undef, length(subset))
84+
for (i, field) in enumerate(subset)
85+
param = getfield(param_set, field)
86+
vec[i] = (field, enum(param; kwargs...))
87+
end
88+
return vec
89+
end
90+
91+
function enum(param_set::P; kwargs...) where {P <: AbstractParameterSet}
92+
return enum(fieldnames(P), param_set; kwargs...)
93+
end
94+
7695
function fieldnames_num(parameter_set::T) where {T <: AbstractParameterSet}
7796
nn = collect(fieldnames(T))
7897
for (i, param_name) in enumerate(nn)

test/test_domains.jl

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ end
5757
@test rand(d_lopen) d_lopen
5858
@test rand(d_ropen) d_ropen
5959
@test rand(d_open) d_open
60+
@testset "enum" verbose = true for d in [d_closed, d_lopen, d_ropen, d_open]
61+
i = 0
62+
for elt in enum(d)
63+
@test eltype(elt) == T
64+
i += 1
65+
if i == 3
66+
break
67+
end
68+
end
69+
end
6070
end
6171
end
6272
@testset "IntegerRange $T" verbose = true for T in (Int32, Int64)
@@ -71,19 +81,26 @@ end
7181
@test_throws ErrorException IntegerRange(max, min)
7282
end
7383
@test rand(d) d
84+
@test enum(d) == typemin(T):1:typemax(T)
85+
@test enum(d, step = 2) == typemin(T):2:typemax(T)
7486
end
7587
@testset "Binary range" begin
7688
b = BinaryRange()
7789
@test lower(b) == false
7890
@test upper(b) == true
7991
@test rand(b) b
92+
for elt in enum(b)
93+
@test eltype(elt) == Bool
94+
end
8095
end
8196
@testset "IntegerSet" verbose = true begin
82-
d = IntegerSet([2, 4, 5, 1, 3, 7])
97+
vecset = [2, 4, 5, 1, 3, 7]
98+
d = IntegerSet(vecset)
8399
@test lower(d) == 1
84100
@test upper(d) == 7
85101
@test (4 d) == true
86102
@test (6 d) == false
87103
@test rand(d) d
104+
enum(d) == Set(vecset)
88105
end
89106
end

test/test_parameters.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,12 @@ end
214214
@test upper_bounds!(subset, param_set, b) == [Inf]
215215
@test eltype(b) == Float64
216216
end
217+
218+
@testset "Enum parameters in ParameterSet" begin
219+
param_set = CatMockSolverParamSet()
220+
enum(param_set) == [
221+
(:real_inf, -6.7108864e7:1.4901161193847656e-8:6.7108864e7),
222+
(:real, ["A", "B", "C", "D"]),
223+
(:int_r, 5:1:20)
224+
]
225+
end

0 commit comments

Comments
 (0)