Skip to content

Improve code coverage #2639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/FileFormats/MPS/MPS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ function Base.read!(io::IO, model::Model)
end
data = TempMPSModel()
header = HEADER_NAME
while !eof(io)
while !eof(io) && header != HEADER_ENDATA
raw_line = readline(io)
if startswith(raw_line, '*')
continue # Lines starting with `*` are comments
Expand Down Expand Up @@ -1219,7 +1219,6 @@ function Base.read!(io::IO, model::Model)
parse_indicators_line(data, items)
else
@assert header == HEADER_ENDATA
break
end
end
copy_to(model, data)
Expand Down Expand Up @@ -1556,7 +1555,7 @@ function parse_single_rhs(
data.row_upper[row] = value
else
@assert data.sense[row] == SENSE_N
error("Cannot have RHS for objective: $(join(items, " "))")
error("Cannot have RHS for free row: $(join(items, " "))")
end
return
end
Expand Down
2 changes: 2 additions & 0 deletions src/Utilities/Utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import LinearAlgebra
import MathOptInterface as MOI
import MutableArithmetics as MA
import OrderedCollections: OrderedDict
import SparseArrays
import Unicode

function print_with_acronym(io::IO, s::AbstractString)
return print(io, replace_acronym(s))
Expand Down
112 changes: 35 additions & 77 deletions src/Utilities/cachingoptimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -341,11 +341,8 @@
vindex_optimizer =
MOI.add_variable(m.optimizer)::MOI.VariableIndex
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
vindex_optimizer = MOI.add_variable(m.optimizer)::MOI.VariableIndex
Expand All @@ -366,11 +363,8 @@
vindices_optimizer =
MOI.add_variables(m.optimizer, n)::Vector{MOI.VariableIndex}
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
vindices_optimizer =
Expand Down Expand Up @@ -413,11 +407,8 @@
MOI.ConstraintIndex{MOI.VariableIndex,S},
}
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
vindex_optimizer, cindex_optimizer = MOI.add_constrained_variable(
Expand Down Expand Up @@ -480,11 +471,8 @@
MOI.ConstraintIndex{MOI.VectorOfVariables,S},
}
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
vindices_optimizer, cindex_optimizer =
Expand Down Expand Up @@ -534,14 +522,11 @@
set,
)::MOI.ConstraintIndex{F,S}
catch err
if err isa MOI.NotAllowedError
# It could be MOI.AddConstraintNotAllowed{F', S'} with F' != F
# or S' != S if, for example, the `F`-in-`S` constraint is bridged
# to other constraints in `m.optimizer`
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
# It could be MOI.AddConstraintNotAllowed{F', S'} with F' != F
# or S' != S if, for example, the `F`-in-`S` constraint is bridged
# to other constraints in `m.optimizer`
reset_optimizer(m)
end
else
cindex_optimizer = MOI.add_constraint(
Expand Down Expand Up @@ -571,11 +556,8 @@
try
MOI.modify(m.optimizer, cindex_optimizer, change_optimizer)
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
MOI.modify(m.optimizer, cindex_optimizer, change_optimizer)
Expand Down Expand Up @@ -607,11 +589,8 @@
replacement_optimizer,
)
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
MOI.set(
Expand Down Expand Up @@ -671,11 +650,8 @@
try
MOI.modify(m.optimizer, obj, change_optimizer)
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
MOI.modify(m.optimizer, obj, change_optimizer)
Expand All @@ -700,11 +676,8 @@
try
MOI.delete(m.optimizer, index_optimizer)
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
MOI.delete(m.optimizer, index_optimizer)
Expand Down Expand Up @@ -734,11 +707,8 @@
try
MOI.delete(m.optimizer, indices_optimizer)
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
reset_optimizer(m)
end
else
MOI.delete(m.optimizer, indices_optimizer)
Expand Down Expand Up @@ -771,11 +741,8 @@
try
MOI.set(m.optimizer, attr, optimizer_value)
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)

Check warning on line 744 in src/Utilities/cachingoptimizer.jl

View check run for this annotation

Codecov / codecov/patch

src/Utilities/cachingoptimizer.jl#L744

Added line #L744 was not covered by tests
reset_optimizer(m)
end
else
MOI.set(m.optimizer, attr, optimizer_value)
Expand All @@ -798,11 +765,8 @@
try
MOI.set(m.optimizer, attr, optimizer_index, optimizer_value)
catch err
if err isa MOI.NotAllowedError
reset_optimizer(m)
else
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)

Check warning on line 768 in src/Utilities/cachingoptimizer.jl

View check run for this annotation

Codecov / codecov/patch

src/Utilities/cachingoptimizer.jl#L768

Added line #L768 was not covered by tests
reset_optimizer(m)
end
else
MOI.set(m.optimizer, attr, optimizer_index, optimizer_value)
Expand Down Expand Up @@ -831,13 +795,15 @@
(m.state == NO_OPTIMIZER || MOI.supports(m.optimizer, attr)::Bool)
end

_rethrow_if_not_NotAllowedError(err) = rethrow(err)

Check warning on line 798 in src/Utilities/cachingoptimizer.jl

View check run for this annotation

Codecov / codecov/patch

src/Utilities/cachingoptimizer.jl#L798

Added line #L798 was not covered by tests

_rethrow_if_not_NotAllowedError(::MOI.NotAllowedError) = nothing

