Skip to content

Commit

Permalink
Use MOI.add_constrained_variable when creating variables (#3863)
Browse files Browse the repository at this point in the history
  • Loading branch information
odow authored Nov 1, 2024
1 parent c63b19c commit be7d350
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 28 deletions.
92 changes: 64 additions & 28 deletions src/variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1965,20 +1965,68 @@ function add_variable(model::GenericModel, v::ScalarVariable, name::String = "")
return _moi_add_variable(backend(model), model, v, name)
end

function _moi_add_constrained_variable(
moi_backend::MOI.ModelLike,
::Nothing,
set::MOI.AbstractScalarSet,
)
x, _ = MOI.add_constrained_variable(moi_backend, set)
return x
end

function _moi_add_constrained_variable(
moi_backend::MOI.ModelLike,
x::MOI.VariableIndex,
set::MOI.AbstractScalarSet,
)
MOI.add_constraint(moi_backend, x, set)
return x
end

function _moi_add_variable(
moi_backend,
model::GenericModel{T},
v::ScalarVariable,
name::String,
) where {T}
index = MOI.add_variable(moi_backend)
var_ref = GenericVariableRef(model, index)
_moi_constrain_variable(moi_backend, index, v.info, T)
if !isempty(name) &&
MOI.supports(moi_backend, MOI.VariableName(), MOI.VariableIndex)
set_name(var_ref, name)
# We don't call the _moi* versions (for example, _moi_set_lower_bound)
# because they have extra checks that are not necessary for newly created
# variables.
index = nothing
info = v.info
if info.has_lb
set_lb =
MOI.GreaterThan{T}(_to_value(T, info.lower_bound, "lower bound"))
index = _moi_add_constrained_variable(moi_backend, index, set_lb)
end
return var_ref
if info.has_ub
set_ub = MOI.LessThan{T}(_to_value(T, info.upper_bound, "upper bound"))
index = _moi_add_constrained_variable(moi_backend, index, set_ub)
end
if info.has_fix
set_eq = MOI.EqualTo{T}(_to_value(T, info.fixed_value, "fixed value"))
index = _moi_add_constrained_variable(moi_backend, index, set_eq)
end
if info.binary
index = _moi_add_constrained_variable(moi_backend, index, MOI.ZeroOne())
end
if info.integer
index = _moi_add_constrained_variable(moi_backend, index, MOI.Integer())
end
if index === nothing
index = MOI.add_variable(moi_backend)
end
x = GenericVariableRef(model, index::MOI.VariableIndex)
if info.has_start && info.start !== nothing
start = _to_value(T, info.start, "start value")
MOI.set(moi_backend, MOI.VariablePrimalStart(), index, start)
end
if !isempty(name)
if MOI.supports(moi_backend, MOI.VariableName(), MOI.VariableIndex)
set_name(x, name)
end
end
return x
end

_to_value(::Type{T}, value::T, ::String) where {T} = value
Expand Down Expand Up @@ -2012,25 +2060,16 @@ function _moi_constrain_variable(
# because they have extra checks that are not necessary for newly created
# variables.
if info.has_lb
_moi_add_constraint(
moi_backend,
index,
MOI.GreaterThan{T}(_to_value(T, info.lower_bound, "lower bound")),
)
lb = _to_value(T, info.lower_bound, "lower bound")
_moi_add_constraint(moi_backend, index, MOI.GreaterThan{T}(lb))
end
if info.has_ub
_moi_add_constraint(
moi_backend,
index,
MOI.LessThan{T}(_to_value(T, info.upper_bound, "upper bound")),
)
ub = _to_value(T, info.upper_bound, "upper bound")
_moi_add_constraint(moi_backend, index, MOI.LessThan{T}(ub))
end
if info.has_fix
_moi_add_constraint(
moi_backend,
index,
MOI.EqualTo{T}(_to_value(T, info.fixed_value, "fixed value")),
)
eq = _to_value(T, info.fixed_value, "fixed value")
_moi_add_constraint(moi_backend, index, MOI.EqualTo{T}(eq))
end
if info.binary
_moi_add_constraint(moi_backend, index, MOI.ZeroOne())
Expand All @@ -2039,13 +2078,10 @@ function _moi_constrain_variable(
_moi_add_constraint(moi_backend, index, MOI.Integer())
end
if info.has_start && info.start !== nothing
MOI.set(
moi_backend,
MOI.VariablePrimalStart(),
index,
_to_value(T, info.start, "start value"),
)
start = _to_value(T, info.start, "start value")
MOI.set(moi_backend, MOI.VariablePrimalStart(), index, start)
end
return
end

"""
Expand Down
38 changes: 38 additions & 0 deletions test/test_variable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1662,4 +1662,42 @@ function test_value_number()
return
end

function test_add_constrained_variable()
model = Model()
@variable(model, x1 >= 0)
@test has_lower_bound(x1)
@variable(model, x2 <= 0)
@test has_upper_bound(x2)
@variable(model, x3 == 0)
@test is_fixed(x3)
@variable(model, x4, Int)
@test is_integer(x4)
@variable(model, x5, Bin)
@test is_binary(x5)
@variable(model, x6 >= 0, Int)
@test has_lower_bound(x6)
@test is_integer(x6)
return
end

function test_add_variable_in_set()
model = Model()
@variable(model, x1 >= 0, set = MOI.Integer())
@test has_lower_bound(x1)
@test is_integer(x1)
@variable(model, x2 <= 0, set = MOI.Integer())
@test has_upper_bound(x2)
@test is_integer(x2)
@variable(model, x3 == 0, set = MOI.Integer())
@test is_fixed(x3)
@test is_integer(x3)
@variable(model, x4 in MOI.EqualTo(3.0), Int)
@test is_fixed(x4)
@test is_integer(x4)
@variable(model, x5 in MOI.EqualTo(3.0), Bin)
@test is_fixed(x5)
@test is_binary(x5)
return
end

end # module TestVariable

0 comments on commit be7d350

Please sign in to comment.