Modification of the Gurobi model is slow, can I directly modify the constraint matrix?

I want to make changes to the coefficients in the existing model. Currently (with the Python API) I am looping through the constraints and calling model.chgCoeff, but this is pretty slow. Is there a faster way, possibly direct access to the constraint matrix in the Python and / or C API?

Sample code below. The reason it slows down is mainly due to the loop itself; replacing with chgCoeffany other operation, still slow. I usually went around this using vector operations, not for loops, but without access to the constraint matrix, I don't think I can do it.

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)

Output:

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

np.copy (2000, 300) 3 . , , ?

+4
1

Gurobi, Python. , np.copy, CSR, . , , . , , , .

, rets -1, , .

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

Source: https://habr.com/ru/post/1614034/


All Articles