From bf9c7b79a13d166a6bbce77474d3b99c540f15a4 Mon Sep 17 00:00:00 2001 From: odow Date: Mon, 19 Feb 2024 14:34:13 +1300 Subject: [PATCH] [FileFormats.MPS] tidy and refactor test/FileFormats/MPS/MPS.jl --- test/FileFormats/MPS/MPS.jl | 933 ++++++++++++++++++------------------ 1 file changed, 459 insertions(+), 474 deletions(-) diff --git a/test/FileFormats/MPS/MPS.jl b/test/FileFormats/MPS/MPS.jl index 6430b5e7e9..4641ae420d 100644 --- a/test/FileFormats/MPS/MPS.jl +++ b/test/FileFormats/MPS/MPS.jl @@ -9,35 +9,30 @@ module TestMPS using Test import MathOptInterface as MOI -import MathOptInterface.Utilities as MOIU import DataStructures: OrderedDict const MPS = MOI.FileFormats.MPS -const MPS_TEST_FILE = "test.mps" - function runtests() - for name in names(@__MODULE__, all = true) + 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(MPS_TEST_FILE, force = true) return end -function _test_write_to_file(input::String, output::String) - model = MPS.Model() +function _test_write_to_file(input::String, output::String; kwargs...) + model = MPS.Model(; kwargs...) MOI.Utilities.loadfromstring!(model, input) data = sprint(write, model) if data != output print(data) end @test data == output - return + return model end function _test_model_equality( @@ -48,22 +43,26 @@ function _test_model_equality( kwargs..., ) model = MPS.Model(; kwargs...) - MOIU.loadfromstring!(model, model_string) - MOI.write_to_file(model, MPS_TEST_FILE) + MOI.Utilities.loadfromstring!(model, model_string) + io = IOBuffer() + write(io, model) model_2 = MPS.Model() - MOI.read_from_file(model_2, MPS_TEST_FILE) - return MOI.Test.util_test_models_equal( + seekstart(io) + read!(io, model_2) + MOI.Test.util_test_models_equal( model, model_2, variables, constraints, args..., ) + return end function test_show() @test sprint(show, MPS.Model()) == "A Mathematical Programming System (MPS) model" + return end function test_nonempty() @@ -78,6 +77,7 @@ function test_nonempty() model, joinpath(@__DIR__, "failing_models", "bad_name.mps"), ) + return end function test_failing_models() @@ -101,6 +101,7 @@ function test_empty_row_name() MOI.LessThan(1.0), ) @test_throws Exception sprint(MPS.write_rows, model) + return end function test_sos() @@ -142,6 +143,7 @@ function test_maximization() MOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x) @test sprint(MPS.write_columns, model, true, OrderedDict(x => 1)) == "COLUMNS\n x OBJ -1\n" + return end function test_maximization_objsense_false() @@ -150,32 +152,32 @@ function test_maximization_objsense_false() MOI.set(model, MOI.VariableName(), x, "x") MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) MOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x) - sprint(MPS.write, model) @test sprint(MPS.write_columns, model, false, OrderedDict(x => 1)) == "COLUMNS\n x OBJ 1\n" + return end function test_stacked_data() model = MPS.Model() MOI.read_from_file(model, joinpath(@__DIR__, "stacked_data.mps")) model_2 = MPS.Model() - MOIU.loadfromstring!( + MOI.Utilities.loadfromstring!( model_2, """ -variables: x, y, z -maxobjective: x + y + z + 2.5 -blank_obj: 1.0 * x + 2.0 * y in Interval(-Inf, Inf) -con1: 1.0 * x in Interval(1.0, 5.0) -con2: 1.0 * x in Interval(2.0, 6.0) -con3: 1.0 * x in Interval(3.0, 7.0) -con4: 2.0 * x in Interval(4.0, 8.0) -y in Integer() -y in Interval(1.0, 4.0) -z in ZeroOne() -""", + variables: x, y, z + maxobjective: x + y + z + 2.5 + blank_obj: 1.0 * x + 2.0 * y in Interval(-Inf, Inf) + con1: 1.0 * x in Interval(1.0, 5.0) + con2: 1.0 * x in Interval(2.0, 6.0) + con3: 1.0 * x in Interval(3.0, 7.0) + con4: 2.0 * x in Interval(4.0, 8.0) + y in Integer() + y in Interval(1.0, 4.0) + z in ZeroOne() + """, ) MOI.set(model_2, MOI.Name(), "stacked_data") - return MOI.Test.util_test_models_equal( + MOI.Test.util_test_models_equal( model, model_2, ["x", "y", "z"], @@ -186,166 +188,178 @@ z in ZeroOne() ("z", MOI.ZeroOne()), ], ) + return end function test_free_integer() model = MPS.Model() MOI.read_from_file(model, joinpath(@__DIR__, "free_integer.mps")) model_2 = MPS.Model() - MOIU.loadfromstring!( + MOI.Utilities.loadfromstring!( model_2, """ -variables: x -minobjective: x -con1: 1.0 * x >= 1.0 -x in Integer() -""", + variables: x + minobjective: x + con1: 1.0 * x >= 1.0 + x in Integer() + """, ) - return MOI.Test.util_test_models_equal( + MOI.Test.util_test_models_equal( model, model_2, ["x"], ["con1"], [("x", MOI.Integer())], ) + return end function test_min_objective() - return _test_model_equality( + _test_model_equality( """ - variables: x - minobjective: x -""", + variables: x + minobjective: x + """, ["x"], String[], ) + return end function test_objconst() - return _test_model_equality( + _test_model_equality( """ - variables: x - minobjective: 1.1 * x + 1.2 -""", + variables: x + minobjective: 1.1 * x + 1.2 + """, ["x"], String[], ) + return end function test_default_rhs_greater() - return _test_model_equality( + _test_model_equality( """ -variables: x -minobjective: x -c1: 2.0 * x >= 0.0 -""", + variables: x + minobjective: x + c1: 2.0 * x >= 0.0 + """, ["x"], ["c1"], ) + return end function test_default_rhs_less() - return _test_model_equality( + _test_model_equality( """ - variables: x - minobjective: x - c1: 2.0 * x <= 0.0 -""", + variables: x + minobjective: x + c1: 2.0 * x <= 0.0 + """, ["x"], ["c1"], ) + return end function test_default_rhs_equal() - return _test_model_equality( + _test_model_equality( """ -variables: x -minobjective: x -c1: 2.0 * x == 0.0 -""", + variables: x + minobjective: x + c1: 2.0 * x == 0.0 + """, ["x"], ["c1"], ) + return end function test_min_scalaraffine() - return _test_model_equality( + _test_model_equality( """ -variables: x -minobjective: 1.2x -""", + variables: x + minobjective: 1.2x + """, ["x"], String[], ) + return end function test_scalaraffine_greaterthan() - return _test_model_equality( + _test_model_equality( """ -variables: x -minobjective: 1.2x -c1: 1.1 * x >= 2.0 -""", + variables: x + minobjective: 1.2x + c1: 1.1 * x >= 2.0 + """, ["x"], ["c1"], ) + return end function test_scalaraffine_lessthan() - return _test_model_equality( + _test_model_equality( """ -variables: x -minobjective: 1.2x -c1: 1.1 * x <= 2.0 -""", + variables: x + minobjective: 1.2x + c1: 1.1 * x <= 2.0 + """, ["x"], ["c1"], ) + return end function test_scalaraffine_equalto() - return _test_model_equality( + _test_model_equality( """ -variables: x -minobjective: 1.2x -c1: 1.1 * x == 2.0 -""", + variables: x + minobjective: 1.2x + c1: 1.1 * x == 2.0 + """, ["x"], ["c1"], ) + return end function test_scalaraffine_interval() - return _test_model_equality( + _test_model_equality( """ -variables: x -minobjective: 1.2x -c1: 1.1 * x in Interval(1.0, 2.0) -""", + variables: x + minobjective: 1.2x + c1: 1.1 * x in Interval(1.0, 2.0) + """, ["x"], ["c1"], ) + return end function test_objsense_max() _test_model_equality( """ -variables: x -maxobjective: 1.2x -c1: 1.0 * x >= 0.0 -""", + variables: x + maxobjective: 1.2x + c1: 1.0 * x >= 0.0 + """, ["x"], - ["c1"], + ["c1"]; print_objsense = true, ) _test_model_equality( """ -variables: x -minobjective: 1.2x -c1: 1.0 * x >= 0.0 -""", + variables: x + minobjective: 1.2x + c1: 1.0 * x >= 0.0 + """, ["x"], - ["c1"], + ["c1"]; print_objsense = true, ) return @@ -353,21 +367,23 @@ end function test_MARKER_INT() model = MPS.Model() - MOIU.loadfromstring!( + MOI.Utilities.loadfromstring!( model, """ -variables: x, y, z -minobjective: x + y + z -x in Integer() -c2: 2 * x + -1.0 * z <= 1.0 -z in ZeroOne() -x >= 1.0 -""", + variables: x, y, z + minobjective: x + y + z + x in Integer() + c2: 2 * x + -1.0 * z <= 1.0 + z in ZeroOne() + x >= 1.0 + """, ) - MOI.write_to_file(model, MPS_TEST_FILE) + io = IOBuffer() + write(io, model) + seekstart(io) model_2 = MPS.Model() - MOI.read_from_file(model_2, MPS_TEST_FILE) - return MOI.Test.util_test_models_equal( + read!(io, model_2) + MOI.Test.util_test_models_equal( model, model_2, ["x", "y", "z"], @@ -378,23 +394,26 @@ x >= 1.0 ("x", MOI.GreaterThan(1.0)), ], ) + return end function test_zero_variable_bounds() model = MPS.Model() - MOIU.loadfromstring!( + MOI.Utilities.loadfromstring!( model, """ -variables: x, y, z -minobjective: x + y + z -x >= 0.0 -y <= 0.0 -""", + variables: x, y, z + minobjective: x + y + z + x >= 0.0 + y <= 0.0 + """, ) - MOI.write_to_file(model, MPS_TEST_FILE) + io = IOBuffer() + write(io, model) + seekstart(io) model_2 = MPS.Model() - MOI.read_from_file(model_2, MPS_TEST_FILE) - return MOI.Test.util_test_models_equal( + read!(io, model_2) + MOI.Test.util_test_models_equal( model, model_2, ["x", "y", "z"], @@ -404,25 +423,28 @@ y <= 0.0 ("y", MOI.LessThan{Float64}(0.0)), ], ) + return end function test_nonzero_variable_bounds() model = MPS.Model() - MOIU.loadfromstring!( + MOI.Utilities.loadfromstring!( model, """ -variables: w, x, y, z -minobjective: w + x + y + z -x == 1.0 -y >= 2.0 -z <= 3.0 -w in Interval(4.0, 5.0) -""", + variables: w, x, y, z + minobjective: w + x + y + z + x == 1.0 + y >= 2.0 + z <= 3.0 + w in Interval(4.0, 5.0) + """, ) - MOI.write_to_file(model, MPS_TEST_FILE) + io = IOBuffer() + write(io, model) + seekstart(io) model_2 = MPS.Model() - MOI.read_from_file(model_2, MPS_TEST_FILE) - return MOI.Test.util_test_models_equal( + read!(io, model_2) + MOI.Test.util_test_models_equal( model, model_2, ["w", "x", "y", "z"], @@ -434,32 +456,32 @@ w in Interval(4.0, 5.0) ("w", MOI.Interval{Float64}(4.0, 5.0)), ], ) + return end function test_multiple_variable_bounds() - model = MPS.Model() - MOIU.loadfromstring!( - model, + _test_write_to_file( + """ + variables: a_really_long_name + minobjective: a_really_long_name + a_really_long_name >= 1.0 + a_really_long_name <= 2.0 + """, """ -variables: a_really_long_name -minobjective: a_really_long_name -a_really_long_name >= 1.0 -a_really_long_name <= 2.0 -""", + NAME + ROWS + N OBJ + COLUMNS + a_really_long_name OBJ 1 + RHS + RANGES + BOUNDS + LO bounds a_really_long_name 1 + UP bounds a_really_long_name 2 + ENDATA + """, ) - MOI.write_to_file(model, MPS_TEST_FILE) - @test read(MPS_TEST_FILE, String) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - "COLUMNS\n" * - " a_really_long_name OBJ 1\n" * - "RHS\n" * - "RANGES\n" * - "BOUNDS\n" * - " LO bounds a_really_long_name 1\n" * - " UP bounds a_really_long_name 2\n" * - "ENDATA\n" + return end function test_unused_variable() @@ -467,20 +489,23 @@ function test_unused_variable() # coefficient since it does not appear in the objective or in the # constraints. model = MPS.Model() - MOIU.loadfromstring!( + MOI.Utilities.loadfromstring!( model, """ -variables: x, y -minobjective: y -c1: 2.0 * y >= 1.0 -x >= 0.0 -""", + variables: x, y + minobjective: y + c1: 2.0 * y >= 1.0 + x >= 0.0 + """, ) - MOI.write_to_file(model, MPS_TEST_FILE) @test MOI.get(model, MOI.NumberOfVariables()) == 2 - model2 = MPS.Model() - MOI.read_from_file(model2, MPS_TEST_FILE) - @test MOI.get(model2, MOI.NumberOfVariables()) == 2 + io = IOBuffer() + write(io, model) + seekstart(io) + model_2 = MPS.Model() + read!(io, model_2) + @test MOI.get(model_2, MOI.NumberOfVariables()) == 2 + return end function test_names_with_spaces() @@ -506,86 +531,89 @@ function test_names_with_spaces() "BOUNDS\n" * " FR bounds x[1,_2]\n" * "ENDATA\n" + return end function test_objsense_default() - model = MPS.Model() - x = MOI.add_variable(model) - MOI.set(model, MOI.VariableName(), x, "x") - MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) - MOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x) - @test sprint(write, model) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - "COLUMNS\n" * - " x OBJ -1\n" * - "RHS\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds x\n" * - "ENDATA\n" + _test_write_to_file( + """ + variables: x + maxobjective: x + """, + """ + NAME + ROWS + N OBJ + COLUMNS + x OBJ -1 + RHS + RANGES + BOUNDS + FR bounds x + ENDATA + """, + ) + return end function test_objsense_true() - model = MPS.Model(; print_objsense = true) - x = MOI.add_variable(model) - MOI.set(model, MOI.VariableName(), x, "x") - MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) - MOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x) - @test sprint(write, model) == - "NAME\n" * - "OBJSENSE\n" * - " MAX\n" * - "ROWS\n" * - " N OBJ\n" * - "COLUMNS\n" * - " x OBJ 1\n" * - "RHS\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds x\n" * - "ENDATA\n" + _test_write_to_file( + """ + variables: x + maxobjective: x + """, + """ + NAME + OBJSENSE + MAX + ROWS + N OBJ + COLUMNS + x OBJ 1 + RHS + RANGES + BOUNDS + FR bounds x + ENDATA + """; + print_objsense = true, + ) + return end function test_sos_constraints() - model = MPS.Model() - x = MOI.add_variables(model, 3) - MOI.set.(model, MOI.VariableName(), x, ["x1", "x2", "x3"]) - MOI.add_constraint( - model, - MOI.VectorOfVariables(x), - MOI.SOS1([1.0, 2.0, 3.0]), - ) - MOI.add_constraint( - model, - MOI.VectorOfVariables(reverse(x)), - MOI.SOS2([1.2, 2.3, 3.4]), + model = _test_write_to_file( + """ + variables: x1, x2, x3 + [x1, x2, x3] in SOS1([1.0, 2.0, 3.0]) + [x3, x2, x1] in SOS2([1.2, 2.3, 3.4]) + """, + """ + NAME + ROWS + N OBJ + COLUMNS + x1 OBJ 0 + x2 OBJ 0 + x3 OBJ 0 + RHS + RANGES + BOUNDS + FR bounds x1 + FR bounds x2 + FR bounds x3 + SOS + S1 SOS1 + x1 1 + x2 2 + x3 3 + S2 SOS2 + x3 1.2 + x2 2.3 + x1 3.4 + ENDATA + """, ) - @test sprint(write, model) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - "COLUMNS\n" * - " x1 OBJ 0\n" * - " x2 OBJ 0\n" * - " x3 OBJ 0\n" * - "RHS\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds x1\n" * - " FR bounds x2\n" * - " FR bounds x3\n" * - "SOS\n" * - " S1 SOS1\n" * - " x1 1\n" * - " x2 2\n" * - " x3 3\n" * - " S2 SOS2\n" * - " x3 1.2\n" * - " x2 2.3\n" * - " x1 3.4\n" * - "ENDATA\n" io = IOBuffer() write(io, model) seekstart(io) @@ -598,254 +626,211 @@ function test_sos_constraints() end function test_generic_names() - model = MPS.Model(; generic_names = true) - x = MOI.add_variable(model) - y = MOI.add_variable(model) - c = MOI.add_constraint( - model, - MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(1.0, [x, y]), 0.0), - MOI.EqualTo(1.0), + _test_write_to_file( + """ + variables: x, y + c: x + y == 1.0 + y >= 2.0 + """, + """ + NAME + ROWS + N OBJ + E R1 + COLUMNS + C1 R1 1 + C2 R1 1 + RHS + rhs R1 1 + RANGES + BOUNDS + FR bounds C1 + LO bounds C2 2 + PL bounds C2 + ENDATA + """; + generic_names = true, ) - MOI.add_constraint(model, y, MOI.GreaterThan(2.0)) - @test sprint(write, model) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - " E R1\n" * - "COLUMNS\n" * - " C1 R1 1\n" * - " C2 R1 1\n" * - "RHS\n" * - " rhs R1 1\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds C1\n" * - " LO bounds C2 2\n" * - " PL bounds C2\n" * - "ENDATA\n" + return end function test_rew_filename() model = MOI.FileFormats.Model(; filename = "test.rew") - x = MOI.add_variable(model) - y = MOI.add_variable(model) - c = MOI.add_constraint( - model, - MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(1.0, [x, y]), 0.0), - MOI.EqualTo(1.0), - ) - MOI.add_constraint(model, y, MOI.GreaterThan(2.0)) - @test sprint(write, model) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - " E R1\n" * - "COLUMNS\n" * - " C1 R1 1\n" * - " C2 R1 1\n" * - "RHS\n" * - " rhs R1 1\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds C1\n" * - " LO bounds C2 2\n" * - " PL bounds C2\n" * - "ENDATA\n" + @test model isa MPS.Model + @test model.ext[:MPS_OPTIONS].generic_names == true + return end function test_rew_format() model = MOI.FileFormats.Model(; format = MOI.FileFormats.FORMAT_REW) - x = MOI.add_variable(model) - y = MOI.add_variable(model) - c = MOI.add_constraint( - model, - MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(1.0, [x, y]), 0.0), - MOI.EqualTo(1.0), - ) - MOI.add_constraint(model, y, MOI.GreaterThan(2.0)) - @test sprint(write, model) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - " E R1\n" * - "COLUMNS\n" * - " C1 R1 1\n" * - " C2 R1 1\n" * - "RHS\n" * - " rhs R1 1\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds C1\n" * - " LO bounds C2 2\n" * - " PL bounds C2\n" * - "ENDATA\n" + @test model isa MPS.Model + @test model.ext[:MPS_OPTIONS].generic_names == true + return end function test_infinite_interval() - model = MPS.Model() - x = MOI.add_variable(model) - MOI.add_constraint(model, 1.0 * x, MOI.Interval(-Inf, Inf)) - MOI.add_constraint(model, 1.0 * x, MOI.Interval(-Inf, 1.0)) - MOI.add_constraint(model, 1.0 * x, MOI.Interval(2.0, Inf)) - MOI.add_constraint(model, 1.0 * x, MOI.Interval(3.0, 4.0)) - @test sprint(write, model) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - " N c1\n" * - " L c2\n" * - " G c3\n" * - " L c4\n" * - "COLUMNS\n" * - " x1 c1 1\n" * - " x1 c2 1\n" * - " x1 c3 1\n" * - " x1 c4 1\n" * - "RHS\n" * - " rhs c2 1\n" * - " rhs c3 2\n" * - " rhs c4 4\n" * - "RANGES\n" * - " rhs c4 1\n" * - "BOUNDS\n" * - " FR bounds x1\n" * - "ENDATA\n" + _test_write_to_file( + """ + variables: x1 + 1.0 * x1 in Interval(-Inf, Inf) + 1.0 * x1 in Interval(-Inf, 1.0) + 1.0 * x1 in Interval(2.0, Inf) + 1.0 * x1 in Interval(3.0, 4.0) + """, + """ + NAME + ROWS + N OBJ + N c1 + L c2 + G c3 + L c4 + COLUMNS + x1 c1 1 + x1 c2 1 + x1 c3 1 + x1 c4 1 + RHS + rhs c2 1 + rhs c3 2 + rhs c4 4 + RANGES + rhs c4 1 + BOUNDS + FR bounds x1 + ENDATA + """, + ) return end function test_quadobj_gurobi() - model = MPS.Model() - MOIU.loadfromstring!( - model, + _test_write_to_file( """ -variables: x, y -minobjective: x + y + 5.0 * x * x + 1.0 * x * y + 1.0 * y * x + 1.2 * y * y -""", + variables: x, y + minobjective: x + y + 5.0 * x * x + 1.0 * x * y + 1.0 * y * x + 1.2 * y * y + """, + """ + NAME + ROWS + N OBJ + COLUMNS + x OBJ 1 + y OBJ 1 + RHS + RANGES + BOUNDS + FR bounds x + FR bounds y + QUADOBJ + x x 10 + x y 2 + y y 2.4 + ENDATA + """, ) - MOI.write_to_file(model, MPS_TEST_FILE) - @test read(MPS_TEST_FILE, String) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - "COLUMNS\n" * - " x OBJ 1\n" * - " y OBJ 1\n" * - "RHS\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds x\n" * - " FR bounds y\n" * - "QUADOBJ\n" * - " x x 10\n" * - " x y 2\n" * - " y y 2.4\n" * - "ENDATA\n" return end function test_quadobj_cplex() - model = MPS.Model(; quadratic_format = MPS.kQuadraticFormatCPLEX) - MOIU.loadfromstring!( - model, + _test_write_to_file( + """ + variables: x, y + minobjective: x + y + 5.0 * x * x + 1.0 * x * y + 1.0 * y * x + 1.2 * y * y + """, """ -variables: x, y -minobjective: x + y + 5.0 * x * x + 1.0 * x * y + 1.0 * y * x + 1.2 * y * y -""", + NAME + ROWS + N OBJ + COLUMNS + x OBJ 1 + y OBJ 1 + RHS + RANGES + BOUNDS + FR bounds x + FR bounds y + QMATRIX + x x 10 + x y 2 + y x 2 + y y 2.4 + ENDATA + """; + quadratic_format = MPS.kQuadraticFormatCPLEX, ) - MOI.write_to_file(model, MPS_TEST_FILE) - @test read(MPS_TEST_FILE, String) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - "COLUMNS\n" * - " x OBJ 1\n" * - " y OBJ 1\n" * - "RHS\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds x\n" * - " FR bounds y\n" * - "QMATRIX\n" * - " x x 10\n" * - " x y 2\n" * - " y x 2\n" * - " y y 2.4\n" * - "ENDATA\n" return end function test_quadcon_gurobi() - model = MPS.Model() - MOIU.loadfromstring!( - model, + _test_write_to_file( """ -variables: x, y -c1: x + y + 5.0 * x * x + 1.0 * x * y + 1.0 * y * x + 1.2 * y * y <= 1.0 -""", + variables: x, y + c1: x + y + 5.0 * x * x + 1.0 * x * y + 1.0 * y * x + 1.2 * y * y <= 1.0 + """, + """ + NAME + ROWS + N OBJ + L c1 + COLUMNS + x c1 1 + y c1 1 + RHS + rhs c1 1 + RANGES + BOUNDS + FR bounds x + FR bounds y + QCMATRIX c1 + x x 10 + x y 2 + y x 2 + y y 2.4 + ENDATA + """, ) - MOI.write_to_file(model, MPS_TEST_FILE) - @test read(MPS_TEST_FILE, String) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - " L c1\n" * - "COLUMNS\n" * - " x c1 1\n" * - " y c1 1\n" * - "RHS\n" * - " rhs c1 1\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds x\n" * - " FR bounds y\n" * - "QCMATRIX c1\n" * - " x x 10\n" * - " x y 2\n" * - " y x 2\n" * - " y y 2.4\n" * - "ENDATA\n" return end function test_quadcon_cplex() - model = MPS.Model(; quadratic_format = MPS.kQuadraticFormatCPLEX) - MOIU.loadfromstring!( - model, + _test_write_to_file( """ -variables: x, y -c1: x + y + 5.0 * x * x + 1.0 * x * y + 1.0 * y * x + 1.2 * y * y <= 1.0 -""", + variables: x, y + c1: x + y + 5.0 * x * x + 1.0 * x * y + 1.0 * y * x + 1.2 * y * y <= 1.0 + """, + """ + NAME + ROWS + N OBJ + L c1 + COLUMNS + x c1 1 + y c1 1 + RHS + rhs c1 1 + RANGES + BOUNDS + FR bounds x + FR bounds y + QCMATRIX c1 + x x 10 + x y 2 + y x 2 + y y 2.4 + ENDATA + """; + quadratic_format = MPS.kQuadraticFormatCPLEX, ) - MOI.write_to_file(model, MPS_TEST_FILE) - @test read(MPS_TEST_FILE, String) == - "NAME\n" * - "ROWS\n" * - " N OBJ\n" * - " L c1\n" * - "COLUMNS\n" * - " x c1 1\n" * - " y c1 1\n" * - "RHS\n" * - " rhs c1 1\n" * - "RANGES\n" * - "BOUNDS\n" * - " FR bounds x\n" * - " FR bounds y\n" * - "QCMATRIX c1\n" * - " x x 10\n" * - " x y 2\n" * - " y x 2\n" * - " y y 2.4\n" * - "ENDATA\n" return end function test_round_trip_quadobj_gurobi() _test_model_equality( """ -variables: x, y -minobjective: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y -""", + variables: x, y + minobjective: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y + """, ["x", "y"], String[], ) @@ -855,9 +840,9 @@ end function test_round_trip_qmatrix_cplex() _test_model_equality( """ -variables: x, y -minobjective: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y -""", + variables: x, y + minobjective: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y + """, ["x", "y"], String[]; quadratic_format = MPS.kQuadraticFormatCPLEX, @@ -868,10 +853,10 @@ end function test_round_trip_qcmatrix_gurobi() _test_model_equality( """ -variables: x, y -minobjective: 1.3 * x * x + 0.5 * x * y -c1: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y <= 1.0 -""", + variables: x, y + minobjective: 1.3 * x * x + 0.5 * x * y + c1: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y <= 1.0 + """, ["x", "y"], ["c1"], ) @@ -881,10 +866,10 @@ end function test_round_trip_qcmatrix_cplex() _test_model_equality( """ -variables: x, y -minobjective: 1.3 * x * x + 0.5 * x * y -c1: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y <= 1.0 -""", + variables: x, y + minobjective: 1.3 * x * x + 0.5 * x * y + c1: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y <= 1.0 + """, ["x", "y"], ["c1"]; quadratic_format = MPS.kQuadraticFormatCPLEX, @@ -895,10 +880,10 @@ end function test_round_trip_qcmatrix_mosek() _test_model_equality( """ -variables: x, y -minobjective: 1.3 * x * x + 0.5 * x * y -c1: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y <= 1.0 -""", + variables: x, y + minobjective: 1.3 * x * x + 0.5 * x * y + c1: 1.2x + 2.1 * x * x + 1.2 * x * y + 0.2 * y * x + 0.5 * y * y <= 1.0 + """, ["x", "y"], ["c1"]; quadratic_format = MPS.kQuadraticFormatMosek, @@ -909,11 +894,11 @@ end function test_round_trip_indicator_lessthan() _test_model_equality( """ -variables: x, y, z -minobjective: 1.0 * x + y + z -z in ZeroOne() -c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ONE}(LessThan(1.0)) -""", + variables: x, y, z + minobjective: 1.0 * x + y + z + z in ZeroOne() + c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ONE}(LessThan(1.0)) + """, ["x", "y", "z"], ["c1"], [("z", MOI.ZeroOne())], @@ -924,11 +909,11 @@ end function test_round_trip_indicator_greaterthan() _test_model_equality( """ -variables: x, y, z -minobjective: 1.0 * x + y + z -z in ZeroOne() -c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ONE}(GreaterThan(1.0)) -""", + variables: x, y, z + minobjective: 1.0 * x + y + z + z in ZeroOne() + c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ONE}(GreaterThan(1.0)) + """, ["x", "y", "z"], ["c1"], [("z", MOI.ZeroOne())], @@ -939,11 +924,11 @@ end function test_round_trip_indicator_equalto() _test_model_equality( """ -variables: x, y, z -minobjective: 1.0 * x + y + z -z in ZeroOne() -c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ONE}(EqualTo(1.0)) -""", + variables: x, y, z + minobjective: 1.0 * x + y + z + z in ZeroOne() + c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ONE}(EqualTo(1.0)) + """, ["x", "y", "z"], ["c1"], [("z", MOI.ZeroOne())], @@ -954,11 +939,11 @@ end function test_round_trip_indicator_lessthan_false() _test_model_equality( """ -variables: x, y, z -minobjective: 1.0 * x + y + z -z in ZeroOne() -c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ZERO}(LessThan(1.0)) -""", + variables: x, y, z + minobjective: 1.0 * x + y + z + z in ZeroOne() + c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ZERO}(LessThan(1.0)) + """, ["x", "y", "z"], ["c1"], [("z", MOI.ZeroOne())], @@ -969,11 +954,11 @@ end function test_round_trip_indicator_greaterthan_false() _test_model_equality( """ -variables: x, y, z -minobjective: 1.0 * x + y + z -z in ZeroOne() -c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ZERO}(GreaterThan(1.0)) -""", + variables: x, y, z + minobjective: 1.0 * x + y + z + z in ZeroOne() + c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ZERO}(GreaterThan(1.0)) + """, ["x", "y", "z"], ["c1"], [("z", MOI.ZeroOne())], @@ -984,11 +969,11 @@ end function test_round_trip_indicator_equalto_false() _test_model_equality( """ -variables: x, y, z -minobjective: 1.0 * x + y + z -z in ZeroOne() -c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ZERO}(EqualTo(1.0)) -""", + variables: x, y, z + minobjective: 1.0 * x + y + z + z in ZeroOne() + c1: [z, 1.0 * x + 1.0 * y] in Indicator{ACTIVATE_ON_ZERO}(EqualTo(1.0)) + """, ["x", "y", "z"], ["c1"], [("z", MOI.ZeroOne())],