Skip to content

Commit 0edc47e

Browse files
authored
Fix SigFig Bug (#344)
* fix sigfig bug * Fix api * fix function name * fix typo * doc updates * fix typo * fix test
1 parent dc1e303 commit 0edc47e

File tree

10 files changed

+269
-175
lines changed

10 files changed

+269
-175
lines changed

docs/src/develop/extensions.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ template is provided in
2323
[`./test/extensions/infinite_domain.jl`](https://github.com/infiniteopt/InfiniteOpt.jl/blob/master/test/extensions/infinite_domain.jl).
2424
The extension steps employed are:
2525
1. Define the new `struct` infinite domain type (only thing required as bare minimum)
26-
2. Extend [`InfiniteOpt.supports_in_domain`](@ref) (enables error checking of supports)
27-
3. Extend [`InfiniteOpt.generate_support_values`](@ref) (enables support generation via `num_supports` keyword arguments)
28-
4. If a lower bound and upper bound can be reported, extend `JuMP` lower bound and upper bound methods (enables automatic bound detection in `integral`)
29-
5. Extend [`InfiniteOpt.MeasureToolbox.generate_expect_data`](@ref) (enables the use of `expect`)
26+
2. Extend[`InfiniteOpt.round_domain`](@ref) (enables safe use of significant digit rounding)
27+
3. Extend [`InfiniteOpt.supports_in_domain`](@ref) (enables error checking of supports)
28+
4. Extend [`InfiniteOpt.generate_support_values`](@ref) (enables support generation via `num_supports` keyword arguments)
29+
5. If a lower bound and upper bound can be reported, extend `JuMP` lower bound and upper bound methods (enables automatic bound detection in `integral`)
30+
6. Extend [`InfiniteOpt.MeasureToolbox.generate_expect_data`](@ref) (enables the use of `expect`)
3031

3132
As an example, let's create a univariate disjoint interval domain as an infinite
3233
domain type. This corresponds to the domain ``[lb_1, ub_1] \cup [lb_2, ub_2]``
@@ -82,13 +83,25 @@ to extend [`generate_integral_data`](@ref). See [`Measure Evaluation Techniques`
8283
for details.
8384

8485
To enable support domain checking which is useful to avoid strange bugs, we will
85-
extend [`InfiniteOpt.supports_in_domain`](@ref). This returns a `Bool` to
86-
indicate if a vector of supports are in the domain:
86+
extend [`InfiniteOpt.round_domain`](@ref) which rounds the domain to use proper
87+
significant digits and [`InfiniteOpt.supports_in_domain`](@ref) which returns a
88+
`Bool` whether a vector of supports is in the domain:
8789
```jldoctest domain_ext; output = false
90+
function InfiniteOpt.round_domain(
91+
domain::DisjointDomain,
92+
sig_digits::Int
93+
)
94+
lb1 = round(domain.lb1, sigdigits = sig_digits)
95+
ub1 = round(domain.ub1, sigdigits = sig_digits)
96+
lb2 = round(domain.lb2, sigdigits = sig_digits)
97+
ub2 = round(domain.ub2, sigdigits = sig_digits)
98+
return DisjointDomain(lb1, ub1, lb2, ub2)
99+
end
100+
88101
function InfiniteOpt.supports_in_domain(
89102
supports::Union{Number, Vector{<:Number}},
90103
domain::DisjointDomain
91-
)::Bool
104+
)
92105
return all((domain.lb1 .<= supports .<= domain.ub1) .| (domain.lb2 .<= supports .<= domain.ub2))
93106
end
94107
@@ -113,7 +126,7 @@ function InfiniteOpt.generate_support_values(
113126
domain::DisjointDomain;
114127
num_supports::Int = InfiniteOpt.DefaultNumSupports,
115128
sig_digits::Int = InfiniteOpt.DefaultSigDigits
116-
)::Tuple{Vector{Float64}, DataType}
129+
)
117130
length_ratio = (domain.ub1 - domain.lb1) / (domain.ub1 - domain.lb1 + domain.ub2 - domain.lb2)
118131
num_supports1 = Int64(ceil(length_ratio * num_supports))
119132
num_supports2 = num_supports - num_supports1

docs/src/guide/constraint.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ argument. This includes a wealth of constraint types including:
242242
For example, we could define the following semi-definite constraint:
243243
```jldoctest constrs
244244
julia> @constraint(model, [yb 2yb; 3yb 4yb] >= ones(2, 2), PSDCone())
245-
[yb(t) - 1 2 yb(t) - 1;
245+
[yb(t) - 1 2 yb(t) - 1
246246
3 yb(t) - 1 4 yb(t) - 1] ∈ PSDCone(), ∀ t ∈ [0, 10]
247247
```
248248
See [`JuMP`'s constraint documentation](https://jump.dev/JuMP.jl/v1/manual/constraints/)

docs/src/guide/derivative.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
```@meta
22
DocTestFilters = [r"≥|>=", r" == | = ", r" ∈ | in ", r" for all | ∀ ", r"d|∂",
3-
r"integral|∫", r".*scalar_parameters.jl:783"]
3+
r"integral|∫", r".*scalar_parameters.jl:790"]
44
```
55

66
# [Derivative Operators](@id deriv_docs)
@@ -502,7 +502,7 @@ julia> derivative_constraints(d1)
502502
503503
julia> add_supports(t, 0.2)
504504
┌ Warning: Support/method changes will invalidate existing derivative evaluation constraints that have been added to the InfiniteModel. Thus, these are being deleted.
505-
└ @ InfiniteOpt ~/work/infiniteopt/InfiniteOpt.jl/src/scalar_parameters.jl:783
505+
└ @ InfiniteOpt ~/work/infiniteopt/InfiniteOpt.jl/src/scalar_parameters.jl:790
506506
507507
julia> has_derivative_constraints(d1)
508508
false

docs/src/manual/domains.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ JuMP.set_lower_bound(::AbstractInfiniteDomain, ::Real)
2222
JuMP.has_upper_bound(::AbstractInfiniteDomain)
2323
JuMP.upper_bound(::AbstractInfiniteDomain)
2424
JuMP.set_upper_bound(::AbstractInfiniteDomain, ::Real)
25+
InfiniteOpt.round_domain
2526
```
2627

2728
## Support Point Labels

src/array_parameters.jl

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,38 @@
22
# CORE DISPATCHVARIABLEREF METHOD EXTENSIONS
33
################################################################################
44
# Extend dispatch_variable_ref
5-
function dispatch_variable_ref(model::InfiniteModel,
6-
index::DependentParameterIndex
7-
)::DependentParameterRef
5+
function dispatch_variable_ref(
6+
model::InfiniteModel,
7+
index::DependentParameterIndex
8+
)
89
return DependentParameterRef(model, index)
910
end
1011

1112
# Extend _add_data_object
12-
function _add_data_object(model::InfiniteModel,
13-
object::MultiParameterData
14-
)::DependentParametersIndex
13+
function _add_data_object(
14+
model::InfiniteModel,
15+
object::MultiParameterData
16+
)
1517
index = MOIUC.add_item(model.dependent_params, object)
1618
push!(model.param_object_indices, index)
1719
return index
1820
end
1921

2022
# Extend _data_dictionary (type based)
21-
function _data_dictionary(model::InfiniteModel,
22-
::Type{DependentParameters})::MOIUC.CleverDict
23+
function _data_dictionary(
24+
model::InfiniteModel,
25+
::Type{DependentParameters}
26+
)
2327
return model.dependent_params
2428
end
2529

2630
# Extend _data_dictionary (ref based)
27-
function _data_dictionary(pref::DependentParameterRef)::MOIUC.CleverDict
31+
function _data_dictionary(pref::DependentParameterRef)
2832
return JuMP.owner_model(pref).dependent_params
2933
end
3034

3135
# Extend _data_object
32-
function _data_object(pref::DependentParameterRef)::MultiParameterData
36+
function _data_object(pref::DependentParameterRef)
3337
object = get(_data_dictionary(pref), JuMP.index(pref).object_index, nothing)
3438
if isnothing(object)
3539
error("Invalid dependent parameter reference, cannot find ",
@@ -40,17 +44,17 @@ function _data_object(pref::DependentParameterRef)::MultiParameterData
4044
end
4145

4246
# Extend _core_variable_object
43-
function _core_variable_object(pref::DependentParameterRef)::DependentParameters
47+
function _core_variable_object(pref::DependentParameterRef)
4448
return _data_object(pref).parameters
4549
end
4650

4751
# Return the number of dependent parameters involved
48-
function _num_parameters(pref::DependentParameterRef)::Int
52+
function _num_parameters(pref::DependentParameterRef)
4953
return length(_data_object(pref).names)
5054
end
5155

5256
# Extend _delete_data_object
53-
function _delete_data_object(vref::DependentParameterRef)::Nothing
57+
function _delete_data_object(vref::DependentParameterRef)
5458
delete!(_data_dictionary(vref), JuMP.index(vref).object_index)
5559
return
5660
end
@@ -59,7 +63,7 @@ end
5963
# PARAMETER DEFINITION
6064
################################################################################
6165
# Check that multi-dimensional domains are all the same
62-
function _check_same_domain(_error::Function, domains)::Nothing
66+
function _check_same_domain(_error::Function, domains)
6367
if !_allequal(domains)
6468
_error("Conflicting infinite domains. Only one multi-dimensional ",
6569
"can be specified. Otherwise, scalar domains can be used ",
@@ -74,7 +78,7 @@ function _make_array_domain(
7478
_error::Function,
7579
domains::Vector{T},
7680
inds::Collections.ContainerIndices
77-
)::T where {T <: MultiDistributionDomain}
81+
) where {T <: MultiDistributionDomain}
7882
_check_same_domain(_error, domains)
7983
dist = first(domains).distribution
8084
if size(dist) != size(inds)
@@ -99,7 +103,7 @@ function _make_array_domain(
99103
_error::Function,
100104
domains::Vector{T},
101105
inds::Collections.ContainerIndices
102-
)::T where {T <: CollectionDomain}
106+
) where {T <: CollectionDomain}
103107
_check_same_domain(_error, domains)
104108
if length(collection_domains(first(domains))) != length(inds)
105109
_error("The dimensions of the parameters and the specified ",
@@ -125,7 +129,7 @@ function _make_array_domain(
125129
_error::Function,
126130
domains::Vector{T},
127131
inds::Collections.ContainerIndices
128-
)::T where {T <: InfiniteArrayDomain}
132+
) where {T <: InfiniteArrayDomain}
129133
_check_same_domain(_error, domains)
130134
return first(domains)
131135
end
@@ -135,7 +139,7 @@ function _make_array_domain(
135139
_error::Function,
136140
domains::Vector{T},
137141
inds::Collections.ContainerIndices
138-
)::CollectionDomain{T} where {T <: InfiniteScalarDomain}
142+
) where {T <: InfiniteScalarDomain}
139143
return CollectionDomain(domains)
140144
end
141145

@@ -151,7 +155,7 @@ function _process_supports(
151155
supps::Vector{<:Real},
152156
domain,
153157
sig_digits
154-
)::Dict{Vector{Float64}, Set{DataType}}
158+
)
155159
if !supports_in_domain(reshape(supps, length(supps), 1), domain)
156160
_error("Support violates the infinite domain.")
157161
end
@@ -165,7 +169,7 @@ function _process_supports(
165169
vect_supps::Vector{<:Vector{<:Real}},
166170
domain,
167171
sig_digits
168-
)::Dict{Vector{Float64}, Set{DataType}}
172+
)
169173
len = length(first(vect_supps))
170174
if any(length(s) != len for s in vect_supps)
171175
_error("Inconsistent support dimensions.")
@@ -185,7 +189,7 @@ function _process_derivative_methods(
185189
_error::Function,
186190
methods::V,
187191
domains
188-
)::V where {V <: Vector{<:NonGenerativeDerivativeMethod}}
192+
) where {V <: Vector{<:NonGenerativeDerivativeMethod}}
189193
return methods
190194
end
191195

