#python #optaplanner #optapy
#питон #оптический ключ #оптотерапия
Вопрос:
Я пытаюсь распределить спортивные матчи по временным интервалам и хотел бы, чтобы в течение дня не было пустых временных интервалов (поэтому заканчивайте как можно раньше). Я думаю, что isEqual и isNotEqual должны помочь, но застряли в синтаксисе версии Python. Я думаю, что я близок (соответствующий код ниже)
в domain.py
@problem_fact class Timeslot: def __init__(self, id, match_date, date_str, start_time, end_time): self.id = id self.match_date = match_date self.date_str = date_str # java does not have date or datetime equivalent so str also needed self.start_time = start_time self.end_time = end_time @planning_id def get_id(self): return self.id def __str__(self): return ( f"Timeslot(" f"id={self.id}, " f"match_date={self.match_date}, " f"date_str={self.date_str}, " f"start_time={self.start_time}, " f"end_time={self.end_time})"
в constraints.py
def fill_pitches_from_start(constraint_factory): # A pitch should not be empty if possible return constraint_factory .from_(TimeslotClass).ifNotExists(MatchClass, Joiners.equal(Timeslot.get_id(), Match.get_timeslot() ) ) .join(TimeslotClass).ifExists(MatchClass, Joiners.equal(Timeslot.get_id(), Match.get_timeslot())) .filter(lambda slot1, slot2: datetime.combine(slot1.date_str, slot1.timeslot.start_time) lt; datetime.combine(slot2.date_str, slot2.start_time) ) .penalize("Pitch Empty with Later pitches populated", HardSoftScore.ofSoft(10))
Это порождает и ожидаемую ошибку: Ошибка типа: get_id() отсутствует 1 требуемый позиционный аргумент: ‘self’
Но я не могу выработать правильный синтаксис — возможно, используя лямбда?
Ответ №1:
Вы близки; это должно сработать:
def fill_pitches_from_start(constraint_factory): # A pitch should not be empty if possible return constraint_factory .from_(TimeslotClass).ifNotExists(MatchClass, Joiners.equal(lambda timeslot: timeslot.get_id(), lambda match: match.get_timeslot() ) ) .join(TimeslotClass).ifExists(MatchClass, Joiners.equal(lambda timeslot1, timeslot2: timeslot2.get_id(), lambda match: match.get_timeslot())) .filter(lambda slot1, slot2: datetime.combine(slot1.date_str, slot1.timeslot.start_time) lt; datetime.combine(slot2.date_str, slot2.start_time) ) .penalize("Pitch Empty with Later pitches populated", HardSoftScore.ofSoft(10))
Вероятно , его можно улучшить с помощью Joiners.lessThan
, но для этого потребуется optapy
сначала обновить, чтобы столяры могли работать с любым типом Python. (Обновит этот ответ, когда optapy
будет обновлен для поддержки указанной функции).
Комментарии:
1. Большое спасибо — он запускается и сообщает мне Правду или ложь в журнале. Однако результаты не меняются. Связано ли это с тем, что planning_entity является совпадением, а временной интервал-проблемой? Как бы здесь был оштрафован класс совпадения объединенного класса временных интервалов вместо начального класса временных интервалов, у которого еще нет класса совпадения (пока)!?
2. Мне кажется, я знаю, в чем проблема. Есть несколько полей, на которых можно сыграть матч одновременно. Поэтому мне нужно знать, есть ли какие-либо пустые поля одновременно, поэтому ifNotExists(класс соответствия) на самом деле не будет работать, так как мне нужно знать, имеет ли временной интервал 8 классов соответствия, если у меня 8 полей. Это усложняется тем, что каждый шаг может иметь разное время, поэтому я думаю, что мне нужно изменить класс временного интервала, чтобы включить шаг и создать временные интервалы с включенными шагами (и удалить шаг из матча и оставить его только с временным интервалом).
3. Я думаю, что у вас есть непонимание того, как работают потоки ограничений. Отдельные лица/проблемные факты не наказываются/не вознаграждаются. Вместо этого уникальные кортежи наказываются (кортежи создаются фабрикой ограничений). from_, groupBy и join изменяют кортеж. Эти кортежи затем фильтруются фильтрами и объединителями, а те, которые остаются, наказываются/вознаграждаются. ifExists/ifNotExist не изменяют кортеж и действуют как фильтр. Для этого конкретного ограничения наказывается (timeslot1, timeslot2), где timeslot1 из from_ и timeslot2 из соединения (при условии, что оно проходит все фильтры).
4. Это конкретное ограничение, как написано выше, гласит: «для каждого временного интервала 1, в котором не существует совпадения с временным интервалом 1, и существует временной интервал 2, в котором существует совпадение с временным интервалом 2, а временной интервал 1 предшествует временному интервалу 2, оштрафуйте пару (временной интервал 1, временной интервал 2) на 10%».