Branching solution accepted although it violates presently added lazy constraints

The only guarantee that Gurobi gives with respect to lazy constraints is the following: before accepting an integer point as incumbent (the solution with current best objective value), Gurobi will always give you the opportunity to reject it.

In order to reject an incumbent, you must provide a constraint that cuts off the current solution (subject to numerical tolerances). In other words, you must provide one or more constraint(s) of the form a^{T}x \geq b with a^{T} \bar{x} < b (inequality), or a^{T}x = b with a^{T} \bar{x} \neq b (equality). Once you have rejected a solution \bar{x}, Gurobi guarantees that you will never encounter \bar{x} again.

What Gurobi does not guarantee:

  • That future integer solutions will satisfy the constraint(s) you have just submitted
  • That such constraints will be included in the LP relaxation, thus…
  • … that fractional solutions will satisfy the submitted constraints

Things that can typically happen:

  • You have a bug in your code
  • The constraint you are submitting is not actually violated, causing Gurobi to accept the solution
  • There are multiple solutions with same objective value and you did not cutoff all of them. This includes the case where Gurobi rejected the previous candidate solution but chose not to include the constraint in the formulation.

For debugging, you can keep track of all the solutions you encountered within the callback. If you see the same solution twice, then congratulations, you may have found a bug in Gurobi! If you never encounter the same solution twice, then consider some of the points above (especially the third one).

5 Likes