Search code examples
pythonlinear-programmingpulpscipy-optimize-minimize

PuLP - Why cant you use a generator/list expression for UpBounds? "TypeError: must be real number, not list"


I am trying to code the upper bounds of a set of variables (x1, x2...xn) for my problem in Pulp. I already have a list of the upper bounds that i want to use. the problem is that a generator or list expression yields an error.

UpBounds=[370.94, 490.81, 1582.52, 3681.33, 213.85, 61.15, 66.09, 55.32, 55.94, 147.13, 17.02, 27.09, 155.67, 51.61, 166.18, 61.93, 66.27, 46.57, 25.33, 69.86, 126.68, 12.95, 65.03, 121.75, 103.71, 44.07, 46.71, 19.99, 44.12, 91.54, 59.54, 24.6, 42.84, 135.04, 30.91, 61.05, 26.5, 52.74, 11.88, 4.21, 111.1, 187.04, 370.94, 490.81, 687.89, 205.43, 1582.52, 3681.33, 23993.51, 1515.28, 275.62, 127.21, 130.46, 757.46, 118.15, 137.27, 495.62, 1240.92, 260.85, 637.26, 15.1, 415.94, 462.88, 118.33, 270.73, 83.52, 499.7, 433.21, 136.33, 24.22, 484.35, 4346.76, 82.92, 26.64, 2901.47, 6155.17, 78.6, 0.0, 0.0, 18654.02, 28.97, 0.0, 0.0, 7496.19, 10.0, 182.07, 31.01, 127.26, 55.77, 206.89, 98.65, 200.0, 29.18, 200.37, 21.04, 199.75]

x = pl.LpVariable.matrix('x', range(0,96), 0, [up for up in UpBounds])

>>>TypeError: must be real number, not list

A numpy array does not work either.

the annoying thing is is that this works no problem in linprog which is supposed to be the inferior solver, e.g.

bounds=[(0,up) for up in UpBounds)]

Does anyone know how i write the above, i.e. for every variable x_n to have its own upper bounds UpBound[i]?

EDIT

The problem is when i try to solve i.e. prob.solve() it throws an error, pointing to the upper bound:

>>>(name, variable.upBound))
TypeError: must be real number, not list

model to solve is simply:

prob += pl.lpSum([x[i]*-constants[i] for i in range(len(constants))])

Solution

  • Ahhh, hence we come back to the SO guidance of putting in a Minimum Reproducible Example. :)

    Anyhow, easiest solution is just to add in your upper bounds as a constraint, which is (I'm quite sure) an equivalent action in the eyes of the solver. There are a couple ways to do this. Here is one using your list of upper bounds:

    # pulp upper bounds on dv
    
    import pulp
    
    ub_list = [1,2,3]
    
    prob = pulp.LpProblem("UB setter", pulp.LpMaximize)
    
    X = pulp.LpVariable.matrix('X', range(3), lowBound=0, cat='Continuous')
    
    for idx in range(3):
        prob += X[idx] <= ub_list[idx]
    
    prob += pulp.lpSum(X[i] for i in range(3))
    
    prob.solve()
    pulp.LpStatus[prob.status]
    
    for idx in range(3):
        print(f'X[{idx}]: {X[idx].varValue}')
    

    Yields:

    X[0]: 1.0
    X[1]: 2.0
    X[2]: 3.0