Decision Optimization

 View Only
  • 1.  Using Generic Callback to add Lazy constraints, User cuts and use as an HeuristicCallback

    Posted Wed March 01, 2023 04:50 PM

    Hello everyone, 

    I am working on a MILP that is decomposable into a master problem (MP) containing only integer variables (x) and a sub-problem (SP) containing only continuous variables (y). This is known as Benders decomposition.  

    I start by solving the MP. Then for every incumbent solution (x vars are integer and feasible), the SP  is solved to generate feasibility cuts (I am only interested in these cuts).

    In addition to the Benders feasibility cuts, I am also interested in adding violated lazy constraints (that are removed initially from the MP and then added only if they are violated by the current incumbent solution, thus containing only integer var), and user cuts to improve the LP relaxation (containing both x and y vars). 

    Thus, I am trying to use the generic callback to add:

    • Lazy constraints and Benders Feasibility cuts in Candidate context.
    • User cuts in Relaxation context.

    While adding the lazy constraints doesn't pose any problem, I am getting the following error when adding user cuts : ilog.cplex.CpxException: CPLEX Error  1006: Error during callback.

    I will try to show how I initialized the callback, and be as simple as possible:

    //I initialize the callback taking MP as argument: Callback callback = new Callback(master);

    //attach it to the master problem, to generate both lazy and user cuts: master.use(callback, IloCplex.Callback.Context.Id.Candidate | IloCplex.Callback.Context.Id.Relaxation);

    public class Callback implements IloCplex.Callback.Function  {

    public synchronized void invoke(final IloCplex.Callback.Context context){

    if(context.inRelaxation()) { //add user cuts 

    I got the vars values using context.getRelaxationPoint(x), and since the user cuts contain also y var from SP, i got the values of y using Ilocplex.getValue(y)

    For instance if the cuts to be added should be y <= x then it is added as following:  

    expression.addTerm(1, y);

    expression.addTerm(-1, x);

    IloRange range = master.getCplex.le(expression, 0);

    context.addUserCut(range, IloCplex.CutManagement.UseCutForce, false); I suspect that the error comes from here.

    if(context.inCandidate()) {

    I got the vars values using context.getCandidatePoint(x), and the violated lazy constraints and feasibility cuts are added. }

    }

    I have a couple of questions regarding this: 

    1. What am I doing wrong ? and How to use both callbacks using the generic callback ? 
    2. Is it possible to use a callback for the SP when it's feasible ? 
    3. I am also interested in using Heuristic Callback to change a fractional solution to an integer one using my own Routine (or change an integer feasible solution with an own one). I know CPXXcallbackpostheursoln and CPXcallbackpostheursoln has to be used. Does anyone has a small example on using these routines ? In which context has to be called (Relaxation context then use the routine) ? 

    Thank you for your help. It is much appreciated.



    ------------------------------
    ISSA .
    ------------------------------


  • 2.  RE: Using Generic Callback to add Lazy constraints, User cuts and use as an HeuristicCallback

    IBM Champion
    Posted Wed March 01, 2023 06:49 PM

    If I understand this correctly (which is by no means certain), you are trying to add cuts to the master problem that contain variables y that only appear in the subproblem and do not belong to the master problem. That would certainly cause an error.



    ------------------------------
    Paul Rubin
    Professor Emeritus
    Michigan State University
    ------------------------------



  • 3.  RE: Using Generic Callback to add Lazy constraints, User cuts and use as an HeuristicCallback

    Posted Thu March 02, 2023 07:28 AM

    Hello Paul, thank you (always) for your help.

    Yes you understood this correctly. The y variables do not belong to the MP, they only appear in the SP.

    Everytime the MP finds a feasible and integer solution, the SP which is an LP is solved once to generate feasibility cuts (takes as input fixed integer x vars) that are added to the MP. In addition violated lazy constraints are also added.

    I see now why that would cause an error. 

    Do you think there's a way to add those user cuts (for fractional x vars) ?

    While this can be done by solving a MILP model containing both x and y vars, I can't add anymore my feasibility cuts since the complicated constraints connecting x and y are already in the model, and hence always feasible with respects to those constraints.

    I am not sure though how this can be done using the MP and SP models. 

    Any ideas are much appreciated. Thank you.

      



    ------------------------------
    ISSA .
    ------------------------------



  • 4.  RE: Using Generic Callback to add Lazy constraints, User cuts and use as an HeuristicCallback

    IBM Champion
    Posted Thu March 02, 2023 02:50 PM

    There is a programmatic tactic that would allow you to add the user cuts, but I very much doubt they would behave the way you expect. Let's say the feasible regions are x in X for the master problem and y in Y for the subproblem, and you add a cut a'x + b'y <= c in the master problem. The difficulty here is that the master problem is not going to restrict y to Y. Using your example of y <= x for a user cut in the MP, and assuming x and y are nonnegative, what would stop CPLEX from simply setting y = 0, regardless of whether that would be accepted in the subproblem? So the question is, are you confident that the user cuts would make a meaningful improvement in the MP (and be valid) without the MP knowing anything about the feasible region Y of the subproblem?



    ------------------------------
    Paul Rubin
    Professor Emeritus
    Michigan State University
    ------------------------------



  • 5.  RE: Using Generic Callback to add Lazy constraints, User cuts and use as an HeuristicCallback

    Posted Mon April 10, 2023 09:17 AM

    Hello again Paul, 

    What I actually want is to reject the x variables that violate such inequalities. As you mentioned adding y <= x in the MP wouldnt be usefull for the MP neither the sub-problem. So my idea is to find these violated inequalities after solving the MP and SP, then when the SP is created again, these constraints are added to it. Then we check for the given x whether the SP is feasible or not.

    Let's assume the inequalties I want to check are y >= eps * x, where eps is a very small constant. In other words, if y = 0 and x > 0 then a violated inequality exists and should be added to the sub-problem.

    when I recreate the SP, I add the following constraint y >= 0 then change the rhs based on the value of x. 

    Let's assume that the MP contains only integer variables x, and the SP contains the continuous variables y. 

    First the MP is solved, then supply the SP with x* then solve the SP which has two cases:

    case 1: If SP is infeasible I find benders feasibility cuts and add them to the MP. 
    case 2: if SP is optimal: I find violated inequalities and add them in a list. 

    I am using Generic callback to add the cuts in the MP. In addition, I use deterministic parallel search by creating a copy of the SP on a different thread similarly to the example provided by CPLEX BendersATSP2.java. 

    So basically the first copy of the SP has zero cuts since it's the first iteration. Then, if any violaed inequality is found, it is added to a list to be used when I create SP.

    However, when creating new subproblems on different thread I got the following error: 

    ilog.cplex.IloCplex$MultipleUseException: attempt to use modeling element in more than one model
        at ilog.cplex.CplexI.checkCplexI(CplexI.java:354)
        at ilog.cplex.CplexI.useVars(CplexI.java:1542)
        at ilog.cplex.CpxRange.init(CpxRange.java:1309)
        at ilog.cplex.CpxRange.<init>(CpxRange.java:1342)
        at ilog.cplex.IloCplexModeler.addRange(IloCplexModeler.java:3821)
        at ilog.cplex.IloCplexModeler.addGe(IloCplexModeler.java:4104)
        at com.renault.sicg.optimfcc.test.BendersMPSub.add_ValidInequalities(BendersMPSub.java:343)
        at com.renault.sicg.optimfcc.test.BendersMPSub.<init>(BendersMPSub.java:120)
        at com.renault.sicg.optimfcc.test.MPBendersCallback.invoke(MPBendersCallback.java:150)
        at ilog.cplex.CplexI.invokeGenericCallback(CplexI.java:8145)

    The line in the code where this exception is raised is the following:  cut[s][r][t] = sub.addGe(expression, 0);

    It seems this happens when I try to add the cut in model on different thread ( I suppose) at the same time. 

    I also add the log below.The exception is raised when 2 SP are created on thread 3 and 4.  What am I doing wrong ? andis there a way to make this working? Thank you. 

    Version identifier: 20.1.0.0 | 2020-11-10 | 9bedb6d68
    CPXPARAM_MIP_Interval                            1
    Generic callback                                 0x66
    2023-04-10 14:06:40.117 [worker-1] DEBUG - Sub-problem created from thread 0  | Cuts size 0
    Lazy constraint(s) or lazy constraint/branch callback is present.
        Disabling dual reductions (CPX_PARAM_REDUCE) in presolve.
        Disabling presolve reductions that prevent crushing forms (CPX_PARAM_PREREFORM).
    stop
    1 of 1 MIP starts provided solutions.
    MIP start 'm1' defined initial solution with objective 16400.5922.
    Tried aggregator 1 time.
    MIP Presolve modified 7 coefficients.
    Reduced MIP has 151 rows, 140 columns, and 464 nonzeros.
    Reduced MIP has 0 binaries, 140 generals, 0 SOSs, and 0 indicators.
    Presolve time = 0.00 sec. (0.16 ticks)
    Tried aggregator 1 time.
    Reduced MIP has 151 rows, 140 columns, and 464 nonzeros.
    Reduced MIP has 0 binaries, 140 generals, 0 SOSs, and 0 indicators.
    Presolve time = 0.00 sec. (0.14 ticks)
    MIP emphasis: balance optimality and feasibility.
    MIP search method: dynamic search.
    Parallel mode: deterministic, using up to 12 threads.
    Root relaxation solution time = 0.00 sec. (0.22 ticks)

            Nodes                                         Cuts/
       Node  Left     Objective  IInf  Best Integer    Best Bound    ItCnt     Gap

    *     0+    0                        16400.5922        0.0000           100.00%
          0     0    14173.3562     1    16400.5922    14173.3562       25   13.58%
    2023-04-10 14:06:56.084 [read-746] DEBUG - Sub-problem created from thread 3  | Cuts size 1
    2023-04-10 14:06:56.085 [read-747] DEBUG - Sub-problem created from thread 4  | Cuts size 1





    ------------------------------
    ISSA .
    ------------------------------



  • 6.  RE: Using Generic Callback to add Lazy constraints, User cuts and use as an HeuristicCallback

    Posted Mon April 10, 2023 09:56 AM

    Update. I found where the error comes from. 
    Suppose I am looking for viloated cuts in a SP created on thread 0. If such a cut ecists I added the linear expression containing the y variables for this SP in a List to be used in other SP . 
    Then when I try to add the linear expression in newly createdSp on different threads I got this error since these linear expressions are for model created on thread 0. 

    I change the list of Linear expression to another one that gets the indices of variables to be used and it works perfectly. 



    ------------------------------
    ISSA .
    ------------------------------