我正在尝试解决在Gurobi / python中使用稀疏矩阵表示的LP问题。
max c'x,受A x = b,L≤x≤U
其中A是大小为~1000 2 的SciPy linked list sparse matrix。使用代码
model = gurobipy.Model()
rows, cols = len(b), len(c)
for j in range(cols):
model.addVar(lb=L[j], ub=U[j], obj=c[j])
model.update()
vars = model.getVars()
S = scipy.sparse.coo_matrix(A)
expr, used = [], []
for i in range(rows):
expr.append(gurobipy.LinExpr())
used.append(False)
for i, j, s in zip(S.row, S.col, S.data):
expr[i] += s*vars[j]
used[i] = True
for i in range(rows):
if used[i]:
model.addConstr(lhs=expr[i], sense=gurobipy.GRB.EQUAL, rhs=b[i])
model.update()
model.ModelSense = -1
model.optimize()
该问题在~1s内建立并解决,比Gurobi / Matlab中的相同任务慢约10-100倍。您是否有任何提高问题定义效率的建议,或避免转换为sparse coordinate格式的建议?
答案 0 :(得分:3)
在处理稀疏矩阵时,MATLAB总是比scipy更有效。但是,有一些事情可以尝试加快速度。
Gurobi的Python界面采用了单独的稀疏约束。这意味着您希望以压缩的稀疏行格式(而不是坐标格式)访问矩阵。
尝试做:
S = S.tocsr()
或以压缩稀疏行格式直接构建矩阵。
此page表示您可以从CSR格式的scipy稀疏矩阵访问原始数据,指示和行指针。因此,您应该能够按如下方式迭代这些:
model = gurobipy.Model()
row, cols = len(b), len(c)
x = []
for j in xrange(cols):
x.append(model.addVar(lb=L[j], ub=U[j], obj=c[j])
model.update()
# iterate over the rows of S adding each row into the model
for i in xrange(rows):
start = S.indptr[i]
end = S.indptr[i+1]
variables = [x[j] for j in S.indices[start:end]]
coeff = S.data[start:end]
expr = gurobipy.LinExpr(coeff, variables)
model.addConstr(lhs=expr, sense=gurobipy.GRB.EQUAL, rhs=b[i])
model.update()
model.ModelSense = -1
model.optimize()
请注意,我使用LinExpr()构造函数将所有术语一次添加到表达式中。