0

I have been working on a combinatorial optimization problem which can be modeled as an integer linear programming. I implemented it as a c++ project in visual studio 2017 and CPLEX1271. Since there are exponentially many constraints, I implemented lazy constraints by IloCplex::LazyConstraintCallbackI. In my mind the following procedure is how an optimal soution is produced: everytime an integer solution is identified, LazyConstraintCallbackI will check it and add some violated constraints to the model untill an optimal integer solution is obtained.

However, the objective values given by my implementation for different inputs are not always correct. After almost one year's intermittent debug and test, I finally figured out the reason, which is very problem related but can be explained(hopefully) by the following tiny example:  an integer linear programming involving four bool variables x1, x2, x3 and x4

minimize x1
subject to: 
x1  ≥  x2
x1  ≥  x3
x1  ≥  x4
x2  + x3  ≥ 1
x1, x2, x3 and x4  ∈ {0, 1}​

The result given by cplex is:

Solution status = Optimal
Objective value = 1
x1 = 1
x2 = 1
x3 = 1
x4 = 1​

Undoubtedly, the objective value is correct .The weird thing is that cplex sets  x4 = 1. Although whether x4 equals 1 or 0 has no impact on the objective value in this programming. But, when lazy constraint callback is used, this could lead to a problem by adding some incorrect contraint and integer programming is solved by iteratively adding violated constraints. I'd like to know:

  1. why cplex set "unrelated" variable  x4  as 1, instead of 0?
  2. What should I do to tell CPLEX that I want to leave such "unrelated" variable as 0?
Mengfan Ma
  • 351
  • 2
  • 13
  • 2
    Imho the solver won't guarantee anything in regards to the value of x4: it's final value is some result obtained from a complex interaction between the lp-relaxation and tons of internal heuristics. Adding some guarantees will only take away all the good stuff from those highly-optimized general-purpose solvers. So basically: *you can't assume anything about x4 and if your lazy-constraints are doing this, they are wrong and need to be changed*. You can't do much, except for enforcing some preference by adding it to the objective (x1 + x4), but this is problem-dependent (and might get complex). – sascha Jun 18 '20 at 11:21
  • `integer programming is solved by iteratively adding violated constraints` Be careful there not to mix (user-)cuts with lazy-constraints. CPLEX solved integer-programming long before lazy-constraints where added and the rules to obey are completely different. – sascha Jun 18 '20 at 11:23
  • @sascha Thanks for your reply. By "the solver won't guarantee anything in regards to the value of x4", did you mean that such variable is not always assigned 1 and may get a value of 0? – Mengfan Ma Jun 18 '20 at 11:33
  • Yes. In general, it might get set to 0 or 1. In non-deterministic optimization-mode, this might even change from run to run (and in deterministic mode it ?might? change from OS to OS: e.g. AIX vs. Windows). But (hopefully) some CPLEX guys (active here) will confirm this. (remark on top of my first comment about changing the objective to include some preference: as said -> highly problem-dependent and you might need some *weighting* like min x1 + 0.001 * x4 to guarantee sane solutions in regards to your original non-regularized problem) – sascha Jun 18 '20 at 11:37
  • @sascha Actually I've considered the workaround your mentioned here. It is, in some sense, not very "elegant". But it seems that I have to do it. – Mengfan Ma Jun 18 '20 at 11:47

1 Answers1

5

Since there is nothing that forces x4=0 in an optimal solution, there is no guarantee that CPLEX will set x4=0? Why would it? Why is 0 preferred over 1? The model has two optimal solutions, one with x4=0 and one with x4=1. Both have objective value 1. CPLEX is completely free to choose one of them.

Like sascha said in his comments, the only way to force x4=0 in an optimal solution is to add this constraint to the model, for example by setting the objective coefficient to a small positive value.

However, it seems strange that your lazy constraint callback would generate invalid constraints from integer feasible solutions. This looks like a bug: Either the callback makes invalid assumptions about the model (namely that x4=0 in any optimal solution) or there is a bug somewhere in the logic of the callback. Note that in the model at hand it would actually be fine for the callback to cut off the solution with x4=1 since that still leaves the equivalent optimal solution with x4=0 and CPLEX would eventually find that.

Daniel Junglas
  • 5,830
  • 1
  • 5
  • 22
  • My LazyConstraintCallbackI made the assumption that "unrelated " variables like x4 would always be 0. If some of them turn out to be 1, the callback may generate invalid inequations. – Mengfan Ma Jun 20 '20 at 01:44
  • 1
    General remark: if you make this sort of assumption then you should at least put an assertion that verifies this in debug mode. That way you can easily and quickly find out that assumptions are wrong in case you get unexpected results. – Daniel Junglas Jun 22 '20 at 04:22