Добавление бинарной переменной в Gurobi - PullRequest
0 голосов
/ 17 марта 2019

Поэтому я хочу добавить двоичную переменную z, где z[i, j] = 1, когда расстояние между i и j меньше или равно 150 и z[i, j] = 0 в противном случае. У меня есть список c, где каждый c[i][j] представляет расстояние между i и j. Я определенно не могу установить z как обычную двоичную переменную ниже:

y = m.addVars(I, J, vtype=GRB.BINARY, name="assign")

И я хочу добавить ограничения:

# 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")

где h - список с целыми числами. Как мне настроить z?

1 Ответ

0 голосов
/ 26 марта 2019

Сначала вам нужно добавить z в виде двоичной переменной:

z = m.addVars(I, J, vtype=GRB.BINARY, name="z")

Затем вам понадобятся ограничения, чтобы гарантировать, что z[i, j] = 1 тогда и только тогда, когда c[i, j] <= 150.Один из способов сделать это - использовать ограничения индикатора:

z = 1 -> c <= 150
z = 0 -> c >= 150

Это эквивалентно

c > 150 -> z = 0
c < 150 -> z = 1

Вы можете добавить их следующим образом:

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)

Вы можететакже смоделируйте это непосредственно: если у вас есть верхняя и нижняя границы M и m для значения c[i][j] - 150 (то есть, M >= c[i][j] - 150 >= m для всех i, j), вы можете использовать следующие ограничения:

M * (1-z) >= c - 150
m * z <= c - 150

Если c > 150, правые части обоих неравенств будут положительными.Первый затем заставляет 1 - z = 1 и, следовательно, z = 0.Второе неравенство будет тривиально выполнено.

Если c < 150, правые части отрицательны.Первое неравенство становится тривиальным, в то время как второе вынуждает z = 1.

. Для M будет использоваться максимальная запись в c, для m вы можете выбрать -150, если все c[i][j]неотрицательно.

Вы добавляете эти ограничения следующим образом:

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 )

Обратите внимание, что я пренебрег случаем, когда c = 150.Это связано с тем, что для чисел с плавающей точкой равенства всегда считаются выполненными только в пределах допусков и, следовательно, нет простого способа отличить строгие и нестрогие неравенства.Вы можете аппроксимировать это эпсилоном, например:

z = 0 -> c >= 150 + epsilon
...