JuMP: the other implication for indicator constraints

In JuMP there is some support for indicator constraints. The documentation reads

Indicator constraints consist of a binary variable and a linear constraint. The constraint holds when the binary variable takes the value 1. The constraint may or may not hold when the binary variable takes the value 0. To enforce the constraint x + y <= 1 when the binary variable a is 1, use:

julia> model = Model();

julia> @variable(model, x)
x

julia> @variable(model, y)
y

julia> @variable(model, a, Bin)
a

julia> @constraint(model, a --> {x + y <= 1})
a --> {x + y ≤ 1}

Now, is only one of the two logical implications implemented? Namely, if the binary variable a==1, then the inequality is satisfied enforced, but how about the other logical implications? That is, if the inequality is satisfied, does it imply that the binary variable is 1?

And if not, can it be expressed somehow? The warning in the documentation reads

You cannot use an expression for the left-hand side of an indicator constraint.

which suggests that it is just not allowed to write anything like

julia
{x + y ≤ 1} --> a

There is no support for reversing the direction of the implication.

The main reason is that some solvers have special support for the variable-implies-inequality type of constraint, and they don’t have support for inequality-implies-variable.

I’m not sure if there is an easy way to write the one-sided implication off the top of my head. Someone else might have an idea.

Do you want the reification?

model = Model()
@variable(model, x)
@variable(model, y)
@variable(model, a, Bin)
@constraint(model, a --> {x + y <= 1})
@constraint(model, !a --> {x + y >= 1+1e-6})
1 Like

I am not sure I understand the term reification, an in particular in this context here. But yes, the last two lines in your code, that is

@constraint(model, a --> {x + y <= 1})
@constraint(model, !a --> {x + y >= 1+1e-6})

seem to do the job. So, what are the shortcomings of this solution (besides the epsilon tolerance)?

I know I can always resort to the Big-M technique for both implications. But now I understand that for the forward implication (a=1) \implies (x+y\leq 1) some mixed-integer solvers offer a more straightforward path by switching certain linear constraints on or off. At first I thought that for the backward implication (x+y\leq 1) \implies (a=1), I will have to resort to the Big-M stuff. But the reformulation \neg (a=1) \implies \neg(x+y\leq 1), that is, (a=0) \implies (x+y> 1) seems to offer an elegant trick to avoid the big-M reformulation. I suspect it must have some shortcoming.

I suspect it must have some shortcoming.

The shortcoming is the tolerance.

Reification

MiniZinc uses “reification” to mean “<–>” instead of the one-sided implication: 2.9. FlatZinc and Flattening — The MiniZinc Handbook 2.8.7