Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.

 View Only
  • 1.  Adding lazy constraints using callback in CPLEX python API

    Posted 02/11/17 06:17 PM

    Originally posted by: SinaF


    Hi,

    I used to work with Gurobi-python interface to solve my optimization problem and I have recently switched to CPLEX python API. I want to add some lazy constraints through callback function. In Gurobi, once a MIP solution is found, I can check a condition and if it is necessary, I will add the lazy constraints. The only example of callback function for CPLEX python API is as follows:

     

    class BendersLazyConsCallback(LazyConstraintCallback):

        def __call__(self):
            x = self.x
            workerLP = self.workerLP
            numNodes = len(x)

            # Get the current x solution
            sol = []
            for i in range(numNodes):
                sol.append([])
                sol[i] = self.get_values(x[i])

            # Benders' cut separation
            if workerLP.separate(sol, x):
                self.add(constraint=workerLP.cutLhs,
                         sense="G",
                         rhs=workerLP.cutRhs)

     

    Now, I have some basic questions:

    1- Do I have to define a class?

    2- What is 'self' here?

    3- How can I make sure that this function is called when a MIP solution is found?

    4- Can I simply call this function as model.solve(callback)?

    I appreciate your help in advance.


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: Adding lazy constraints using callback in CPLEX python API

    Posted 02/12/17 12:38 AM

    First of all, the example you quoted is not the only example. Please take a look at the admipex5.py example shipped with CPLEX. This has a much simpler example for a lazy constraint callback.

    Now for your questions:

    1. Yes. In the CPLEX Python API any custom callback is defined by deriving a class from the appropriate callback class.
    2. 'self' is a reference to the instance calling this function. This is a Python keyword. If you are unclear about this you probably need to read up on how define classes in Python.
    3. You have to register the callback with the Cplex instance that performs the solve. This is done via the cplex.register_callback. Again, check the admipex5.py example how to do that.
    4. No, the solve() function takes no callback arguments.

    For your benefit I have copied the relevant parts from admipex5 here and added some comments:

    # Define a lazy constraint callback class.
    # The __call__ function will be invoked whenever CPLEX finds a feasible solution.
    # The proposed new integer solution is available via get_values(), lazy constraints
    # are added via add()
    class MyLazy(LazyConstraintCallback):
    
        def __call__(self):
            indices = ["W11", "W12", "W13", "W14", "W15"]
            act = 0.0
            for i in indices:
                act += self.get_values(i)
            if act > 3.01:
                self.add(constraint=cplex.SparsePair(ind=indices, val=[1.0] * 5),
                         sense="L",
                         rhs=3.0)
                         
    ...
    # Register the callback with the Cplex instance that performs the solve.
    # Function register_callback() creates a new instance of the specified class.
    # The newly created instance is returned in case you need to set some fields etc.
    cplex.register_callback(MyLazy)
    ...
    # Solve the model. The callback will be invoked automatically for any integer feasible
    # solution CPLEX finds.
    cplex.solve()
    

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: Adding lazy constraints using callback in CPLEX python API

    Posted 02/12/17 10:47 AM

    Originally posted by: SinaF


    I really appreciate your help. Do I need to change any parameter to improve the performance of Cplex when I add lazy constraints? Once I add this function, optimization becomes very slow.


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: Adding lazy constraints using callback in CPLEX python API

    Posted 02/12/17 02:41 PM

    A lazy constraint callback is a control callback. When adding a control callback then by default two things happen

    1. CPLEX switches from dynamic search to traditional search.
    2. CPLEX switches from multi-threaded to single-threaded mode.

    You cannot do anything about 1 (dynamic search is just not compatible with control callbacks) but you can switch back to multi-threading by explicit setting the thread count. For example:

    cplex.parameters.threads.set(cplex.get_num_cores())

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: Adding lazy constraints using callback in CPLEX python API

    Posted 02/22/17 10:50 AM

    Originally posted by: SinaF


    Do you know how can I print the lazy constraints that I am adding through callback function? I just want to make sure that I am adding correct constraints as lazy.


    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: Adding lazy constraints using callback in CPLEX python API

    Posted 02/27/17 09:46 AM

    Ryan explained how to print lazy constraints here.


    #CPLEXOptimizers
    #DecisionOptimization