Моделирование теннисных матчей с Choco (CSP)

Я пытаюсь смоделировать проблему с Choco, чтобы получить комбинации возможных матчей в теннисе (или любом другом виде спорта).

Как я пытаюсь это сделать, у меня есть следующее:

// Set of timeslots when the event is held (i.e. 10am-10pm)
int nTimeslots = 12;

// Courts available: court #1, #2 and #3
int nCourts = 3;

String[] players = { "Novak", "Andy", "Roger", "Stan", "Rafel", "Kei", "Tomas", "David" };
int nPlayers = players.length;

// Timeslots when each player cannot play for whatever reason
int[][] unavailability = {
    { 0, 1, 5 },
    { 8, 10, 11 },
    { 1, 2, 11 },
    { 0, 1 },
    { 2, 3, 4, 5, 6 },
    { 3, 4, 9, 10, 11 },
    { 4, 5 },
    { 2, 3 }
};

// Number of timeslots each match will occupy
int matchDuration = 2;

// This will hold the final combinations
// rows -> players, columns -> timeslots, matches[i][j] -> court where the player plays at that timeslot (0 means the player does not play at that time)
IntVar[][] matches;

Моя главная проблема заключается в том, что с этой настройкой я не могу придумать, как определить свою проблему. Я тратил на это дни, но безуспешно. У меня кажутся немного похожие задачи, но количество различных элементов, которые должны быть объединены, меньше, обычно 1 или 2, но в моей задаче их 3: игроки, временные интервалы и корты.

Потратив на это много времени, я не смог продвинуться дальше этого:

for (int player = 0; player < nPlayers; player++) {
    for (int timeslot = 0; timeslot < nTimeslots; timeslot++) {
        for (int playerUnavailbleTimeslot : unavailability[player]) {
            if (playerUnavailbleTimeslot != timeslot) {
                solver.post(IntConstraintFactory.arithm(matches[player][playerUnavailbleTimeslot], ">=", 0));
            } else {
                for (int i = 0; i < matchDuration; i++)
                    if (playerUnavailbleTimeslot - i >= 0)
                        solver.post(IntConstraintFactory.arithm(matches[player][playerUnavailbleTimeslot - i], "=", 0));
            }
        }
    }
}

IntVar matchesSum = VariableFactory.enumerated("Matches sum", 1 * matchDuration, nCourts * matchDuration, solver);
for (int player = 0; player < nPlayers; player++) {
    solver.post(IntConstraintFactory.sum(matches[player], matchesSum));
    //solver.post(IntConstraintFactory.nvalues(matches[player], VariableFactory.fixed(2, solver)));
}

Первый двойной цикл просто обнуляет те временные интервалы, в которых игрок недоступен (плюс диапазон, основанный на значении продолжительности матча), и больше или равно, если он доступен. Таким образом, окончательная матрица начинает выглядеть так:

0 0 ? ? ? 0 ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? 0 0 0 0 ?
.........................

Затем я просто убеждаюсь, что сумма значений во временных интервалах каждого игрока находится между кортом с наименьшим числом, умноженным на продолжительность матча, и кортом с наибольшим числом, умноженным на продолжительность матча. Это одно из ограничений, о которых я подумал, поэтому каждая строка выглядит так, например, игрок 0 играет на корте 2 в временные интервалы 3 и 4:

0 0 0 2 2 0 0 0 0 0 0 0 

Я попытался определить ограничение nvalues, которое должно обеспечивать соответствие массиву не более n различных значений, но если я использую его, как вы можете видеть выше, проблема просто отображает одно решение (что?!).

Однако мне нужно определить больше ограничений, я даже не знаю, как начать:

  • Для каждого ряда корт, на котором играет игрок, должен иметь последовательные номера, если он действительно назначен этому корту.
  • Для каждой строки у меня могут быть только 0 и номер суда [1 - nCourts]
  • Столбцы должны объединяться в пары, чтобы создать матчи между парой игроков.
  • Один и тот же корт не может быть объединен в пару более одного раза для одного и того же диапазона временных интервалов (это означает, что на корте может проходить не более одного матча одновременно).

Это все, что я могу придумать с точки зрения ограничений, но я уверен, что их больше.

Я был бы рад любому предложению, которое помогло бы мне продолжать это делать, потому что прямо сейчас я чувствую себя абсолютно невежественным, и в Интернете практически нет информации о Choco, которая могла бы помочь мне прояснить это.


person dabadaba    schedule 02.03.2016    source источник


