更新 Gurobi 和 Python 中特定约束的 RHS 和 LHS
Updating the RHS and LHS of specific constraints in Gurobi and Python
使用 gurobi 和 python 我正在尝试解决以下形式的水平衡(类似于 classic 运输问题)线性规划问题:
根据以下条件将 c'x 最小化:
Ax=b
lb<=x<=ub
A、L 是稀疏 crs scipy 矩阵,c,b,lb,ub 是向量。
我的问题应该更新多个步骤,并且一些元素已更新为新值。具体来说,A 是固定的,所有其他元素在每一步都获得新值。以下代码片段完美运行,是我目前使用的基础(忽略 "self",因为模型嵌入在求解器 class 中,而“water_network 是保存值的图形对象,每个步骤的属性):
### Snippet 1: Formulating/initializing the problem
# unitC is the c vector
# Bounds holds both lb and ub values for each x
self.model = gurobipy.Model()
rows, cols = len(self.water_network.node_list), len(self.water_network.edge_name_list)
self.x1 = []
for j in range(cols):
self.x1.append(self.model.addVar(lb=self.water_network.Bounds[j,0], ub=self.water_network.Bounds[j,1],obj=self.water_network.unitC[j]))
self.model.update()
self.EqualityConstraintA=[]
for i in range(rows):
start = self.water_network.A_sparse.indptr[i]
end = self.water_network.A_sparse.indptr[i+1]
variables = [self.x1[j] for j in self.water_network.A_sparse.indices[start:end]]
coeff = self.water_network.A_sparse.data[start:end]
expr = gurobipy.LinExpr(coeff, variables)
self.EqualityConstraintA.append(self.model.addConstr(lhs=expr, sense=gurobipy.GRB.EQUAL, rhs=self.water_network.b [i],name='A'+str(i)))
self.model.update()
self.model.ModelSense = 1
self.model.optimize()
以下简单片段用于更新每一步的问题。注意我使用 getConstrs 函数:
#### Snippet 2: Updating the constraints, working ok for every step.
self.model.setAttr("LB",self.model.getVars(), self.water_network.Bounds[:,0])
self.model.setAttr("UB", self.model.getVars(), self.water_network.Bounds[:,1])
self.model.setAttr("OBJ", self.model.getVars(), self.water_network.unitC)
self.model.setAttr("RHS", self.model.getConstrs(),self.water_network.b)
当应该向问题添加一组新的约束时出现问题,形式为:
Lx=0 其中L是每一步更新的稀疏矩阵!现在在公式中,我在片段 1 之后添加以下内容:
self.EqualityConstraintL=[]
leakrows= len(self.water_network.ZeroVector)
for i in range(leakrows):
start = self.water_network.L_sparse.indptr[i]
end=self.water_network.L_sparse.indptr[i+1]
variables=[self.x1[j] for j in self.water_network.L_sparse.indices[start:end]]
coeff=self.water_network.L_sparse.data[start:end]
expr = gurobipy.LinExpr(coeff, variables)
self.EqualityConstraintL.append(self.model.addConstr(lhs=expr, sense=gurobipy.GRB.EQUAL, rhs=self.water_network.ZeroVector[i],name='L'+str(i)))
但是,我不能再使用 getConstrs 一次更新所有约束,因为有些只需要更改 RHS,而另一些只需要更改 LHS。所以我做了以下更新(片段 3):
self.model.setAttr("LB",self.model.getVars(), self.water_network.Bounds[:,0])
self.model.setAttr("UB", self.model.getVars(), self.water_network.Bounds[:,1])
self.model.setAttr("OBJ", self.model.getVars(), self.water_network.unitC)
# Update A rhs...
for i in range(len(self.water_network.edge_name_list)):
self.model.setAttr("RHS", self.model.getConstrs()[i],self.water_network.b[i])
# Update L expr...
x1=self.model.getVars()
n=len(self.water_network.node_list) # because there are n rows in the A constrains, and L constraints are added after
# Now i rebuild the LHS expressions
for i in range(len(self.water_network.ZeroVector)):
start = self.water_network.L_sparse.indptr[i]
end=self.water_network.L_sparse.indptr[i+1]
variables=[x1[j] for j in self.water_network.L_sparse.indices[start:end]]
coeff=self.water_network.L_sparse.data[start:end]
expr = gurobipy.LinExpr(coeff, variables)
self.model.setAttr("LHS",self.model.getConstrs()[n+i],expr)
self.model.update()
self.model.optimize()
当我 运行 问题时,它初始化正常,但在第二步 returns 这个错误:
File "model.pxi", line 1709, in gurobipy.Model.setAttr
TypeError: object of type 'Constr' has no len()
违规行是:
self.model.setAttr("RHS", self.model.getConstrs()[i],self.water_network.b[i])
两个问题:1) 为什么会这样?将 getConstrs()[i]
替换为 getConstrByName('A'+str(i))
也会因完全相同的错误而失败。如何更新特定约束的RHS/LHS?
2) 有没有办法更有效地更新 self.EqualityConstraintA 列表中包含的约束的 RHS,然后更新 self.EqualityConstraintL 列表中包含的其他约束的 LHS?
非常感谢!
滴
模型对象上的setAttr
函数用于
- 在模型上全局设置属性
- 设置变量列表的属性
- 设置约束列表的属性
单个约束和变量对象有自己的 setAttr 函数来设置单个变量和约束的属性。在你的情况下,
for i in range(len(self.water_network.edge_name_list)):
self.model.getConstrs()[i].setAttr('RHS', self.water_network.b[i])
它可以被更多 pythonic 替代(并且可能更有效)
m = self.model
constrs = m.getConstrs()[:len(self.water_network.edge_name_list)]
m.setAttr('RHS', constrs, self.water_network.b)
使用 gurobi 和 python 我正在尝试解决以下形式的水平衡(类似于 classic 运输问题)线性规划问题:
根据以下条件将 c'x 最小化:
Ax=b
lb<=x<=ub
A、L 是稀疏 crs scipy 矩阵,c,b,lb,ub 是向量。
我的问题应该更新多个步骤,并且一些元素已更新为新值。具体来说,A 是固定的,所有其他元素在每一步都获得新值。以下代码片段完美运行,是我目前使用的基础(忽略 "self",因为模型嵌入在求解器 class 中,而“water_network 是保存值的图形对象,每个步骤的属性):
### Snippet 1: Formulating/initializing the problem
# unitC is the c vector
# Bounds holds both lb and ub values for each x
self.model = gurobipy.Model()
rows, cols = len(self.water_network.node_list), len(self.water_network.edge_name_list)
self.x1 = []
for j in range(cols):
self.x1.append(self.model.addVar(lb=self.water_network.Bounds[j,0], ub=self.water_network.Bounds[j,1],obj=self.water_network.unitC[j]))
self.model.update()
self.EqualityConstraintA=[]
for i in range(rows):
start = self.water_network.A_sparse.indptr[i]
end = self.water_network.A_sparse.indptr[i+1]
variables = [self.x1[j] for j in self.water_network.A_sparse.indices[start:end]]
coeff = self.water_network.A_sparse.data[start:end]
expr = gurobipy.LinExpr(coeff, variables)
self.EqualityConstraintA.append(self.model.addConstr(lhs=expr, sense=gurobipy.GRB.EQUAL, rhs=self.water_network.b [i],name='A'+str(i)))
self.model.update()
self.model.ModelSense = 1
self.model.optimize()
以下简单片段用于更新每一步的问题。注意我使用 getConstrs 函数:
#### Snippet 2: Updating the constraints, working ok for every step.
self.model.setAttr("LB",self.model.getVars(), self.water_network.Bounds[:,0])
self.model.setAttr("UB", self.model.getVars(), self.water_network.Bounds[:,1])
self.model.setAttr("OBJ", self.model.getVars(), self.water_network.unitC)
self.model.setAttr("RHS", self.model.getConstrs(),self.water_network.b)
当应该向问题添加一组新的约束时出现问题,形式为:
Lx=0 其中L是每一步更新的稀疏矩阵!现在在公式中,我在片段 1 之后添加以下内容:
self.EqualityConstraintL=[]
leakrows= len(self.water_network.ZeroVector)
for i in range(leakrows):
start = self.water_network.L_sparse.indptr[i]
end=self.water_network.L_sparse.indptr[i+1]
variables=[self.x1[j] for j in self.water_network.L_sparse.indices[start:end]]
coeff=self.water_network.L_sparse.data[start:end]
expr = gurobipy.LinExpr(coeff, variables)
self.EqualityConstraintL.append(self.model.addConstr(lhs=expr, sense=gurobipy.GRB.EQUAL, rhs=self.water_network.ZeroVector[i],name='L'+str(i)))
但是,我不能再使用 getConstrs 一次更新所有约束,因为有些只需要更改 RHS,而另一些只需要更改 LHS。所以我做了以下更新(片段 3):
self.model.setAttr("LB",self.model.getVars(), self.water_network.Bounds[:,0])
self.model.setAttr("UB", self.model.getVars(), self.water_network.Bounds[:,1])
self.model.setAttr("OBJ", self.model.getVars(), self.water_network.unitC)
# Update A rhs...
for i in range(len(self.water_network.edge_name_list)):
self.model.setAttr("RHS", self.model.getConstrs()[i],self.water_network.b[i])
# Update L expr...
x1=self.model.getVars()
n=len(self.water_network.node_list) # because there are n rows in the A constrains, and L constraints are added after
# Now i rebuild the LHS expressions
for i in range(len(self.water_network.ZeroVector)):
start = self.water_network.L_sparse.indptr[i]
end=self.water_network.L_sparse.indptr[i+1]
variables=[x1[j] for j in self.water_network.L_sparse.indices[start:end]]
coeff=self.water_network.L_sparse.data[start:end]
expr = gurobipy.LinExpr(coeff, variables)
self.model.setAttr("LHS",self.model.getConstrs()[n+i],expr)
self.model.update()
self.model.optimize()
当我 运行 问题时,它初始化正常,但在第二步 returns 这个错误:
File "model.pxi", line 1709, in gurobipy.Model.setAttr
TypeError: object of type 'Constr' has no len()
违规行是:
self.model.setAttr("RHS", self.model.getConstrs()[i],self.water_network.b[i])
两个问题:1) 为什么会这样?将 getConstrs()[i]
替换为 getConstrByName('A'+str(i))
也会因完全相同的错误而失败。如何更新特定约束的RHS/LHS?
2) 有没有办法更有效地更新 self.EqualityConstraintA 列表中包含的约束的 RHS,然后更新 self.EqualityConstraintL 列表中包含的其他约束的 LHS?
非常感谢!
滴
模型对象上的setAttr
函数用于
- 在模型上全局设置属性
- 设置变量列表的属性
- 设置约束列表的属性
单个约束和变量对象有自己的 setAttr 函数来设置单个变量和约束的属性。在你的情况下,
for i in range(len(self.water_network.edge_name_list)):
self.model.getConstrs()[i].setAttr('RHS', self.water_network.b[i])
它可以被更多 pythonic 替代(并且可能更有效)
m = self.model
constrs = m.getConstrs()[:len(self.water_network.edge_name_list)]
m.setAttr('RHS', constrs, self.water_network.b)