I want to trigger a piecewise linear (PWL) constraint in Gurobi when an indicator variable is true, else the PWL could be violated. Is there a way to achieve this ? I am facing some difficulties when using the addGenConstrIndicator
function in Gurobi.
In Gurobi, I don't think that we can directly state b = 1 => y = f(x)
where b is the indicator variable and f is any general constraint like piecewise linear constraint. But we can achieve the purpose by having another intermediate variable, say, z
and the write the constraint as:
b = 1 => z = y
So you can use z in place of y (y becomes redundant now). Whenever b is true, z = y (PWL constraint enforced), else when b is false then constraint (z = y) could be violated.
Example
import gurobipy as gp
from gurobipy import GRB
model = gp.Model("")
x = model.addVar(vtype = GRB.INTEGER, lb = 0, ub = 10)
y = model.addVar(vtype = GRB.CONTINUOUS, lb = 0, ub = 100)
z = model.addVar(vtype = GRB.CONTINUOUS, lb = 0, ub = 100)
b = model.addVar(vtype = GRB.BINARY)
model.addGenConstrPWL(x, y, [0, 1, 2, 3, 4, 5], [1.5, 0, 3, 5, 7, 2], "myPWLConstr")
model.addGenConstrIndicator(b, 1, z == y)
# artificially making the indicator variable true,
# thus enforcing PWL constraint
model.addConstr(b == 1)
model.setObjective(z, sense = GRB.MAXIMIZE)
model.optimize()
print("x = " + str(x.X)) #4
print("b = " + str(b.X)) #1
print("z = " + str(z.X)) #7
PWL constraint is enforced, and value of z = 7, which is maximum you can hit given the PWL constraint in place.
However, if you make b = 0, then value of z (which we are maximising) goes upto 100, which is upper bound of z