# Using logical constraints with gurobi

**URL:** <https://discourse.julialang.org/t/using-logical-constraints-with-gurobi/106311>\
**Category:** Optimization (Mathematical)\
**Tags:** question, jump, gurobi\
**Created:** [November 16, 2023, 11:05am UTC](https://discourse.julialang.org/t/using-logical-constraints-with-gurobi/106311 "2023-11-16T11:05:18Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![raian](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raian/32/203969_2.png) [@raian](https://discourse.julialang.org/u/raian)\
**Post date:** [November 16, 2023, 11:05am UTC](https://discourse.julialang.org/t/using-logical-constraints-with-gurobi/106311/1 "2023-11-16T11:05:18Z")

</div>

Hi,  
I’m trying to use logical constraints on JuMP, ex:  
x5 = x1 AND x3 AND x4

In the doc of gurobi, there is a function that directly construct this constraint without having to linearize it manually :

model.addGenConstrAnd(x5, [x1, x3, x4], “andconstr”)

Is there an equivalent way when using Gurobi on JuMP ?  
thank you

---

<div class="post-metadata">

**Author:** ![jd-foster](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jd-foster/32/35824_2.png) [@jd-foster](https://discourse.julialang.org/u/jd-foster)\
**Post date:** [November 16, 2023, 11:27am UTC](https://discourse.julialang.org/t/using-logical-constraints-with-gurobi/106311/2 "2023-11-16T11:27:09Z")

</div>

Welcome to the forum!

The general way to do this at the model level is described in the [Mosek Cookbook](https://docs.mosek.com/modeling-cookbook/mio.html#boolean-operators) (it’s just about the maths, not specific to the Mosek solver).

The JuMP model would look like

```julia
using JuMP
import Gurobi

n = 3 # number of "AND" terms

model = Model(Gurobi.Optimizer)
@variable(model, x[1:n], Bin)
@variable(model, z, Bin) # z is x[1] AND ... AND x[n]
@constraint(model, [i=1:n], x[i] >= z)
@constraint(model, z + (n-1) >= sum(x))

```

Test it with:

```julia-repl
julia> @objective(model, Max, sum(x))
julia> optimize!(model)
julia> value.(x)
3-element Vector{Float64}:
 1.0
 1.0
 1.0

julia> value.(z)
1.0

julia> fix(x[3], 0)

julia> value.(x)
3-element Vector{Float64}:
 1.0
 1.0
 0.0

julia> @objective(model, Max, sum(x))
julia> value.(z)
0.0

```

---

<div class="post-metadata">

**Author:** ![hdavid16](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hdavid16/32/11531_2.png) [@hdavid16](https://discourse.julialang.org/u/hdavid16)\
**Post date:** [November 16, 2023, 5:19pm UTC](https://discourse.julialang.org/t/using-logical-constraints-with-gurobi/106311/3 "2023-11-16T17:19:57Z")

</div>

@raian you can also consider using [DisjunctiveProgramming.jl](https://github.com/hdavid16/DisjunctiveProgramming.jl):

```julia
using DisjunctiveProgramming
using Gurobi

model = GDPModel(Gurobi.Optimizer)
@variable(model, x[1:5], Logical)
@constraint(model, x[5] == (x[1] && x[3] && x[4]) := true)
optimize!(model)
print(model)

Feasibility
Subject to
 x[4] - x[5] ≥ 0
 x[3] - x[5] ≥ 0
 -x[1] - x[3] - x[4] + x[5] ≥ -2
 x[1] - x[5] ≥ 0
 x[1] binary
 x[2] binary
 x[3] binary
 x[4] binary
 x[5] binary

```

The way this works is:

- x[1:5] is a vector of `LogicalVariable`
- you can then define logical propositions using Boolean algebra (unicode operators supported too)
- you can then either call `reformulate_model` to transform the logical model into a MIP. Alternately, you can leave all the logical constraints and call `optimize!(model)`, the model will be reformulated in the background by transforming the logical constraints into algebraic constraints with binary variables.

Note, the transformation creates binary variables from the logical variables and adds the 3 algebraic constraints @jd-foster gave above. The extra constraint `x[1] + x[3] + x[4] - x[5] <= 2` forces the reverse implication on `x[5]`. Without it, the constraint being added is `x5 implies x1 AND x3 AND x4` (instead of `x5 iff x1 AND x3 AND x4`).

Note: the code above works on `master`.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [November 16, 2023, 6:57pm UTC](https://discourse.julialang.org/t/using-logical-constraints-with-gurobi/106311/4 "2023-11-16T18:57:35Z")

</div>

Hi @raian,

You can also use Gurobi’s C API for this: [GitHub - jump-dev/Gurobi.jl: Julia interface for Gurobi Optimizer](https://github.com/jump-dev/Gurobi.jl#c-api)

I didn’t test, but something like this should work:

```julia
using JuMP, Gurobi
model = direct_model(Gurobi.Optimizer())
@variable(model, x[1:5])
grb = backend(model)
c_cols = Gurobi.c_column.(grb, index.(x))
GRBaddgenconstrAnd(grb, "andconstr", c_cols[5], 3, c_cols[[1, 3, 4]])

```
