【问题标题】:Why is quicksum very slow in SCIP python interface为什么scip python接口中的quicksum很慢
【发布时间】:2016-07-18 10:23:28
【问题描述】:

我在 ubuntu 上使用 scip python 接口。我正在尝试使用 quicksum 添加约束:

m.addCons(quicksum(covfinal[i,j]*weightVars[i]*weightVars[j] \
          for i in I for j in J)<=z)

由于某种原因,此步骤需要很长时间。我有I=range(2500)J=range(2500)。有没有办法让这一步更高效?

【问题讨论】:

    标签: python scip


    【解决方案1】:

    目前,除了addCons() 方法之外,没有其他方法可以添加约束。与 Python 的内置 sum() 相比,quicksum() 大大减少了必要的时间,因为只创建了一个表达式实例,然后使用单个术语进行迭代更新。否则会创建大量新的表达式对象,代价非常高。

    该命令需要一些时间的(可能的)原因是因为您尝试添加具有 625 万个系数的约束 - 假设 covfinal 是一个密集矩阵。

    另外,请务必始终使用latest PySCIPOpt version from GitHub

    【讨论】:

    • 嗨,有一个切题的问题。 scip 在效率方面与 gurobi 相比如何?
    • Gurobi 拥有更强大的 C 基础,尤其是在 LP 和 MIP 性能方面。建模方面应该没有太大区别——两个 Python 接口都使用 Cython 和一些类似的结构。 PySCIPOpt 提供了更大的灵活性,因为该接口允许在 Python 中编写整个插件,而 Gurobi 的回调入口点数量有限。
    【解决方案2】:

    这是一个老问题,但是,quicksum 在当前的 PySCIPOpt 中仍然运行缓慢。作为 quicksum 的替代方法,我建议创建空约束并稍后添加变量系数。这里是 MWE。

    from scipy import sparse
    import random
    from pyscipopt import Model, quicksum, Expr
    from pyscipopt.scip import Term
    import time as t
    
    ## construct model:
    # max {c'x}
    # A * x <= b
    #   A: random positive sparse matrix 200 x 300
    #   b: random right hand side
    #   c: objective vector
    #   x: variables
    
    numvars    = 200
    numconstr  = 300
    A = sparse.rand(numconstr,numvars,density=0.005,format="csr")
    b = [random.uniform(1,10) for _ in range(numconstr)]
    c = [random.uniform(1,10) for _ in range(numvars)]
    
    ## 1. benchmark quicksum approach:
    m1 = Model()
    m1.setMaximize()
    x1 = [m1.addVar(obj=c[i]) for i in range(numvars)] # creating variables
    t0 = t.time()
    for i in range(numconstr): # generating and adding constraints in a loop
        m1.addCons(quicksum(A[i,j]*x1[j] for j in range(numvars)) <= b[i])
    print("1: construction time ",t.time()-t0,"seconds")
    m1.optimize()
    print("1: Optimum ",m1.getObjVal())
    
    ## 2. Add rows and set coefficients
    m2 = Model()
    m2.setMaximize()
    x3 = [m2.addVar(obj=c[i]) for i in range(numvars)] # creating variables
    t0 = t.time()
    constr = [m2.addCons(Expr() <= b_i) for b_i in b]
    for k,a_ineq in zip(constr,A):
        X = [x3[i] for i in a_ineq.indices]
        for x,a in zip(X,a_ineq.data):
            m2.addConsCoeff(k,x,a)
    print("2: construction time ",t.time()-t0,"seconds")
    m2.freeTransform()
    m2.optimize()
    print("2: Optimum ",m2.getObjVal())
    

    输出:

    1: construction time  3.013126850128174 seconds
    1: Optimum  11581263.217800427
    2: construction time  0.019999980926513672 seconds
    2: Optimum  11581263.217800427
    

    不是 100% 确定这是否是您所要求的,因为您的约束似乎包含二次项。无论如何,希望这对其他人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-15
      • 2014-04-19
      • 1970-01-01
      • 2018-12-30
      • 2019-10-02
      • 2010-10-30
      • 2023-04-03
      • 1970-01-01
      相关资源
      最近更新 更多