maxpulplinear-optimization

in PuLP, I need a way to set a decision variable equal to the maximum of a list of decision variables


I have been using Gurobi and also its Python API (gurobipy) for my linear optimization problem with mixed integer programming. Due to sorts of reasons, the organization's decided to stop Gurobi licensing, so I've rebuilt my model with PuLP instead, and testing feasibilities with open-source solvers.

However, for one of my constraints associated with 2 of the decision variables y (boolean) and z (boolean), I couldn't really find an alternative method that can do the same thing as "max_()" from gurobipy. Basically, I want to restrict variable y as 1 if there is any z equals to 1 in the current iteration, which gurobipy.max_() can do the exact job.

For bigger picture, y is one of the boolean variables that can turn the integer variable x on or off, so the formulated sum of x can go into final objective for minimization. y is regulated by z as mentioned above. See the code snippet below:

import gurobipy as gp
for d in days_list:
    model.addConstrs(
        (y[c, d] == gp.max_([z[s, d] for s in df1.loc[c]]))
        for c in df2
    )

    model.addConstrs(
        gp.quicksum(x[s, d] for s in df1.loc[c])
        <= 32 * y[c, d]
        for c in df2
    )

Hope someone who has more LP experiences can help find a proper alternative so that I can replace gp.max_() with something else!

I've tried the following, but apparently, it gives error because one can't do operations on LpVariables, so the Python max() or sum() won't work either.

for day in days_list:
    for c in df2:
        for s in df1.loc[c]:
            if plp.lpSum(z[s, day].value for s in df1.loc[c]) > 0:
                problem.addConstraint(y[c, day]==1)
            else:
                problem.addConstraint(y[c, day]==0)

Solution

  • So the fundamental challenge is that you want to enforce:

    any(z[s]) ==> y=1
    

    and presumably:

    no(z[s]) ==> y=0
    

    where y and z are both boolean variables

    I think you can just do this with 2 constraints:

    y >= sum(z[s]) / |s|
    
    y <= sum(z[s]) * |s|