функция оптимизации записи - PullRequest
2 голосов
/ 06 октября 2008

Я пытаюсь написать систему бронирования тенниса, и я застрял с этой проблемой. Допустим, у вас есть игроки с их префами относительно номера корта, дня и часа. Также каждый игрок ранжируется, так что если есть слот день / час и есть несколько игроков с предпочтениями для этого слота следует выбрать тот, который имеет наивысший приоритет. Я думаю об использовании некоторых алгоритмов оптимизации для решения этой проблемы, но я не уверен, какую функцию и / или алгоритм лучше всего использовать. Любой совет? Еще одна вещь, которую я предпочел бы использовать Python, но некоторые не зависящие от языка советы также приветствуются. Спасибо!

редактирование:

некоторые уточнения-

выигрывает игрок с лучшим приоритетом, а проигравший перемещается в ближайший слот, довольно гибкий вопрос о временных интервалах да, максимальное количество людей, получающих наиболее предпочтительное время

Ответы [ 8 ]

3 голосов
/ 07 октября 2008

Основной алгоритм

Я бы сортировал игроков по их рангу, так как высокопоставленные всегда отталкивали низкосортных. Затем вы начинаете с игрока с самым высоким рангом, даете ему то, о чем он просил (если он действительно самый высокий, он всегда выигрывает, поэтому вы также можете дать ему все, что он просил). Тогда я бы начал со второго по величине. Если он запросил что-то, уже взятое самой высокой, попытайтесь найти слот поблизости и назначьте этот слот ему. Теперь идет третий по величине. Если он попросит что-то, что уже было принято старшим, переместите его в слот поблизости. Если этот слот уже занят вторым по величине, переместите его в слот еще дальше. Продолжите со всеми другими игроками.

Некоторые настройки для рассмотрения:

Если несколько игроков могут иметь один и тот же ранг, вам может потребоваться реализовать некоторую «справедливость». Все игроки с одинаковым рангом будут иметь случайный порядок друг с другом, если вы сортируете их, например. используя QuickSort. Вы можете получить некоторую справедливость, если вы не делаете это игрок за игроком, но ранг за ранг. Вы начинаете с самого высокого ранга и первым игроком этого ранга. Обработайте его первый запрос. Однако перед обработкой его второго запроса обработайте первый запрос следующего игрока, имеющего наивысший ранг, а затем третьего игрока, имеющего наивысший ранг. Алгоритм такой же, как и выше, но при условии, что у вас есть 10 игроков, а игроки 1-4 имеют наивысший ранг, игроки 5-7 - низкие, а игроки 8-10 - очень низкие, и каждый игрок сделал 3 запроса, вы обрабатываете их как

Player 1 - Request 1
Player 2 - Request 1
Player 3 - Request 1
Player 4 - Request 1
Player 1 - Request 2
Player 2 - Request 2
:

Таким образом, у вас есть немного справедливости. Вы также можете выбирать случайным образом в классе ранжирования каждый раз, это также может обеспечить некоторую справедливость.

Вы можете реализовать справедливость даже в разных рядах. Например. если у вас 4 ранга, вы можете сказать

Rank 1 - 50%
Rank 2 - 25%
Rank 3 - 12,5%
Rank 4 - 6,25%

(Только примерные значения, вы можете использовать ключ, отличный от всегда умножения на 0,5, например, умножение на 0,8, что приводит к более медленному уменьшению чисел)

Теперь вы можете сказать, что вы начинаете обработку с Ранга 1, однако, как только 50% всех запросов Ранга 1 были выполнены, вы переходите к Уровню 2 и убедитесь, что 25% их запросов были выполнены, и так далее. Таким образом, даже пользователь с рангом 4 может победить пользователя с рангом 1, несколько победив первоначальный алгоритм, однако вы предлагаете некоторую справедливость. Даже игрок 4 ранга может иногда получить его запрос, он не «иссякнет». В противном случае игрок с рангом 1, планирующий каждый запрос в то же время, что и игрок с рангом 4, удостоверится, что у игрока с рангом 4 нет шансов когда-либо получить один запрос. Таким образом, есть хотя бы небольшой шанс, что он его получит.

После того, как вы убедились, что у каждого был обработан минимальный процент (и чем выше ранг, тем больше это), вы возвращаетесь к началу, снова начиная с 1-го ранга, и обрабатываете остальные свои запросы, затем остальные Запросы уровня 2 и т. Д.

