CPLEX with Python API - 如何更快地制作模型?

时间:2018-06-06 07:18:56

标签: python cplex

我转向CPLEX,因为我有很大的线性问题需要解决 如果我们使用scipy.optimize.linprog表示法:

最小化:c ^ T * x
受制于:A_ub * x< = b_ub和A_eq * x == b_eq,

然后我的 A_ub 矩阵的形状大致为(20000,10000):20000个约束,10000个变量。

使用numpy构建矩阵 A_ub,A_eq 和向量 c,b_ub,b_eq 非常快。
但是创建一个CPLEX问题需要大约30秒(这在我的情况下是不可接受的)。发生这种情况,因为他们的Python API不能将矩阵作为输入(至少在测试不同场景几天后我找不到这样的功能)。
创建问题的唯一方法是逐列或逐行构造它,如下所示:

problem = cplex.Cplex()
problem.set_problem_type(problem.problem_type.LP)
problem.objective.set_sense(problem.objective.sense.minimize)
problem.variables.add(obj=c)

n_constraints, n_vars = A_ub.shape
index = list(range(n_vars))
list_rhs = list(b_ub)
# for each row (constraint) create a SparsePair instance
sparse_pairs = [cplex.SparsePair(ind=index, val=A_ub[i]) for i in range(n_constraints)]

# this piece takes 30 seconds
problem.linear_constraints.add(
    lin_expr=sparse_pairs,
    rhs=list_rhs,
    senses=['L'] * n_less_cons
)

我也尝试逐列并直接填充系数,但一切都同样慢。

我无法相信这是正常的,制定问题需要比实际解决问题长6-7倍(解决需要4-5秒)。 有没有人知道,是否有更快的方法在CPLEX中创建问题?
目前,使用开源GLPK(15秒)使用cvxopt解决问题的速度更快,因为它直接将矩阵作为输入,如scipy.linprog。

P.S。我还检查了Gurobi的Python API,它也有同样的问题(它工作得更慢)。

3 个答案:

答案 0 :(得分:3)

Docplex有一个CplexTransformer类(docplex.mp.sktrans.transformers.py),它根据矩阵和成本向量构建和求解线性模型。 它接受numpy矩阵,pandas数据帧和scipys的稀疏co矩阵 (对于非常稀疏的矩阵,co矩阵公式可以真正起作用)。

这是一个非常小的代码片段,展示了CplexTransformer的使用:

# ----- a very small CplexTransformer example
from docplex.mp.sktrans.transformers import CplexTransformer
import scipy.sparse as sp


def solve_cpxtrans_sparse_coo():
    xs = [0, 0, 1, 1, 0, 1]
    ys = [0, 1, 1, 2, 3, 3]
    dd = [1, 1, 1, 1, 5, 7]
    spm = sp.coo_matrix((dd, (xs, ys)), shape=(2, 4))
    ubs = 10
    res = CplexTransformer(sense="min").transform(spm, y=[3, 2, 1], ubs=ubs, sense='ge')
    print(res)
    xs= res['value'].tolist()
    print(xs)

答案 1 :(得分:1)

假设A_ub是一个稀疏矩阵,

a_rows = A_ub.row.tolist()
a_cols = A_ub.col.tolist()
a_vals = A_ub.data
list_rhs = list(b_ub)
problem.linear_constraints.add(rhs=list_rhs, senses=['L'] * n_less_cons)
problem.linear_constraints.set_coefficients(zip(a_rows, a_cols, a_vals))

您可以尝试。就我而言,效果更好。

答案 2 :(得分:0)

此处讨论了相同的问题:https://github.com/cvxgrp/cvxpy/issues/617。 这个问题似乎仍然没有解决方案。