带有 Python API 的 CPLEX - 如何加快模型制定速度?

Bi0*_*max 4 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
)
Run Code Online (Sandbox Code Playgroud)

我也尝试逐列并直接填充系数来完成此操作,但一切都同样缓慢。

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

PS我还检查了Gurobi的Python API,它也有同样的问题(它运行得更慢)。

小智 5

Docplex 有一个 CplexTransformer 类 (docplex.mp.sktrans.transformers.py),它根据矩阵和成本向量构建和求解线性模型。它接受 numpy 矩阵、pandas 数据帧和 scipys 的稀疏 coo 矩阵(对于非常稀疏的矩阵,coo 矩阵公式确实很有帮助)。

这是一个非常小的代码片段,显示了 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)
Run Code Online (Sandbox Code Playgroud)