@@ -219,6 +223,7 @@ function _build_parameters(
219223
end
220224
# process the infinite domain
221225
domain = _make_array_domain(_error, domains, orig_inds)
226+
domain = round_domain(domain, sig_digits)
222227
# we have supports
223228
if !isempty(supports)
224229
supp_dict = _process_supports(_error, supports, domain, sig_digits)
@@ -272,7 +277,7 @@ function add_parameters(
272277
model::InfiniteModel,
273278
params::DependentParameters,
274279
names::Vector{String}
275-
)::Vector{GeneralVariableRef}
280+
)
276281
# get the number of parameters
277282
num_params = length(params.domain)
278283
# process the names
@@ -297,7 +302,7 @@ end
297302
# NAMING
298303
################################################################################
299304
# Get the parameter index in the DependentParameters object
300-
_param_index(pref::DependentParameterRef)::Int = JuMP.index(pref).param_index
305+
_param_index(pref::DependentParameterRef) = JuMP.index(pref).param_index
301306

302307
"""
303308
JuMP.name(pref::DependentParameterRef)::String
@@ -311,7 +316,7 @@ julia> name(pref)
311316
"par_name"
312317
```
313318
"""
314-
function JuMP.name(pref::DependentParameterRef)::String
319+
function JuMP.name(pref::DependentParameterRef)
315320
object = get(_data_dictionary(pref), JuMP.index(pref).object_index, nothing)
316321
return isnothing(object) ? "" : object.names[_param_index(pref)]
317322
end
@@ -330,7 +335,7 @@ julia> name(vref)
330335
"para_name"
331336
```
332337
"""
333-
function JuMP.set_name(pref::DependentParameterRef, name::String)::Nothing
338+
function JuMP.set_name(pref::DependentParameterRef, name::String)
334339
_data_object(pref).names[_param_index(pref)] = name
335340
JuMP.owner_model(pref).name_to_param = nothing
336341
return

0 commit comments

Comments
 (0)