Scipy:使用稀疏矩阵进行线性编程

时间:2016-01-15 23:59:35

标签: python scipy sparse-matrix linear-programming

我想在python中解决一个线性程序。变量的数量(我将从现在开始称之为N)非常大(~50000)并且为了以scipy.optimize.linprog所需的方式来表示问题,我必须构造两个N×N矩阵({ {1}}和A以下)。 LP可以写成

B

其中minimize: c.x subject to: A.x <= a B.x = b x_i >= 0 for all i in {0, ..., n} 表示点积,.ab是长度为N的向量。

我的经验是构建如此大的矩阵(cA都有大约50000x50000 = 25 * 10 ^ 8个条目)带来一些问题:如果硬件不是很强大,NumPy可能会拒绝构建这样大的矩阵(例如参见Very large matrices using Python and NumPy),即使NumPy创建矩阵没有问题,也存在巨大的性能问题。对于NumPy必须处理的大量数据,这是很自然的。

然而,即使我的线性程序带有N个变量,我使用的矩阵也非常稀疏。其中一个在第一行中只有条目,另一个仅在前M行中有条目,其中M <1。 N / 2。当然我想利用这个事实。

据我所读(例如Trying to solve a Scipy optimization problem using sparse matrices and failing),B不适用于稀疏矩阵。因此,我有以下问题:

  • SciPy是否真的没有提供用稀疏矩阵求解线性程序的任何可能性? (如果没有,我该怎么办?)
  • 您是否知道任何替代库可以解决问题更有效比非稀疏矩阵的SciPy? (library中建议的thread above似乎对我的目的不够灵活 - 据我了解其文档而言)
  • 可以预期利用矩阵稀疏性的单纯形算法(使用普通Python,没有C)的新实现比使用非稀疏矩阵的SciPy更有效吗?

3 个答案:

答案 0 :(得分:2)

我想说形成一个密集矩阵(或两个)来解决一个大的稀疏LP可能不是正确的事情。在求解大型稀疏LP时,使用具有处理此类问题的工具的解算器以及以不明确创建任何这些零元素的方式生成模型非常重要。

在Python中编写一个稳定,快速,稀疏的Simplex LP解算器作为SciPy密集解算器的替代并非易事。此外,用纯Python编写的求解器可能效果不佳。

对于您指出的大小,虽然不是非常非常大(可能是大型中型模型将是一个很好的分类),您可能需要考虑商业求解器,如CplexGurobi或{ {3}}。这些求解器非常快速且非常可靠(它们基本上解决了你向它们抛出的任何LP问题)。它们都有Python API。对于学者来说,解算器是免费或非常便宜的。

如果要使用开源解算器,可能需要查看COIN CLP解算器。它还有一个Mosek

如果您的模型更复杂,那么您也可能需要考虑使用Python建模工具,例如Python interfacePulp(Gurobi在Python中也有很好的建模支持)。

答案 1 :(得分:0)

我无法相信没有人指出你PuLP的方向!您将能够有效地创建问题,如下所示:

import pulp
prob = pulp.LpProblem("test problem",pulp.LpMaximize)
x = pulp.LpVariable.dicts('x', range(5), lowBound=0.0)
prob += pulp.lpSum([(ix+1)*x[ix] for ix in range(5)]), "objective"
prob += pulp.lpSum(x)<=3, "capacity"

prob.solve()
for k, v in prob.variablesDict().iteritems():
    print k, v.value()

PuLP很棒,有一个非常好的求解器(CBC),可以连接到开源和商业求解器。我目前正在林业公司的生产中使用它,并为我们遇到的最困难(整数)问题探索Dippy。祝你好运!

答案 2 :(得分:0)

linprog  ( ... A=sparse.csc_matrix(), method="interior-point" ) 在scipy 1.2中工作正常, 我发现内部点比默认的“ simplex”更快。
一个可参数化的test case (m * n个变量,m + n个约束,密度2 /(m + n)),例如

lpgen_2d: m 1000  n 2000  A (3000, 2000000) 4e+07 bytes sparse float32

在我的2.7 GHz iMac上大约需要90秒的真实时间和120秒的cpu(多核)。
欢迎链接到更多稀疏测试用例。