9

我必须尝试从非基于类的编码风格转变为基于类的编码风格,但面临一个问题。optimize() 函数采用回调函数 mycallback()。该代码在非基于类的方法中运行良好,但是当我将其移至基于类的方法时,出现错误“mycallback() 恰好需要 3 个参数(给定 1 个)”。

在基于类的方法中传递回调函数的正确方法是什么?

(A) 非基于类的方法:

def mycallback(model, where):
    pass

model = Model()
model.optimize(mycallback)

(B) 基于类的方法:

class A:
    def __init__(self):
        self.model = Model()

    def solve(self):
        # Try method 1:
        self.model.optimize(self.mycallback())      <--- Error: mycallback() takes exactly 3 arguments (1 given)
        # Try method 2:
        # self.model.optimize(self.mycallback)  <--- Error:  Callback argument must be a function

    def mycallback(self, model, where):     
        pass

虽然这是一个关于将回调函数传递给 Gurobi(优化求解器)内置函数的问题,但我相信这是一个更普遍的问题,即如何将一个类中定义的回调函数传递给 Python 中的另一个函数。


方法 2 的错误:

   self.model.optimize(self.mycallback)  
   File "model.pxi", line 458, in gurobipy.Model.optimize      (../../src/python/gurobipy.c:34263)
   gurobipy.GurobiError: Callback argument must be a function

看起来很可能是 Gurobi API 问题。想知道是否有任何 Gurobi 开发人员会做出回应。

4

4 回答 4

5

一般来说,self.model.optimize(self.mycallback)应该可以工作(注意:在 之后没有括号mycallback)。

如果代码序列化可调用,例如通过管道/套接字发送到另一个进程(即使在不同的机器上),它可能会失败:

from multiprocessing import Pool

class C:
    def method(self, i):
        return "called", i

if __name__=="__main__":
    print(Pool().map(C().method, range(10)))

它适用于方法可选的最新 Python 版本。

或者,如果model.optimize()有错误并检查确切的函数类型而不是接受任何可调用的,它可能会失败。

于 2014-03-29T13:02:03.150 回答
1

这个问题在 gurobi 中仍然存在9.1。我发现一个简单的解决方法是将回调放在类的方法中,例如:

def solve(self):
    self.model.update()
       def lazyCallback(model, where):
       ...
    self.model.optimize(lazyCallback)
于 2021-06-01T23:03:20.733 回答
0

似乎如果您从对象中删除回调,那么它就可以工作。您可以将其用作解决方法,直到您可以在课堂上获得回调。也就是说,从课堂上调用这条线......

def solve(self):
    self.model.optimize(mycallback)

...到类之外的这个函数。

def mycallback(self, model, where):     
    pass

一点也不优雅,但希望开发人员能加入进来。

于 2014-03-31T03:47:24.760 回答
0

问题self.mycallback在于它是一种方法,而 Gurobi 的optimize方法确实需要一个函数

有多种方法可以创建self.mycallback一个函数。这里有些例子:

一种方法是制作mycallback静态方法:

@staticmethod
def mycallback(model, where): 
    pass

另一个是将方法包装到一个函数中,如下所示:

self.model.optimize(lambda model, where: self.mycallback(model, where))    
于 2021-10-11T09:26:04.883 回答