Ответы (1)


Я бы начал с записи по математике того, что вы хотите.

Не уверен, что это полезно, но вот моя реализация, решающая ее как задачу математического программирования. Он не использует программирование с ограничениями, но все может выглядеть так же, как в Choco:

введите здесь описание изображения

Я стараюсь максимизировать минимальное количество игр игрока, чтобы у нас не было ни одного игрока, играющего в ноль игр. Можно придумать множество вариантов, например, не играть все время против одного и того же человека и т. д.

Результаты выглядят так:

введите здесь описание изображения

Цифры в таблице — это номера кортов (-1 означает, что игра запрещена). В этом расписании каждый играет по три раза.

person Erwin Kalvelagen    schedule 03.03.2016
comment
Это большая помощь. Хотя мне трудно понять, для чего нужны некоторые переменные и уравнения. Как вы это реализовали? Можете ли вы пролить свет на то, как это сделать в Choco? Еще раз, большое спасибо, вы проделали большую работу над этим ответом, и это определенно помогает. Однако почему некоторые игроки играют более одного матча? Или это просто представляет все возможные комбинации? - person dabadaba; 03.03.2016
comment
Я мало что знаю о Чоко. Множественные спички - мое изобретение. Моя цель — запланировать как можно больше матчей (ну, если быть точным, максимизировать минимальное количество матчей). Его легко заменить чем-то гораздо более скучным, например, ограничением, которое требует ровно одно совпадение для каждого человека (или что-то связанное). - person Erwin Kalvelagen; 03.03.2016
comment
Могу ли я сделать так, чтобы он работал так, как вы задумали, а также ограничил его только одним матчем для каждого игрока? (таким образом, это будет работать как для круговых событий, так и для событий с одним выбыванием). Я хочу спросить об уравнениях Twoslots1 и Twoslots2. Для чего они предназначены? Почему их два? Дело не в том, что в моей исходной задаче matchDuration является переменной, поэтому совпадения не предназначены для диапазона 2 слотов для matchDuration слотов. - person dabadaba; 03.03.2016
comment
Невозможно максимизировать количество матчей на одного игрока и при этом зафиксировать одно и то же на одном. (По крайней мере, для меня это не имеет особого смысла). - person Erwin Kalvelagen; 03.03.2016
comment
Twoslots1 сопоставляется между началом матча (обозначается g) и двумя соответствующими крестиками (x указывает, когда кто-то играет). Twoslots2 говорит, что совпадение не может начаться в t и в t+1. Я предполагаю, что каждый матч занимает два последовательных периода (см. результаты). - person Erwin Kalvelagen; 03.03.2016
comment
О первом комментарии: хорошо, я понимаю, что это не имеет математического смысла. Но я думаю, что я мог бы просто разветвить свой код и применить то или иное ограничение в зависимости от типа турнира :) - person dabadaba; 03.03.2016
comment
По поводу второго комментария: я вроде понял это знаю, спасибо. Но можно ли переместить последовательные периоды в другую переменную (вместо того, чтобы считать ее значение равным 2)? Если возможно, как изменятся уравнения (я предполагаю, что это повлияет только на уравнения Twoslots1 и Twoslots2). - person dabadaba; 03.03.2016
comment
Да, это можно переформулировать для обработки любого заданного числа. Также нелинейность может быть линеаризована, чтобы обеспечить более быстрые решатели. - person Erwin Kalvelagen; 03.03.2016
comment
Спасибо. Я пытаюсь реализовать это прямо сейчас с Choco. Однако меня все еще смущает одно из объяснений, которые вы упомянули ранее. Twoslots2 говорит, что совпадение не может начинаться в моменты времени t и t+1. Я предполагаю, что это сделано для предотвращения совпадения совпадений? Но как уравнение гарантирует это? - person dabadaba; 03.03.2016
comment
(продолжая предыдущий комментарий) Я хочу переформулировать Twoslots1 и 2, чтобы продолжительность совпадения была переменной, а не 2. Думаю, для Twoslots1 я мог бы просто зациклить x от t до t+matchDuration и убедиться, что g_p,c,t равно накопленному ценность. Я прав? А как насчет Twslots2? Выполнение такого же цикла в сумме не приведет к значению 0 или 1. Как я мог достичь той же идеи? Большое спасибо за эти ответы. Вы буквально единственный человек, помогающий мне с тех пор, как я начал этот проект несколько недель назад. - person dabadaba; 03.03.2016