Я работал с OR-Tools над созданием расписания баскетбольного турнира.
Однако, когда я переключился со своей машины на запуск ее на виртуальной машине (Heroku), она начала тихо давать сбой для больших расписаний, или на решение в целом уходит все больше времени. Я сузил проблему до двух функций, описанных ниже. Когда я комментирую любую из этих функций, мой решатель работает без проблем, но когда они обе включены, он ломается. Я считаю, что где-то здесь есть противоречивое условие, но я не могу его найти.
Я запускаю этот инструмент на Heroku с Python 3.12.8. Я просмотрел другие сообщения о переполнении стека, например этот и этот.
Функция 1:
def add_conflict_constraints(model, game_vars, unscheduled_games, game_slots):
# Precompute numeric times for each slot if using datetime
# For example, convert slot.DateTime to an integer representing minutes since a fixed start:
slot_time_map = {}
base_time = min(s.DateTime for s in game_slots)
for slot in game_slots:
# Convert to minutes from base_time
delta = slot.DateTime - base_time
slot_time_map[slot.Id] = int(delta.total_seconds() // 60)
for game in unscheduled_games:
for slot in game_slots:
game_var = game_vars.get((game.Id, slot.Id))
if game_var is None:
continue # No variable, skip
# Identify conflicting games and determine order
# We'll store the order constraints for each (game, other_game) pair
# to avoid contradictory constraints.
# Key: other_game.Id, Value: 'na', 'this_first', or 'other_first'
conflict_orders = {}
for other_game in unscheduled_games:
if other_game.Id == game.Id:
continue
order = None
if game.Matchup.Type == 1:
if other_game.Matchup.Type == 1:
# Same type 1 -> if teams overlap, no order needed ('na'), just cannot be simultaneous
if {game.Matchup.HomeTeam.Id, game.Matchup.AwayTeam.Id}.intersection(
{other_game.Matchup.HomeTeam.Id, other_game.Matchup.AwayTeam.Id}
):
order = 'na'
elif other_game.Matchup.Type == 2:
# Type 1 vs Type 2 -> if they share a pool, this game should occur before
# or after the other, depending on scenario. Let's say type 1 first:
if {game.Matchup.HomeTeam.PoolId, game.Matchup.AwayTeam.PoolId}.intersection(
{other_game.Matchup.HomeTeam.PoolId, other_game.Matchup.AwayTeam.PoolId}
):
order = 'this_first'
elif game.Matchup.Type == 2:
if other_game.Matchup.Type == 2:
# Bracket progression: if this game's winner feeds into other_game, this game is first
if game.Id in other_game.Matchup.get_bracket_paths_as_flat_list():
order = 'other_first'
elif other_game.Id in game.Matchup.get_bracket_paths_as_flat_list():
order = 'this_first'
elif other_game.Matchup.Type == 1:
# Reverse scenario of type 1 vs type 2
if {game.Matchup.HomeTeam.PoolId, game.Matchup.AwayTeam.PoolId}.intersection(
{other_game.Matchup.HomeTeam.PoolId, other_game.Matchup.AwayTeam.PoolId}
):
order = 'other_first'
# If we found an order for this other_game, store it
# If multiple conditions apply for the same pair, decide how to handle:
if order is not None:
# If there's already an order stored and it's different, we must reconcile
# For simplicity, if conflict arises, pick a precedence rule or skip.
if other_game.Id in conflict_orders and conflict_orders[other_game.Id] != order:
# Potential conflict in ordering - handle as needed,
# e.g. skip or unify. Here, we just skip adding a second contradictory order.
continue
else:
conflict_orders[other_game.Id] = order
# Now, based on determined orders and conflicts, add constraints
slot_time = slot_time_map[slot.Id]
for other_game in unscheduled_games:
if other_game.Id not in conflict_orders:
continue
other_game_var = None
order = conflict_orders[other_game.Id]
# We want to ensure no overlapping within 1 hour on the same day:
# We'll create pairwise constraints for all slots of other_game that occur the same day.
for other_slot in game_slots:
# Check if same date
if slot.Date == other_slot.Date:
other_slot_time = slot_time_map[other_slot.Id]
other_game_var = game_vars.get((other_game.Id, other_slot.Id))
if other_game_var is None:
continue
# First, ensure they can't both be chosen within 1 hour of each other
# If both are scheduled, they must differ by at least 1 hour.
# To do this linearly:
# If both are scheduled, we must have abs(slot_time - other_slot_time) >= 60.
# This can be tricky because CP-SAT does not allow abs directly.
# Instead, we can forbid them both if they violate the 1-hour rule.
# If the slots are within 1 hour, add a constraint that they can't both be chosen.
if abs(slot_time - other_slot_time) = slot_time + 60).OnlyEnforceIf([game_var, other_game_var])
# If order is 'other_first':
# other_game must occur before this_game by at least 60 minutes
if order == 'other_first':
# If both chosen:
# slot_time >= other_slot_time + 60
model.Add(slot_time >= other_slot_time + 60).OnlyEnforceIf([game_var, other_game_var])
Функция 2:
if restriction.Type == 2:
if restriction.Date and restriction.Date != slot.Date:
continue # Skip if the restriction date does not match the slot date
slot_time = convert_to_24_hour(slot.Time)
start_time = convert_to_24_hour(restriction.StartTime) if restriction.StartTime else None
end_time = convert_to_24_hour(restriction.EndTime) if restriction.EndTime else None
if start_time and not end_time and slot_time >= start_time:
model.Add(game_var == 0)
elif end_time and not start_time and slot_time < end_time:
model.Add(game_var == 0)
elif start_time and end_time and (start_time
Подробнее здесь: https://stackoverflow.com/questions/793 ... ity-silent
Решатель OR-Tools CP-SAT Оптимизация Python, медленное время выполнения, невозможность, тихий сбой ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Почему мой решатель IDA* дает более длинный путь, чем мой решатель A*? [закрыто]
Anonymous » » в форуме JAVA - 0 Ответы
- 23 Просмотры
-
Последнее сообщение Anonymous
-