puLP solver error

27.1k views Asked by At

I am trying to solve MILP in puLP (Python), and I keep getting the following error:

Traceback (most recent call last):
  File "main_lp.py", line 63, in <module>
    ans = solve_lp(C)
  File "/home/ashwin/Documents/Williams/f2014/math317_or/project/solve_lp.py", line 36, in solve_lp
    prob.solve()
  File "/usr/local/lib/python2.7/dist-packages/PuLP-1.5.6-py2.7.egg/pulp/pulp.py", line 1619, in solve
    status = solver.actualSolve(self, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/PuLP-1.5.6-py2.7.egg/pulp/solvers.py", line 1283, in actualSolve
    return self.solve_CBC(lp, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/PuLP-1.5.6-py2.7.egg/pulp/solvers.py", line 1346, in solve_CBC
    raise PulpSolverError("Pulp: Error while executing "+self.path)
pulp.solvers.PulpSolverError: Pulp: Error while executing /usr/local/lib/python2.7/dist-packages/PuLP-1.5.6-py2.7.egg/pulp/solverdir/cbc-32

For my linear programming problem, I am attempting to take sums of different vectors as the constraint, and I think I must have done that wrong somehow, because a much simpler problem works with no hitches. I have attached the code (C is an N by N numpy array).

def solve_lp(C):
    N = len(C)
    prob=LpProblem('Scheduling',LpMinimize)

    X = [[LpVariable('X' + str(i+1) + str(j+1), 0, C[i,j],LpBinary)
          for j in range(N)] for i in range(N)]
    X = np.array(X)
    X_o = [LpVariable('X0' + str(i), 0, None, LpBinary) for i in range(N)]
    X_t = [LpVariable('X' + str(i) + 't', 0, None, LpBinary) for i in range(N)]

    # Objective Function                                                                                                                                                
    ones_vec = list(np.ones(len(X_o)))
    prob += lpDot(ones_vec,X_o), 'Minimize Buses'

    # Constraints                                                                                                                                                       
    for i in range(N):
        row = list(X[i,:]) + [X_t[i]]
        ones_vec = list(np.ones(len(row)))
        prob += lpDot(ones_vec, row) == 1, 'Only one destination for ' + str(i)

    for j in range(N):
        col = list(X[:,j]) + [X_o[j]]
        ones_vec = list(np.ones(len(col)))
        prob += lpDot(ones_vec,col) == 1, 'Only one source for ' + str(j)

    prob.solve()
    return X, value(prob.objective)
9

There are 9 answers

0
Pedro Esmeriz On

I recently had a similar problem due to Nan inputs in the model. I had the data in a DataFrame where some the cells should not bee converted to variables to improve performance. However, upon creating the objective function and the constraints, I noticed the presence of Nan and when I changed them it worked perfectly.

1
levis501 On

Make sure you don't have duplicate LpVariable names, and watch out for LpVariable names with the unsupported characters -+[] ->/ since all of those characters are silently converted to underscores _

Setting LpSolverDefault.msg = 1 before calling prob.solve() may help by printing the solvers output to the console.

1
aleon On

I think that you have duplicate LpVariable names. I just had the same problem and saw it thanks to levis501's answer. Here:

X = [[LpVariable('X' + str(i+1) + str(j+1), 0, C[i,j],LpBinary)
      for j in range(N)] for i in range(N)]

X contains some variables with the same name. For example for i = 0 and j = 10 you get 'X111', and for i = 10 and j = 0 you also get 'X111'.

1
Sibusiso On

On your LP problem remove NAN or nan from your equation that you want to solve

0
xiaoxia On

I had a similar problem, and indeed with duplicate LpVariable names just like levis501's answer and aleon answered.

my code was:

var = [[pulp.LpVariable(f'x{i}{j}', lowBound=0, cat=pulp.LpInteger) for j in range(col)] for i in range(row)]

when i=1 j=11, x would be x111, and when i=11 j=1, x also would be x111

I changed to:

var = [[pulp.LpVariable(f'x{i}_{j}', lowBound=0, cat=pulp.LpInteger) for j in range(col)] for i in range(row)]

After changing, it runs successfully.

2
fmars On

I have met some similar problem which because of some PuLP's bug. When some problem is infeasible and the solver failed to solve the problem, PuLP raise an exception rather than return status equals to infeasible. Below is the reason.

(You may first want to check out latest codebase of PuLP because the line number you paste doesn't match the latest one. I'll explain based on latest one but you can look at yours very simply.)

https://github.com/coin-or/pulp/blob/master/src/pulp/solvers.py#L1405-L1406 This is where exception prompt.

   if not os.path.exists(tmpSol):
      raise PulpSolverError("Pulp: Error while executing "+self.path) 

tmpSol is the temporary file where stores the solution. If PuLP cannot find such solution file, it will throw the exception you saw. And the bug I mentioned above is, if the problem itself is infeasible, then PuLP won't be able to generate such temporary file. So it will always throw such exception.

One thing you can do is, send a pull request to PuLP repo and fix it. And a simple workaround is, rather than directly invoke

 prob.solve()

in your code, you should always do

try:
     prob.solve()
except Exception:
     logger.debug('Problem infeasible')
0
GrayOnGray On

I had this problem today, and it was because the temporary files for CBC were trying to be written in a location whose path had spaces in it, and the command that pulp passes to subprocess.Popen() to run CBC does not use quotes, and thus the command was misinterpreted and CBC couldn't find the location to create temp files.

For this I found two solutions:

(1) Explicitly set a temporary file directory that doesn't have spaces in it,

pulp.LpSolverDefault.tmpDir = self.tmp_file_dir  # tmp_file_dir can't have spaces!
prob.solve()

or (2) don't use CBC (my problem is small)

prob.solve(pulp.GLPK_CMD())

I have a work-related constraint that a lot of my work is stuck in directories that have spaces.

0
Billal Naseem On

I recently had the same error raised aswell. The reason this error code was raised in my case was that my data frame was not correctly populated. i incorrectly had NaN on the RHS on some of my constraints

What is had was something like:

Matrix = df.pivot(1st_dimension, 2nd_dimension, value)

This operation automatically puts NaN for the instances that are not in the original dataframe.

in my case the NaN'sare replaced with 0 which is what i was expecting it to be:

Matrix = Matrix.fillna(0)

1
T.S. Wolter On

I experienced the same issue when launching multiple instances of the LPSolver class. As fmars stated, the problem is that the path 'tmpSol' does not exist, which is defined in the following lines of code within the solvers.py file of pulp:

pid = os.getpid()
tmpLp = os.path.join(self.tmpDir, "%d-pulp.lp" % pid)
tmpMps = os.path.join(self.tmpDir, "%d-pulp.mps" % pid)
tmpSol = os.path.join(self.tmpDir, "%d-pulp.sol" % pid)

This bit of code appears in every solver. The problem is that these paths are deleted later on, but may coincide for different instances of the LPSolver class (as the variable pid is not unique).

The solution is to get a unique path for each instance of LPSolver, using, for example, the current time. Replacing the above lines by the following four will do the trick.

currentTime = time()
tmpLp = os.path.join(self.tmpDir, "%f3-pulp.lp" % currentTime)
tmpMps = os.path.join(self.tmpDir, "%f3-pulp.mps" % currentTime)
tmpSol = os.path.join(self.tmpDir, "%f3-pulp.sol" % currentTime)

Don't forget to

from time import time

Cheers, Tim