【问题标题】:Gurobi model modification slow, can I modify the constraint matrix directly?Gurobi模型修改慢,可以直接修改约束矩阵吗?
【发布时间】:2016-02-01 08:59:46
【问题描述】:

我想更改现有模型中的系数。目前(使用 Python API)我正在遍历约束并调用 model.chgCoeff 但它很慢。在 Python 和/或 C API 中是否有更快的方法,可能直接访问约束矩阵?

下面的示例代码。它缓慢的原因似乎主要是因为循环本身。用任何其他操作替换 chgCoeff 仍然很慢。通常我会通过使用向量运算而不是 for 循环来解决这个问题,但如果不访问约束矩阵,我认为我做不到。

from __future__ import division
import gurobipy as gp
import numpy as np
import time
N = 300
M = 2000
m = gp.Model()
m.setParam('OutputFlag', False)

masks = [np.random.rand(N) for i in range(M)]
p = 1/np.random.rand(N)
rets = [p * masks[i] - 1 for i in range(M)]
v = np.random.rand(N)*10000 * np.round(np.random.rand(N))

t = m.addVar()
x = [m.addVar(vtype=gp.GRB.SEMICONT, lb=1000, ub=v[i]) for i in range(N)]
m.update()
cons = [m.addConstr(t <= gp.LinExpr(ret, x)) for ret in rets]

m.setObjective(t, gp.GRB.MAXIMIZE)
m.update()

start_time = time.time()
m.optimize()
solve_ms = int(((time.time() - start_time)*1000))

print('First solve took %s ms' % solve_ms)

p = 1/np.random.rand(N)
rets = [p * masks[i] - 1 for i in range(M)]
start_time = time.time()
for i in range(M):
    for j in range(N):
        if rets[i][j] != -1:
            m.chgCoeff(cons[i], x[j], -rets[i][j])
m.update()
update_ms = int(((time.time() - start_time)*1000))
print('Model update took %s ms' % update_ms)

start_time = time.time()
m.optimize()
solve_ms = int(((time.time() - start_time)*1000))
print('Second solve took %s ms' % solve_ms)

k = 2
start_time = time.time()
for i in range(M):
    for j in range(N):
        if rets[i][j] != -1:
            k *= rets[i][j]
solve_ms = int(((time.time() - start_time)*1000))
print('Plain loop took %s ms' % solve_ms)

R = np.array(rets)
start_time = time.time()
S = np.copy(R)
copy_ms = int(((time.time() - start_time)*1000))
print('np.copy() took %s ms' % copy_ms)

输出:

First solve took 1767 ms
Model update took 2051 ms
Second solve took 1872 ms
Plain loop took 1103 ms
np.copy() took 3 ms

在大小 (2000, 300) 约束矩阵上调用 np.copy 需要 3 毫秒。我错过了整个模型更新不能那么快的根本原因吗?

【问题讨论】:

  • 您能否使用一个示例模型来更新您的问题,该示例模型展示了更新操作的缓慢性?
  • @josilber 我添加了一个示例来大致展示我正在尝试做的事情。
  • 你可能想试试unofficial Gurobi API,它声称更快。我从来没有检查过。从 C API 你可以change all coefficients of a row directly

标签: python mathematical-optimization linear-programming gurobi


【解决方案1】:

您无法使用 Python 接口直接在 Gurobi 中访问约束矩阵。即使可以,您也无法执行 np.copy 操作,因为矩阵采用 CSR 格式,而不是密集格式。要对约束进行大规模更改,最好通过删除约束并添加新约束来修改约束矩阵。在您的情况下,每个更改都非常重要,以至于您不会从热启动中获得太多好处,因此您不会因为不保留相同的约束对象而失去任何东西。

假设您在上面的代码中针对 -1 特殊情况调整了 rets 数组,那么下面的代码会满足您的需要并且速度更快。

for con in cons:               
    m.remove(con)
new_cons = [m.addConstr(t <= gp.LinExpr(ret, x)) for ret in rets]

【讨论】:

  • 谢谢,即使是 CSR 副本也比重建所有我想象的约束要快得多。 C API 呢?
猜你喜欢
  • 2020-07-24
  • 1970-01-01
  • 2018-01-14
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
相关资源
最近更新 更多