1

I have an array which holds a linear expression in terms of decision variable. Let's say decision variables take values such that the array = [1.7 , 0.3, 0]. Now what I want is the following :

1) If any of the values from the above array is > 0.5, then decision variables : y1 (binary) = 1, else 0. so y1 should turn out to be [1, 0, 0]

2) If any of the values from the above array is > 0.5, then decision variables : y2 (real-valued) = the value, else 0. Hence y2 = [1.7, 0, 0]

3) If any value in the array is > 0 and <= 0.5, then decision variables : y3 (binary) = 1, else 0. Hence y3 = [0, 1, 0]

I know that big M formulation can help, but I am struggling to find a way. Can somebody please help me with the formulation of above 3 points. I am working on pyomo and gurobi for programming the problem.

  • 4
    All you need is: *indicator variables* (1 + 3) and *linearization of binary-continuous products* (indicator multiplied with original variable) (2): see [pdf: 7.1 +7.7](https://download.aimms.com/aimms/download/manuals/AIMMS3OM_IntegerProgrammingTricks.pdf). – sascha Nov 28 '19 at 13:20
  • Thank you ! pdf that you shared is super helpful!! – Bhartendu Awasthi Dec 16 '19 at 13:04

1 Answers1

0

Following pdf pointed by sascha, below is the formulation of the 3 constraints.

import gurobipy as gp
from gurobipy import GRB

arr = [1.7 , 0.3, 0]

model = gp.Model()

x = model.addVars(range(len(arr)), lb = arr, ub = arr)

y1 = model.addVars(range(len(arr)), vtype = GRB.BINARY)
y2 = model.addVars(range(len(arr)), vtype = GRB.CONTINUOUS)
y3 = model.addVars(range(len(arr)), vtype = GRB.BINARY)

e = 0.0001

# constraint 1:
for i in range(len(arr)):
    model.addGenConstrIndicator(y1[i], 0, x[i] <= 0.5 - e)
    model.addGenConstrIndicator(y1[i], 1, x[i] >= 0.5 + e)
    
# constraint 2:
u = max(arr) + 1 # upper bound on x
for i in range(len(arr)):
    model.addConstr(y2[i] <= u * y1[i])
    model.addConstr(y2[i] <= x[i])
    model.addConstr(y2[i] >= x[i] - u * (1 - y1[i]))
    
    
# constraint 3:
big_M = 100

y3 = model.addVars(range(len(arr)), vtype = GRB.BINARY)
temp = model.addVars(range(len(arr)), vtype = GRB.BINARY)

for i in range(len(arr)):

    model.addGenConstrIndicator(y3[i], 1, x[i] >= e)
    model.addGenConstrIndicator(y3[i], 1, x[i] <= 0.5)
    
    model.addGenConstrIndicator(y3[i], 0, x[i] <= (big_M * temp[i]))
    model.addGenConstrIndicator(y3[i], 0, x[i] >= 0.5 + e - big_M * (1 - temp[i]))
    
model.optimize()

post optimisation:
y1 = [1, 0, 0]
y2 = [1.7, 0, 0]
y3 = [0, 1, 0]