# JuMP/CPLEX: seemingly not all lazy cuts are respected

**URL:** <https://discourse.julialang.org/t/jump-cplex-seemingly-not-all-lazy-cuts-are-respected/95798>\
**Category:** Optimization (Mathematical)\
**Created:** [March 9, 2023, 1:34pm UTC](https://discourse.julialang.org/t/jump-cplex-seemingly-not-all-lazy-cuts-are-respected/95798 "2023-03-09T13:34:17Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mike\_k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike_k/32/211864_2.png) [@mike\_k](https://discourse.julialang.org/u/mike_k)\
**Post date:** [March 9, 2023, 1:34pm UTC](https://discourse.julialang.org/t/jump-cplex-seemingly-not-all-lazy-cuts-are-respected/95798/1 "2023-03-09T13:34:17Z")

</div>

Dear folks,  
it seems that CPLEX sometimes does not respect all lazy cuts in the final solution. I know that there is no guarantee that it respects submitted cuts immediately, but it should do in the final solution afaik. Unfortunately, I am not able to produce an MWE for what I observe:  
I try to solve an ILP in which I add computationally expensive lazy cuts in a solver-specific callback. Thus, I want to avoid generating an already known cut for a candidate solution. In the callback I do something like:

```julia
if cut_already_submitted_for_current_candidate_solution
  return #"early-exit"
end
construct_and_submit_cut()
return

```

because CPLEX frequently suggests one-and-the-same candidate solution. Thus, without the “early-exit” in the if-statement, one-and-the-same cut might be generated and submitted more than once, in which case the solutions are always correct. However, with the “early-exit”, sometimes seemingly not all cuts are respected in the final solution - for some reason I do not know.  
As a workaround, I created a copy of my initial model and pass it to my callback function. Whenever I submit a `LazyConstraint()` to the initial model, I also add it as @constraint() to the copied model. Finally, after solving the branch-and-cut (with “early-exit”) for the initial model, I solve the (compact) copied model and obtain the expected solution.

Note: in case the objective value of my initial model is wrong, it is always lower than it should be (because I solve a minimization problem whose objective value is pushed up by the lazy constraints).  
Further note: I also tried to set the option `CPX_USECUT_FORCE` which did not help.

I tried different versions CPLEX 12.10 - 22.1. Moreover, I use JuMP v1.9.0, CPLEX.jl v0.9.7, MathOptInterface v1.13.1, and Julia 1.8.5.

Do you have any ideas why this strange behavior appears sometimes? Many thanks in advance.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 9, 2023, 5:45pm UTC](https://discourse.julialang.org/t/jump-cplex-seemingly-not-all-lazy-cuts-are-respected/95798/2 "2023-03-09T17:45:53Z")

</div>

The early exit is wrong. If cplex asks for the same point you need to give the cut again.

This can happen for a number of reasons.

To avoid recomputing, cache the cuts in a dictionary mapping point to cut.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 9, 2023, 8:32pm UTC](https://discourse.julialang.org/t/jump-cplex-seemingly-not-all-lazy-cuts-are-respected/95798/3 "2023-03-09T20:32:26Z")

</div>

I’ve opened a PR to improve our documentation of this: [[docs] clarify lazy constraint revisiting point by odow · Pull Request #3278 · jump-dev/JuMP.jl · GitHub](https://github.com/jump-dev/JuMP.jl/pull/3278)

---

<div class="post-metadata">

**Author:** ![mike\_k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike_k/32/211864_2.png) [@mike\_k](https://discourse.julialang.org/u/mike_k)\
**Post date:** [March 10, 2023, 1:02pm UTC](https://discourse.julialang.org/t/jump-cplex-seemingly-not-all-lazy-cuts-are-respected/95798/4 "2023-03-10T13:02:25Z")

</div>

Thanks @odow. One thing is to remark: always re-adding a cut early if I already know it for a candidate point does not work. It works, however, if I only re-add it early if it is currently violated.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 10, 2023, 5:44pm UTC](https://discourse.julialang.org/t/jump-cplex-seemingly-not-all-lazy-cuts-are-respected/95798/5 "2023-03-10T17:44:41Z")

</div>

This is mentioned in the docs [Solver-independent Callbacks · JuMP](https://jump.dev/JuMP.jl/stable/manual/callbacks/#Lazy-constraints).

Solver callbacks have a very particular set of assumptions that you must not violate.
