Skip to content

Commit 147a5b9

Browse files
authored
Improve code coverage (#2639)
1 parent d68b3fb commit 147a5b9

28 files changed

+580
-108
lines changed

src/FileFormats/MPS/MPS.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,7 +1153,7 @@ function Base.read!(io::IO, model::Model)
11531153
end
11541154
data = TempMPSModel()
11551155
header = HEADER_NAME
1156-
while !eof(io)
1156+
while !eof(io) && header != HEADER_ENDATA
11571157
raw_line = readline(io)
11581158
if startswith(raw_line, '*')
11591159
continue # Lines starting with `*` are comments
@@ -1219,7 +1219,6 @@ function Base.read!(io::IO, model::Model)
12191219
parse_indicators_line(data, items)
12201220
else
12211221
@assert header == HEADER_ENDATA
1222-
break
12231222
end
12241223
end
12251224
copy_to(model, data)
@@ -1556,7 +1555,7 @@ function parse_single_rhs(
15561555
data.row_upper[row] = value
15571556
else
15581557
@assert data.sense[row] == SENSE_N
1559-
error("Cannot have RHS for objective: $(join(items, " "))")
1558+
error("Cannot have RHS for free row: $(join(items, " "))")
15601559
end
15611560
return
15621561
end

src/Utilities/Utilities.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import LinearAlgebra
1010
import MathOptInterface as MOI
1111
import MutableArithmetics as MA
1212
import OrderedCollections: OrderedDict
13+
import SparseArrays
14+
import Unicode
1315

1416
function print_with_acronym(io::IO, s::AbstractString)
1517
return print(io, replace_acronym(s))

src/Utilities/cachingoptimizer.jl

Lines changed: 35 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,8 @@ function MOI.add_variable(m::CachingOptimizer)
341341
vindex_optimizer =
342342
MOI.add_variable(m.optimizer)::MOI.VariableIndex
343343
catch err
344-
if err isa MOI.NotAllowedError
345-
reset_optimizer(m)
346-
else
347-
rethrow(err)
348-
end
344+
_rethrow_if_not_NotAllowedError(err)
345+
reset_optimizer(m)
349346
end
350347
else
351348
vindex_optimizer = MOI.add_variable(m.optimizer)::MOI.VariableIndex
@@ -366,11 +363,8 @@ function MOI.add_variables(m::CachingOptimizer, n)
366363
vindices_optimizer =
367364
MOI.add_variables(m.optimizer, n)::Vector{MOI.VariableIndex}
368365
catch err
369-
if err isa MOI.NotAllowedError
370-
reset_optimizer(m)
371-
else
372-
rethrow(err)
373-
end
366+
_rethrow_if_not_NotAllowedError(err)
367+
reset_optimizer(m)
374368
end
375369
else
376370
vindices_optimizer =
@@ -413,11 +407,8 @@ function MOI.add_constrained_variable(
413407
MOI.ConstraintIndex{MOI.VariableIndex,S},
414408
}
415409
catch err
416-
if err isa MOI.NotAllowedError
417-
reset_optimizer(m)
418-
else
419-
rethrow(err)
420-
end
410+
_rethrow_if_not_NotAllowedError(err)
411+
reset_optimizer(m)
421412
end
422413
else
423414
vindex_optimizer, cindex_optimizer = MOI.add_constrained_variable(
@@ -480,11 +471,8 @@ function MOI.add_constrained_variables(
480471
MOI.ConstraintIndex{MOI.VectorOfVariables,S},
481472
}
482473
catch err
483-
if err isa MOI.NotAllowedError
484-
reset_optimizer(m)
485-
else
486-
rethrow(err)
487-
end
474+
_rethrow_if_not_NotAllowedError(err)
475+
reset_optimizer(m)
488476
end
489477
else
490478
vindices_optimizer, cindex_optimizer =
@@ -534,14 +522,11 @@ function MOI.add_constraint(
534522
set,
535523
)::MOI.ConstraintIndex{F,S}
536524
catch err
537-
if err isa MOI.NotAllowedError
538-
# It could be MOI.AddConstraintNotAllowed{F', S'} with F' != F
539-
# or S' != S if, for example, the `F`-in-`S` constraint is bridged
540-
# to other constraints in `m.optimizer`
541-
reset_optimizer(m)
542-
else
543-
rethrow(err)
544-
end
525+
_rethrow_if_not_NotAllowedError(err)
526+
# It could be MOI.AddConstraintNotAllowed{F', S'} with F' != F
527+
# or S' != S if, for example, the `F`-in-`S` constraint is bridged
528+
# to other constraints in `m.optimizer`
529+
reset_optimizer(m)
545530
end
546531
else
547532
cindex_optimizer = MOI.add_constraint(
@@ -571,11 +556,8 @@ function MOI.modify(
571556
try
572557
MOI.modify(m.optimizer, cindex_optimizer, change_optimizer)
573558
catch err
574-
if err isa MOI.NotAllowedError
575-
reset_optimizer(m)
576-
else
577-
rethrow(err)
578-
end
559+
_rethrow_if_not_NotAllowedError(err)
560+
reset_optimizer(m)
579561
end
580562
else
581563
MOI.modify(m.optimizer, cindex_optimizer, change_optimizer)
@@ -607,11 +589,8 @@ function _replace_constraint_function_or_set(
607589
replacement_optimizer,
608590
)
609591
catch err
610-
if err isa MOI.NotAllowedError
611-
reset_optimizer(m)
612-
else
613-
rethrow(err)
614-
end
592+
_rethrow_if_not_NotAllowedError(err)
593+
reset_optimizer(m)
615594
end
616595
else
617596
MOI.set(
@@ -671,11 +650,8 @@ function MOI.modify(
671650
try
672651
MOI.modify(m.optimizer, obj, change_optimizer)
673652
catch err
674-
if err isa MOI.NotAllowedError
675-
reset_optimizer(m)
676-
else
677-
rethrow(err)
678-
end
653+
_rethrow_if_not_NotAllowedError(err)
654+
reset_optimizer(m)
679655
end
680656
else
681657
MOI.modify(m.optimizer, obj, change_optimizer)
@@ -700,11 +676,8 @@ function MOI.delete(m::CachingOptimizer, index::MOI.Index)
700676
try
701677
MOI.delete(m.optimizer, index_optimizer)
702678
catch err
703-
if err isa MOI.NotAllowedError
704-
reset_optimizer(m)
705-
else
706-
rethrow(err)
707-
end
679+
_rethrow_if_not_NotAllowedError(err)
680+
reset_optimizer(m)
708681
end
709682
else
710683
MOI.delete(m.optimizer, index_optimizer)
@@ -734,11 +707,8 @@ function MOI.delete(m::CachingOptimizer, indices::Vector{<:MOI.Index})
734707
try
735708
MOI.delete(m.optimizer, indices_optimizer)
736709
catch err
737-
if err isa MOI.NotAllowedError
738-
reset_optimizer(m)
739-
else
740-
rethrow(err)
741-
end
710+
_rethrow_if_not_NotAllowedError(err)
711+
reset_optimizer(m)
742712
end
743713
else
744714
MOI.delete(m.optimizer, indices_optimizer)
@@ -771,11 +741,8 @@ function MOI.set(m::CachingOptimizer, attr::MOI.AbstractModelAttribute, value)
771741
try
772742
MOI.set(m.optimizer, attr, optimizer_value)
773743
catch err
774-
if err isa MOI.NotAllowedError
775-
reset_optimizer(m)
776-
else
777-
rethrow(err)
778-
end
744+
_rethrow_if_not_NotAllowedError(err)
745+
reset_optimizer(m)
779746
end
780747
else
781748
MOI.set(m.optimizer, attr, optimizer_value)
@@ -798,11 +765,8 @@ function MOI.set(
798765
try
799766
MOI.set(m.optimizer, attr, optimizer_index, optimizer_value)
800767
catch err
801-
if err isa MOI.NotAllowedError
802-
reset_optimizer(m)
803-
else
804-
rethrow(err)
805-
end
768+
_rethrow_if_not_NotAllowedError(err)
769+
reset_optimizer(m)
806770
end
807771
else
808772
MOI.set(m.optimizer, attr, optimizer_index, optimizer_value)
@@ -831,13 +795,15 @@ function MOI.supports(
831795
(m.state == NO_OPTIMIZER || MOI.supports(m.optimizer, attr)::Bool)
832796
end
833797

798+
_rethrow_if_not_NotAllowedError(err) = rethrow(err)
799+
800+
_rethrow_if_not_NotAllowedError(::MOI.NotAllowedError) = nothing
801+
834802
function _get_model_attribute(model::CachingOptimizer, attr::MOI.ObjectiveValue)
835803
try
836804
return MOI.get(model.optimizer, attr)
837805
catch err
838-
if !(err isa MOI.GetAttributeNotAllowed)
839-
rethrow(err)
840-
end
806+
_rethrow_if_not_NotAllowedError(err)
841807
return get_fallback(model, attr)
842808
end
843809
end
@@ -849,9 +815,7 @@ function _get_model_attribute(
849815
try
850816
return MOI.get(model.optimizer, attr)
851817
catch err
852-
if !(err isa MOI.GetAttributeNotAllowed)
853-
rethrow(err)
854-
end
818+
_rethrow_if_not_NotAllowedError(err)
855819
MOI.check_result_index_bounds(model, attr)
856820
# We don't know what coefficient type to use, so just use whatever the
857821
# objective value type is. This is slightly inefficient, but it
@@ -996,10 +960,7 @@ function _get_fallback(
996960
model.model_to_optimizer_map[index],
997961
)
998962
catch err
999-
# Thrown if .optimizer doesn't support attr
1000-
if !(err isa MOI.GetAttributeNotAllowed)
1001-
rethrow(err)
1002-
end
963+
_rethrow_if_not_NotAllowedError(err)
1003964
return get_fallback(model, attr, index)
1004965
end
1005966
end
@@ -1016,10 +977,7 @@ function _get_fallback(
1016977
[model.model_to_optimizer_map[i] for i in indices],
1017978
)
1018979
catch err
1019-
# Thrown if .optimizer doesn't support attr
1020-
if !(err isa MOI.GetAttributeNotAllowed)
1021-
rethrow(err)
1022-
end
980+
_rethrow_if_not_NotAllowedError(err)
1023981
return [get_fallback(model, attr, i) for i in indices]
1024982
end
1025983
end

src/Utilities/print.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,13 +683,25 @@ end
683683

684684
Base.show(io::IO, ::MIME"text/latex", model::_LatexModel) = show(io, model)
685685

686-
function Base.print(model::MOI.ModelLike; kwargs...)
686+
function _get_ijulia_latex_display()
687687
for d in Base.Multimedia.displays
688688
if Base.Multimedia.displayable(d, "text/latex") &&
689689
startswith("$(typeof(d))", "IJulia.")
690-
return display(d, "text/latex", latex_formulation(model; kwargs...))
690+
return d
691691
end
692692
end
693+
return
694+
end
695+
696+
function Base.print(
697+
model::MOI.ModelLike;
698+
_latex_display = _get_ijulia_latex_display(),
699+
kwargs...,
700+
)
701+
if _latex_display !== nothing
702+
formulation = latex_formulation(model; kwargs...)
703+
return display(_latex_display, "text/latex", formulation)
704+
end
693705
return print(stdout, model; kwargs...)
694706
end
695707

src/Utilities/sparse_matrix.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
# Use of this source code is governed by an MIT-style license that can be found
55
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
66

7-
import SparseArrays
8-
97
"""
108
abstract type AbstractIndexing end
119

src/Utilities/struct_of_constraints.jl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,6 @@ end
213213

214214
_typed(s::SymbolFS) = s.typed ? Expr(:curly, esc(s.s), esc(:T)) : esc(s.s)
215215

216-
# Base.lowercase is moved to Unicode.lowercase in Julia v0.7
217-
import Unicode
218-
219216
function _field(s::SymbolFS)
220217
return Symbol(replace(Unicode.lowercase(string(s.s)), "." => "_"))
221218
end

src/Utilities/variables_container.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ end
117117
# inference.
118118
function _throw_if_lower_bound_set_inner(variable, S2, mask, T)
119119
S1 = _flag_to_set_type(mask, T)
120-
throw(MOI.LowerBoundAlreadySet{S1,S2}(variable))
121-
return
120+
return throw(MOI.LowerBoundAlreadySet{S1,S2}(variable))
122121
end
123122

124123
function _throw_if_lower_bound_set(variable, S2, mask, T)
@@ -135,8 +134,7 @@ end
135134
# inference.
136135
function _throw_if_upper_bound_set_inner(variable, S2, mask, T)
137136
S1 = _flag_to_set_type(mask, T)
138-
throw(MOI.UpperBoundAlreadySet{S1,S2}(variable))
139-
return
137+
return throw(MOI.UpperBoundAlreadySet{S1,S2}(variable))
140138
end
141139

142140
function _throw_if_upper_bound_set(variable, S2, mask, T)

src/indextypes.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ end
9393

9494
function Base.showerror(io::IO, err::InvalidIndex)
9595
return print(
96+
io,
9697
"The index $(err.index) is invalid. Note that an index becomes invalid after it has been deleted.",
9798
)
9899
end

src/instantiate.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct OptimizerWithAttributes
2424
end
2525

2626
_to_param(param::Pair{<:AbstractOptimizerAttribute}) = param
27+
2728
function _to_param(param::Pair{String})
2829
return RawOptimizerAttribute(param.first) => param.second
2930
end

test/Benchmarks/Benchmarks.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ function test_baseline()
4343
suite = MOI.Benchmarks.suite() do
4444
return MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}())
4545
end
46+
@test_throws(
47+
ErrorException("You create a baseline with `create_baseline` first."),
48+
MOI.Benchmarks.compare_against_baseline(
49+
suite,
50+
"baseline";
51+
directory = @__DIR__,
52+
samples = 1,
53+
verbose = true,
54+
),
55+
)
4656
MOI.Benchmarks.create_baseline(
4757
suite,
4858
"baseline";

test/FileFormats/FileFormats.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,19 @@ function test_generic_names()
189189
return
190190
end
191191

192+
function test_unique_names()
193+
model = MOI.Utilities.Model{Float64}()
194+
x = MOI.add_variables(model, 3)
195+
MOI.set.(model, MOI.VariableName(), x, "x")
196+
c = MOI.add_constraint.(model, 1.0 .* x, MOI.EqualTo(1.0))
197+
MOI.set.(model, MOI.ConstraintName(), c, "c")
198+
MOI.set(model, MOI.ConstraintName(), c[2], "c_1")
199+
MOI.FileFormats.create_unique_names(model)
200+
@test MOI.get.(model, MOI.VariableName(), x) == ["x", "x_1", "x_2"]
201+
@test MOI.get.(model, MOI.ConstraintName(), c) == ["c", "c_1", "c_2"]
202+
return
203+
end
204+
192205
end
193206

194207
TestFileFormats.runtests()

0 commit comments

Comments
 (0)