Skip to main content

Getting a first integer feasible point with callbacks

Ongoing

Comments

4 comments

  • Official comment
    Simranjit Kaur
    Gurobi Staff Gurobi Staff
    This post is more than three years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum. Or why not try our AI Gurobot?.
  • Maliheh Aramon
    Gurobi Staff Gurobi Staff

    Hi Lukas, 

    An easier approach might be to use the SolutionLimit parameter as a termination criterion. By setting the SolutionLimit parameter to 1, the optimization would terminate as soon as one feasible solution is found.

    To answer your question about the callback, the error occurs because the self.cb is not a function. It is an instance method of an object. There is a difference between methods and functions in Python. A method is invoked by an object and it cannot exist without an object calling to it. However, a function is independent and is invoked by its name.

    There are two options to fix this:

    • The first option is to make the self.cb method a static method as shown below:
    class Method:
    @staticmethod
    def cb(model, where):
    if where == GRB.Callback.MIPSOL:
    model._ub = model.cbGet(GRB.Callback.MIPSOL_OBJ)
    model.terminate()
    • The second option is to define the callback as a function outside the class and pass it as an argument to the method calling the optimize() method.

    To pass data to the callback function, you should do it through the Model object. You should define the statement model._ub = float("inf") before the optimization begins, then your callback function can query the value of model._ub. Note that the name of the user data field must begin with an underscore.

    You might find the snippet below useful as a minimum working example of what you are interested in.

    import gurobipy
    from gurobipy import GRB

    class Model:
    def__init__(self):
    self.model = gurobipy.read("examples/data/glass4.mps")
    # Initialize the upper bound
    self.model._ub = float("inf")

    @staticmethod
    def cb(model, where):
    if where == GRB.Callback.MIPSOL:
    model._ub = model.cbGet(GRB.Callback.MIPSOL_OBJ)
    model.terminate()

    def get_first_solution(self):
    self.model.optimize(Model.cb)
    print(f"ub: {self.model._ub}")

    if __name__ == "__main__":
    model = Model()
    model.get_first_solution()
     

    Best regards,

    Maliheh

    0
  • Lukas Winkel
    Gurobi-versary
    Conversationalist
    First Question

    Hi Maliheh,

    thank you for the fast answer, the solution approach with the SolutionLimit set to 1 is perfectly feasible for my use case. Also thank you for explaining the problems with callbacks!

    Best,

    Lukas

    0
  • Akhilesh Soni
    Gurobi-versary
    First Comment

    Is the following way of using the nested function a reasonable way to do this? I have a lot of instance attributes that I need to pass to the callback.
    I am curious if there is any latency that might arise if callback accesses instance data (e.g., large data matrix) from a nested function.


    import gurobipy
    from gurobipy import GRB

    class Model:
    def __init__(self):
    self.model = gurobipy.read("examples/data/glass4.mps")
    # Initialize the upper bound
    # self.model._ub = float("inf")
    self.ub=float("inf)


    def get_first_solution(self):
    def cb(model, where):
    if where == GRB.Callback.MIPSOL:
    self.ub = model.cbGet(GRB.Callback.MIPSOL_OBJ) # note the use of self here
    model.terminate()
    self.model.optimize(cb)
    print(f"ub: {self.ub}")
    0

Post is closed for comments.