Originally posted by: SystemAdmin
I will try to shed some light on this issue...
Let's talk about sequential and opportunistic parallel mode first.
In this case, the cut callback is called at every node with fractional LP solution. If the cut callback adds cuts, the LP is re-solved, and the cut callback is called again until no more cuts are found.
If the LP solution is integral, then CPLEX scans the user cuts and lazy constraints tables and adds violated inequalities. Additionally, the cut callback is called. Again, if at least one constraint has been added, the LP is re-solved and the process is iterated until the LP solution is fractional or no additional cuts have been found.
So, I think that all what you need is indeed already there.
Deterministic parallel mode is a bit more complicated.
The cut callback is again called at every node, but if it finds cuts we cannot immediately add them to the LP because this is incompatible with how we manage the data structures during deterministic parallel MIP solving. Instead, the cuts are only moved into some internal pool and then added to the LP at the next synchronization point. As a consequence, the LP at the current node is not resolved (because no cuts have been added immediately) and no second round of cuts is generated.
In the case of integral LP solutions, however, we are basically doing the same as in the opportunistic and sequential cases by using some trick. The user cuts and lazy constraint tables are scanned for violated inequalities and the cut callback is called. If at least one cut has been found, the cuts are directly added to the LP, the LP is solved and the process is iterated, just like in the opportunistic case. If no more cuts have been found, we force a synchronization such that we can keep the cuts in the LP even in deterministic parallel mode. Note that this forcing of a synchronization can be pretty time consuming, which is why we do not use the same trick for the regular cuts. But in the case of integer feasible LP solutions, we need to continue searching for cuts until the LP solution is fractional or no cuts are found, which means the solution is a new incumbent. Thus, there is no other way than doing this trick with forcing synchronization.
Hope this helps. The suggestion of Paul to queue cuts found in the incumbent callback makes some sense but is actually not necessary. It should suffice to just reject infeasible solutions in the incumbent callback without generating a cut. The incumbent callback is mainly used for solutions that have been generated by primal heuristics. Therefore, a cut that cuts off such a solution may not be very useful for the search tree since the heuristic solution may be very far away from any LP solution that is encountered during the search. Since the cut callback is called for every integral LP solution, it suffices to separate cuts in the cut callback.
I don't understand the reason why you would even need a branch callback. This sounds very strange...
Tobias
#CPLEXOptimizers#DecisionOptimization