Skip to content

Conversation

@odow
Copy link
Member

@odow odow commented Jun 9, 2022

Closes #1777

With @blegat's example, the state is now EMPTY_OPTIMIZER, and the set is <= 2.0 as desired.

julia> using MathOptInterface

julia> const MOI = MathOptInterface
MathOptInterface

julia> MOI.Utilities.@model(
           NoFreeVariablesModel,
           (),
           (MOI.LessThan,),
           (MOI.Nonnegatives,),
           (),
           (),
           (MOI.ScalarAffineFunction,),
           (MOI.VectorOfVariables,),
           ()
       )
MathOptInterface.Utilities.GenericModel{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, NoFreeVariablesModelFunctionConstraints{T}} where T

julia> function MOI.supports_constraint(
           ::NoFreeVariablesModel{T},
           ::Type{MOI.VectorOfVariables},
           ::Type{MOI.Reals},
       ) where {T}
           return false
       end

julia> function MOI.supports_add_constrained_variables(
           ::NoFreeVariablesModel,
           ::Type{MOI.Nonnegatives},
       )
           return true
       end

julia> MOI.supports_add_constrained_variables(::NoFreeVariablesModel, ::Type{MOI.Reals}) = false

julia> function MOI.get(model::NoFreeVariablesModel, attr::MOI.ConstraintFunction, ci::MOI.ConstraintIndex)
           return MOI.get_fallback(model, attr, ci)
       end

julia> function bug()
           inner = NoFreeVariablesModel{Float64}()
           bridged = MOI.Bridges.full_bridge_optimizer(inner, Float64)
           model = MOI.Utilities.CachingOptimizer(
               MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
               bridged,
           )
           x = MOI.add_variable(model)
           c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(1.0))
           MOI.Utilities.attach_optimizer(model)
           MOI.set(model, MOI.ConstraintSet(), c, MOI.LessThan(2.0))
           return model
           end
bug (generic function with 1 method)

julia> bug()
MOIU.CachingOptimizer{MOIB.LazyBridgeOptimizer{MOIU.GenericModel{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, NoFreeVariablesModelFunctionConstraints{Float64}}}, MOIU.UniversalFallback{MOIU.Model{Float64}}}
in state EMPTY_OPTIMIZER
in mode AUTOMATIC
with model cache MOIU.UniversalFallback{MOIU.Model{Float64}}
  fallback for MOIU.Model{Float64}
with optimizer MOIB.LazyBridgeOptimizer{MOIU.GenericModel{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, NoFreeVariablesModelFunctionConstraints{Float64}}}
  with 0 variable bridges
  with 0 constraint bridges
  with 0 objective bridges
  with inner model MOIU.GenericModel{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, NoFreeVariablesModelFunctionConstraints{Float64}}

julia> print(bug())
Feasibility

Subject to:

ScalarAffineFunction{Float64}-in-LessThan{Float64}
 0.0 + 1.0 v[1] <= 2.0

where previously

julia> bug()
ERROR: ArgumentError: MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, NoFreeVariablesModelFunctionConstraints{Float64}} does not support getting the attribute MathOptInterface.ConstraintFunction().
Stacktrace:
 [1] get_fallback(model::MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, NoFreeVariablesModelFunctionConstraints{Float64}}, attr::MathOptInterface.ConstraintFunction, #unused#::MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}})
   @ MathOptInterface ~/.julia/packages/MathOptInterface/RuRWI/src/attributes.jl:367
 [2] get(model::MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, NoFreeVariablesModelFunctionConstraints{Float64}}, attr::MathOptInterface.ConstraintFunction, ci::MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}})
   @ Main ./REPL[9]:2
 [3] get(b::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, NoFreeVariablesModelFunctionConstraints{Float64}}}, attr::MathOptInterface.ConstraintFunction, ci::MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}})
   @ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/RuRWI/src/Bridges/bridge_optimizer.jl:1222
 [4] set
   @ ~/.julia/packages/MathOptInterface/RuRWI/src/Bridges/bridge_optimizer.jl:1262 [inlined]
 [5] _replace_constraint_function_or_set(m::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, NoFreeVariablesModelFunctionConstraints{Float64}}}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, attr::MathOptInterface.ConstraintSet, cindex::MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}}, replacement::MathOptInterface.LessThan{Float64})
   @ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/RuRWI/src/Utilities/cachingoptimizer.jl:595
 [6] set
   @ ~/.julia/packages/MathOptInterface/RuRWI/src/Utilities/cachingoptimizer.jl:627 [inlined]
 [7] bug()
   @ Main ./REPL[10]:11
 [8] top-level scope
   @ REPL[11]:1

Copy link
Member

@blegat blegat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Throw NotAllowedError in get_fallback

3 participants