puLP求解器错误

时间:2014-12-10 17:09:17

标签: python pulp coin-or-cbc

我正在尝试在puLP(Python)中解决MILP,并且我不断收到以下错误:

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

对于我的线性规划问题,我试图将不同向量的总和作为约束,我认为我必须以某种方式做错了,因为一个更简单的问题可以解决问题。我附加了代码(C是一个N乘N numpy数组)。

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)

8 个答案:

答案 0 :(得分:5)

确保您没有重复的LpVariable名称,并注意带有不受支持的字符_的LpVariable名称,因为所有这些字符都会以静默方式转换为下划线LpSolverDefault.msg = 1

在调用prob.solve()之前设置emplace()可能有助于将解算器输出打印到控制台。

答案 1 :(得分:3)

我认为您有重复的LpVariable名称。我遇到了同样的问题,感谢levis501's answer看到了它。在这里:

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包含一些具有相同名称的变量。例如,对于i = 0和j = 10,您将获得“ X111”;对于i = 10和j = 0,您还将获得“ X111”。

答案 2 :(得分:2)

由于模型中的Nan输入,我最近遇到了类似的问题。我在DataFrame中有数据,其中一些单元格不应转换为变量以提高性能。然而,在创建目标函数和约束时,我注意到了Nan的存在,当我更改它们时,它工作得很好。

答案 3 :(得分:1)

我有一个类似的问题,确实有重复的LpVariable名称,就像levis501的答案和aleon的答案一样。

我的代码是:

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

当i = 1 j = 11时,x为x111,当i = 11 j = 1时,x也为x111

我更改为:

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

更改后,它将成功运行。

答案 4 :(得分:1)

我最近也提出了同样的错误。在我的情况下引发此错误代码的原因是我的数据框未正确填充。由于某些限制,我错误地在RHS上使用了NaN

所发生的事情类似于:

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

此操作会自动为不在原始数据帧中的实例放置NaN

在我的情况下,NaN's0所取代,这正是我所期望的:

Matrix = Matrix.fillna(0)

答案 5 :(得分:0)

我遇到了一些类似的问题,因为有些PuLP的错误。当某些问题不可行并且解算器未能解决问题时,PuLP会引发异常,而不是返回状态等于不可行。以下是原因。

(您可能首先要查看PuLP的最新代码库,因为您粘贴的行号与最新的行号不一致。我将根据最新的行号进行解释,但您可以非常简单地看一下。)

https://github.com/coin-or/pulp/blob/master/src/pulp/solvers.py#L1405-L1406 这是异常提示的地方。

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

tmpSol是存储解决方案的临时文件。如果PuLP找不到这样的解决方案文件,它将抛出你看到的异常。我上面提到的错误是,如果问题本身不可行,那么PuLP将无法生成这样的临时文件。所以它总会抛出这样的异常。

您可以做的一件事是,向PuLP仓库发送拉取请求并修复它。 一个简单的解决方法是,而不是直接调用

 prob.solve()

在你的代码中,你应该总是这样做

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

答案 6 :(得分:0)

启动LPSolver类的多个实例时遇到了同样的问题。正如fmars所说,问题在于路径“tmpSol&#39;不存在,这是在纸浆的solvers.py文件中的以下代码行中定义的:

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)

这段代码出现在每个解算器中。问题是这些路径稍后会被删除,但可能与LPSolver类的不同实例重合(因为变量pid不是唯一的)。

解决方案是使用例如当前时间为LPSolver的每个实例获取唯一路径。用以下四个代替上面的那些就行了。

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)

别忘了

from time import time

干杯, 添

答案 7 :(得分:0)

我今天遇到了这个问题,这是因为CBC的临时文件试图写在路径中有空格的位置,而纸浆传递给subprocess.Popen()来运行CBC的命令却没有使用引号,因此该命令被误解,CBC无法找到创建临时文件的位置。

为此,我找到了两种解决方案:

(1)明确设置一个没有空格的临时文件目录,

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

或 (2)不要使用CBC(我的问题很小)

prob.solve(pulp.GLPK_CMD())

我有一个与工作相关的约束,我的很多工作都停留在有空格的目录中。