function _get_model_attribute(model::CachingOptimizer, attr::MOI.ObjectiveValue)
try
return MOI.get(model.optimizer, attr)
catch err
if !(err isa MOI.GetAttributeNotAllowed)
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
return get_fallback(model, attr)
end
end
Expand All @@ -849,9 +815,7 @@
try
return MOI.get(model.optimizer, attr)
catch err
if !(err isa MOI.GetAttributeNotAllowed)
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
MOI.check_result_index_bounds(model, attr)
# We don't know what coefficient type to use, so just use whatever the
# objective value type is. This is slightly inefficient, but it
Expand Down Expand Up @@ -996,10 +960,7 @@
model.model_to_optimizer_map[index],
)
catch err
# Thrown if .optimizer doesn't support attr
if !(err isa MOI.GetAttributeNotAllowed)
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
return get_fallback(model, attr, index)
end
end
Expand All @@ -1016,10 +977,7 @@
[model.model_to_optimizer_map[i] for i in indices],
)
catch err
# Thrown if .optimizer doesn't support attr
if !(err isa MOI.GetAttributeNotAllowed)
rethrow(err)
end
_rethrow_if_not_NotAllowedError(err)
return [get_fallback(model, attr, i) for i in indices]
end
end
Expand Down
16 changes: 14 additions & 2 deletions src/Utilities/print.jl
Original file line number Diff line number Diff line change
Expand Up @@ -683,13 +683,25 @@ end

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

function Base.print(model::MOI.ModelLike; kwargs...)
function _get_ijulia_latex_display()
for d in Base.Multimedia.displays
if Base.Multimedia.displayable(d, "text/latex") &&
startswith("$(typeof(d))", "IJulia.")
return display(d, "text/latex", latex_formulation(model; kwargs...))
return d
end
end
return
end

function Base.print(
model::MOI.ModelLike;
_latex_display = _get_ijulia_latex_display(),
kwargs...,
)
if _latex_display !== nothing
formulation = latex_formulation(model; kwargs...)
return display(_latex_display, "text/latex", formulation)
end
return print(stdout, model; kwargs...)
end

Expand Down
2 changes: 0 additions & 2 deletions src/Utilities/sparse_matrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
# Use of this source code is governed by an MIT-style license that can be found
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.

import SparseArrays

"""
abstract type AbstractIndexing end

Expand Down
3 changes: 0 additions & 3 deletions src/Utilities/struct_of_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,6 @@ end

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

# Base.lowercase is moved to Unicode.lowercase in Julia v0.7
import Unicode

function _field(s::SymbolFS)
return Symbol(replace(Unicode.lowercase(string(s.s)), "." => "_"))
end
Expand Down
6 changes: 2 additions & 4 deletions src/Utilities/variables_container.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,7 @@ end
# inference.
function _throw_if_lower_bound_set_inner(variable, S2, mask, T)
S1 = _flag_to_set_type(mask, T)
throw(MOI.LowerBoundAlreadySet{S1,S2}(variable))
return
return throw(MOI.LowerBoundAlreadySet{S1,S2}(variable))
end

function _throw_if_lower_bound_set(variable, S2, mask, T)
Expand All @@ -135,8 +134,7 @@ end
# inference.
function _throw_if_upper_bound_set_inner(variable, S2, mask, T)
S1 = _flag_to_set_type(mask, T)
throw(MOI.UpperBoundAlreadySet{S1,S2}(variable))
return
return throw(MOI.UpperBoundAlreadySet{S1,S2}(variable))
end

function _throw_if_upper_bound_set(variable, S2, mask, T)
Expand Down
1 change: 1 addition & 0 deletions src/indextypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ end

function Base.showerror(io::IO, err::InvalidIndex)
return print(
io,
"The index $(err.index) is invalid. Note that an index becomes invalid after it has been deleted.",
)
end
Expand Down
1 change: 1 addition & 0 deletions src/instantiate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct OptimizerWithAttributes
end

_to_param(param::Pair{<:AbstractOptimizerAttribute}) = param

function _to_param(param::Pair{String})
return RawOptimizerAttribute(param.first) => param.second
end
Expand Down
10 changes: 10 additions & 0 deletions test/Benchmarks/Benchmarks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ function test_baseline()
suite = MOI.Benchmarks.suite() do
return MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}())
end
@test_throws(
ErrorException("You create a baseline with `create_baseline` first."),
MOI.Benchmarks.compare_against_baseline(
suite,
"baseline";
directory = @__DIR__,
samples = 1,
verbose = true,
),
)
MOI.Benchmarks.create_baseline(
suite,
"baseline";
Expand Down
13 changes: 13 additions & 0 deletions test/FileFormats/FileFormats.jl
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,19 @@ function test_generic_names()
return
end

function test_unique_names()
model = MOI.Utilities.Model{Float64}()
x = MOI.add_variables(model, 3)
MOI.set.(model, MOI.VariableName(), x, "x")
c = MOI.add_constraint.(model, 1.0 .* x, MOI.EqualTo(1.0))
MOI.set.(model, MOI.ConstraintName(), c, "c")
MOI.set(model, MOI.ConstraintName(), c[2], "c_1")
MOI.FileFormats.create_unique_names(model)
@test MOI.get.(model, MOI.VariableName(), x) == ["x", "x_1", "x_2"]
@test MOI.get.(model, MOI.ConstraintName(), c) == ["c", "c_1", "c_2"]
return
end

end

TestFileFormats.runtests()
Loading
Loading