From d2299e4da6c105a3fe0a5a98389a7f5a470cf991 Mon Sep 17 00:00:00 2001 From: odow Date: Fri, 11 May 2018 19:26:28 +1200 Subject: [PATCH 01/15] Comprehensive testing of basic constraint functionality --- src/Test/UnitTests/basic_constraint_tests.jl | 184 +++++++++++++++++++ src/Test/UnitTests/unit_tests.jl | 2 + 2 files changed, 186 insertions(+) create mode 100644 src/Test/UnitTests/basic_constraint_tests.jl diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl new file mode 100644 index 0000000000..91c1c26035 --- /dev/null +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -0,0 +1,184 @@ +""" + basic_constraint_tests(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int; delete::Bool=true) + +Test some basic constraint tests. `f` is a function that takes a vector of `N` +variables and returns a constraint function. + +If `delete=true`, test `candelete` and `delete!`. + +### Example + + basic_constraint_tests(model, config, MOI.LessThan(1.0), 1; delete=false) do x + MOI.ScalarAffineFunction(model, [x], [1.0], 0.0) + end +""" +function basic_constraint_tests(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int=1; delete::Bool=true) + MOI.empty!(model) + x = MOI.addvariables!(model, N) + constraint_function = f(x) + F, S = typeof(constraint_function), typeof(set) + + @testset "NumberOfConstraints" begin + @test MOI.canget(model, MOI.NumberOfConstraints{F,S}()) + end + + @testset "canaddconstraint" begin + @test MOI.canaddconstraint(model, F, S) + end + + @testset "addconstraint!" begin + n = MOI.get(model, MOI.NumberOfConstraints{F,S}()) + c = MOI.addconstraint!(model, constraint_function, set) + @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == n + 1 + end + + @testset "addconstraints!" begin + n = MOI.get(model, MOI.NumberOfConstraints{F,S}()) + cc = MOI.addconstraints!(model, + [constraint_function, constraint_function], + [set, set] + ) + @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == n + 2 + end + + @testset "ListOfConstraintIndices" begin + @test MOI.canget(model, MOI.ListOfConstraintIndices{F,S}()) + c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + @test length(c_indices) == MOI.get(model, MOI.NumberOfConstraints{F,S}()) == 3 + end + + @testset "isvalid" begin + c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + @test length(c_indices) == 3 # check that we've added a constraint + @test all(MOI.isvalid.(model, c_indices)) + end + + if delete + @testset "candelete" begin + c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + @test length(c_indices) == 3 # check that we've added a constraint + @test MOI.candelete(model, c_indices[1]) + end + @testset "delete!" begin + c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + @test length(c_indices) == 3 # check that we've added a constraint + MOI.delete!(model, c_indices[1]) + @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == length(c_indices)-1 == 2 + @test !MOI.isvalid(model, c_indices[1]) + end + end +end + +""" + test_scalaraffine_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`LessThan{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_scalaraffine_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.LessThan(1.0)) do x + MOI.ScalarAffineFunction(x, [1.0], 0.0) + end +end +unittests["test_scalaraffine_in_lessthan"] = test_scalaraffine_in_lessthan + + +""" + test_scalaraffine_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`GreaterThan{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_scalaraffine_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.GreaterThan(1.0)) do x + MOI.ScalarAffineFunction(x, [1.0], 0.0) + end +end +unittests["test_scalaraffine_in_greaterthan"] = test_scalaraffine_in_greaterthan + +""" + test_scalaraffine_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`EqualTo{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_scalaraffine_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.EqualTo(1.0)) do x + MOI.ScalarAffineFunction(x, [1.0], 0.0) + end +end +unittests["test_scalaraffine_in_equalto"] = test_scalaraffine_in_equalto + +""" + test_scalaraffine_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Interval{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_scalaraffine_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0)) do x + MOI.ScalarAffineFunction(x, [1.0], 0.0) + end +end +unittests["test_scalaraffine_in_interval"] = test_scalaraffine_in_interval + +""" + test_singlevariable_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `SingleVariable`-in-`LessThan{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_singlevariable_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.LessThan(1.0)) do x + MOI.SingleVariable(x[1]) + end +end +unittests["test_singlevariable_in_lessthan"] = test_singlevariable_in_lessthan + + +""" + test_singlevariable_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `SingleVariable`-in-`GreaterThan{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_singlevariable_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.GreaterThan(1.0)) do x + MOI.SingleVariable(x[1]) + end +end +unittests["test_singlevariable_in_greaterthan"] = test_singlevariable_in_greaterthan + +""" + test_singlevariable_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `SingleVariable`-in-`EqualTo{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_singlevariable_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.EqualTo(1.0)) do x + MOI.SingleVariable(x[1]) + end +end +unittests["test_singlevariable_in_equalto"] = test_singlevariable_in_equalto + +""" + test_singlevariable_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `SingleVariable`-in-`Interval{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_singlevariable_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0)) do x + MOI.SingleVariable(x[1]) + end +end +unittests["test_singlevariable_in_interval"] = test_singlevariable_in_interval diff --git a/src/Test/UnitTests/unit_tests.jl b/src/Test/UnitTests/unit_tests.jl index c772742d3e..cf86f3eab9 100644 --- a/src/Test/UnitTests/unit_tests.jl +++ b/src/Test/UnitTests/unit_tests.jl @@ -95,5 +95,7 @@ end include("variables.jl") include("objectives.jl") include("constraints.jl") +include("basic_constraint_tests.jl") + @moitestset unit From 1ae99c1b1376c52ed2cf94f7c16cb5546e57a9f0 Mon Sep 17 00:00:00 2001 From: odow Date: Sat, 12 May 2018 11:50:38 +1200 Subject: [PATCH 02/15] More unit tests --- src/Test/UnitTests/basic_constraint_tests.jl | 156 +++++++++++++++++-- test/runtests.jl | 2 +- 2 files changed, 147 insertions(+), 11 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index 91c1c26035..eaa4cf48ae 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -1,10 +1,13 @@ """ basic_constraint_tests(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int; delete::Bool=true) -Test some basic constraint tests. `f` is a function that takes a vector of `N` -variables and returns a constraint function. +Test some basic constraint tests. + +`f` is a function that takes a vector of `N` variables and returns a constraint +function. If `delete=true`, test `candelete` and `delete!`. +If `config.query=true`, test getting `ConstraintFunction` and `ConstraintSet`. ### Example @@ -30,6 +33,26 @@ function basic_constraint_tests(f::Function, model::MOI.ModelLike, config::TestC n = MOI.get(model, MOI.NumberOfConstraints{F,S}()) c = MOI.addconstraint!(model, constraint_function, set) @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == n + 1 + + @testset "ConstraintName" begin + @test MOI.canget(model, MOI.ConstraintName(), typeof(c)) + @test MOI.get(model, MOI.ConstraintName(), c) == "" + @test MOI.canset(model, MOI.ConstraintName(), typeof(c)) + MOI.set!(model, MOI.ConstraintName(), c, "c") + @test MOI.get(model, MOI.ConstraintName(), c) == "c" + end + + if config.query + @testset "ConstraintFunction" begin + @test MOI.canget(model, MOI.ConstraintFunction(), typeof(c)) + @test MOI.get(model, MOI.ConstraintFunction(), c) ≈ constraint_function + end + + @testset "ConstraintSet" begin + @test MOI.canget(model, MOI.ConstraintSet(), typeof(c)) + @test MOI.get(model, MOI.ConstraintSet(), c) == set + end + end end @testset "addconstraints!" begin @@ -77,7 +100,7 @@ Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Less If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalaraffine_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.LessThan(1.0)) do x + basic_constraint_tests(model, config, MOI.LessThan(1.0); delete=delete) do x MOI.ScalarAffineFunction(x, [1.0], 0.0) end end @@ -92,7 +115,7 @@ Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Grea If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalaraffine_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.GreaterThan(1.0)) do x + basic_constraint_tests(model, config, MOI.GreaterThan(1.0); delete=delete) do x MOI.ScalarAffineFunction(x, [1.0], 0.0) end end @@ -106,7 +129,7 @@ Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Equa If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalaraffine_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.EqualTo(1.0)) do x + basic_constraint_tests(model, config, MOI.EqualTo(1.0); delete=delete) do x MOI.ScalarAffineFunction(x, [1.0], 0.0) end end @@ -120,12 +143,69 @@ Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Inte If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalaraffine_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0)) do x + basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x MOI.ScalarAffineFunction(x, [1.0], 0.0) end end unittests["test_scalaraffine_in_interval"] = test_scalaraffine_in_interval +""" + test_scalarquadratic_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`LessThan{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_scalarquadratic_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.LessThan(1.0); delete=delete) do x + MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) + end +end +unittests["test_scalarquadratic_in_lessthan"] = test_scalarquadratic_in_lessthan + + +""" + test_scalarquadratic_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`GreaterThan{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_scalarquadratic_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.GreaterThan(1.0); delete=delete) do x + MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) + end +end +unittests["test_scalarquadratic_in_greaterthan"] = test_scalarquadratic_in_greaterthan + +""" + test_scalarquadratic_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`EqualTo{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_scalarquadratic_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.EqualTo(1.0); delete=delete) do x + MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) + end +end +unittests["test_scalarquadratic_in_equalto"] = test_scalarquadratic_in_equalto + +""" + test_scalarquadratic_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`Interval{Float64}`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_scalarquadratic_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x + MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) + end +end +unittests["test_scalarquadratic_in_interval"] = test_scalarquadratic_in_interval + """ test_singlevariable_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) @@ -134,7 +214,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`LessThan{Float64}`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.LessThan(1.0)) do x + basic_constraint_tests(model, config, MOI.LessThan(1.0); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -149,7 +229,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`GreaterThan{Float64 If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.GreaterThan(1.0)) do x + basic_constraint_tests(model, config, MOI.GreaterThan(1.0); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -163,7 +243,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`EqualTo{Float64}`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.EqualTo(1.0)) do x + basic_constraint_tests(model, config, MOI.EqualTo(1.0); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -177,8 +257,64 @@ Basic tests for constraints of the form `SingleVariable`-in-`Interval{Float64}`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0)) do x + basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x MOI.SingleVariable(x[1]) end end unittests["test_singlevariable_in_interval"] = test_singlevariable_in_interval + +""" + test_singlevariable_in_zeroone(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `SingleVariable`-in-`ZeroOne`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_singlevariable_in_zeroone(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.ZeroOne(); delete=delete) do x + MOI.SingleVariable(x[1]) + end +end +unittests["test_singlevariable_in_zeroone"] = test_singlevariable_in_zeroone + +""" + test_singlevariable_in_integer(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `SingleVariable`-in-`Integer`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_singlevariable_in_integer(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.Integer(); delete=delete) do x + MOI.SingleVariable(x[1]) + end +end +unittests["test_singlevariable_in_integer"] = test_singlevariable_in_integer + +""" + test_singlevariable_in_semicontinuous(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `SingleVariable`-in-`Semicontinuous`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_singlevariable_in_semicontinuous(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.Semicontinuous(1.0, 2.0); delete=delete) do x + MOI.SingleVariable(x[1]) + end +end +unittests["test_singlevariable_in_semicontinuous"] = test_singlevariable_in_semicontinuous + +""" + test_singlevariable_in_semiinteger(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `SingleVariable`-in-`Semiinteger`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_singlevariable_in_semiinteger(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + basic_constraint_tests(model, config, MOI.Semiinteger(1.0, 2.0); delete=delete) do x + MOI.SingleVariable(x[1]) + end +end +unittests["test_singlevariable_in_semiinteger"] = test_singlevariable_in_semiinteger diff --git a/test/runtests.jl b/test/runtests.jl index b873738439..079993d0d6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -19,7 +19,7 @@ end # Model supporting every MOI functions and sets MOIU.@model(Model, (ZeroOne, Integer), - (EqualTo, GreaterThan, LessThan, Interval), + (EqualTo, GreaterThan, LessThan, Interval, Semicontinuous, Semiinteger), (Reals, Zeros, Nonnegatives, Nonpositives, SecondOrderCone, RotatedSecondOrderCone, GeometricMeanCone, ExponentialCone, DualExponentialCone, PositiveSemidefiniteConeTriangle, PositiveSemidefiniteConeSquare, RootDetConeTriangle, RootDetConeSquare, LogDetConeTriangle, LogDetConeSquare), (PowerCone, DualPowerCone, SOS1, SOS2), (SingleVariable,), From ea2d5546b2a66b4bb148f42fb81a2672d6c9dcab Mon Sep 17 00:00:00 2001 From: odow Date: Sat, 12 May 2018 13:13:11 +1200 Subject: [PATCH 03/15] Add VoV and SOS tests --- src/Test/UnitTests/basic_constraint_tests.jl | 66 ++++++++++++++------ src/sets.jl | 6 ++ 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index eaa4cf48ae..3d7697f3db 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -1,5 +1,5 @@ """ - basic_constraint_tests(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int; delete::Bool=true) + test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int; delete::Bool=true) Test some basic constraint tests. @@ -11,11 +11,11 @@ If `config.query=true`, test getting `ConstraintFunction` and `ConstraintSet`. ### Example - basic_constraint_tests(model, config, MOI.LessThan(1.0), 1; delete=false) do x + test_basic_constraint_functionality(model, config, MOI.LessThan(1.0), 1; delete=false) do x MOI.ScalarAffineFunction(model, [x], [1.0], 0.0) end """ -function basic_constraint_tests(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int=1; delete::Bool=true) +function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int=1; delete::Bool=true) MOI.empty!(model) x = MOI.addvariables!(model, N) constraint_function = f(x) @@ -100,7 +100,7 @@ Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Less If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalaraffine_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.LessThan(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.LessThan(1.0); delete=delete) do x MOI.ScalarAffineFunction(x, [1.0], 0.0) end end @@ -115,7 +115,7 @@ Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Grea If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalaraffine_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.GreaterThan(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.GreaterThan(1.0); delete=delete) do x MOI.ScalarAffineFunction(x, [1.0], 0.0) end end @@ -129,7 +129,7 @@ Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Equa If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalaraffine_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.EqualTo(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.EqualTo(1.0); delete=delete) do x MOI.ScalarAffineFunction(x, [1.0], 0.0) end end @@ -143,7 +143,7 @@ Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Inte If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalaraffine_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x MOI.ScalarAffineFunction(x, [1.0], 0.0) end end @@ -157,7 +157,7 @@ Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`L If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalarquadratic_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.LessThan(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.LessThan(1.0); delete=delete) do x MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) end end @@ -172,7 +172,7 @@ Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`G If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalarquadratic_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.GreaterThan(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.GreaterThan(1.0); delete=delete) do x MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) end end @@ -186,7 +186,7 @@ Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`E If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalarquadratic_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.EqualTo(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.EqualTo(1.0); delete=delete) do x MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) end end @@ -200,7 +200,7 @@ Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`I If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_scalarquadratic_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) end end @@ -214,7 +214,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`LessThan{Float64}`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.LessThan(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.LessThan(1.0); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -229,7 +229,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`GreaterThan{Float64 If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.GreaterThan(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.GreaterThan(1.0); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -243,7 +243,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`EqualTo{Float64}`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.EqualTo(1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.EqualTo(1.0); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -257,7 +257,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`Interval{Float64}`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -271,7 +271,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`ZeroOne`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_zeroone(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.ZeroOne(); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.ZeroOne(); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -285,7 +285,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`Integer`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_integer(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.Integer(); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.Integer(); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -299,7 +299,7 @@ Basic tests for constraints of the form `SingleVariable`-in-`Semicontinuous`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_semicontinuous(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.Semicontinuous(1.0, 2.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.Semicontinuous(1.0, 2.0); delete=delete) do x MOI.SingleVariable(x[1]) end end @@ -313,8 +313,36 @@ Basic tests for constraints of the form `SingleVariable`-in-`Semiinteger`. If `delete=true`, test `MOI.candelete` and `MOI.delete!`. """ function test_singlevariable_in_semiinteger(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - basic_constraint_tests(model, config, MOI.Semiinteger(1.0, 2.0); delete=delete) do x + test_basic_constraint_functionality(model, config, MOI.Semiinteger(1.0, 2.0); delete=delete) do x MOI.SingleVariable(x[1]) end end unittests["test_singlevariable_in_semiinteger"] = test_singlevariable_in_semiinteger + +""" + test_vectorofvariables_in_sos1(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorOfVariables`-in-`SOS1`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectorofvariables_in_sos1(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.SOS1([1.0, 2.0, 3.0]), 3; delete=delete) do x + MOI.VectorOfVariables(x) + end +end +unittests["test_vectorofvariables_in_sos1"] = test_vectorofvariables_in_sos1 + +""" + test_vectorofvariables_in_sos2(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorOfVariables`-in-`SOS2`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectorofvariables_in_sos2(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.SOS2([1.0, 2.0, 3.0]), 3; delete=delete) do x + MOI.VectorOfVariables(x) + end +end +unittests["test_vectorofvariables_in_sos2"] = test_vectorofvariables_in_sos2 diff --git a/src/sets.jl b/src/sets.jl index 4b45d06481..d506782c45 100644 --- a/src/sets.jl +++ b/src/sets.jl @@ -379,6 +379,9 @@ struct SOS1{T <: Real} <: AbstractVectorSet weights::Vector{T} end +Base.:(==)(a::SOS1{T}, b::SOS1{T}) where T = a.weights == b.weights +Base.isapprox(a::SOS1{T}, b::SOS1{T}; kwargs...) where T = isapprox(a.weights, b.weights; kwargs...) + """ SOS2{T <: Real}(weights::Vector{T}) @@ -392,4 +395,7 @@ struct SOS2{T <: Real} <: AbstractVectorSet weights::Vector{T} end +Base.:(==)(a::SOS2{T}, b::SOS2{T}) where T = a.weights == b.weights +Base.isapprox(a::SOS2{T}, b::SOS2{T}; kwargs...) where T = isapprox(a.weights, b.weights; kwargs...) + dimension(s::Union{SOS1, SOS2}) = length(s.weights) From fc24d71f67ab8664564888ce0e62f3814aa20fc7 Mon Sep 17 00:00:00 2001 From: odow Date: Sat, 12 May 2018 13:22:56 +1200 Subject: [PATCH 04/15] Add supportsconstrainttest --- src/Test/UnitTests/basic_constraint_tests.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index 3d7697f3db..8922559e8b 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -21,6 +21,8 @@ function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, constraint_function = f(x) F, S = typeof(constraint_function), typeof(set) + @test MOI.supportsconstraint(model, F, S) + @testset "NumberOfConstraints" begin @test MOI.canget(model, MOI.NumberOfConstraints{F,S}()) end From edd9c84edc9bdefa91ea081621f9cfd0789252b1 Mon Sep 17 00:00:00 2001 From: odow Date: Sat, 12 May 2018 14:26:43 +1200 Subject: [PATCH 05/15] VoV in vector sets --- src/Test/UnitTests/basic_constraint_tests.jl | 56 ++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index 8922559e8b..fbd0073deb 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -348,3 +348,59 @@ function test_vectorofvariables_in_sos2(model::MOI.ModelLike, config::TestConfig end end unittests["test_vectorofvariables_in_sos2"] = test_vectorofvariables_in_sos2 + +""" + test_vectorofvariables_in_reals(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorOfVariables`-in-`Reals`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectorofvariables_in_reals(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.Reals(3), 3; delete=delete) do x + MOI.VectorOfVariables(x) + end +end +unittests["test_vectorofvariables_in_reals"] = test_vectorofvariables_in_reals + +""" + test_vectorofvariables_in_nonnegatives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorOfVariables`-in-`Nonnegatives`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectorofvariables_in_nonnegatives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.Nonnegatives(3), 3; delete=delete) do x + MOI.VectorOfVariables(x) + end +end +unittests["test_vectorofvariables_in_nonnegatives"] = test_vectorofvariables_in_nonnegatives + +""" + test_vectorofvariables_in_nonpositives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorOfVariables`-in-`Nonpositives`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectorofvariables_in_nonpositives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.Nonpositives(3), 3; delete=delete) do x + MOI.VectorOfVariables(x) + end +end +unittests["test_vectorofvariables_in_nonpositives"] = test_vectorofvariables_in_nonpositives + +""" + test_vectorofvariables_in_zeros(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorOfVariables`-in-`Zeros`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectorofvariables_in_zeros(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.Zeros(3), 3; delete=delete) do x + MOI.VectorOfVariables(x) + end +end +unittests["test_vectorofvariables_in_zeros"] = test_vectorofvariables_in_zeros From 46a0a0f2b283201126e348cdea9a994ff96d895f Mon Sep 17 00:00:00 2001 From: odow Date: Sat, 12 May 2018 14:40:26 +1200 Subject: [PATCH 06/15] VAF in sets --- src/Test/UnitTests/basic_constraint_tests.jl | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index fbd0073deb..766a622089 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -404,3 +404,46 @@ function test_vectorofvariables_in_zeros(model::MOI.ModelLike, config::TestConfi end end unittests["test_vectorofvariables_in_zeros"] = test_vectorofvariables_in_zeros + + +""" + test_vectoraffinefunction_in_zeros(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorAffine`-in-`Zeros`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectoraffinefunction_in_zeros(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.Zeros(2), 2; delete=delete) do x + MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) + end +end +unittests["test_vectoraffinefunction_in_zeros"] = test_vectoraffinefunction_in_zeros + +""" + test_vectoraffinefunction_in_nonnegatives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorAffine`-in-`Nonnegatives`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectoraffinefunction_in_nonnegatives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.Nonnegatives(2), 2; delete=delete) do x + MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) + end +end +unittests["test_vectoraffinefunction_in_nonnegatives"] = test_vectoraffinefunction_in_nonnegatives + +""" + test_vectoraffinefunction_in_nonpositives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + +Basic tests for constraints of the form `VectorAffine`-in-`Nonpositives`. + +If `delete=true`, test `MOI.candelete` and `MOI.delete!`. +""" +function test_vectoraffinefunction_in_nonpositives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) + test_basic_constraint_functionality(model, config, MOI.Nonpositives(2), 2; delete=delete) do x + MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) + end +end +unittests["test_vectoraffinefunction_in_nonpositives"] = test_vectoraffinefunction_in_nonpositives From 7ec5ff2f496734a6c52c5fae47067c13e3f3ba27 Mon Sep 17 00:00:00 2001 From: odow Date: Sat, 12 May 2018 15:41:51 +1200 Subject: [PATCH 07/15] Move a few tests around --- src/Test/UnitTests/basic_constraint_tests.jl | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index 766a622089..f6cedc90b2 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -22,15 +22,12 @@ function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, F, S = typeof(constraint_function), typeof(set) @test MOI.supportsconstraint(model, F, S) + @test MOI.canaddconstraint(model, F, S) @testset "NumberOfConstraints" begin @test MOI.canget(model, MOI.NumberOfConstraints{F,S}()) end - @testset "canaddconstraint" begin - @test MOI.canaddconstraint(model, F, S) - end - @testset "addconstraint!" begin n = MOI.get(model, MOI.NumberOfConstraints{F,S}()) c = MOI.addconstraint!(model, constraint_function, set) @@ -79,13 +76,11 @@ function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, end if delete - @testset "candelete" begin + @testset "delete!" begin c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) @test length(c_indices) == 3 # check that we've added a constraint @test MOI.candelete(model, c_indices[1]) - end - @testset "delete!" begin - c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + @test length(c_indices) == 3 # check that we've added a constraint MOI.delete!(model, c_indices[1]) @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == length(c_indices)-1 == 2 From 2993c5292fe6c01c41456846017b3c4a2beed72c Mon Sep 17 00:00:00 2001 From: odow Date: Sun, 13 May 2018 19:24:02 +1200 Subject: [PATCH 08/15] Rejig basic constraint tests --- src/Test/UnitTests/basic_constraint_tests.jl | 468 +++++-------------- test/Test/unit.jl | 6 + 2 files changed, 118 insertions(+), 356 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index f6cedc90b2..c137ddb62d 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -1,13 +1,20 @@ """ - test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int; delete::Bool=true) + test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int; + delete::Bool = true, + get_constraint_function::Bool = true, + get_constraint_set::Bool = true + ) Test some basic constraint tests. +See also `basic_constraint_tests`. + `f` is a function that takes a vector of `N` variables and returns a constraint function. -If `delete=true`, test `candelete` and `delete!`. -If `config.query=true`, test getting `ConstraintFunction` and `ConstraintSet`. +If `delete = true`, it will test the deletion of constraints. +If `get_constraint_function = true`, it will test the getting of `ConstraintFunction`. +If `get_constraint_set = true`, it will test the getting of `ConstraintSet`. ### Example @@ -15,7 +22,11 @@ If `config.query=true`, test getting `ConstraintFunction` and `ConstraintSet`. MOI.ScalarAffineFunction(model, [x], [1.0], 0.0) end """ -function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int=1; delete::Bool=true) +function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int=1; + delete::Bool = true, + get_constraint_function::Bool = true, + get_constraint_set::Bool = true + ) MOI.empty!(model) x = MOI.addvariables!(model, N) constraint_function = f(x) @@ -41,12 +52,13 @@ function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, @test MOI.get(model, MOI.ConstraintName(), c) == "c" end - if config.query + if get_constraint_function @testset "ConstraintFunction" begin @test MOI.canget(model, MOI.ConstraintFunction(), typeof(c)) @test MOI.get(model, MOI.ConstraintFunction(), c) ≈ constraint_function end - + end + if get_constraint_set @testset "ConstraintSet" begin @test MOI.canget(model, MOI.ConstraintSet(), typeof(c)) @test MOI.get(model, MOI.ConstraintSet(), c) == set @@ -89,356 +101,100 @@ function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, end end -""" - test_scalaraffine_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`LessThan{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_scalaraffine_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.LessThan(1.0); delete=delete) do x - MOI.ScalarAffineFunction(x, [1.0], 0.0) - end -end -unittests["test_scalaraffine_in_lessthan"] = test_scalaraffine_in_lessthan - - -""" - test_scalaraffine_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`GreaterThan{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_scalaraffine_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.GreaterThan(1.0); delete=delete) do x - MOI.ScalarAffineFunction(x, [1.0], 0.0) - end -end -unittests["test_scalaraffine_in_greaterthan"] = test_scalaraffine_in_greaterthan - -""" - test_scalaraffine_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`EqualTo{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_scalaraffine_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.EqualTo(1.0); delete=delete) do x - MOI.ScalarAffineFunction(x, [1.0], 0.0) - end -end -unittests["test_scalaraffine_in_equalto"] = test_scalaraffine_in_equalto - -""" - test_scalaraffine_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `ScalarAffineFunction{Float64}`-in-`Interval{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_scalaraffine_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x - MOI.ScalarAffineFunction(x, [1.0], 0.0) - end -end -unittests["test_scalaraffine_in_interval"] = test_scalaraffine_in_interval - -""" - test_scalarquadratic_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`LessThan{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_scalarquadratic_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.LessThan(1.0); delete=delete) do x - MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) - end -end -unittests["test_scalarquadratic_in_lessthan"] = test_scalarquadratic_in_lessthan - - -""" - test_scalarquadratic_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`GreaterThan{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_scalarquadratic_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.GreaterThan(1.0); delete=delete) do x - MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) - end -end -unittests["test_scalarquadratic_in_greaterthan"] = test_scalarquadratic_in_greaterthan - -""" - test_scalarquadratic_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`EqualTo{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_scalarquadratic_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.EqualTo(1.0); delete=delete) do x - MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) - end -end -unittests["test_scalarquadratic_in_equalto"] = test_scalarquadratic_in_equalto - -""" - test_scalarquadratic_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `ScalarQuadraticFunction{Float64}`-in-`Interval{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_scalarquadratic_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x - MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) - end -end -unittests["test_scalarquadratic_in_interval"] = test_scalarquadratic_in_interval - -""" - test_singlevariable_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `SingleVariable`-in-`LessThan{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_singlevariable_in_lessthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.LessThan(1.0); delete=delete) do x - MOI.SingleVariable(x[1]) - end -end -unittests["test_singlevariable_in_lessthan"] = test_singlevariable_in_lessthan - - -""" - test_singlevariable_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `SingleVariable`-in-`GreaterThan{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_singlevariable_in_greaterthan(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.GreaterThan(1.0); delete=delete) do x - MOI.SingleVariable(x[1]) - end -end -unittests["test_singlevariable_in_greaterthan"] = test_singlevariable_in_greaterthan - -""" - test_singlevariable_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `SingleVariable`-in-`EqualTo{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_singlevariable_in_equalto(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.EqualTo(1.0); delete=delete) do x - MOI.SingleVariable(x[1]) - end -end -unittests["test_singlevariable_in_equalto"] = test_singlevariable_in_equalto - -""" - test_singlevariable_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `SingleVariable`-in-`Interval{Float64}`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_singlevariable_in_interval(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Interval(0.0, 1.0); delete=delete) do x - MOI.SingleVariable(x[1]) - end -end -unittests["test_singlevariable_in_interval"] = test_singlevariable_in_interval - -""" - test_singlevariable_in_zeroone(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `SingleVariable`-in-`ZeroOne`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_singlevariable_in_zeroone(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.ZeroOne(); delete=delete) do x - MOI.SingleVariable(x[1]) - end -end -unittests["test_singlevariable_in_zeroone"] = test_singlevariable_in_zeroone - -""" - test_singlevariable_in_integer(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `SingleVariable`-in-`Integer`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_singlevariable_in_integer(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Integer(); delete=delete) do x - MOI.SingleVariable(x[1]) - end -end -unittests["test_singlevariable_in_integer"] = test_singlevariable_in_integer - -""" - test_singlevariable_in_semicontinuous(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `SingleVariable`-in-`Semicontinuous`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_singlevariable_in_semicontinuous(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Semicontinuous(1.0, 2.0); delete=delete) do x - MOI.SingleVariable(x[1]) - end -end -unittests["test_singlevariable_in_semicontinuous"] = test_singlevariable_in_semicontinuous - -""" - test_singlevariable_in_semiinteger(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `SingleVariable`-in-`Semiinteger`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_singlevariable_in_semiinteger(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Semiinteger(1.0, 2.0); delete=delete) do x - MOI.SingleVariable(x[1]) - end -end -unittests["test_singlevariable_in_semiinteger"] = test_singlevariable_in_semiinteger - -""" - test_vectorofvariables_in_sos1(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorOfVariables`-in-`SOS1`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectorofvariables_in_sos1(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.SOS1([1.0, 2.0, 3.0]), 3; delete=delete) do x - MOI.VectorOfVariables(x) - end -end -unittests["test_vectorofvariables_in_sos1"] = test_vectorofvariables_in_sos1 - -""" - test_vectorofvariables_in_sos2(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorOfVariables`-in-`SOS2`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectorofvariables_in_sos2(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.SOS2([1.0, 2.0, 3.0]), 3; delete=delete) do x - MOI.VectorOfVariables(x) - end -end -unittests["test_vectorofvariables_in_sos2"] = test_vectorofvariables_in_sos2 - -""" - test_vectorofvariables_in_reals(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorOfVariables`-in-`Reals`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectorofvariables_in_reals(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Reals(3), 3; delete=delete) do x - MOI.VectorOfVariables(x) - end -end -unittests["test_vectorofvariables_in_reals"] = test_vectorofvariables_in_reals - -""" - test_vectorofvariables_in_nonnegatives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorOfVariables`-in-`Nonnegatives`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectorofvariables_in_nonnegatives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Nonnegatives(3), 3; delete=delete) do x - MOI.VectorOfVariables(x) - end -end -unittests["test_vectorofvariables_in_nonnegatives"] = test_vectorofvariables_in_nonnegatives - -""" - test_vectorofvariables_in_nonpositives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorOfVariables`-in-`Nonpositives`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectorofvariables_in_nonpositives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Nonpositives(3), 3; delete=delete) do x - MOI.VectorOfVariables(x) - end -end -unittests["test_vectorofvariables_in_nonpositives"] = test_vectorofvariables_in_nonpositives - -""" - test_vectorofvariables_in_zeros(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorOfVariables`-in-`Zeros`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectorofvariables_in_zeros(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Zeros(3), 3; delete=delete) do x - MOI.VectorOfVariables(x) - end -end -unittests["test_vectorofvariables_in_zeros"] = test_vectorofvariables_in_zeros - - -""" - test_vectoraffinefunction_in_zeros(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorAffine`-in-`Zeros`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectoraffinefunction_in_zeros(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Zeros(2), 2; delete=delete) do x - MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) - end -end -unittests["test_vectoraffinefunction_in_zeros"] = test_vectoraffinefunction_in_zeros - -""" - test_vectoraffinefunction_in_nonnegatives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorAffine`-in-`Nonnegatives`. - -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectoraffinefunction_in_nonnegatives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Nonnegatives(2), 2; delete=delete) do x - MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) - end -end -unittests["test_vectoraffinefunction_in_nonnegatives"] = test_vectoraffinefunction_in_nonnegatives - -""" - test_vectoraffinefunction_in_nonpositives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - -Basic tests for constraints of the form `VectorAffine`-in-`Nonpositives`. +const dummy_single_variable = (x) -> MOI.SingleVariable(x[1]) +const dummy_vectorofvariables = (x) -> MOI.VectorOfVariables(x) +const dummy_scalar_affine = (x) -> MOI.ScalarAffineFunction(x, [1.0], 0.0) +const dummy_scalar_quadratic = (x) -> MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) +const dummy_vector_affine = (x) -> MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) + +const BasicConstraintTests = Dict( + (MOI.SingleVariable, MOI.LessThan{Float64}) => ( dummy_single_variable, 1, MOI.LessThan(1.0) ), + (MOI.SingleVariable, MOI.GreaterThan{Float64}) => ( dummy_single_variable, 1, MOI.GreaterThan(1.0) ), + (MOI.SingleVariable, MOI.EqualTo{Float64}) => ( dummy_single_variable, 1, MOI.EqualTo(1.0) ), + (MOI.SingleVariable, MOI.Interval{Float64}) => ( dummy_single_variable, 1, MOI.Interval(1.0, 2.0) ), + + (MOI.SingleVariable, MOI.ZeroOne) => ( dummy_single_variable, 1, MOI.ZeroOne() ), + (MOI.SingleVariable, MOI.Integer) => ( dummy_single_variable, 1, MOI.Integer() ), + (MOI.SingleVariable, MOI.Semicontinuous{Float64}) => ( dummy_single_variable, 1, MOI.Semicontinuous(1.0, 2.0) ), + (MOI.SingleVariable, MOI.Semiinteger{Float64}) => ( dummy_single_variable, 1, MOI.Semiinteger(1.0, 2.0) ), + + (MOI.VectorOfVariables, MOI.SOS1{Float64}) => ( dummy_vectorofvariables, 2, MOI.SOS1([1.0, 2.0]) ), + (MOI.VectorOfVariables, MOI.SOS2{Float64}) => ( dummy_vectorofvariables, 2, MOI.SOS2([1.0, 2.0]) ), + (MOI.VectorOfVariables, MOI.Reals) => ( dummy_vectorofvariables, 2, MOI.Reals(2) ), + (MOI.VectorOfVariables, MOI.Zeros) => ( dummy_vectorofvariables, 2, MOI.Zeros(2) ), + (MOI.VectorOfVariables, MOI.Nonpositives) => ( dummy_vectorofvariables, 2, MOI.Nonpositives(2) ), + (MOI.VectorOfVariables, MOI.Nonnegatives) => ( dummy_vectorofvariables, 2, MOI.Nonnegatives(2) ), + + (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => ( dummy_scalar_affine, 1, MOI.LessThan(1.0) ), + (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => ( dummy_scalar_affine, 1, MOI.GreaterThan(1.0) ), + (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => ( dummy_scalar_affine, 1, MOI.EqualTo(1.0) ), + (MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => ( dummy_scalar_affine, 1, MOI.Interval(1.0, 2.0) ), + + (MOI.ScalarQuadraticFunction{Float64}, MOI.LessThan{Float64}) => ( dummy_scalar_quadratic, 1, MOI.LessThan(1.0) ), + (MOI.ScalarQuadraticFunction{Float64}, MOI.GreaterThan{Float64}) => ( dummy_scalar_quadratic, 1, MOI.GreaterThan(1.0) ), + (MOI.ScalarQuadraticFunction{Float64}, MOI.EqualTo{Float64}) => ( dummy_scalar_quadratic, 1, MOI.EqualTo(1.0) ), + (MOI.ScalarQuadraticFunction{Float64}, MOI.Interval{Float64}) => ( dummy_scalar_quadratic, 1, MOI.Interval(1.0, 2.0) ), + + (MOI.VectorAffineFunction{Float64}, MOI.Reals) => ( dummy_vector_affine, 2, MOI.Reals(2) ), + (MOI.VectorAffineFunction{Float64}, MOI.Zeros) => ( dummy_vector_affine, 2, MOI.Zeros(2) ), + (MOI.VectorAffineFunction{Float64}, MOI.Nonpositives) => ( dummy_vector_affine, 2, MOI.Nonpositives(2) ), + (MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives) => ( dummy_vector_affine, 2, MOI.Nonnegatives(2) ) +) +""" + basic_constraint_tests(model::MOI.ModelLike, config::TestConfig; + delete = true, + get_constraint_function = true, + get_constraint_set = true, + include = Any[], + exclude = Any[] + ) -If `delete=true`, test `MOI.candelete` and `MOI.delete!`. -""" -function test_vectoraffinefunction_in_nonpositives(model::MOI.ModelLike, config::TestConfig; delete::Bool=true) - test_basic_constraint_functionality(model, config, MOI.Nonpositives(2), 2; delete=delete) do x - MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) +Test basic constraint functionality for all function-in-set combinations that +are supported by `model`. + +See also `test_basic_constraint_functionality`. + +If `delete = true`, it will test the deletion of constraints. +If `get_constraint_function = true`, it will test the getting of `ConstraintFunction`. +If `get_constraint_set = true`, it will test the getting of `ConstraintSet`. + +`include` and `exclude` can be used to run a subset of the tests, although only +one can be used in each call. + +### Examples + + basic_constraint_tests(model, config; exclude = [ + (MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) + ]) + + basic_constraint_tests(model, config; + delete = false, + include = [ + (MOI.VectorOfVariables, MOI.SOS2{Float64}) + ] + ) +""" +function basic_constraint_tests(model::MOI.ModelLike, config::TestConfig; + delete = true, + get_constraint_function = true, + get_constraint_set = true, + include = Any[], + exclude = Any[] + ) + if length(include) > 0 && length(exclude) > 0 + error("Don't use `include` and `exclude` together.") + end + test_keys = length(include) > 0 ? include : Iterators.filter(x->!(x in exclude), keys(BasicConstraintTests)) + for (F,S) in test_keys + if MOI.supportsconstraint(model, F, S) + @testset "$(F)-$(S)" begin + (cf, N, set) = BasicConstraintTests[(F,S)] + test_basic_constraint_functionality(cf, model, config, set, N; + delete = delete, + get_constraint_function = get_constraint_function, + get_constraint_set = get_constraint_set + ) + end + end end end -unittests["test_vectoraffinefunction_in_nonpositives"] = test_vectoraffinefunction_in_nonpositives diff --git a/test/Test/unit.jl b/test/Test/unit.jl index f18416a8c2..1caabd5f8a 100644 --- a/test/Test/unit.jl +++ b/test/Test/unit.jl @@ -1,3 +1,9 @@ +@testset "Basic Constraint Tests" begin + mock = MOIU.MockOptimizer(Model{Float64}()) + config = MOIT.TestConfig() + MOIT.basic_constraint_tests(mock, config) +end + @testset "Unit Tests" begin mock = MOIU.MockOptimizer(Model{Float64}()) config = MOIT.TestConfig() From cd45109c774c3ff71606f91d3376760a1add16ba Mon Sep 17 00:00:00 2001 From: odow Date: Sun, 13 May 2018 19:41:02 +1200 Subject: [PATCH 09/15] VectorQuadratic --- src/Test/UnitTests/basic_constraint_tests.jl | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index c137ddb62d..a7848d7d5e 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -101,11 +101,24 @@ function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, end end +# x const dummy_single_variable = (x) -> MOI.SingleVariable(x[1]) +# x₁, x₂ const dummy_vectorofvariables = (x) -> MOI.VectorOfVariables(x) +# 1.0 * x const dummy_scalar_affine = (x) -> MOI.ScalarAffineFunction(x, [1.0], 0.0) +# 1.0 * x + 1.0 * x^2 const dummy_scalar_quadratic = (x) -> MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) +# x₁ + - 1 +# + x₂ + 1 const dummy_vector_affine = (x) -> MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) +# x₁ + + x₁^2 +# + x₂ + + x₂^2 +const dummy_vector_quadratic = (x) -> MOI.VectorQuadraticFunction( + [1,2], x, [1.0, 1.0], # affine component + [1,2], x, x, [1.0, 1.0], # quadratic component + [0.0, 0.0] # constant term +) const BasicConstraintTests = Dict( (MOI.SingleVariable, MOI.LessThan{Float64}) => ( dummy_single_variable, 1, MOI.LessThan(1.0) ), @@ -138,7 +151,12 @@ const BasicConstraintTests = Dict( (MOI.VectorAffineFunction{Float64}, MOI.Reals) => ( dummy_vector_affine, 2, MOI.Reals(2) ), (MOI.VectorAffineFunction{Float64}, MOI.Zeros) => ( dummy_vector_affine, 2, MOI.Zeros(2) ), (MOI.VectorAffineFunction{Float64}, MOI.Nonpositives) => ( dummy_vector_affine, 2, MOI.Nonpositives(2) ), - (MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives) => ( dummy_vector_affine, 2, MOI.Nonnegatives(2) ) + (MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives) => ( dummy_vector_affine, 2, MOI.Nonnegatives(2) ), + + (MOI.VectorQuadraticFunction{Float64}, MOI.Reals) => ( dummy_vector_quadratic, 2, MOI.Reals(2) ), + (MOI.VectorQuadraticFunction{Float64}, MOI.Zeros) => ( dummy_vector_quadratic, 2, MOI.Zeros(2) ), + (MOI.VectorQuadraticFunction{Float64}, MOI.Nonpositives) => ( dummy_vector_quadratic, 2, MOI.Nonpositives(2) ), + (MOI.VectorQuadraticFunction{Float64}, MOI.Nonnegatives) => ( dummy_vector_quadratic, 2, MOI.Nonnegatives(2) ) ) """ basic_constraint_tests(model::MOI.ModelLike, config::TestConfig; From 6a2523a634196e4b70997e7c105fcd0c598b0b42 Mon Sep 17 00:00:00 2001 From: odow Date: Mon, 14 May 2018 11:17:25 +1200 Subject: [PATCH 10/15] Test some conic sets --- src/Test/UnitTests/basic_constraint_tests.jl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index a7848d7d5e..705ea0e4a4 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -102,19 +102,19 @@ function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, end # x -const dummy_single_variable = (x) -> MOI.SingleVariable(x[1]) +const dummy_single_variable = (x::Vector{MOI.VariableIndex}) -> MOI.SingleVariable(x[1]) # x₁, x₂ -const dummy_vectorofvariables = (x) -> MOI.VectorOfVariables(x) +const dummy_vectorofvariables = (x::Vector{MOI.VariableIndex}) -> MOI.VectorOfVariables(x) # 1.0 * x -const dummy_scalar_affine = (x) -> MOI.ScalarAffineFunction(x, [1.0], 0.0) +const dummy_scalar_affine = (x::Vector{MOI.VariableIndex}) -> MOI.ScalarAffineFunction(x, [1.0], 0.0) # 1.0 * x + 1.0 * x^2 -const dummy_scalar_quadratic = (x) -> MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) +const dummy_scalar_quadratic = (x::Vector{MOI.VariableIndex}) -> MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) # x₁ + - 1 # + x₂ + 1 -const dummy_vector_affine = (x) -> MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) +const dummy_vector_affine = (x::Vector{MOI.VariableIndex}) -> MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) # x₁ + + x₁^2 # + x₂ + + x₂^2 -const dummy_vector_quadratic = (x) -> MOI.VectorQuadraticFunction( +const dummy_vector_quadratic = (x::Vector{MOI.VariableIndex}) -> MOI.VectorQuadraticFunction( [1,2], x, [1.0, 1.0], # affine component [1,2], x, x, [1.0, 1.0], # quadratic component [0.0, 0.0] # constant term @@ -138,6 +138,12 @@ const BasicConstraintTests = Dict( (MOI.VectorOfVariables, MOI.Nonpositives) => ( dummy_vectorofvariables, 2, MOI.Nonpositives(2) ), (MOI.VectorOfVariables, MOI.Nonnegatives) => ( dummy_vectorofvariables, 2, MOI.Nonnegatives(2) ), + (MOI.VectorOfVariables, MOI.SecondOrderCone) => ( dummy_vectorofvariables, 3, MOI.SecondOrderCone(3) ), + (MOI.VectorOfVariables, MOI.RotatedSecondOrderCone) => ( dummy_vectorofvariables, 3, MOI.RotatedSecondOrderCone(3) ), + (MOI.VectorOfVariables, MOI.GeometricMeanCone) => ( dummy_vectorofvariables, 3, MOI.GeometricMeanCone(3) ), + (MOI.VectorOfVariables, MOI.ExponentialCone) => ( dummy_vectorofvariables, 3, MOI.ExponentialCone() ), + (MOI.VectorOfVariables, MOI.DualExponentialCone) => ( dummy_vectorofvariables, 3, MOI.DualExponentialCone() ), + (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => ( dummy_scalar_affine, 1, MOI.LessThan(1.0) ), (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => ( dummy_scalar_affine, 1, MOI.GreaterThan(1.0) ), (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => ( dummy_scalar_affine, 1, MOI.EqualTo(1.0) ), From 7114fa4c852817e0dc1ff514150558fba8fb8c24 Mon Sep 17 00:00:00 2001 From: odow Date: Tue, 15 May 2018 08:59:37 +1200 Subject: [PATCH 11/15] Add conic constraints --- src/Test/UnitTests/basic_constraint_tests.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index 705ea0e4a4..7279d7080b 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -143,6 +143,15 @@ const BasicConstraintTests = Dict( (MOI.VectorOfVariables, MOI.GeometricMeanCone) => ( dummy_vectorofvariables, 3, MOI.GeometricMeanCone(3) ), (MOI.VectorOfVariables, MOI.ExponentialCone) => ( dummy_vectorofvariables, 3, MOI.ExponentialCone() ), (MOI.VectorOfVariables, MOI.DualExponentialCone) => ( dummy_vectorofvariables, 3, MOI.DualExponentialCone() ), + (MOI.VectorOfVariables, MOI.PowerCone) => ( dummy_vectorofvariables, 3, MOI.PowerCone(2.0) ), + (MOI.VectorOfVariables, MOI.DualPowerCone) => ( dummy_vectorofvariables, 3, MOI.DualPowerCone(2.0) ), + + (MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle) => ( dummy_vectorofvariables, 6, MOI.PositiveSemidefiniteConeTriangle(3) ), + (MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeSquare) => ( dummy_vectorofvariables, 9, MOI.PositiveSemidefiniteConeSquare(3) ), + (MOI.VectorOfVariables, MOI.LogDetConeTriangle) => ( dummy_vectorofvariables, 6, MOI.LogDetConeTriangle(3) ), + (MOI.VectorOfVariables, MOI.LogDetConeSquare) => ( dummy_vectorofvariables, 9, MOI.LogDetConeSquare(3) ), + (MOI.VectorOfVariables, MOI.RootDetConeTriangle) => ( dummy_vectorofvariables, 6, MOI.RootDetConeTriangle(3) ), + (MOI.VectorOfVariables, MOI.RootDetConeSquare) => ( dummy_vectorofvariables, 9, MOI.RootDetConeSquare(3) ), (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => ( dummy_scalar_affine, 1, MOI.LessThan(1.0) ), (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => ( dummy_scalar_affine, 1, MOI.GreaterThan(1.0) ), From ca419742f1908a6cdb835d920d36cea296c96e8d Mon Sep 17 00:00:00 2001 From: odow Date: Tue, 15 May 2018 21:19:50 +1200 Subject: [PATCH 12/15] Correct dimension of some conic sets --- src/Test/UnitTests/basic_constraint_tests.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index 7279d7080b..b0eabaf6c7 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -146,12 +146,12 @@ const BasicConstraintTests = Dict( (MOI.VectorOfVariables, MOI.PowerCone) => ( dummy_vectorofvariables, 3, MOI.PowerCone(2.0) ), (MOI.VectorOfVariables, MOI.DualPowerCone) => ( dummy_vectorofvariables, 3, MOI.DualPowerCone(2.0) ), - (MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle) => ( dummy_vectorofvariables, 6, MOI.PositiveSemidefiniteConeTriangle(3) ), - (MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeSquare) => ( dummy_vectorofvariables, 9, MOI.PositiveSemidefiniteConeSquare(3) ), - (MOI.VectorOfVariables, MOI.LogDetConeTriangle) => ( dummy_vectorofvariables, 6, MOI.LogDetConeTriangle(3) ), - (MOI.VectorOfVariables, MOI.LogDetConeSquare) => ( dummy_vectorofvariables, 9, MOI.LogDetConeSquare(3) ), - (MOI.VectorOfVariables, MOI.RootDetConeTriangle) => ( dummy_vectorofvariables, 6, MOI.RootDetConeTriangle(3) ), - (MOI.VectorOfVariables, MOI.RootDetConeSquare) => ( dummy_vectorofvariables, 9, MOI.RootDetConeSquare(3) ), + (MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle) => ( dummy_vectorofvariables, 7, MOI.PositiveSemidefiniteConeTriangle(3) ), + (MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeSquare) => ( dummy_vectorofvariables, 10, MOI.PositiveSemidefiniteConeSquare(3) ), + (MOI.VectorOfVariables, MOI.LogDetConeTriangle) => ( dummy_vectorofvariables, 7, MOI.LogDetConeTriangle(3) ), + (MOI.VectorOfVariables, MOI.LogDetConeSquare) => ( dummy_vectorofvariables, 10, MOI.LogDetConeSquare(3) ), + (MOI.VectorOfVariables, MOI.RootDetConeTriangle) => ( dummy_vectorofvariables, 7, MOI.RootDetConeTriangle(3) ), + (MOI.VectorOfVariables, MOI.RootDetConeSquare) => ( dummy_vectorofvariables, 10, MOI.RootDetConeSquare(3) ), (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => ( dummy_scalar_affine, 1, MOI.LessThan(1.0) ), (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => ( dummy_scalar_affine, 1, MOI.GreaterThan(1.0) ), From a7b74f531125a510250d247249ba52611fc2d84c Mon Sep 17 00:00:00 2001 From: odow Date: Tue, 15 May 2018 21:26:48 +1200 Subject: [PATCH 13/15] Update comments --- src/Test/UnitTests/basic_constraint_tests.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index b0eabaf6c7..19b0562627 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -78,22 +78,23 @@ function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, @testset "ListOfConstraintIndices" begin @test MOI.canget(model, MOI.ListOfConstraintIndices{F,S}()) c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + # for sanity, check that we've added 3 constraints as expected. @test length(c_indices) == MOI.get(model, MOI.NumberOfConstraints{F,S}()) == 3 end @testset "isvalid" begin c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) - @test length(c_indices) == 3 # check that we've added a constraint + # for sanity, check that we've added 3 constraints as expected. + @test length(c_indices) == 3 @test all(MOI.isvalid.(model, c_indices)) end if delete @testset "delete!" begin c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) - @test length(c_indices) == 3 # check that we've added a constraint + # for sanity, check that we've added 3 constraints as expected. + @test length(c_indices) == 3 @test MOI.candelete(model, c_indices[1]) - - @test length(c_indices) == 3 # check that we've added a constraint MOI.delete!(model, c_indices[1]) @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == length(c_indices)-1 == 2 @test !MOI.isvalid(model, c_indices[1]) From 88329b2fc26577a81b1b416087b9604cbdd762f7 Mon Sep 17 00:00:00 2001 From: odow Date: Tue, 15 May 2018 21:36:51 +1200 Subject: [PATCH 14/15] More fixes for generality --- src/Test/UnitTests/basic_constraint_tests.jl | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index 19b0562627..334aa3064f 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -106,19 +106,19 @@ end const dummy_single_variable = (x::Vector{MOI.VariableIndex}) -> MOI.SingleVariable(x[1]) # x₁, x₂ const dummy_vectorofvariables = (x::Vector{MOI.VariableIndex}) -> MOI.VectorOfVariables(x) -# 1.0 * x -const dummy_scalar_affine = (x::Vector{MOI.VariableIndex}) -> MOI.ScalarAffineFunction(x, [1.0], 0.0) -# 1.0 * x + 1.0 * x^2 -const dummy_scalar_quadratic = (x::Vector{MOI.VariableIndex}) -> MOI.ScalarQuadraticFunction(x, [1.0], x, x, [1.0], 0.0) -# x₁ + - 1 -# + x₂ + 1 -const dummy_vector_affine = (x::Vector{MOI.VariableIndex}) -> MOI.VectorAffineFunction([1, 2], x, [1.0, 1.0], [-1.0, 1.0]) -# x₁ + + x₁^2 -# + x₂ + + x₂^2 +# 1.0 * x + 0.0 +const dummy_scalar_affine = (x::Vector{MOI.VariableIndex}) -> MOI.ScalarAffineFunction(x, ones(Float64, length(x)), 0.0) +# 1.0 * x + 1.0 * x^2 + 0.0 +const dummy_scalar_quadratic = (x::Vector{MOI.VariableIndex}) -> MOI.ScalarQuadraticFunction(x, ones(Float64, length(x)), x, x, ones(Float64, length(x)), 0.0) +# x₁ + + 0.0 +# + x₂ + 0.0 +const dummy_vector_affine = (x::Vector{MOI.VariableIndex}) -> MOI.VectorAffineFunction(collect(1:length(x)), x, ones(Float64, length(x)), zeros(Float64, length(x))) +# x₁ + + x₁^2 + 0.0 +# + x₂ + + x₂^2 + 0.0 const dummy_vector_quadratic = (x::Vector{MOI.VariableIndex}) -> MOI.VectorQuadraticFunction( - [1,2], x, [1.0, 1.0], # affine component - [1,2], x, x, [1.0, 1.0], # quadratic component - [0.0, 0.0] # constant term + collect(1:length(x)), x, ones(Float64, length(x)), # affine component + collect(1:length(x)), x, x, ones(Float64, length(x)), # quadratic component + zeros(Float64, length(x)) # constant term ) const BasicConstraintTests = Dict( From ae6abf2c04324e3d44dfc9119e32a7ec650b1f4d Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 16 May 2018 08:32:15 +1200 Subject: [PATCH 15/15] rename methods and reorg file --- src/Test/UnitTests/basic_constraint_tests.jl | 215 ++++++++++--------- 1 file changed, 109 insertions(+), 106 deletions(-) diff --git a/src/Test/UnitTests/basic_constraint_tests.jl b/src/Test/UnitTests/basic_constraint_tests.jl index 334aa3064f..4486755970 100644 --- a/src/Test/UnitTests/basic_constraint_tests.jl +++ b/src/Test/UnitTests/basic_constraint_tests.jl @@ -1,107 +1,3 @@ -""" - test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int; - delete::Bool = true, - get_constraint_function::Bool = true, - get_constraint_set::Bool = true - ) - -Test some basic constraint tests. - -See also `basic_constraint_tests`. - -`f` is a function that takes a vector of `N` variables and returns a constraint -function. - -If `delete = true`, it will test the deletion of constraints. -If `get_constraint_function = true`, it will test the getting of `ConstraintFunction`. -If `get_constraint_set = true`, it will test the getting of `ConstraintSet`. - -### Example - - test_basic_constraint_functionality(model, config, MOI.LessThan(1.0), 1; delete=false) do x - MOI.ScalarAffineFunction(model, [x], [1.0], 0.0) - end -""" -function test_basic_constraint_functionality(f::Function, model::MOI.ModelLike, config::TestConfig, set::MOI.AbstractSet, N::Int=1; - delete::Bool = true, - get_constraint_function::Bool = true, - get_constraint_set::Bool = true - ) - MOI.empty!(model) - x = MOI.addvariables!(model, N) - constraint_function = f(x) - F, S = typeof(constraint_function), typeof(set) - - @test MOI.supportsconstraint(model, F, S) - @test MOI.canaddconstraint(model, F, S) - - @testset "NumberOfConstraints" begin - @test MOI.canget(model, MOI.NumberOfConstraints{F,S}()) - end - - @testset "addconstraint!" begin - n = MOI.get(model, MOI.NumberOfConstraints{F,S}()) - c = MOI.addconstraint!(model, constraint_function, set) - @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == n + 1 - - @testset "ConstraintName" begin - @test MOI.canget(model, MOI.ConstraintName(), typeof(c)) - @test MOI.get(model, MOI.ConstraintName(), c) == "" - @test MOI.canset(model, MOI.ConstraintName(), typeof(c)) - MOI.set!(model, MOI.ConstraintName(), c, "c") - @test MOI.get(model, MOI.ConstraintName(), c) == "c" - end - - if get_constraint_function - @testset "ConstraintFunction" begin - @test MOI.canget(model, MOI.ConstraintFunction(), typeof(c)) - @test MOI.get(model, MOI.ConstraintFunction(), c) ≈ constraint_function - end - end - if get_constraint_set - @testset "ConstraintSet" begin - @test MOI.canget(model, MOI.ConstraintSet(), typeof(c)) - @test MOI.get(model, MOI.ConstraintSet(), c) == set - end - end - end - - @testset "addconstraints!" begin - n = MOI.get(model, MOI.NumberOfConstraints{F,S}()) - cc = MOI.addconstraints!(model, - [constraint_function, constraint_function], - [set, set] - ) - @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == n + 2 - end - - @testset "ListOfConstraintIndices" begin - @test MOI.canget(model, MOI.ListOfConstraintIndices{F,S}()) - c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) - # for sanity, check that we've added 3 constraints as expected. - @test length(c_indices) == MOI.get(model, MOI.NumberOfConstraints{F,S}()) == 3 - end - - @testset "isvalid" begin - c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) - # for sanity, check that we've added 3 constraints as expected. - @test length(c_indices) == 3 - @test all(MOI.isvalid.(model, c_indices)) - end - - if delete - @testset "delete!" begin - c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) - # for sanity, check that we've added 3 constraints as expected. - @test length(c_indices) == 3 - @test MOI.candelete(model, c_indices[1]) - MOI.delete!(model, c_indices[1]) - @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == length(c_indices)-1 == 2 - @test !MOI.isvalid(model, c_indices[1]) - end - end -end - # x const dummy_single_variable = (x::Vector{MOI.VariableIndex}) -> MOI.SingleVariable(x[1]) # x₁, x₂ @@ -186,7 +82,7 @@ const BasicConstraintTests = Dict( Test basic constraint functionality for all function-in-set combinations that are supported by `model`. -See also `test_basic_constraint_functionality`. +See also `basic_constraint_test_helper`. If `delete = true`, it will test the deletion of constraints. If `get_constraint_function = true`, it will test the getting of `ConstraintFunction`. @@ -223,7 +119,7 @@ function basic_constraint_tests(model::MOI.ModelLike, config::TestConfig; if MOI.supportsconstraint(model, F, S) @testset "$(F)-$(S)" begin (cf, N, set) = BasicConstraintTests[(F,S)] - test_basic_constraint_functionality(cf, model, config, set, N; + basic_constraint_test_helper(model, config, cf, set, N; delete = delete, get_constraint_function = get_constraint_function, get_constraint_set = get_constraint_set @@ -232,3 +128,110 @@ function basic_constraint_tests(model::MOI.ModelLike, config::TestConfig; end end end + +""" + basic_constraint_test_helper(model::MOI.ModelLike, config::TestConfig, func::Function, set::MOI.AbstractSet, N::Int; + delete::Bool = true, + get_constraint_function::Bool = true, + get_constraint_set::Bool = true + ) + +A helper function for `basic_constraint_tests`. + +This function tests the basic functionality of the constraint type `F`-in-`S` +where `S = typeof(set)`, and `func` is a function that takes a vector of `N` +variables and returns a `MOI.AbstractFunction` of type `F`. + +If `delete = true`, it will test the deletion of constraints. +If `get_constraint_function = true`, it will test the getting of `ConstraintFunction`. +If `get_constraint_set = true`, it will test the getting of `ConstraintSet`. + +### Example + + basic_constraint_test_helper(model, config, + (x) -> MOI.ScalarAffineFunction(model, [x], [1.0], 0.0), + MOI.LessThan(1.0), + 1; + delete=false + ) + +""" +function basic_constraint_test_helper(model::MOI.ModelLike, config::TestConfig, func::Function, set::MOI.AbstractSet, N::Int=1; + delete::Bool = true, + get_constraint_function::Bool = true, + get_constraint_set::Bool = true + ) + MOI.empty!(model) + x = MOI.addvariables!(model, N) + constraint_function = func(x) + F, S = typeof(constraint_function), typeof(set) + + @test MOI.supportsconstraint(model, F, S) + @test MOI.canaddconstraint(model, F, S) + + @testset "NumberOfConstraints" begin + @test MOI.canget(model, MOI.NumberOfConstraints{F,S}()) + end + + @testset "addconstraint!" begin + n = MOI.get(model, MOI.NumberOfConstraints{F,S}()) + c = MOI.addconstraint!(model, constraint_function, set) + @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == n + 1 + + @testset "ConstraintName" begin + @test MOI.canget(model, MOI.ConstraintName(), typeof(c)) + @test MOI.get(model, MOI.ConstraintName(), c) == "" + @test MOI.canset(model, MOI.ConstraintName(), typeof(c)) + MOI.set!(model, MOI.ConstraintName(), c, "c") + @test MOI.get(model, MOI.ConstraintName(), c) == "c" + end + + if get_constraint_function + @testset "ConstraintFunction" begin + @test MOI.canget(model, MOI.ConstraintFunction(), typeof(c)) + @test MOI.get(model, MOI.ConstraintFunction(), c) ≈ constraint_function + end + end + if get_constraint_set + @testset "ConstraintSet" begin + @test MOI.canget(model, MOI.ConstraintSet(), typeof(c)) + @test MOI.get(model, MOI.ConstraintSet(), c) == set + end + end + end + + @testset "addconstraints!" begin + n = MOI.get(model, MOI.NumberOfConstraints{F,S}()) + cc = MOI.addconstraints!(model, + [constraint_function, constraint_function], + [set, set] + ) + @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == n + 2 + end + + @testset "ListOfConstraintIndices" begin + @test MOI.canget(model, MOI.ListOfConstraintIndices{F,S}()) + c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + # for sanity, check that we've added 3 constraints as expected. + @test length(c_indices) == MOI.get(model, MOI.NumberOfConstraints{F,S}()) == 3 + end + + @testset "isvalid" begin + c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + # for sanity, check that we've added 3 constraints as expected. + @test length(c_indices) == 3 + @test all(MOI.isvalid.(model, c_indices)) + end + + if delete + @testset "delete!" begin + c_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) + # for sanity, check that we've added 3 constraints as expected. + @test length(c_indices) == 3 + @test MOI.candelete(model, c_indices[1]) + MOI.delete!(model, c_indices[1]) + @test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == length(c_indices)-1 == 2 + @test !MOI.isvalid(model, c_indices[1]) + end + end +end