cplex boolVarArray дает двойные значения

Я пытался реализовать ILP с использованием CPLEX Java и застрял в проблеме в течение длительного времени. Вот несколько переменных 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);
}

Значение numRect равно 1. В конце программы я вывожу эти значения:

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]));
            }
        }

Вот вывод, который я получаю:

0.0
0.0
9.313225750491594E-10
0.9999999990686774
1.0

Я не понимаю, почему я получаю двойные значения вместо логических. Любая помощь будет оценена. Благодарю.

2 ответа

Решение

IloBoolVar - это просто IloNumVar, ограниченный 0 или 1. По умолчанию все в пределах 0,00001 от 0 или 1 считается целым числом. Вы можете изменить это, установив параметр EpInt. Параметр может быть установлен на ноль, но вы вызываете проблемы с производительностью. Лучше всего округлять значения. Фактически, каждый раз, когда вы работаете с числами с плавающей запятой, вы должны знать о таких проблемах округления.

Вы не сказали, какой язык вы используете. По какой-то причине версия Concert для C++ имеет

IloCplex.GetIntValue()

и вы получите 0 или 1.

Концерт для Java и C# (я не знаю о других языках) только IloCplex.GetValue(). Вам нужно будет округлить значения до 0 или 1. Я бы также сначала проверил, что значения находятся в пределах небольшого значения от нуля до единицы, просто чтобы убедиться, что вы на самом деле решаете MIP, а не LP.

Другие вопросы по тегам