-
Notifications
You must be signed in to change notification settings - Fork 92
Why is Bridges.Variable.ZerosBridge needed? #1767
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
It makes the formulation simpler. For CSDP, otherwise, it would need to add a free variables, bridged into 2 variables and then add a linear constraint. It makes sense to disable it when running the MOI.Test but in practice it is useful. |
Which formulation? |
How common is it to write If it's okay for most solvers to remove, why not make it opt-in for CSDP? |
The reformulation is always what the user would expect. Without this bridge, the problem would silently be bridged to a non-optimal formulation, I don't like that. The bridges that are currently opt-out leads to |
Again. Which problem? |
I mean the model. Consider the addition of a variable constrained on creation to be in
We could check if 2. indeed holds. Otherwise, we should check if we don't need to introduce bridge costs to make this happen but if 2. holds I don't see any issue.
I don't like the idea of using a larger formulation by default. |
I meant a mathematical formulation of an optimization problem in which this bridge is useful. I don't see what this bridge has to do with Are people really writing models with Edit: I think we need to talk over the phone about this. |
Okay, for some reason which I don't fully understand, using an outer caching optimizer changes the bridges that are applied: julia> using ECOS
julia> const MOI = ECOS.MOI
MathOptInterface
julia> model = MOI.instantiate(ECOS.Optimizer; with_bridge_type = Float64)
MOIB.LazyBridgeOptimizer{MOIU.CachingOptimizer{ECOS.Optimizer, MOIU.UniversalFallback{MOIU.Model{Float64}}}}
with 0 variable bridges
with 0 constraint bridges
with 0 objective bridges
with inner model MOIU.CachingOptimizer{ECOS.Optimizer, 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 ECOS.Optimizer
julia> x = MOI.add_variable(model)
MathOptInterface.VariableIndex(1)
julia> c = MOI.add_constraint(model, x, MOI.EqualTo(1.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}}(1)
julia> MOI.optimize!(model)
ECOS 2.0.8 - (C) embotech GmbH, Zurich Switzerland, 2012-15. Web: www.embotech.com/ECOS
It pcost dcost gap pres dres k/t mu step sigma IR | BT
0 +0.000e+00 -0.000e+00 +0e+00 2e-15 0e+00 1e+00 1e+00 --- --- 0 0 - | - -
OPTIMAL (within feastol=2.4e-15, reltol=nan, abstol=0.0e+00).
Runtime: 0.000404 seconds.
julia> MOI.get(model, MOI.ConstraintDual(), c)
-0.0 julia> using ECOS
julia> const MOI = ECOS.MOI
MathOptInterface
julia> model = MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MOI.instantiate(ECOS.Optimizer; with_bridge_type = Float64),
)
MOIU.CachingOptimizer{MOIB.LazyBridgeOptimizer{MOIU.CachingOptimizer{ECOS.Optimizer, MOIU.UniversalFallback{MOIU.Model{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.CachingOptimizer{ECOS.Optimizer, MOIU.UniversalFallback{MOIU.Model{Float64}}}}
with 0 variable bridges
with 0 constraint bridges
with 0 objective bridges
with inner model MOIU.CachingOptimizer{ECOS.Optimizer, 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 ECOS.Optimizer
julia> x = MOI.add_variable(model)
MathOptInterface.VariableIndex(1)
julia> c = MOI.add_constraint(model, x, MOI.EqualTo(1.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}}(1)
julia> MOI.optimize!(model)
julia> MOI.get(model, MOI.ConstraintDual(), c)
ERROR: ArgumentError: Bridge of type `MathOptInterface.Bridges.Variable.ZerosBridge{Float64}` does not support accessing the attribute `MathOptInterface.ConstraintDual(1)`. If you encountered this error unexpectedly, it probably means your model has been reformulated using the bridge, and you are attempting to query an attribute that we haven't implemented yet for this bridge. Please open an issue at https://github.com/jump-dev/MathOptInterface.jl/issues/new and provide a reproducible example explaining what you were trying to do.
Stacktrace:
[1] get(#unused#::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, attr::MathOptInterface.ConstraintDual, bridge::MathOptInterface.Bridges.Variable.ZerosBridge{Float64})
@ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge.jl:85
[2] (::MathOptInterface.Bridges.var"#3#4"{typeof(MathOptInterface.get), MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.ConstraintDual, Tuple{}})(bridge::MathOptInterface.Bridges.Variable.ZerosBridge{Float64})
@ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:308
[3] (::MathOptInterface.Bridges.Variable.var"#23#24"{MathOptInterface.Bridges.Variable.Map, MathOptInterface.Bridges.var"#3#4"{typeof(MathOptInterface.get), MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.ConstraintDual, Tuple{}}, Int64})()
@ MathOptInterface.Bridges.Variable ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/Variable/map.jl:476
[4] call_in_context(map::MathOptInterface.Bridges.Variable.Map, bridge_index::Int64, f::MathOptInterface.Bridges.Variable.var"#23#24"{MathOptInterface.Bridges.Variable.Map, MathOptInterface.Bridges.var"#3#4"{typeof(MathOptInterface.get), MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.ConstraintDual, Tuple{}}, Int64})
@ MathOptInterface.Bridges.Variable ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/Variable/map.jl:461
[5] call_in_context
@ ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/Variable/map.jl:476 [inlined]
[6] call_in_context
@ ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:269 [inlined]
[7] call_in_context(b::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, ci::MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Zeros}, f::MathOptInterface.Bridges.var"#3#4"{typeof(MathOptInterface.get), MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.ConstraintDual, Tuple{}})
@ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:288
[8] call_in_context
@ ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:305 [inlined]
[9] get(b::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, attr::MathOptInterface.ConstraintDual, ci::MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Zeros})
@ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:1295
[10] get(model::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, attr::MathOptInterface.ConstraintDual, bridge::MathOptInterface.Bridges.Variable.VectorizeBridge{Float64, MathOptInterface.Zeros})
@ MathOptInterface.Bridges.Variable ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/Variable/vectorize.jl:127
[11] (::MathOptInterface.Bridges.var"#3#4"{typeof(MathOptInterface.get), MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.ConstraintDual, Tuple{}})(bridge::MathOptInterface.Bridges.Variable.VectorizeBridge{Float64, MathOptInterface.Zeros})
@ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:308
[12] (::MathOptInterface.Bridges.Variable.var"#23#24"{MathOptInterface.Bridges.Variable.Map, MathOptInterface.Bridges.var"#3#4"{typeof(MathOptInterface.get), MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.ConstraintDual, Tuple{}}, Int64})()
@ MathOptInterface.Bridges.Variable ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/Variable/map.jl:476
[13] call_in_context(map::MathOptInterface.Bridges.Variable.Map, bridge_index::Int64, f::MathOptInterface.Bridges.Variable.var"#23#24"{MathOptInterface.Bridges.Variable.Map, MathOptInterface.Bridges.var"#3#4"{typeof(MathOptInterface.get), MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.ConstraintDual, Tuple{}}, Int64})
@ MathOptInterface.Bridges.Variable ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/Variable/map.jl:461
[14] call_in_context
@ ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/Variable/map.jl:476 [inlined]
[15] call_in_context
@ ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:269 [inlined]
[16] call_in_context
@ ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:288 [inlined]
[17] call_in_context
@ ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:305 [inlined]
[18] get(b::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, attr::MathOptInterface.ConstraintDual, ci::MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}})
@ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/U4enZ/src/Bridges/bridge_optimizer.jl:1295
[19] get(model::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ECOS.Optimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, attr::MathOptInterface.ConstraintDual, index::MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/U4enZ/src/Utilities/cachingoptimizer.jl:873
[20] top-level scope
@ REPL[14]:1 |
In the first case, it goes through the bridge layer as a constraint after creation so variable bridges cannot be applied. In the second case, |
It can also be bridged to
No, that's why I'm talking about |
Yeah I originally thought this was because of our change to |
@blegat and I discussed this offline. There's a few conflicting issues going on:
So the conclusion is to leave it for now. And solvers encountering the duality error should remove the bridge in testing. We can revisit if we get anyone encountering this issue in the wild. |
When a
VectorOfVariables
-in-Zeros
constraint gets added, for example:MathOptInterface.jl/src/Test/test_conic.jl
Lines 298 to 299 in e9b1f4a
It may get bridged by
MathOptInterface.jl/src/Bridges/Variable/zeros.jl
Lines 1 to 17 in e9b1f4a
The lack of dual variables causes problems in ECOS and Clp:
The solution is just to remove the bridge. In what cases is it actually useful? I get that it can make some formulations simpler, but which ones? Why not just add the extra variables?
The text was updated successfully, but these errors were encountered: