Ограничение на стандартное отклонение отсчетов всегда ноль

В настоящее время я пытаюсь решить проблему планирования для спортивной команды. Мои переменные решения объявлены как:

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,

В конечном счете, мои вопросы:

  1. Нарушаю ли я какое-то правило OPL и использую операторы так, как не следует?
  2. Если да к вышесказанному, есть ли законный, действительный способ выразить ограничение, которое я ищу?
  3. Если нет к вышесказанному, то почему OPL не может рассчитать стандартное отклонение в моем ограничении?

0 ответов

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