Skip to content
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
2 changes: 1 addition & 1 deletion src/FileFormats/LP/LP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@
for token in tokens[3:end]
items = String.(split(token, ":"))
if length(items) != 2
error("Invalid sequence: $(token)")
error("Invalid token in SOS constraint: $(token)")

Check warning on line 1004 in src/FileFormats/LP/LP.jl

View check run for this annotation

Codecov / codecov/patch

src/FileFormats/LP/LP.jl#L1004

Added line #L1004 was not covered by tests
end
push!(variables, _get_variable_from_name(model, cache, items[1]))
push!(weights, parse(Float64, items[2]))
Expand Down
25 changes: 25 additions & 0 deletions test/FileFormats/CBF/CBF.jl
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,15 @@ const _WRITE_READ_MODELS = [
c1: [x, y, z] in ExponentialCone()
""",
),
(
"VectorOfVariables as function in ExponentialCone",
"""
variables: x, y, z
minobjective: x
c0: [x, y, z] in Nonnegatives(3)
c1: [x, y, z] in ExponentialCone()
""",
),
(
"VectorOfVariables in DualExponentialCone",
"""
Expand All @@ -301,6 +310,15 @@ const _WRITE_READ_MODELS = [
c1: [x, y, z] in DualExponentialCone()
""",
),
(
"VectorOfVariables as function in DualExponentialCone",
"""
variables: x, y, z
minobjective: x
c0: [x, y, z] in Nonnegatives(3)
c1: [x, y, z] in DualExponentialCone()
""",
),
(
"VectorOfVariables in PowerCone",
"""
Expand Down Expand Up @@ -674,6 +692,13 @@ function test_roundtrip_DualExponentialCone()
return
end

function test_supports_quadratic_objective()
model = CBF.Model()
F = MOI.ScalarQuadraticFunction{Float64}
@test !MOI.supports(model, MOI.ObjectiveFunction{F}())
return
end

end # module

TestCBF.runtests()
28 changes: 25 additions & 3 deletions test/FileFormats/FileFormats.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,10 @@ function test_compression()
filename = joinpath(@__DIR__, "free_integer.mps")
MOI.write_to_file(model, filename * ".garbage")
for ext in ["", ".bz2", ".gz"]
MOI.write_to_file(model, filename * ext)
model2 = MOI.FileFormats.Model(filename = filename * ext)
MOI.read_from_file(model2, filename)
filename_ext = filename * ext
MOI.write_to_file(model, filename_ext)
model2 = MOI.FileFormats.Model(filename = filename_ext)
MOI.read_from_file(model2, filename_ext)
end

sleep(1.0) # Allow time for unlink to happen.
Expand Down Expand Up @@ -167,6 +168,27 @@ function test_Model()
)
end

function test_generic_names()
# These methods were added to MOI, but then we changed the REW model to not
# need them.
model = MOI.Utilities.Model{Float64}()
x = MOI.add_variables(model, 2)
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")
c2 = MOI.add_constraint(model, 1.0 * x[2], MOI.LessThan(1.0))
MOI.set(model, MOI.ConstraintName(), c2, "R2")
MOI.FileFormats.create_generic_names(model)
@test MOI.get.(model, MOI.VariableName(), x) == ["C1", "C2"]
c_name = MOI.get.(model, MOI.ConstraintName(), c)
c2_name = MOI.get(model, MOI.ConstraintName(), c2)
names = vcat(c_name, c2_name)
# The names depend on the order that the constraints are parsed. Either is
# okay.
@test names == ["R1", "R2", "R3"] || names == ["R1", "R3", "R2"]
return
end

end

TestFileFormats.runtests()
43 changes: 32 additions & 11 deletions test/FileFormats/LP/LP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ import MathOptInterface.FileFormats: LP

const LP_TEST_FILE = "test.lp"

function runtests()
for name in names(@__MODULE__, all = true)
if startswith("$(name)", "test_")
@testset "$name" begin
getfield(@__MODULE__, name)()
end
end
end
sleep(1.0) # Allow time for unlink to happen.
rm(LP_TEST_FILE, force = true)
return
end

function test_show()
@test sprint(summary, LP.Model()) == "MOI.FileFormats.LP.Model"
return
Expand Down Expand Up @@ -1065,19 +1078,27 @@ function test_VectorAffineFunction_SOS()
return
end

function runtests()
for name in names(@__MODULE__, all = true)
if startswith("$(name)", "test_")
@testset "$name" begin
getfield(@__MODULE__, name)()
end
end
end
sleep(1.0) # Allow time for unlink to happen.
rm(LP_TEST_FILE, force = true)
function test_comprehensive_write()
model = LP.Model()
io = IOBuffer()
print(
io,
"""
minimize
obj: x + y
subject to
SOS
c11: S1:: x 1.0 y 2.0
""",
)
seekstart(io)
@test_throws(
ErrorException("Invalid token in SOS constraint: x"),
read!(io, model),
)
return
end

end
end # module

TestLP.runtests()
55 changes: 55 additions & 0 deletions test/FileFormats/MOF/MOF.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,27 @@ function test_nonlinear_variable_real_nodes()
return
end

function test_nonlinear_variable_complex_nodes()
x = MOI.VariableIndex(1)
object = Dict{String,Any}(
"type" => "ScalarNonlinearFunction",
"root" => MOF.Dict{String,Any}(
"type" => "^",
"args" => Any[
Dict{String,Any}("type" => "node", "index" => 1),
Dict{String,Any}("type" => "node", "index" => 2),
],
),
"node_list" => Any[
Dict{String,Any}("type" => "variable", "name" => "x"),
Dict{String,Any}("type" => "complex", "real" => 2.0, "imag" => 3.0),
],
)
f = MOI.ScalarNonlinearFunction(:^, Any[x, 2.0+3im])
@test MOF.function_to_moi(object, Dict("x" => x)) ≈ f
return
end

function test_mof_scalaraffinefunction()
x = MOI.VariableIndex(1)
f = 1.0 * x + 2.0
Expand Down Expand Up @@ -1535,6 +1556,40 @@ function test_mof_scalarquadraticfunction()
return
end

function test_nonlinear_expression_not_call()
model = MOF.Model()
x = MOI.add_variable(model)
expr = :($x[1])
con = MOI.add_constraint(model, MOF.Nonlinear(expr), MOI.EqualTo(1.0))
io = IOBuffer()
@test_throws(
ErrorException(
"Expected an expression that was a function. Got $expr.",
),
write(io, model),
)
return
end

function test_write_NLPBlock_no_objective()
model = MOF.Model()
x = MOI.add_variables(model, 4)
for (index, variable) in enumerate(x)
MOI.set(model, MOI.VariableName(), variable, "var_$(index)")
end
MOI.add_constraints(model, x, Ref(MOI.Interval(1.0, 5.0)))
block = HS071(x)
new_block =
MOI.NLPBlockData(block.constraint_bounds, block.evaluator, false)
MOI.set(model, MOI.NLPBlock(), new_block)
io = IOBuffer()
write(io, model)
seekstart(io)
contents = read(io, String)
@test occursin(""""objective":{"sense":"feasibility"}""", contents)
return
end

end

TestMOF.runtests()
33 changes: 33 additions & 0 deletions test/FileFormats/MPS/MPS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,39 @@ function test_qcmatrix_read_cplex()
return
end

function test_model_Name()
model = MPS.Model()
MOI.set(model, MOI.Name(), "TestFoo")
io = IOBuffer()
write(io, model)
seekstart(io)
contents = read(io, String)
@test occursin("NAME TestFoo", contents)
return
end

function test_model_large_integer()
model = MPS.Model()
x = MOI.add_constrained_variable(model, MOI.GreaterThan(123.0))
io = IOBuffer()
write(io, model)
seekstart(io)
contents = read(io, String)
@test occursin("LO bounds x1 123", contents)
return
end

function test_model_not_empty()
model = MPS.Model()
x = MOI.add_variable(model)
io = IOBuffer()
@test_throws(
ErrorException("Cannot read in file because model is not empty."),
read!(io, model),
)
return
end

end # TestMPS

TestMPS.runtests()
4 changes: 4 additions & 0 deletions test/FileFormats/MPS/free_integer.mps
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
* A model with blank lines and comments
NAME

OBJSENSE MIN

ROWS
N obj
G con1

COLUMNS
MARKER 'MARKER' 'INTORG'
x obj 1 con1 1
Expand Down
10 changes: 10 additions & 0 deletions test/FileFormats/NL/sol.jl
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,16 @@ function test_result_count()
return
end

function test_eol()
model = NL.Model()
io = IOBuffer()
@test_throws(
ErrorException("Reached end of sol file unexpectedly."),
NL.SolFileResults(io, model),
)
return
end

end

TestNonlinearSolFiles.runtests()
43 changes: 31 additions & 12 deletions test/FileFormats/SDPA/SDPA.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,24 @@ using Test

import MathOptInterface as MOI
import MathOptInterface.Utilities as MOIU
const SDPA = MOI.FileFormats.SDPA
import MathOptInterface.FileFormats: SDPA

const SDPA_TEST_FILE = "test.sdpa"
const SDPA_MODELS_DIR = joinpath(@__DIR__, "models")

function runtests()
for name in names(@__MODULE__, all = true)
if startswith("$(name)", "test_")
@testset "$name" begin
getfield(@__MODULE__, name)()
end
end
end
sleep(1.0) # Allow time for unlink to happen.
rm(SDPA_TEST_FILE, force = true)
return
end

function _set_var_and_con_names(model::MOI.ModelLike)
variable_names = String[]
for j in MOI.get(model, MOI.ListOfVariableIndices())
Expand Down Expand Up @@ -330,19 +344,24 @@ function test_dim_reader()
end
end

function runtests()
for name in names(@__MODULE__, all = true)
if startswith("$(name)", "test_")
@testset "$name" begin
getfield(@__MODULE__, name)()
end
end
end
sleep(1.0) # Allow time for unlink to happen.
rm(SDPA_TEST_FILE, force = true)
function test_integer_before_variables()
file = """
*INTEGER
*1
"""
io = IOBuffer()
print(io, file)
seekstart(io)
model = SDPA.Model()
@test_throws(
ErrorException(
"The number of variables should be given before *INTEGER section.",
),
read!(io, model),
)
return
end

end
end # module

TestSDPA.runtests()
Loading