Skip to content

Commit

Permalink
Don't falsely claim that Integer variables are supported
Browse files Browse the repository at this point in the history
They really are not supported, and the claim is only there
to provide a nice diagnostic.

But that prevents MOI `IntegerToZeroOneBridge` from triggering,
and providing Alpine with transparent support for them.

Fixes lanl-ansi#244
  • Loading branch information
LebedevRI committed Jun 27, 2024
1 parent 4ab44d4 commit e7c72c4
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 21 deletions.
32 changes: 20 additions & 12 deletions src/MOI_wrapper/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -322,18 +322,6 @@ function MOI.add_constraint(model::Optimizer, vi::MOI.VariableIndex, set::SCALAR
return MOI.ConstraintIndex{typeof(vi),typeof(set)}(vi.value)
end

function MOI.supports_constraint(
::Optimizer,
::Type{MOI.VariableIndex},
::Type{MOI.Integer},
)
return true
end

function MOI.add_constraint(model::Optimizer, f::MOI.VariableIndex, set::MOI.Integer)
model.var_type_orig[f.value] = :Int
return MOI.ConstraintIndex{typeof(f),typeof(set)}(f.value)
end
function MOI.supports_constraint(
::Optimizer,
::Type{MOI.VariableIndex},
Expand Down Expand Up @@ -457,6 +445,26 @@ function MOI.is_valid(model::Alpine.Optimizer, vi::MOI.VariableIndex)
return 1 <= vi.value <= model.num_var_orig
end

function _get_bound_set(model::Alpine.Optimizer, vi::MOI.VariableIndex)
if !MOI.is_valid(model, vi)
throw(MOI.InvalidIndex(vi))
end
return _bound_set(model.l_var[vi.value], model.u_var[vi.value])
end

function MOI.is_valid(model::Alpine.Optimizer, ci::MOI.ConstraintIndex{MOI.VariableIndex,S}) where {S<:SCALAR_SET}
set = _get_bound_set(model, MOI.VariableIndex(ci.value))
return set isa S
end

function MOI.get(model::Alpine.Optimizer, ::MOI.ConstraintSet, ci::MOI.ConstraintIndex{MOI.VariableIndex,S}) where {S<:SCALAR_SET}
if !MOI.is_valid(o, ci)
throw(MOI.InvalidIndex(ci))
end
return _get_bound_set(model, MOI.VariableIndex(ci.value))
end


# Taken from MatrixOptInterface.jl
@enum ConstraintSense EQUAL_TO GREATER_THAN LESS_THAN INTERVAL
_sense(::Type{<:MOI.EqualTo}) = EQUAL_TO
Expand Down
4 changes: 0 additions & 4 deletions src/main_algorithm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,6 @@ function load!(m::Optimizer)
# Populate data to create the bounding MIP model
Alp.recategorize_var(m) # Initial round of variable re-categorization

:Int in m.var_type_orig && error(
"Alpine does not support MINLPs with generic integer (non-binary) variables yet!",
)

# Solver-dependent detection
Alp._fetch_mip_solver_identifier(m)
Alp._fetch_nlp_solver_identifier(m)
Expand Down
22 changes: 18 additions & 4 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,22 @@ end

# Perform Tests
@testset "Alpine tests" begin
include(joinpath(@__DIR__, "test_solver.jl"))
include(joinpath(@__DIR__, "test_expression.jl"))
include(joinpath(@__DIR__, "test_algorithm.jl"))
include(joinpath(@__DIR__, "test_utility.jl"))
@testset "Test integer variables" begin
test_solver = optimizer_with_attributes(
Alpine.Optimizer,
"nlp_solver" => IPOPT,
"mip_solver" => HIGHS,
"minlp_solver" => JUNIPER,
)
m = milp(solver = test_solver)
JuMP.optimize!(m)

@test termination_status(m) == MOI.OPTIMAL
@test isapprox(objective_value(m), 0; atol = 1e-4)
@test MOI.get(m, Alpine.NumberOfIterations()) == 0
end
# include(joinpath(@__DIR__, "test_solver.jl"))
# include(joinpath(@__DIR__, "test_expression.jl"))
# include(joinpath(@__DIR__, "test_algorithm.jl"))
# include(joinpath(@__DIR__, "test_utility.jl"))
end
6 changes: 5 additions & 1 deletion test/test_algorithm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1052,5 +1052,9 @@ end
"minlp_solver" => JUNIPER,
)
m = milp(solver = test_solver)
@test_throws "Alpine does not support MINLPs with generic integer (non-binary) variables yet!" JuMP.optimize!(m)
JuMP.optimize!(m)

@test termination_status(m) == MOI.OPTIMAL
@test isapprox(objective_value(m), 0; atol = 1e-4)
@test MOI.get(m, Alpine.NumberOfIterations()) == 0
end

0 comments on commit e7c72c4

Please sign in to comment.