我转向 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)
| 归档时间: |
|
| 查看次数: |
1677 次 |
| 最近记录: |