Search code examples
pythonoptaplanneroptapy

OptaPy Constraint to groupBy 2 variables for the same target


I am trying to add a constraint_factory using OptaPy, the Python variant of OptaPlanner, (using the School Timetabling quickstart as a base) for scheduling sports matches. Each match has 2 teams, so there are 2 variables in the Match class : team1 and team2 along with a time_slot and pitch.

How can I have a constraint where I can reward or penalise if a team (in either team1 or team2 variable) has been assigned more than 2 matches in a day?


Solution

  • I suggest to approach it differently. Start from Team, join with Match where either of the teams are equal, and count() that in a groupBy(). You will need to add a composite group key in that groupBy, your team and your match day.

    This is how such a constraint would look in Java, the native language of OptaPlanner:

    constraintFactory.forEach(Team.class)
        .join(Match.class, 
            Joiners.filtering((team, match) -> team == match.team1 || team == match.team2))
        .groupBy((team, match) -> team, 
             (team, match) -> match.day, 
             countBi())
        .filter((team, day, matchCount) -> matchCount > 2)
        .penalize(..., (team, day, matchCount) -> matchCount - 2);
    

    It should be relatively easy to get a Python variant off of that; another answer may provide it.