Python Gurobi模型修改缓慢,我可以直接修改约束矩阵吗?

Python Gurobi模型修改缓慢,我可以直接修改约束矩阵吗?,python,mathematical-optimization,linear-programming,gurobi,Python,Mathematical Optimization,Linear Programming,Gurobi,我想对现有模型中的系数进行修改。目前(使用PythonAPI),我正在遍历约束并调用model.chgCoeff,但速度非常慢。在Python和/或C API中是否有一种更快的方法,可能是直接访问约束矩阵 下面是示例代码。它之所以慢似乎主要是因为循环本身;用任何其他操作替换chgCoeff仍然很慢。通常我会通过使用向量运算而不是循环来解决这个问题,但是如果没有访问约束矩阵,我想我无法做到这一点 from __future__ import division import gurobipy as

我想对现有模型中的系数进行修改。目前(使用PythonAPI),我正在遍历约束并调用
model.chgCoeff
,但速度非常慢。在Python和/或C API中是否有一种更快的方法,可能是直接访问约束矩阵

下面是示例代码。它之所以慢似乎主要是因为循环本身;用任何其他操作替换
chgCoeff
仍然很慢。通常我会通过使用向量运算而不是循环来解决这个问题,但是如果没有访问约束矩阵,我想我无法做到这一点

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)

对大小(2000300)约束矩阵调用
np.copy
,需要3毫秒。整个模型更新不能那么快,这是我忽略的一个根本原因吗?

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

假设您为-1特例调整了上面代码中的
rets
数组,下面的代码将满足您的需要,并且速度更快

for con in cons:               
    m.remove(con)
new_cons = [m.addConstr(t <= gp.LinExpr(ret, x)) for ret in rets]
对于con-in-cons:
m、 移除(con)

新的cons=[m.addconst(t你能用一个示例模型来更新你的问题吗?@josilber我添加了一个示例来大致说明我正在尝试做什么。你可能想尝试一个,据说它更快。不过我从未检查过。从C API你可以。谢谢,即使是CSR副本也比rebu快得多我会考虑所有的约束,那么C API呢?
for con in cons:               
    m.remove(con)
new_cons = [m.addConstr(t <= gp.LinExpr(ret, x)) for ret in rets]