Ограничение на стандартное отклонение отсчетов всегда ноль
В настоящее время я пытаюсь решить проблему планирования для спортивной команды. Мои переменные решения объявлены как:
dvar int plays[Games][0..1] in Teams;
куда Games
это диапазон от 0..19
а также Teams
это диапазон от 0..9
в этом конкретном случае. Это формирует матрицу 20 на 2, которая показывает, какие команды играют в каждую игру.
[
[3, 7],
[2, 4],
[9, 1]
]
Пример трех игровой матрицы, которая показывает, что команда 3 играет команду 7 в первой игре, а затем команда 2 против команды 4, которая завершается командой 9 против команды 1.
В своих ограничениях я пытаюсь выразить, что каждая команда должна играть примерно с одинаковым количеством игр. Моя попытка выразить это ограничение заключается в следующем:
subject to {
gameBalance:
standardDeviation(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t)) < 1;
}
Я полагаю, что эта формулировка является правильной - однако мне кажется, что я сталкиваюсь с каким-то неопределенным поведением, поскольку ограничение не выполняется, хотя CPLEX говорит, что возвращает "оптимальное" решение [18, 18, 0, 0, 0, 0, 0, 0, 0]
для случая 9 команд.
Подсчитав вручную, я получаю стандартное отклонение 7.59
что явно не меньше единицы. Чтобы убедиться в этом, я поместил следующее в раздел данных результатов моей модели:
int playcounts[Teams] = all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t);
float std = standardDeviation(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t));
execute {
writeln("counts: " + playcounts);
writeln("std: " + std);
}
Что дает следующий вывод:
// solution with objective 0
counts: [18 18 0 0 0 0 0 0 0]
std: 7.48331477
Что еще раз подтверждает, что что-то в написанном мною ограничении неверно. Для дальнейшей отладки ситуации я использовал следующее ограничение:
standardDeviation(foo) < 1;
куда foo
был объявлен целочисленным массивом [1, 100, 10000, 1000000, 100000000]
- что определенно не имеет стандартное отклонение меньше 1. Как и ожидалось, эта модель оказалась недопустимой, что показывает, что стандартное отклонение работает, как и ожидалось, поэтому проблема должна заключаться в том, как я строю массив отсчетов. Затем я попробовал следующее ограничение:
standardDeviation(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t)) + 2.999999999 < 3;
Моя теория заключалась в том, что если стандартное отклонение обрабатывается как ненулевое, то это должно сделать модель неосуществимой. К моему удивлению, модель прошла с такой же тривиальной [18, 18, 0, ...]
Решение выше. Путем изменения 2.999...
3, модель была невозможна. Таким образом, я пришел к выводу, что стандартное отклонение, которое я вычисляю, оценивается как 0 в ограничении, но оно вычисляется правильно в разделе данных результата после завершения поиска.
На данный момент я уверен, что проблема связана с тем, как я вычисляю массив счетчиков (all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t)
), но часть, которую я не понимаю, заключается в том, почему она работает в данных результата, а не в ограничениях (как показано playcounts
распечатка выше).
Кроме того, следующее ограничение работает отлично:
// The total number of games played must be exactly 36
sum(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t) == 36;
Что приводит меня к мысли, что проблема заключается в all(t in Teams)...
часть ограничения. Чтобы проверить эту теорию, я использовал следующее ограничение:
// The number of games the first team plays must be exactly 18
(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t))[0] == 18;
Теоретически это должно быть избыточное ограничение, поскольку возвращаемое тривиальное решение начинается с [18, 18, 0, ...]
, К моему удивлению, это создало неосуществимую модель. Даже с == 0
вместо == 18
Модель была еще невозможна. Таким образом, я хотел выяснить, к чему это число относится. С этой целью я добавил следующую переменную решения:
dvar int a;
И изменил целевую функцию на:
maximize a;
Со следующим ограничением:
(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t))[0] == a;
Что привело к модели, которая имела оптимальное решение. Решение было a
установлен в -9007199254740991
, Тот же результат произойдет, если я попытаюсь minimize
эта модель.
Если я попытаюсь сдержать a
чтобы быть неотрицательным, то CPLEX падает с ### UNEXPECTED ERROR
,
В конечном счете, мои вопросы:
- Нарушаю ли я какое-то правило OPL и использую операторы так, как не следует?
- Если да к вышесказанному, есть ли законный, действительный способ выразить ограничение, которое я ищу?
- Если нет к вышесказанному, то почему OPL не может рассчитать стандартное отклонение в моем ограничении?