gpt4 book ai didi

python - Gurobi 问题 - 使用回调函数添加用户剪辑

转载 作者:太空宇宙 更新时间:2023-11-03 19:41:05 25 4
gpt4 key购买 nike

我目前正在研究 MILP 公式,我想使用 Gurobi 和分支剪切方法来解决该公式。我的模型是经典的时间窗取货和送货问题 (PDPTW) 的变体,为此定义了几类有效的不等式。当分支定界求解器运行时,如果满足当前节点中的某些条件,我想添加这些不等式(即,我想添加切割)。我的问题如下:

我的变量被定义为字典,这使得在制定约束时可以轻松使用它们,因为我可以轻松使用它们的原始索引。下面提供了我如何定义变量的示例

tauOD = {}
# Start- End-Service time of trucks
for i in range(0,Nt):
tauOD[i,0]=model.addVar(lb=0.0, ub=truckODTime[i][0],
vtype=GRB.CONTINUOUS,name='tauOD[%s,%s]'%(i,0))
tauOD[i,1]=model.addVar(lb=0.0, ub=truckODTime[i][1],
vtype=GRB.CONTINUOUS,name='tauOD[%s,%s]'%(i,1))

一旦根据变量、约束和成本函数定义了我的模型,在经典的分支定界问题中,我将简单地使用 model.optimize() 来启动该过程。在本例中,我使用命令 model.optimize(my_callback),其中 my_callback 是我定义的用于添加剪切的回调函数。我的问题是,由于某些原因,回调函数不喜欢定义为字典的模型变量。我发现的唯一解决方法如下:

model._vars = model.getVars() #---> added this call right before the optimization starts
model.optimize(mycallback)

然后在回调中我现在可以使用变量的顺序而不是索引来检索变量,如下所示:

def mycallback(model,where):
if where == GRB.Callback.MIPNODE:
status = model.cbGet(GRB.Callback.MIPNODE_STATUS)
# If current node was solved to optimality, add cuts to strenghten
# linear relaxation
if status == GRB.OPTIMAL:
this_Sol = model.cbGetNodeRel(model._vars) # Get variables of current solution
# Adding a cut
model.cbCut(lhs=this_Sol[123]+this_Sol[125],sense=GRB.LESS_EQUAL,rhs=1) #---> Dummy cut just
# for illustration
# purposes

上述剪切只是一个虚拟示例,用于表明我可以使用解决方案中排序的顺序变量而不是索引来添加剪切。例如,我希望能够在回调中编写一个约束:

x[0,3,0] + x[0,5,0] <= 1

但我唯一能做的就是写

this_Sol[123] + this_Sol[125] <= 1 (假设 x[0,3,0] 是我的解向量的第 124 个变量,x[0,5,0] 是第 126 个变量)。尽管知道变量的顺序是可行的,因为这取决于我在设置模型时如何创建它们,但这是一个更具挑战性的过程(并且容易出错),而不是像我在定义时那样能够使用索引我的模型的原始约束(参见下面的示例):

###################
### CONSTRAINTS ###
###################
# For each truck, one active connection from origin depot
for i in range(0,Nt):
thisLHS = LinExpr()
for j in range(0,sigma):
thisLHS += x[0,j+1,i]
thisLHS += x[0,2*sigma+1,i]
model.addConstr(lhs=thisLHS, sense=GRB.EQUAL, rhs=1,
name='C1_'+str(i))

大家有遇到过类似的问题吗?我的一个 friend 告诉我,由于某些原因,Gurobi 不喜欢在回调函数中定义为字典的变量,但我不知道如何规避这一点。任何帮助将不胜感激。谢谢!

亚历山德罗

最佳答案

您应该按照变量的字典复制变量。

要获取变量索引,您还必须复制操作系统索引列表。

试试这个:

model._I = model.I
model._J = model.J
model._K = model.K
model._x = model.x

您需要这些索引列表,以便可以循环每个目标变量 x 来验证某些条件。就像您为模型编写正常约束一样。

然后在回调中您可以进行索引迭代:

def mycallback(model,where):
if where == GRB.Callback.MIPNODE:

x = model.cbGetSolution(model._x)

for i in model._I:
if sum([x[i,j,k] for j in model._J for k in model._K]) > 1:
Add_the_cut()

关于python - Gurobi 问题 - 使用回调函数添加用户剪辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60418048/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com