-
Notifications
You must be signed in to change notification settings - Fork 5
Adding (some) conic constraints. #136
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
base: master
Are you sure you want to change the base?
Changes from all commits
78edb39
984a919
3a83a41
e9837dc
0e0d6a5
a471744
6e87fa2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -251,3 +251,45 @@ function reformulate_disjunct_constraint( | |
| reform_con_np = JuMP.build_constraint(error, new_func_np, _MOI.Nonpositives(con.set.dimension)) | ||
| return [reform_con_nn, reform_con_np] | ||
| end | ||
|
|
||
| ################################################################################ | ||
| # BIG-M FOR CONIC CONSTRAINTS | ||
| ################################################################################ | ||
| # Big-M for `func in K`: add slack `M*(1 - y)*d` along a fixed interior | ||
| # direction `d` of the cone, so `func + M*d in K`. | ||
|
|
||
| # SOC: (t, x...) with t >= ||x||. d = e1 = (1, 0, ...); interior since | ||
| # 1 > ||0|| = 0. Bumping t alone makes (t + M) >= ||x|| hold for big M. | ||
| _conic_bigm_direction(set::_MOI.SecondOrderCone) = | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nonblocking — |
||
| [i == 1 ? 1.0 : 0.0 for i in 1:_MOI.dimension(set)] | ||
| # Rotated SOC: (t, u, x...) with 2*t*u >= ||x||^2, t,u >= 0. d = | ||
| # (1,1,0,...); interior since 2*1*1 = 2 > 0. Both t,u must grow so | ||
| # 2(t+M)(u+M) ~ 2*M^2 dominates ||x||^2; bumping one leaves 2*t*0 = 0. | ||
| _conic_bigm_direction(set::_MOI.RotatedSecondOrderCone) = | ||
| [i <= 2 ? 1.0 : 0.0 for i in 1:_MOI.dimension(set)] | ||
| # Exp cone: (x, y, z) with z >= y*exp(x/y), y >= 0. d = (0, 1, 2); | ||
| # interior since 2 > 1*exp(0) = 1. As M grows, exp(x/(y+M)) -> 1 so the | ||
| # RHS ~ y + M ~ M while z grows as 2M; the factor 2 keeps z above it. | ||
| _conic_bigm_direction(::_MOI.ExponentialCone) = [0.0, 1.0, 2.0] | ||
| # Power cone: (x, y, z) with x^a * y^(1-a) >= |z|, x,y >= 0, a the cone | ||
| # exponent. d = (1,1,0); interior since 1^a * 1^(1-a) = 1 > 0. Bumping | ||
| # x,y makes (x+M)^a (y+M)^(1-a) ~ M dominate the fixed |z|; z untouched. | ||
| _conic_bigm_direction(::_MOI.PowerCone) = [1.0, 1.0, 0.0] | ||
|
|
||
| function reformulate_disjunct_constraint( | ||
| model::JuMP.AbstractModel, | ||
| con::JuMP.VectorConstraint{T, S, R}, | ||
| bvref::Union{JuMP.AbstractVariableRef, JuMP.GenericAffExpr}, | ||
| method::BigM | ||
| ) where { | ||
| T <: Union{JuMP.AbstractVariableRef, JuMP.GenericAffExpr}, | ||
| S <: _ConicSets, R | ||
| } | ||
| M = method.value | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nonblocking — |
||
| d = _conic_bigm_direction(con.set) | ||
| new_func = JuMP.@expression(model, [i=1:_MOI.dimension(con.set)], | ||
| con.func[i] + M*(1 - bvref)*d[i] | ||
| ) | ||
| reform_con = JuMP.build_constraint(error, new_func, con.set) | ||
| return [reform_con] | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -207,10 +207,23 @@ function JuMP.build_constraint( | |
| return _DisjunctConstraint(constr, tag.indicator) | ||
| end | ||
|
|
||
| # MOI conic sets handled by the BigM and Hull conic reformulations | ||
| # (Bernal Neira & Grossmann 2021). The affine map A*x - b sits inside | ||
| # the cone; the nonlinearity is carried by the cone itself. | ||
| const _ConicSets = Union{ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nonblocking — Now that |
||
| _MOI.SecondOrderCone, | ||
| _MOI.RotatedSecondOrderCone, | ||
| _MOI.ExponentialCone, | ||
| _MOI.PowerCone, | ||
| } | ||
|
|
||
| # Allows for building DisjunctConstraints for VectorConstraints since these get parsed differently by JuMP (JuMP changes the set to a MOI.AbstractScalarSet) | ||
| for SetType in ( | ||
| JuMP.Nonnegatives, JuMP.Nonpositives, JuMP.Zeros, | ||
| _MOI.Nonnegatives, _MOI.Nonpositives, _MOI.Zeros | ||
| _MOI.Nonnegatives, _MOI.Nonpositives, _MOI.Zeros, | ||
| JuMP.SecondOrderCone, JuMP.RotatedSecondOrderCone, | ||
| _MOI.SecondOrderCone, _MOI.RotatedSecondOrderCone, | ||
| _MOI.ExponentialCone, _MOI.PowerCone | ||
| ) | ||
| @eval begin | ||
| @doc """ | ||
|
|
||
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.
Nonblocking — Two things a user picking
Mfor a cone needs to know that this paragraph does not say:BigMvalueis used as given — no bound-based tightening — so it has to be chosen by the user.[-10, 10],(x, y + M, z + 2M) ∈ ExponentialConestill has violations atM = 30(the slack enters as(y+M)·exp(x/(y+M)), so roughlyM ≳ x + y - z + x²/(2(y+M))is needed), while the SOC direction is safe as soon asM ≥ max‖x‖ - min t. All four directions are valid atM = 100on that grid.One sentence for each is enough here; the same caveat belongs in the
BigMdocstring or the_conic_bigm_directioncomments.