Gurobi风格的Scipy.linprog?

vlju58qv  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(120)

我想比较Guidelines和Scipy的线性编程工具,比如linprog。Scipy需要在matrix-list-vector-form中指定问题,而Guidance的工作方式类似于here

m = Model()
m.addVar(...) %for variables
m.addConstr(..>) %for constraints
m.update() %for updating the model
m.optimize % for optimizing the model
m.params %for getting parameters
m._vars %for getting variables

比较Scipy

Minimize: c^T * x

Subject to: A_ub * x <= b_ub
A_eq * x == b_eq

c : array_like
Coefficients of the linear objective function to be minimized.
A_ub : array_like, optional
2-D array which, when matrix-multiplied by x, gives the values of the upper-bound inequality constraints at x.
b_ub : array_like, optional
1-D array of values representing the upper-bound of each inequality constraint (row) in A_ub.
A_eq : array_like, optional
2-D array which, when matrix-multiplied by x, gives the values of the equality constraints at x.
b_eq : array_like, optional
1-D array of values representing the RHS of each equality constraint (row) in A_eq.
bounds : sequence, optional

我的目标是只使用一种方法编写代码,并且仍然使用两种求解器对结果进行基准测试。为了加快比较求解器:

  1. Scipy是否存在Gurobi式的LP问题模型构造?
    1.是否存在一些包来使这两个方法可以互换(我可以为Guidelines编写scipy样式,或者为Scipy编写Gurobi样式)?
  2. scipy是否提供任何其他接口来指定线性规划问题?
btxsgosb

btxsgosb1#

这听起来像是一个很大的工作,以显示明显的:

  • 像Guidelines这样的商业求解器比非商业求解器要快得多,也更健壮
  • 还有一些高质量的基准测试通过H. Mittelmann显示了这一点(CLP和GLPK是最流行的非商业基准测试)
  • 虽然scipy的linprog还可以,但它比CBC/CLP,GLPK,lpSolve等开源竞争对手差得多。
  • 速度和鲁棒性!
  • 另外:scipy的linprog似乎真的没有维护open issues

有一些方法可以做到这一点:

***A)**使用linprog的问题定义方式并将其转换为Gurobi风格

  • 很容易将矩阵形式转换为Guidelines模型
    ***B)**使用cvxpy作为建模工具,获取标准格式并为Guidelines编写一个 Package 器(实际上:有一个)和linprog(又是简单的)。这将允许一个非常强大的建模语言被两者使用
  • 缺点:根据问题的不透明转换(例如,abs(some_vector)可能会引入辅助变量)
    ***C)**编写一些MPS-reader /或从其他工具中获取一个,以便在Guidelines中建模问题,输出这些问题并在linprog中读取和解决
  • 候选工具:cvxopt's mps阅读器(隐藏在文档中),一些GLPK接口,甚至一些CBC接口
  • (可能隐藏的转换)

无论你做什么,解决方案过程分析都将是你代码的重要组成部分,因为linprog可能会失败很多。它也不能处理大型稀疏模型。

基于您的gurobi示例的备注

  • 您的示例(TSP)是MIP,而不是LP
  • 对于MIP来说,上面所说的一切都变得更糟(特别是开源和开源之间的性能差异)
  • scipy中没有MIP求解器!
4dbbbstv

4dbbbstv2#

我以一种非常直接的方式做到了这一点。这并不像之前的文章所暗示的那样需要大量的工作。例如

res = linprog(c, A_ub=Aineq, b_ub=Bineq, A_eq=None if len(Aeq) == 0 else Aeq, b_eq=None if len(Beq) == 0 else Beq, bounds=x_bounds, method="highs", integrality=1)
if not res is None: return np.rint(res.x).astype(np.int64)

翻译成:

m = Model()
v = m.addVars(range(len(c)), lb=[x[0] for x in x_bounds], ub=[x[1] for x in x_bounds], vtype=[GRB.BINARY if x == (0,1) else GRB.INTEGER for x in x_bounds], name=labels)
m.addConstrs((sum(v[i]*a for i, a in enumerate(Aineq[j])) <= Bineq[j] for j in range(len(Aineq))))
m.addConstrs((sum(v[i]*a for i, a in enumerate(Aeq[j])) == Beq[j] for j in range(len(Aeq))))
m.setObjective(sum(v[i]*c[i] for i in range(len(c))), GRB.MINIMIZE)
m.update()
m.optimize()
return [int(v.x) for v in m.getVars()] if m.Status == GRB.OPTIMAL else None

当然,如果不是所有的边界都是整数或二进制的,你可能需要更多的变量类型处理,或者scipy提供的其他各种可能性,如列表与标量,无值等。不用说,它可以在几行Python代码中完成。

相关问题