jump-dev/Dualization.jl

add constrained variables

guilhermebodin opened this issue · 7 comments

add constrained variables

This is preventing Dualization to be used to write SDPA files as currently SDPA files do not support affine equalities (because of jump-dev/MathOptInterface.jl#852).

julia> sdpa_model = MOI.FileFormats.Model(filename = "LR_export_cons.sdpa")
A SemiDefinite Programming Algorithm Format (SDPA) model

julia> using Dualization

julia> dual_model = DualOptimizer(MOI.Utilities.MockOptimizer(sdpa_model))
DualOptimizer{Float64,MOIB.LazyBridgeOptimizer{MOIU.CachingOptimizer{MOIU.MockOptimizer{MOI.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}}

julia> model = Model();

julia> @variable(model, X[1:2, 1:2], PSD)
2×2 LinearAlgebra.Symmetric{VariableRef,Array{VariableRef,2}}:
 X[1,1]  X[1,2]
 X[1,2]  X[2,2]

julia> @constraint(model, X[1,1] == 1)
X[1,1] = 1.0

julia> @objective(model, Min, X[1,1] + X[2,2])
X[1,1] + X[2,2]

julia> MOI.copy_to(dual_model, JuMP.backend(model))
ERROR: MathOptInterface.UnsupportedConstraint{MathOptInterface.ScalarAffineFunction{Float64},MathOptInterface.EqualTo{Float64}}: `MathOptInterface.ScalarAffineFunction{Float64}`-in-`MathOptInterface.EqualTo{Float64}` constraint is not supported by the model.
Stacktrace:
 [1] bridge_type(::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}, ::Type{MathOptInterface.ScalarAffineFunction{Float64}}, ::Type{MathOptInterface.EqualTo{Float64}}) at /home/blegat/.julia/packages/MathOptInterface/C1XBe/src/Bridges/lazy_bridge_optimizer.jl:330
 [2] concrete_bridge_type(::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}, ::Type{MathOptInterface.ScalarAffineFunction{Float64}}, ::Type{MathOptInterface.EqualTo{Float64}}) at /home/blegat/.julia/packages/MathOptInterface/C1XBe/src/Bridges/Constraint/bridge.jl:120
 [3] add_constraint(::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}, ::MathOptInterface.ScalarAffineFunction{Float64}, ::MathOptInterface.EqualTo{Float64}) at /home/blegat/.julia/packages/MathOptInterface/C1XBe/src/Bridges/bridge_optimizer.jl:1052
 [4] #normalize_and_add_constraint#106(::Bool, ::typeof(MathOptInterface.Utilities.normalize_and_add_constraint), ::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}, ::MathOptInterface.ScalarAffineFunction{Float64}, ::MathOptInterface.EqualTo{Float64}) at /home/blegat/.julia/packages/MathOptInterface/C1XBe/src/Utilities/constraints.jl:17
 [5] normalize_and_add_constraint(::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}, ::MathOptInterface.ScalarAffineFunction{Float64}, ::MathOptInterface.EqualTo{Float64}) at /home/blegat/.julia/packages/MathOptInterface/C1XBe/src/Utilities/constraints.jl:17
 [6] add_dual_equality_constraints(::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}, ::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, ::Dualization.PrimalDualMap{Float64}, ::DualNames, ::Dualization.PrimalObjective{Float64}, ::Array{Tuple{DataType,DataType},1}, ::Array{MathOptInterface.VariableIndex,1}) at /home/blegat/.julia/packages/Dualization/w9SXv/src/dual_equality_constraints.jl:31
 [7] dualize(::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, ::Dualization.DualProblem{Float64,MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}}, ::DualNames, ::Array{MathOptInterface.VariableIndex,1}, ::Bool) at /home/blegat/.julia/packages/Dualization/w9SXv/src/dualize.jl:51
 [8] #dualize#2 at /home/blegat/.julia/packages/Dualization/w9SXv/src/dualize.jl:16 [inlined]
 [9] dualize at /home/blegat/.julia/packages/Dualization/w9SXv/src/dualize.jl:16 [inlined]
 [10] #copy_to#5(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::typeof(MathOptInterface.copy_to), ::DualOptimizer{Float64,MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}}, ::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}) at /home/blegat/.julia/packages/Dualization/w9SXv/src/MOI_wrapper.jl:84
 [11] copy_to(::DualOptimizer{Float64,MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Utilities.MockOptimizer{MathOptInterface.FileFormats.SDPA.Model{Float64}},Dualization.DualizableModel{Float64}}}}, ::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}) at /home/blegat/.julia/packages/Dualization/w9SXv/src/MOI_wrapper.jl:84
 [12] top-level scope at REPL[24]:1

@blegat Would it still be useful to solve this issue?

Yes, more than even with MOI v0.9.15 I made the sorting functions easily accessible from Utilities/copy.jl precisely for Dualization

julia> sdpa_model = MOI.FileFormats.Model(filename = "LR_export_cons.sdpa")
A SemiDefinite Programming Algorithm Format (SDPA) model

julia> dual_model = DualOptimizer(MOI.Utilities.MockOptimizer(sdpa_model))
DualOptimizer{Float64,MOIB.LazyBridgeOptimizer{MOIU.CachingOptimizer{MOIU.MockOptimizer{MOI.FileFormats.SDPA.Model{Float64}},MOIU.UniversalFallback{Dualization.DualizableModel{Float64}}}}}

julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.

julia> @variable(model, X[1:2, 1:2], PSD)
2×2 LinearAlgebra.Symmetric{VariableRef,Array{VariableRef,2}}:
 X[1,1]  X[1,2]
 X[1,2]  X[2,2]

julia> @constraint(model, X[1,1] == 1)
X[1,1] = 1.0

julia> @objective(model, Min, X[1,1] + X[2,2])
X[1,1] + X[2,2]

julia> MOI.copy_to(dual_model, JuMP.backend(model))
MathOptInterface.Utilities.IndexMap with 5 entries:
  VariableIndex(2)                                                       => VariableIndex(2)
  VariableIndex(3)                                                       => VariableIndex(3)
  VariableIndex(1)                                                       => VariableIndex(1)
  ConstraintIndex{VectorOfVariables,PositiveSemidefiniteConeTriangle}(1) => ConstraintIndex{VectorOfVariables,PositiveSemidefiniteConeTriangle}(1)
  ConstraintIndex{ScalarAffineFunction{Float64},EqualTo{Float64}}(2)     => ConstraintIndex{ScalarAffineFunction{Float64},EqualTo{Float64}}(2)

It is working on master

@blegat can I close this?

Dualization still does not consider constrained variables, does it?
All variables are considered free hence the corresponding dual constraints are all equalities

It does not, I got the point 👍