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
Add SOCtoQuad bridge #478
Closed
Closed
Add SOCtoQuad bridge #478
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
""" | ||
SOCtoQuadBridge{T} | ||
|
||
Constraints of the form `VectorOfVariables`-in-`SecondOrderCone` (resp. | ||
`VectorAffineFunction`-in-`SecondOrderCone`) can be transformed into a | ||
`ScalarQuadraticFunction`-in-`GreaterThan` and a | ||
`SingleVariable`-in-`GreaterThan` (resp. | ||
`ScalarAffineFunction`-in-`SecondOrderCone`). Indeed, the definition of the | ||
second-order cone | ||
```math | ||
t \\ge || x ||_2 \\} | ||
``` | ||
is equivalent to | ||
```math | ||
\\sum x_i^2 \\le t^2 | ||
``` | ||
with ``t \\ge 0``. | ||
""" | ||
struct SOCtoQuadBridge{T, F, G} <: AbstractBridge | ||
quad::CI{F, MOI.GreaterThan{T}} | ||
t_nonneg::CI{G, MOI.GreaterThan{T}} | ||
end | ||
function SOCtoQuadBridge{T, F, G}(model::MOI.ModelLike, | ||
f::MOI.AbstractVectorFunction, | ||
s::MOI.SecondOrderCone) where {T, F, G} | ||
d = s.dimension | ||
f_scalars = MOIU.eachscalar(f) | ||
t = f_scalars[1] | ||
t_nonneg = MOIU.add_scalar_constraint(model, t, MOI.GreaterThan(zero(T))) | ||
quad_f = MOIU.operate(*, T, t, t) | ||
for i in 2:d | ||
x = f_scalars[i] | ||
quad_f = MOIU.operate!(-, T, quad_f, MOIU.operate(*, T, x, x)) | ||
end | ||
quad = MOIU.add_scalar_constraint(model, quad_f, MOI.GreaterThan(zero(T))) | ||
return SOCtoQuadBridge{T, F, G}(quad, t_nonneg) | ||
end | ||
|
||
function MOI.supportsconstraint(::Type{SOCtoQuadBridge{T}}, | ||
::Type{<:MOI.AbstractVectorFunction}, | ||
::Type{MOI.SecondOrderCone}) where T | ||
return true | ||
end | ||
function addedconstrainttypes(::Type{SOCtoQuadBridge{T, F, G}}) where {T, F, G} | ||
list = [(F, MOI.GreaterThan{T})] | ||
if F != G | ||
push!(list, (G, MOI.GreaterThan{T})) | ||
end | ||
return list | ||
end | ||
function concrete_bridge_type(::Type{<:SOCtoQuadBridge{T}}, | ||
H::Type{<:MOI.AbstractVectorFunction}, | ||
::Type{MOI.SecondOrderCone}) where T | ||
G = MOIU.scalar_type(H) | ||
Q = MOIU.promote_operation(*, T, G, G) | ||
F = MOIU.promote_operation(-, T, Q, Q) | ||
return SOCtoQuadBridge{T, F, G} | ||
end | ||
|
||
# Attributes, Bridge acting as an model | ||
function MOI.get(b::SOCtoQuadBridge{T, F, G}, | ||
::MOI.NumberOfConstraints{H, MOI.GreaterThan{T}}) where {T, F, G, H} | ||
return (F == H) + (G == H) | ||
end | ||
function MOI.get(b::SOCtoQuadBridge{T, F, G}, | ||
::MOI.ListOfConstraintIndices{H, MOI.GreaterThan{T}}) where {T, F, G, H} | ||
list = CI{H, MOI.GreaterThan{T}}[] | ||
if F == H | ||
push!(list, b.quad) | ||
end | ||
if G == H | ||
push!(list, b.t_nonneg) | ||
end | ||
return list | ||
end | ||
|
||
# References | ||
function MOI.delete!(model::MOI.ModelLike, bridge::SOCtoQuadBridge) | ||
MOI.delete!(model, bridge.t_nonneg) | ||
MOI.delete!(model, bridge.quad) | ||
end | ||
|
||
need_constraint_primal_fallback(::Type{<:SOCtoQuadBridge}) = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This transformation is recognized by Gurobi/Cplex/Xpress(?) only when
f
is aVectorOfVariables
. They can't handle general affine expressions. That creates a tricky situation because we don't have a way to indicate this restriction in MOI afaik, so I'm questioning if bridges are the right place for this transformation to happen. Maybe the solvers need to supportVectorOfVariables
-in-SecondOrderCone
and then let a bridge handle only the transformation fromVectorAffineFunction
-in-SecondOrderCone
toVectorOfVariables
-in-SecondOrderCone
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They also support x^T Q x +q^T x <= b apparently: http://www.gurobi.com/documentation/8.0/refman/constraints.html#subsubsection:QuadraticConstraints
so if it is a VectorAffineFunction in SOC, it will be transformed into
x^T Q x +q^T x <= b
withQ
PSD an Gurobi will also support it, won't it ?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bridge does not generate a constraint of the form x^T Q x +q^T x <= b where Q is PSD (there's one negative eigenvalue).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, good point. This bridge could create a vector of variables and constraint them to be equal to the affexpr and then use these auxiliary variables to create the quadratic function. This would not only make sense for Gurobi as taking the square of complicated affine expression may not result in a very simple quadratic function so it might be the right idea anyway.
Would that work ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That works for Gurobi et al, but I think there's a larger design issue. Ipopt supports convex and non-convex quadratic constraints but not SOC constraints (there's no special detection for x^T x <= t^2). It this bridge is applied, Ipopt will treat the constraint as a nonconvex quadratic constraint without any guarantees of global optimality. Unless there are additional properties of this transformation that imply that a KKT point must be globally optimal (even though the problem is nonconvex), this means that the user could write down a convex problem using SOC and get a bad answer back from Ipopt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same for CPLEX: https://www.ibm.com/support/knowledgecenter/en/SS9UKU_12.4.0/com.ibm.cplex.zos.help/UsrMan/topics/cont_optim/qcp/18_eg_SOCP.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed about this issue with @mlubin and @ccoffrin. The approach would be to define this bridge in MOI but not add it in
full_bridge_optimizer
so that the user would have to add it manually withJuMP.add_bridge
. By choosing which bridge to add, it would either allowVectorOfVariables
-in-SOC
orVectorAffineFunction
-in-SOC
to add so he is responsible to add the one with which the optimizer works.IMO the optimizer could also simply apply the bridge automatically by itself with a
SingleBridgeOptimizer
. Choosing to build the API on top of quadratic functions instead of SOC constraints was a bad design choice and this is the reason this bridge seems weird because it destroys a structure that the optimizers try to recover afterwards.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the three solvers support SOC´s as special quadratic constraints, the bridge could be very useful. Given Ipopt's problem, we could have it non-default, and add a note about the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joaquimg IMO the right solution for this is for Gurobi/Xpress/CPLEX to explicitly support VoV/VAF-in-SOC in their interfaces. We have no other way to know if a solver secretly supports SOC through quadratic constraints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding this point. As I understand the theory, it does not matter in what form a convex constraint is given to a IPM solver. The KKT convergence guarantees will be the same; so I don't think this a major issue for the case of targeting NLP solvers.