Decision Optimization

Decision Optimization

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


#Analytics
#DecisionOptimization
#DecisionOptimization
 View Only
Expand all | Collapse all

When is IncumbentCallback invoked?

  • 1.  When is IncumbentCallback invoked?

    Posted 08/21/14 08:29 AM

    Originally posted by: VKV7_Anulark_Naber


    I now applied an IncumbentCallback to use the information (objective function value) of a new incumbent to update the parameters that will be used in UserCutCallback, so the cuts will be tighter. In the documentation, it says "The user-written callback will be called each time a new incumbent solution has been found, including when solutions are provided by the user's heuristic callback routine." However, it does not seem that the incumbent callback is called everytime a new solution is found. As you can see in the log output of running 1 thread shown below, there is some delay until it is invoked. How can I force cplex to invoke incumbentcallback every time, or shouls I use any other callback to do the job? This model does have lazy constraints (in a table), and the new incumbent should satisfy the lazy constraints.

    I also need to mention that when I interrupted solve() when a new incumbent is found, the incumbent callback was not invoked when the last solution is found either. I do not prefer this interruption, because when restart, cplex thows out all cuts, and therefore I changed to implement the above incumbentcallback.

    *  1259+  828                           45.3522       41.2124    33900    9.13%
                                                         Table: 3                  
    Found incumbent of value 45.352156 after 1.81 sec. (1495.45 ticks)
       1259   828       45.5000     0       45.3522       41.2124    33900    9.13%    ChangeRes#16 U   1259   1256     48
                                                         Table: 4                  
    -------------Update Parameters with 45.3522
    *  1369   774      integral     0       45.2893       41.2124    35896    9.00%    ChangeRes#13 D   1369   1368     54
                                                         Table: 4                  
    Found incumbent of value 45.289336 after 15.92 sec. (3477.92 ticks)
       1686   977       44.7893    18       45.2893       41.2124    41656    9.00%    AfterStop#44 D   1686   1684     18
       1915  1093       42.8032    20       45.2893       41.2124    48136    9.00%    AfterStop#34 D   1915   1914     16
                                                         Table: 2                  
       2790  1625       41.6561    49       45.2893       41.2124    74035    9.00%    AfterStop#44 D   2790   2789     15
    Elapsed time = 17.13 sec. (4912.57 ticks, tree = 14.04 MB, solutions = 2)
    -------------Update Parameters with 45.2893
    *  2978   881      integral     0       43.2783       41.2124    77404    4.77%    AfterStop#11 U   2978   2975     52
                                                        Table: 11                  
    Found incumbent of value 43.278333 after 19.58 sec. (5462.15 ticks)
    -------------Update Parameters with 43.2783
    *  3078+  892                           43.1734       41.2124    79312    4.54%
    Found incumbent of value 43.173413 after 20.42 sec. (5594.19 ticks)
    -------------Update Parameters with 43.1734
    *  3078+  871                           43.0237       41.2124    79312    4.21%
    Found incumbent of value 43.023718 after 25.59 sec. (6433.54 ticks)
    -------------Update Parameters with 43.0237
    *  3078+  780                           42.8476       41.2124    79312    3.82%
    Found incumbent of value 42.847564 after 28.27 sec. (6935.46 ticks)
       3078   782       42.2583    19       42.8476       41.2124    79312    3.82%   AfterStart#95 D   3078   3077     11
                                                         Table: 2                  
       4139  1415       42.2583    18       42.8476       41.2124   103480    3.82%   AfterStart#36 D   4139   4138     22
       5244  2176       42.2583     7       42.8476       41.2124   127335    3.82%   AfterStart#58 U   5244   5243     18
       6417  2974       41.9856    24       42.8476       41.2124   150945    3.82%     ChangeRes#3 D   6417   6416     16
                                                         Table: 6                  
     

    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: When is IncumbentCallback invoked?

    Posted 08/22/14 01:41 AM

    This looks very odd. The incumbent callback is invoked before a new incumbent is printed to the node log (the callback may reject the incumbent in which case nothing will be printed to the log). Could this be an issue with output buffering? How are you printing the lines from your callback? Are you printing to cplex.out() or to some other stream?


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: When is IncumbentCallback invoked?

    Posted 08/22/14 04:26 AM

    Originally posted by: VKV7_Anulark_Naber


    These lines --------------Update... are printed in IncumbentCallback to std::ofstream along with the node log. 

    These are the settings for cplex output:

    ofstream &file; cplex.setOut(file); cplex.setWarning(file); cplex.setError(file);
     
    cplex.setParam(IloCplex::SimDisplay, 0); cplex.setParam(IloCplex::MIPDisplay, 4);
     

    I am using cplex 12.6.0.1.


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: When is IncumbentCallback invoked?

    Posted 08/22/14 09:08 AM

    I still feel like something must be wrong on your side. I just tried this simple code:

    #include <ilcplex/ilocplex.h>

    ILOINCUMBENTCALLBACK1(inccb, std::ostream &, output) {
       output << "#### Incumbent callback: " << getObjValue() << std::endl;
    }

    int
    main(int argc, char **argv)
    {
       std::ostream &out = std::cout;

       for (int i = 1; i < argc; ++i) {
          IloEnv env;
          IloModel model(env);
          IloCplex cplex(model);
          cplex.setOut(out);
          cplex.setWarning(out);
          cplex.use(inccb(env, out));
          cplex.importModel(model, argv[i]);
          cplex.solve();
          env.end();
       }
       return 0;
    }

    It produces the expected output:

    ...
          0     0     1098.3075    55                    Cuts: 16      944         
    #### Incumbent callback: 1435
    *     0+    0                         1435.0000     1098.3075      944   23.46%
    #### Incumbent callback: 1423
    *     0+    0                         1423.0000     1098.3075      944   22.82%
    #### Incumbent callback: 1169
    *     0+    0                         1169.0000     1098.3075      944    6.05%
    #### Incumbent callback: 1168
    *     0+    0                         1168.0000     1098.3075      944    5.97%
          0     2     1098.3075    55     1168.0000     1098.4376      944    5.96%                        0             0
    Elapsed time = 1.30 sec. (1063.51 ticks, tree = 0.00 MB, solutions = 4)
         25    23     1143.0156    22     1168.0000     1103.9525     1998    5.48%            x365 D     25     24     20
         70    50     1125.7917    35     1168.0000     1107.3700     4139    5.19%            x268 D     70     69      7
        178   109     1146.9736    29     1168.0000     1109.6815     6793    4.99%            x153 D    178    177     15
        335   224     1154.3310    31     1168.0000     1111.3530    10452    4.85%            x270 U    335    334     25
        501   336     1148.0454    27     1168.0000     1113.6307    14164    4.65%            x199 U    501     40      6
        637   428     1160.4792    17     1168.0000     1116.1585    18197    4.44%            x419 U    637    635     39
        782   518     1155.0654    24     1168.0000     1119.3741    22236    4.16%            x397 U    782    781     11
        928   606     1157.8902    23     1168.0000     1121.0777    26517    4.02%            x147 U    928    926     12
       1092   711     1153.1257    17     1168.0000     1122.8651    30435    3.86%             x88 D   1092   1091     64
    #### Incumbent callback: 1162
    *  1450   793      integral     0     1162.0000     1126.1360    39911    3.09%            x352 D   1450   1449     41
    Elapsed time = 3.54 sec. (3792.65 ticks, tree = 0.53 MB, solutions = 5)
    #### Incumbent callback: 1160
    *  1550+  783                         1160.0000     1126.9947    43092    2.85%
       1966   932     1155.7112    30     1160.0000     1132.0412    57356    2.41%              x3 D   1966   1965     29
       2468  1095     1146.4107    30     1160.0000     1136.8281    74076    2.00%            x298 D   2468   2467     32
       3062  1069        cutoff           1160.0000     1142.8966    90662    1.47%            x411 N   3062   1610     22
       3760   858     1155.8244     8     1160.0000     1149.2136   107294    0.93%            x351 D   3760   3759     36
    #### Incumbent callback: 1159
    *  3830+  759                         1159.0000     1149.8031   108633    0.79%
    #### Incumbent callback: 1158
    *  4347   275      integral     0     1158.0000     1154.0122   115604    0.34%            x108 D   4347   3018     33
    ...

    As you can see, the callback is always invoked before anything is printed to the node log. Could you try my simple code on your side?


    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: When is IncumbentCallback invoked?

    Posted 08/22/14 09:43 AM

    Originally posted by: VKV7_Anulark_Naber


    Thank you so much, Daniel. 

    The problem is that I use getIncumbentObjValue() instead of getObjValue(). Now it's working as we expected.

    I misunderstood what it says in the documentation:

    getIncumbentObjValue

    public IloNum getIncumbentObjValue() const

    Returns the value of the objective function of the incumbent solution (that is, the best integer solution found so far) at the time the invoking callback is called by an instance of IloCplex while solving a MIP. If there is no incumbent, this method throws an exception. 

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: When is IncumbentCallback invoked?

    Posted 08/25/14 07:21 AM

    Ah, this is a little subtle in the incumbent callback, I agree. Since the current incumbent has not yet been accepted (the incumbent callback could still reject it), getIncumbentObjValue() will return the objective value for the last incumbent that was accepted and not the incumbent for which the callback is invoked.

    The interesting thing is that you did not get an exception for the very first invocation of the incumbent callback. In that call there is no previous incumbent and getIncumbentObjValue() should throw an exception. Did you just ignore that exception or did you really not get any?


    #CPLEXOptimizers
    #DecisionOptimization


  • 7.  Re: When is IncumbentCallback invoked?

    Posted 08/25/14 07:56 AM

    Originally posted by: VKV7_Anulark_Naber


    No, I did not get any exceptions from getIncumbentObjValue().

    What are the reasons why incumbent callback would reject the current incumbent when it is better anyway? Why not just accept all better ones within tolerances?

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 8.  Re: When is IncumbentCallback invoked?

    Posted 08/25/14 03:34 PM

     

    The user may want reject a proposed incumbent without generating a cut. For instance, one way to collect a bunch of "good" (but not necessarily optimal) solutions is to store proposed incumbent and then reject them (so that they don't move the bound and cut off other good solutions). The solution pool feature might be a better way to do this, but it's possible a user would have criteria for letting the bound change that would be too funky to accomplish with the solution pool.


    #CPLEXOptimizers
    #DecisionOptimization


  • 9.  Re: When is IncumbentCallback invoked?

    Posted 08/26/14 05:26 AM

    Originally posted by: VKV7_Anulark_Naber


    Do you mean that "other good solutions" are those with the same obj value? In my case, I want any optimal solution, because my problem is there are too many solution and therefore slow convergnce to optimality. What I gathered from the difference or delay between getIncumbentObjValue() and getObjValue() is that even if a new solution is found, cplex does not automatically update the bound immediately and so some nodes which could have been pruned with the updated bound are not pruned. That answers the situation i got, when I terminate solve() each time a better solution is found in a solution pool , update bounds manually, and then solve() again., I got a better performance than waiting for IncumbentCallback to update an incumbent for me. The disadvantage of this manual approach is that cplex throws all cuts away and restarts from scratch.

    How can I force IncumbentCallback to do otherwise (as manually)? I would prefer that cplex accepts each BETTER solution and updates the bound immediately.


    #CPLEXOptimizers
    #DecisionOptimization


  • 10.  Re: When is IncumbentCallback invoked?

    Posted 08/26/14 02:42 PM

    Do you mean that "other good solutions" are those with the same obj value?

    Not necessarily. Sometimes decision makers want to see solutions that are suboptimal (but not by "too much") because they be more palatable than the "optimal" solution with respect to criteria not captured by the model. Researchers occasionally (for reasons I do not understand) want to count or characterize the set of all solutions within some epsilon of optimal.

    In my case, I want any optimal solution, because my problem is there are too many solution and therefore slow convergnce to optimality. What I gathered from the difference or delay between getIncumbentObjValue() and getObjValue() is that even if a new solution is found, cplex does not automatically update the bound immediately and so some nodes which could have been pruned with the updated bound are not pruned.

    I do not believe that statement is true. What is correct is that a newly identified solution at node K does not become an incumbent until it has survived both the incumbent callback (if present) and the lazy constraint callback (if present). Once both those callbacks are through, if the new solution has not been rejected/cut off, it becomes the new incumbent at node K and is immediately available for pruning of other nodes.

    That answers the situation i got, when I terminate solve() each time a better solution is found in a solution pool , update bounds manually, and then solve() again., I got a better performance than waiting for IncumbentCallback to update an incumbent for me. The disadvantage of this manual approach is that cplex throws all cuts away and restarts from scratch.

    Restarting the solution process at the root node, with a new incumbent, may allow CPLEX to do some bound tightening and add some cuts at the root node that it previously could not do, which may accelerate the process enough to compensate for the restart. That would be on a case by case basis; I do not think it would be true in general. I do not believe it is the result of any delay in asserting a new incumbent value after clearing the incumbent callback.

    How can I force IncumbentCallback to do otherwise (as manually)? I would prefer that cplex accepts each BETTER solution and updates the bound immediately.

    Again, as far as I know, it does.

     

    Paul

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 11.  Re: When is IncumbentCallback invoked?

    Posted 08/26/14 03:02 PM

    Originally posted by: VKV7_Anulark_Naber


    Thank you. Only one point:

    Do you mean that the incumbent callback is invoked before checking the lazy constraints? Does that also mean that getObjValue() is not really of an incument because it may not pass the lazy constraints? 

    As shown earlier in my log output (in the first post), getIncumbentObjValue() is not updated until later, shown with ---update, but getObjValue() is updated immediately as later corrected.


    #CPLEXOptimizers
    #DecisionOptimization


  • 12.  Re: When is IncumbentCallback invoked?

    Posted 08/26/14 03:08 PM

    I think the lazy constraint callback is invoked before the incumbent callback (but I might be mistaken). Regardless of the order, getObjective() in both callbacks should give the objective value of the proposed incumbent. If whichever callback is first called rejects the proposed incumbent, the second callback will not be called (for that solution -- it could be called at the same node for a different solution).


    #CPLEXOptimizers
    #DecisionOptimization


  • 13.  Re: When is IncumbentCallback invoked?

    Posted 08/26/14 03:12 PM

    Originally posted by: VKV7_Anulark_Naber


    Thank you.


    #CPLEXOptimizers
    #DecisionOptimization


  • 14.  Re: When is IncumbentCallback invoked?

    Posted 12/08/14 07:07 AM

    Originally posted by: VKV7_Anulark_Naber


    I have come across for some instances that the incumbentcallback is not invoked for every incument found. For example, this is the first incumbent found and the log file looks like:

    *   843   500      integral     0       32.8719       32.2571   182988    1.87%    ChangeRes#70 U   1486   1478     65
                                                         Cuts: 54                  
    Found incumbent of value 32.871861 after 18.81 sec. (1814.60 ticks)

    Then, the second incumbent is found and the log file looks like:

     --------Internally Update Parameters with Makespan 32.2571

    *107912+20986                           32.2571       32.2571 10090054    0.00%
                                                         Table: 1                  
    Found incumbent of value 32.257143 after 1523.81 sec. (152654.72 ticks)
     

    The comment line also shows that the incumbent callback is invoked.

    If the incumbent did not pass the lazyconstraints, the incumbent was then rejected, then the log file should not report the "Found incumbent.."

    What can be the reason why it is not doing so for the first incumbent? Thanks for any help.


    #CPLEXOptimizers
    #DecisionOptimization


  • 15.  Re: When is IncumbentCallback invoked?

    Posted 01/06/15 04:30 AM

    That should not happen and smells like a bug :-(

    Do you have an easy way or minimal code that you could provide us so that we can try to figure out what is going wrong?


    #CPLEXOptimizers
    #DecisionOptimization