Последнее, но не менее важное: Вы можете определить максимальное смещение слота. Если слот занят, приложение должно найти ближайший слот, который еще свободен. Однако что, если этот ближайший слот находится очень далеко? Если я запрашиваю слот в понедельник в 16:00 и приложение обнаружит, что следующим свободным будет среда в 9:00, это не очень полезно для меня, не так ли? У меня может не быть времени на среду вообще. Таким образом, вы можете ограничить поиск слотов тем же днем ​​и сказать, что интервал может быть не более 3 часов. Если в этом диапазоне слот не найден, отмените запрос. В этом случае вам необходимо сообщить игроку: «Извините, но мы не смогли найти ближайший слот для вас; пожалуйста, запросите слот на другую дату / время, и мы посмотрим, сможем ли мы найти подходящий слот для вас».

2 голосов
/ 06 октября 2008

Вы описываете проблему соответствия. Возможные ссылки: хранилище алгоритмов Stony Brook и Алгоритм Design by Kleinberg and Tardos . Если количество игроков равно числу кортов, вы можете достичь стабильного соответствия - Проблема стабильного брака . Другие формулировки становятся сложнее.

2 голосов
/ 06 октября 2008

Я думаю, что это NP-полная проблема, поэтому невозможно будет иметь очень быстрый алгоритм для любых больших наборов данных.

Существует также проблема, когда у вас может быть расписание, которое невозможно составить. Учитывая, что это не так, возможно, что-то вроде этого псевдокода является лучшим выбором:

sort players by priority, highest to lowest
start with empty schedule
for player in players:
    for timeslot in player.preferences():
        if timeslot is free:
            schedule.fillslot(timeslot, player)
            break
    else:
        #if we get here, it means this player couldn't be accomodated at all.
        #you'll have to go through the slots that were filled and move another (higher-priority) player's time slot
1 голос
/ 06 октября 2008

Я бы посоветовал использовать алгоритм оценки. По сути, создайте формулу, которая объединит все значения, которые вы описали, в одно число. Тот, кто когда-либо набрал наибольшее количество очков, выигрывает этот слот. Например, простая формула может быть:

FinalScore = ( PlayerRanking * N1 ) + ( PlayerPreference * N2 )

Где N1, N2 - веса для управления формулой.

Это позволит вам быстро получить хорошие (не идеальные) результаты. Мы используем этот подход в гораздо более сложной системе с очень хорошими результатами.

Вы можете добавить больше разнообразия к этому, добавив факторы, сколько раз игрок выиграл или потерял слоты, или (как кто-то предложил), сколько игрок заплатил.

Кроме того, вы можете использовать несколько проходов для назначения слотов в день. Используйте одну стратегию, где она идет в хронологическом порядке, одну - в обратном хронологическом порядке, одну - сначала утром, одну - днем, и т. Д. Затем суммируйте баллы игроков, которые получили места, и затем вы можете выбрать стратегию при условии наилучших результатов. .

1 голос
/ 06 октября 2008

Есть несколько вопросов, которые я хотел бы задать, прежде чем ответить на этот квест:

  • что произойдет, если возникнет конфликт, то есть сначала игрок с худшей игрой, а затем игрок с лучшей площадкой - с той же площадки? Кто выигрывает? что происходит с неудачником?
  • разрешаете ли вы лучшим игрокам играть в течение всего матча или у вас есть фиксированные временные интервалы?
  • как часто выполняется планирование - выполняется ли оно в интерактивном режиме - поэтому потенциально кому-то может быть сказано, что он может играть, только если ему скажут, что он не может; или он работает более пакетно - вы вводите запросы, а потом вам сообщают, если у вас есть слот. Или пользователи устанавливают желаемое количество раз, а затем система должна максимально увеличить количество людей, получающих наиболее предпочтительное время?

Кроме того, вы можете сделать его немного менее сложным, переписав времена как целочисленные индексы (так что вы имеете дело с целыми числами, а не со временем).

0 голосов
/ 04 января 2011

Я думаю, вы должны использовать генетический алгоритм, потому что:

Также взгляните на: аналогичный вопрос и еще один

0 голосов
/ 07 октября 2008

По сути, у вас есть преимущество в том, что у игроков есть приоритеты; поэтому вы сортируете игроков по убыванию приоритета, а затем начинаете выделять им слоты. Первый получает свой предпочтительный слот, затем следующий выбирает его среди свободных и так далее. Это алгоритм O (N).

0 голосов
/ 06 октября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...