3

I have been trying to implement an ILP using CPLEX Java and have been stuck at a problem for a long time. Here are few variables of the ILP:

IloIntVar above = new IloIntVar[numRect][];
IloIntVar below = new IloIntVar[numRect][];
IloIntVar left = new IloIntVar[numRect][];
IloIntVar right = new IloIntVar[numRect][]; 

for (int i = 0; i < numRect; i++) {
        above[i] = cplex.boolVarArray(numRect);
        below[i] = cplex.boolVarArray(numRect);
        left[i] = cplex.boolVarArray(numRect);
        right[i] = cplex.boolVarArray(numRect);
}

The value of numRect is 1. At the end of the program I output these values:

for (int i = 0; i < numRect; i++) {
            for (int j = i + 1; j < numRect; j++) {
                System.out.println(cplex.getValue(left[i][j]));
                System.out.println(cplex.getValue(right[i][j]));
                System.out.println(cplex.getValue(above[i][j]));
                System.out.println(cplex.getValue(below[i][j]));
                System.out.println(cplex.getValue(left[i][j]) +
                                   cplex.getValue(right[i][j]) +
                                   cplex.getValue(above[i][j]) +
                                   cplex.getValue(below[i][j]));
            }
        }

Here is the output I get:

0.0
0.0
9.313225750491594E-10
0.9999999990686774
1.0

I do not understand why am I getting double values instead of booleans. Any help would be appreciated. Thanks.

David Nehme
  • 21,379
  • 8
  • 78
  • 117
user1009285
  • 165
  • 1
  • 1
  • 11

2 Answers2

3

The IloBoolVar is simply a IloNumVar constrained to be 0 or 1. By default, anything within 0.00001 of 0 or 1 is considered to be an integer. You can change this by setting the parameter EpInt. The parameter could be set to zero, but you are inviting performance issues. It is the best practice to round the values. In fact, any time you are working with floating point numbers, you need to be aware of rounding issues like this.

David Nehme
  • 21,379
  • 8
  • 78
  • 117
1

You didn't say which language you're using. For some reason, the C++ version of Concert has

IloCplex.GetIntValue()

and you'll get 0 or 1.

Concert for Java and C# (I don't know about other languages) only have IloCplex.GetValue(). You'll need to round the values to 0 or 1. I would also check first that the values are within some small value of zero or one, just to make sure that you're actually solving a MIP and not a LP.

user327301
  • 2,641
  • 2
  • 26
  • 33
  • Thank you for your reply. I am using Java. The values for the boolean variables are very close to 0 or 1 as you could see in the output. Two of my variables are linear which four are boolean. I guess I should ignore the double values that I am getting as you said because these are very close to 0 or 1. – user1009285 Jul 10 '13 at 15:54
  • 1
    Yep! As David Nehme said in his answer, as long as they're within EpInt of an integer, everything is fine. I also second his note that you shouldn't muck around with EpInt or other tolerance parameters. – user327301 Jul 10 '13 at 22:00
  • I decided not to mess with that parameter. Even when I set it to 0, it did not quite work for me. My constraint: t1 + d <= t2 + Integer.Max_value*(1-b). Here b is a boolean variable, t1 and t2 are integer variables and d is an integer whose value is already defined. Since the Integer.Max_value is so large, cplex was making b very small (like 0.9999992) and make the condition true. When I tried to fix by setting EPInt to 0, it gave boolean variable to b, but the other variables indicate that constraints was not enforced. Hence I replaced Interger.max value with some other integer and it worked. – user1009285 Jul 17 '13 at 14:24
  • I really recommend replacing that Integer.MaxValue with something smaller. I won't get into the details in a comment, but the smaller you can make it (while still making sense as an upper bound) the easier the problem will be to solve. Also, can you mark one of the answers as accepted? – user327301 Jul 18 '13 at 01:32