python中lpsolve的替代品,用于快速设置和解决

时间:2019-04-24 09:33:26

标签: python numpy linear-programming lpsolve

我已经在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数组是 all 个单精度浮点数组,我希望它们保持这种状态。

现在,在经历了所有痛苦的介绍之后,我想问一问:是否有人知道另一个库(带有合理的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矩阵再进行上面所有这些复杂的操作肯定会导致性能下降。

如果可能的话,我宁愿留在开源求解器上,但是任何建议都是最欢迎的。我很长的道歉。

安德里亚。

1 个答案:

答案 0 :(得分:0)

@ infinity77,

我正在考虑使用lpsolve。生成一个.lp文件作为输入是相当简单的,它确实解决了一些较小的问题。但是...我现在正尝试解决节点着色问题。这是一个MIP。我第一次尝试解决500个节点的问题时,lp放松了大约15分钟。自昨晚以来,lpsolve就一直致力于真正的MIP。还在磨。这些着色问题很困难,但是14个小时的视线不尽人意。

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

上发表的优秀基准论文