【问题标题】:Alternatives to lpsolve in Python for fast setup and solvePython 中 lpsolve 的替代方案,用于快速设置和求解
【发布时间】:2019-04-24 09:33:26
【问题描述】:

我在 Python 中使用 lpsolve 已经很长时间了,总体来说效果很好。我什至为它编写了自己的 Cython 包装器,以克服原始 Python 包装器所带来的混乱。

我的 Cython 包装器在设置问题时要快得多,但当然解决时间只取决于 lpsolve C 代码,与 Python 无关。

我只解决实值线性问题,没有 MIP。我必须解决的最新(也是最大的)LP 有一个大小约为 5,000 x 3,000 的约束矩阵,设置加求解大约需要 150 毫秒。问题是,我必须在我的模拟中多次解决相同问题的略微修改版本(约束、RHS、边界等对于具有许多时间步长的模拟来说是时间相关的)。约束矩阵通常非常稀疏,大约为 NNZ 的 0.1% - 0.5% 或更少。

使用 lpsolve,问题的设置和解决如下所示:

import numpy
from lp_solve.lp_solve import PRESOLVE_COLS, PRESOLVE_ROWS, PRESOLVE_LINDEP, PRESOLVE_NONE, SCALE_DYNUPDATE, lpsolve

# The constraint_matrix id a 2D NumPy array  and it contains 
# both equality and inequality constraints
# And I need it to be single precision floating point, like all 
# other NumPy arrays from here onwards
m, n = constraint_matrix.shape

n_le = len(inequality_constraints)
n_e  = len(equality_constraints)

# Setup RHS vector
b = numpy.zeros((m, ), dtype=numpy.float32)

# Assign equality and inequality constraints (= and <=)
b[0:n_e]  = equality_constraints
b[-n_le:] = inequality_constraints

# Tell lpsolve which rows are equalities and which are inequalities
e = numpy.asarray(['LE']*m)
e[0:-n_le] = 'EQ'

# Make the LP
lp = lpsolve('make_lp', m, n)

# Some options for scaling the problem
lpsolve('set_scaling', lp, SCALE_DYNUPDATE)
lpsolve('set_verbose', lp, 'IMPORTANT')

# Use presolve as it is much faster
lpsolve('set_presolve', lp, PRESOLVE_COLS | PRESOLVE_ROWS | PRESOLVE_LINDEP)

# I only care about maximization
lpsolve('set_sense', lp, True)

# Set the objective function of the problem
lpsolve('set_obj_fn', lp, objective_function)
lpsolve('set_mat', lp, constraint_matrix)

# Tell lpsolve about the RHS
lpsolve('set_rh_vec', lp, b)

# Set the constraint type (equality or inequality)
lpsolve('set_constr_type', lp, e)

# Set upper bounds for variables - lower bounds are automatically 0
lpsolve('set_upbo', lp, ub_values)

# Solve the problem
out = lpsolve('solve', lp)

# Retrieve the solution for all the variables
vars_sol = numpy.asarray([lpsolve('get_var_primalresult', lp, i) for i in xrange(m + 1, m + n + 1)], dtype=numpy.float32)

# Delete the problem, timestep done
lpsolve('delete_lp', lp)

由于太长无法解释的原因,我的 NumPy 数组是所有单精度浮点数组,我希望它们保持这种状态。

现在,在所有这些痛苦的介绍之后,我想问一下:有没有人知道另一个库(具有合理的 Python 包装器),它允许我设置和解决这种规模的问题,速度比 lpsolve 快(或可能更快) ?我看过的大多数库(PuLP、CyLP、PyGLPK 等)似乎都没有一种直截了当的方式来表示“这是我的整个约束矩阵,一次性设置它”。它们似乎大多倾向于成为允许像这样花哨的东西的“建模语言”(CyLP 示例):

# Add variables
x = s.addVariable('x', 3)
y = s.addVariable('y', 2)

# Create coefficients and bounds
A = np.matrix([[1., 2., 0],[1., 0, 1.]])
B = np.matrix([[1., 0, 0], [0, 0, 1.]])
D = np.matrix([[1., 2.],[0, 1]])
a = CyLPArray([5, 2.5])
b = CyLPArray([4.2, 3])
x_u= CyLPArray([2., 3.5])

# Add constraints
s += A * x <= a
s += 2 <= B * x + D * y <= b
s += y >= 0
s += 1.1 <= x[1:3] <= x_u

老实说,我并不关心灵活性,我只需要在问题设置和解决过程中的原始速度。创建 NumPy 矩阵以及执行上述所有花哨的操作肯定会成为性能杀手。

如果可能,我宁愿继续使用开源求解器,但欢迎提出任何建议。对于这篇长篇文章,我深表歉意。

安德烈亚。

【问题讨论】:

  • CyLP 可能是候选人。在将稀疏矩阵发布到 clpy(extract: model += lhs * x == rhs)之前,我确实使用了很多更底层的 numpy/scipy 建模 here。当然,这种(scipy 的)稀疏格式需要为 Cbc/Clp 复制/转换,但这在非零的数量上应该是线性的。
  • @sasha:感谢您的评论和链接。看起来很有趣,尽管在我的情况下约束矩阵的生成非常复杂,并且通过转换到稀疏矩阵需要与设置线性问题大约相同的时间(即,2D NumPy 数组到 scipy 稀疏大约需要 70-80 毫秒)。我会以更全面的方式查看您的代码,尽管我不确定它是否能轻松适应我手头的问题......
  • 在 scipy 1.6 中尝试linprog( method="highs-ipm" ... ),使用稀疏的 csR 数组? (我猜稀疏的 float32 将被转换为 float64——doc 没有说。)

标签: python numpy linear-programming lpsolve


【解决方案1】:

@infinity77,

我现在正在考虑使用 lpsolve。为输入生成一个 .lp 文件是相当直接的,它确实解决了几个较小的问题。但是...我现在正在尝试解决节点着色问题。这是一个 MIP。我第一次尝试 500 节点问题运行了大约 15 分钟作为 lp 放松。自昨晚以来,lpsolve 一直在研究真正的 MIP。还在磨。这些着色问题很困难,但看不到尽头的 14 小时实在是太长了。

我所知道的最佳替代方案来自 coin-or.org;[Coin-OR Solvers] 1 根据您要解决的问题类型尝试他们的 clp 和 cbc 求解器。我看到的基准表明它们是 CPLEX 和 Gurobi 之外的最佳选择。它是免费的,但您需要确保它对于您的目的是“合法的”。 Bernhard Meindl 和 Matthias Templ 在Open Source Solver Benchmarks

上撰写的一篇很好的基准论文

【讨论】:

  • 嗨,我没有这种问题,因为我的问题不是 MIP - 而且我知道 lpsolve 不是 MIP 的正确工具。编写文件并将其发送到 Coin-OR 求解器并读取结果肯定会比我所拥有的要慢。我一直在寻找一种工具,它允许我一次性指定整个约束矩阵并通过 API 调用检索结果。以非常快的方式。该工具不存在。
  • 我相信他们有一个 API,可以让您生成问题并通过调用解决它。即使是放松也需要将近 15 分钟。
  • @Infinity77,我的错。我看到你确实参考了几个 Coin 工具。我唯一的借口,我是 OR 开源工具的新手。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-14
  • 2021-09-11
  • 2018-07-24
  • 2013-10-03
相关资源
最近更新 更多