Gurobi的问题-添加带有回调功能的用户剪切



我目前正在研究一个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.moptimize(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))

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

Alessandro

您应该通过变量的dict来复制它们。

要获得变量索引,您还必须制作索引列表的副本。

试试这个:

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()

相关内容

最新更新