Reputation: 25
So I want to add a binary variable z
where z[i, j] = 1
when the distance between i
and j
are less than or equal to 150 and z[i, j] = 0
otherwise. I have a list c
where each c[i][j]
represents the distance between i
and j
. I certainly can't set up z
as an ordinary binary variable below:
y = m.addVars(I, J, vtype=GRB.BINARY, name="assign")
And I want to add constraints:
# One day mailing
m.addConstrs(
z[i,j] <= y[i,j] for i in I for j in J,
"Serve")
# Coverage Constraint
m.addConstr(
quicksum(h[i] * z[i, j] for i in I for j in J) <=
0.9 * quicksum(h[i] * y[i, j] for i in I for j in J),
"Cover")
where h
is a list with integers. How do I set up z
?
Upvotes: 1
Views: 1946
Reputation: 460
First you need to add z
as a binary variable:
z = m.addVars(I, J, vtype=GRB.BINARY, name="z")
Then you need constraints to ensure that z[i, j] = 1
if and only if c[i, j] <= 150
.
One way to do this is by using indicator constraints:
z = 1 -> c <= 150
z = 0 -> c >= 150
This is equivalent to
c > 150 -> z = 0
c < 150 -> z = 1
You add these as follows:
m.addConstrs((z[i, j] == 1) >> (c[i][j] <= 150) for i in I for j in J)
m.addConstrs((z[i, j] == 0) >> (c[i][j] >= 150) for i in I for j in J)
You can also model this yourself explicitly:
If you have upper and lower bounds M
and m
on the value of c[i][j] - 150
(i.e., M >= c[i][j] - 150 >= m
for all i, j
), you can use the following constraints:
M * (1-z) >= c - 150
m * z <= c - 150
If c > 150
, the right-hand-sides of both inequalities will be positive. The first one then forces 1 - z = 1
and hence z = 0
. The second inequality will trivially be satisfied.
If c < 150
, the right-hand-sides are negative. The first inequality becomes trivial while the second one forces z = 1
.
For M
the maximum entry in c
will do, for m
you can choose -150
if all c[i][j]
are non-negative.
You add these constraints as follows:
m.addConstrs( M * (1 - z[i, j]) >= c[i][j] - 150 for i in I for j in J )
m.addConstrs( m * z[i,j] <= c[i][j] - 150 for i in I for j in J )
Note that I neglected the case where c = 150
. This is because for floating point numbers equalities are always only considered to be satisfied within tolerances and hence there is no easy way to distinguish between strict and non-strict inequalities. You can approximate this with an epsilon, e.g.:
z = 0 -> c >= 150 + epsilon
Upvotes: 2