Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python passing callback function in a class

I have to try to move from the non-class-based coding style into class-based coding style, but facing an issue. The optimize() function takes a callback function mycallback(). The code works perfectly fine in Non-class-based method, but when I moved it to class-based method, I got an error "mycallback() takes exactly 3 arguments (1 given)".

What is the right way to pass a callback function in the class-based method?

(A) Non-class-based method:

def mycallback(model, where):
    pass

model = Model()
model.optimize(mycallback)

(B) Class-based method:

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

While this is a problem regarding passing a callback function to Gurobi's (an optimization solver) built-in function, I believe it is a more general question on how to pass a callback function defined in a class to another function in Python.


Error For method 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

Looks like it is likely to be Gurobi API issue. Wonder if any Gurobi dev will response.

like image 215
twfx Avatar asked Mar 29 '14 12:03

twfx


People also ask

How do you pass a callback in Python?

First define two functions, the callback and the calling code, then pass the callback function into the calling code. The callback function has access to the variables and parameters of the calling function.

How do you pass a callback function?

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. The above example is a synchronous callback, as it is executed immediately.

What does __ call __ do in Python?

__call__ in Python The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When the instance is called as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.

Can a callback function return a value Python?

The callback function looks like this: It accepts a value v, the current value of the series. It returns True and the value it found once it finds a value that can be evenly divided by 17. It returns True and None if it reaches the safety limit we set.


2 Answers

In general, self.model.optimize(self.mycallback) should work (note: no parens after mycallback).

It may fail if the code serializes the callable e.g., to be send via pipe/socket to another process (even on different machine):

from multiprocessing import Pool

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

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

It works on recent Python versions where methods are pickable.

Or it may fail if model.optimize() has a bug and check for the exact function type instead of accepting any callable.

like image 181
jfs Avatar answered Sep 18 '22 17:09

jfs


This issue still persists in gurobi 9.1. A simple workaround I found is to put the callback inside a method in your class, for instance:

def solve(self):
    self.model.update()
       def lazyCallback(model, where):
       ...
    self.model.optimize(lazyCallback)
like image 32
rasul Avatar answered Sep 22 '22 17:09

rasul