diff --git a/src/MathOptLazy.jl b/src/MathOptLazy.jl index ca03e1e..8964b4d 100644 --- a/src/MathOptLazy.jl +++ b/src/MathOptLazy.jl @@ -631,6 +631,30 @@ MOI.get(model::Optimizer, ::MOI.SimplexIterations) = model.simplex_iterations MOI.get(model::Optimizer, ::MOI.SolveTimeSec) = model.solve_time_sec +### MathOptLazy.NumberOfConstraintsActive + +""" + NumberOfConstraintsActive{F,LazyScalarSet{S}}() where { + F<:MOI.AbstractScalarFunction, + S<:MOI.AbstractScalarSet, + } + +Return a count of the number of constraints that are active in the subproblem. +""" +struct NumberOfConstraintsActive{ + F<:MOI.AbstractScalarFunction, + S<:LazyScalarSet{<:MOI.AbstractScalarSet}, +} <: MOI.AbstractModelAttribute end + +MOI.is_set_by_optimize(::NumberOfConstraintsActive) = true + +function MOI.get( + model::Optimizer, + ::NumberOfConstraintsActive{F,LazyScalarSet{S}}, +) where {F<:MOI.AbstractScalarFunction,S<:MOI.AbstractScalarSet} + return count(==(_kLAZY_CONSTRAINT_ACTIVE), _data(model, F, S).status) +end + ### MOI.optimize! function _try_get(model::Optimizer, attr::MOI.AbstractModelAttribute, default) diff --git a/test/runtests.jl b/test/runtests.jl index 6e45b69..5dc46ff 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -43,6 +43,9 @@ function test_jump_cached_knapsack() @test termination_status(model) == OPTIMAL @test primal_status(model) == FEASIBLE_POINT @test all(<=(1 + 1e-6), value(x)) + F = MOI.ScalarAffineFunction{Float64} + S = MathOptLazy.LazyScalarSet{MOI.LessThan{Float64}} + @test get_attribute(model, MathOptLazy.NumberOfConstraintsActive{F,S}()) > 0 return end @@ -54,10 +57,15 @@ function test_jump_direct_knapsack() @constraint(model, [i in 1:N], x[i] <= 1, MathOptLazy.Lazy()) @constraint(model, sum(abs(cos(i)) * x[i] for i in 1:N) <= 0.1 * N) @objective(model, Max, sum(abs(sin(i)) * x[i] for i in 1:N)) + F = MOI.ScalarAffineFunction{Float64} + S = MathOptLazy.LazyScalarSet{MOI.LessThan{Float64}} + attr = MathOptLazy.NumberOfConstraintsActive{F,S}() + @test MOI.get(backend(model), attr) == 0 optimize!(model) @test termination_status(model) == OPTIMAL @test primal_status(model) == FEASIBLE_POINT @test all(<=(1 + 1e-6), value(x)) + @test get_attribute(model, attr) > 0 return end