Constraint for curriculum to be met with Optapy – School timetabling optimization

Question:

I am using Optapy library in python and I want to add constraint that the curriculum needs to be met, since I get for now many unassigned lessons even though most of the timeslots and rooms are empty and the teacher resources are mostly unused.
I tried to add the following constraint:

def curriculum_needs_to_be_met(constraint_factory):
return constraint_factory 
    .forEach(LessonClass) 
    .filter(lambda lesson: lesson.timeslot is None) 
    .penalize("Curriculum needs to be met", HardSoftScore.ONE_HARD)

But still I get many unassigned lessons. Any idea how can I define the curriculum constraint?

Asked By: IsKan

||

Answers:

All variables should be assigned without a constraint. The only reason why they would be unassigned is either:

  1. You are checking the input problem (where all the lessons are unassigned) instead of the solution returned from solver.solve (where all the lessons should be assigned, unless the solver terminated before it found a feasible solution (in which case, the solver should be given more time)).

  2. You passed nullable=True to @planning_variable (i.e. the domain looks like this):

     @planning_entity
     class Lesson:
         def __init__(self, id, subject, teacher, student_group, timeslot=None, room=None):
             self.id = id
             self.subject = subject
             self.teacher = teacher
             self.student_group = student_group
             self.timeslot = timeslot
             self.room = room
    
         @planning_id
         def get_id(self):
             return self.id
    
         @planning_variable(Timeslot, ["timeslotRange"], nullable=True)
         def get_timeslot(self):
             return self.timeslot
    
         def set_timeslot(self, new_timeslot):
             self.timeslot = new_timeslot
    
         # ...
    

    which you do if you want to allow the variable to take a None value. However, this is probably not the case, since you don’t want the variable to take a None value.

Thus, I would double check you are using the solution instead of the problem. If you are using the solution and still see unassigned values, then I would update its TerminationConfiguration to give it more time. See the OptaPlanner docs for example termination configurations: https://www.optaplanner.org/docs/optaplanner/latest/optimization-algorithms/optimization-algorithms.html#termination ; You can create a new termination configuration in OptaPy like this:

import optapy.config
termination = optapy.config.solver.termination.TerminationConfig()
termination.setBestScoreFeasible(True) # keep solving until the solution feasible
solver_config = optapy.config.solver.SolverConfig() 
    .withTerminationConfig(termination) 
# rest of SolverConfig setup
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.