# Gurobi: how to add a constraint to make there be only one non-integer value

line1 line2 line3 line4
A 2.3 0 3.1 0
B 0 4 2.2 0
C 1.1 0 0 4.6

Let's say after optimization with certain constraints, my model will generate an optimal production allocation table similar to above. A, B, C are the three product types and the matrix displays the number of hours needed for each production line in order to finish the demand.

I need to add another constraint which allows only one non-integer hour amount for each of the products. what is the easiest way or logic to do this? Please show by model.addVars() and model.addConstrs() if possible.

Update: This is what I wrote according to the answer by Rob:

y = edm.addVars(lines, products, vtype=GRB.INTEGER)
for line in lines:
for product in products:
(
#blocks[line, product] - y[line, product] >= - z[line, product]
y[line, product] - blocks[line, product] <= z[line, product]
),
name = 'constraint 1.1'
)

(
blocks[line, product] - y[line, product] <= z[line, product]
),
name = 'constraint 1.2'
)

(
quicksum(z[line, product] for line in lines) <= 1 for product in products
),
name = 'constraint 2'
)


But my model optimization keeps running and has not given a solution for 2 hours. Any ideas what could be the issue? Thanks

• It might help to add explicit bounds on $y$. Sep 3, 2021 at 13:16

Let $$x_{p,\ell}$$ be the continuous variables in your table. Introduce integer variables $$y_{p,\ell}$$ and binary variables $$z_{p,\ell}$$, and impose linear constraints \begin{align} -z_{p,\ell} \le x_{p,\ell} - y_{p,\ell} &\le z_{p,\ell} &&\text{for all p and \ell} \tag1 \\ \sum_\ell z_{p,\ell} &\le 1 &&\text{for all p} \tag2 \end{align} Constraint $$(1)$$ enforces $$x_{p,\ell} \not= y_{p,\ell} \implies z_{p,\ell} = 1$$. Constraint $$(2)$$ allows this to happen at most once per $$p$$.
If your solver supports indicator constraints, you can replace $$(1)$$ with $$z_{p,\ell} = 0 \implies x_{p,\ell} = y_{p,\ell}$$.