JuMP conditional constraint

One alternative to the “big-M” is to use SOS1 constraints which are supported by Cbc.
In fact, you can even use indicator constraints are they are automatically bridged to SOS1 constraints.
With the following:

using JuMP, Cbc
model = Model(Cbc.Optimizer)
set_silent(model)
T = 3
@variable(model, x[1:T]>=0, Int)
next(t, i) = x[((t - 1 + i) % T) + 1]
@constraint(model, xx1[t=1:T], x[t] => {next(t, 1) + next(t, 2) == 0})
optimize!(model)
@show value.(x)
MOI.Bridges.print_graph(backend(model).optimizer)

I get

value.(x) = [0.0, 0.0, 0.0]
Bridge graph with 3 variable nodes, 7 constraint nodes and 0 objective nodes.
 [1] constrained variables in `MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE,MOI.EqualTo{Float64}}` are supported (distance 2) by adding free variables and then constrain them, see (2).
 [2] constrained variables in `MOI.Nonpositives` are supported (distance 2) by adding free variables and then constrain them, see (6).
 [3] constrained variables in `MOI.Nonnegatives` are supported (distance 2) by adding free variables and then constrain them, see (7).
 (1) `MOI.VectorAffineFunction{Float64}`-in-`MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE,MOI.EqualTo{Float64}}` constraints are bridged (distance 1) by MOIB.Constraint.IndicatorSOS1Bridge{Float64,MOI.EqualTo{Float64},Nothing}.
 (2) `MOI.VectorOfVariables`-in-`MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE,MOI.EqualTo{Float64}}` constraints are bridged (distance 1) by MOIB.Constraint.IndicatorSOS1Bridge{Float64,MOI.EqualTo{Float64},Nothing}.
 (3) `MOI.VectorAffineFunction{Float64}`-in-`MOI.Zeros` constraints are bridged (distance 1) by MOIB.Constraint.ScalarizeBridge{Float64,MOI.ScalarAffineFunction{Float64},MOI.EqualTo{Float64}}.
 (4) `MOI.VectorAffineFunction{Float64}`-in-`MOI.Nonnegatives` constraints are bridged (distance 1) by MOIB.Constraint.ScalarizeBridge{Float64,MOI.ScalarAffineFunction{Float64},MOI.GreaterThan{Float64}}.
 (5) `MOI.VectorAffineFunction{Float64}`-in-`MOI.Nonpositives` constraints are bridged (distance 1) by MOIB.Constraint.ScalarizeBridge{Float64,MOI.ScalarAffineFunction{Float64},MOI.LessThan{Float64}}.
 (6) `MOI.VectorOfVariables`-in-`MOI.Nonpositives` constraints are bridged (distance 1) by MOIB.Constraint.ScalarizeBridge{Float64,MOI.SingleVariable,MOI.LessThan{Float64}}.
 (7) `MOI.VectorOfVariables`-in-`MOI.Nonnegatives` constraints are bridged (distance 1) by MOIB.Constraint.ScalarizeBridge{Float64,MOI.SingleVariable,MOI.GreaterThan{Float64}}.

You see in (1) that the indicator constraint is bridged into SOS1 constraints.

5 Likes