7

我正在尝试在 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 × Nnumpy数组)。

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)
4

8 回答 8

9

确保您没有重复的 LpVariable 名称,并注意带有不受支持字符的 LpVariable 名称,-+[] ->/因为所有这些字符都会被静默转换为下划线_

通过将求解器输出打印到控制台,LpSolverDefault.msg = 1在调用之前进行设置可能会有所帮助。prob.solve()

于 2015-05-30T20:45:05.603 回答
6

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

于 2017-05-17T10:25:08.637 回答
4

我认为您有重复的 LpVariable 名称。由于levis501 的回答,我刚刚遇到了同样的问题并看到了它。这里:

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”。

于 2018-12-16T14:24:25.557 回答
2

我遇到了类似的问题,并且确实有重复的 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)]

修改后,运行成功。

于 2019-01-09T02:35:49.767 回答
2

我最近也提出了同样的错误。在我的案例中出现此错误代码的原因是我的数据框未正确填充。我在 RHS 上错误地NaN了解了我的一些限制

所拥有的是这样的:

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

此操作会自动放入NaN不在原始数据框中的实例。

在我的情况下,NaN's替换0为我所期望的:

Matrix = Matrix.fillna(0)

于 2019-09-30T07:42:33.143 回答
1

我在启动 LP Solver 类的多个实例时遇到了同样的问题。正如 fmars 所说,问题在于路径 'tmpSol' 不存在,它是在纸浆的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

干杯,蒂姆

于 2017-03-27T13:05:57.003 回答
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())

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

于 2018-10-21T02:03:36.857 回答
0

由于一些纸浆的错误,我遇到了一些类似的问题。当某个问题不可行并且求解器未能解决该问题时,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 找不到这样的解决方案文件,它会抛出你看到的异常。而我上面提到的bug是,如果问题本身不可行,那么PuLP将无法生成这样的临时文件。所以它总是会抛出这样的异常。

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

 prob.solve()

在您的代码中,您应该始终这样做

try:
     prob.solve()
except Exception:
     logger.debug('Problem infeasible')
于 2016-11-29T01:13:31.860 回答