From b3a40fd89dc0ace1dd94a570f2508da798c1a032 Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 6 Nov 2024 08:58:58 +1300 Subject: [PATCH] Update --- src/Test/test_model.jl | 17 ++++++++++++ src/variables.jl | 61 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/Test/test_model.jl b/src/Test/test_model.jl index 4c67651198..1b854b8d30 100644 --- a/src/Test/test_model.jl +++ b/src/Test/test_model.jl @@ -1226,3 +1226,20 @@ function test_model_show(model::MOI.ModelLike, ::Config{T}) where {T} @test sprint(show, model) isa String return end + +function test_model_add_constrained_variale_tuple( + model::MOI.ModelLike, + ::Config{T}, +) where {T} + F = MOI.VariableIndex + set = (MOI.GreaterThan(zero(T)), MOI.LessThan(one(T))) + @requires MOI.supports_add_constrained_variable(model, typeof(set)) + x, (c_l, c_u) = MOI.add_constrained_variable(model, set) + @test c_l == MOI.ConstraintIndex{F,MOI.GreaterThan{T}}(x.value) + @test c_u == MOI.ConstraintIndex{F,MOI.LessThan{T}}(x.value) + @test MOI.get(model, MOI.ConstraintFunction(), c_l) == x + @test MOI.get(model, MOI.ConstraintSet(), c_l) == set[1] + @test MOI.get(model, MOI.ConstraintFunction(), c_u) == x + @test MOI.get(model, MOI.ConstraintSet(), c_u) == set[2] + return +end diff --git a/src/variables.jl b/src/variables.jl index c13f1c5349..2b14216937 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -124,10 +124,63 @@ function add_constrained_variable(model::ModelLike, set::AbstractScalarSet) return variable, constraint end -function add_constrained_variable(model::ModelLike, set1::AbstractScalarSet, set2::AbstractScalarSet) - variable, constraint1 = add_constrained_variable(model, set1) - constraint2 = add_constraint(model, variable, set2) - return variable, constraint1, constraint2 +""" + add_constrained_variable( + model::ModelLike, + set::Tuple{<:GreaterThan,<:LessThan}, + ) + +A special-case method to add a scalar variable with a lower and upper bound. + +This method should be implemented by optimizers which have native support for +adding a variable with bounds and which cannot performantly modify the variable +bounds after creation. + +## Example + +```jldoctest +julia> import MathOptInterface as MOI + +julia> model = MOI.Utilities.Model{Float64}(); + +julia> set = (MOI.GreaterThan(1.0), MOI.LessThan(2.0)); + +julia> x, (c_l, c_u) = MOI.add_constrained_variable(model, set); + +julia> c_l +MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1) + +julia> c_u +MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64}}(1) + +julia> print(model) +Feasibility + +Subject to: + +VariableIndex-in-GreaterThan{Float64} + v[1] >= 1.0 + +VariableIndex-in-LessThan{Float64} + v[1] <= 2.0 +``` +""" +function add_constrained_variable( + model::ModelLike, + set::Tuple{<:GreaterThan,<:LessThan}, +) + set_1, set_2 = set + x, c_1 = add_constrained_variable(model, set_1) + c_2 = add_constraint(model, x, set_2) + return x, (c_1, c_2) +end + +function supports_add_constrained_variable( + model::ModelLike, + ::Type{Tuple{L,U}}, +) where {L<:GreaterThan,U<:LessThan} + return supports_add_constrained_variable(model, L) && + supports_constraint(model, VariableIndex, U) end """