- [These are the outputs] [1]: https://i.stack.imgur.com/aVepW.png
- constraints.py
from optapy import constraint_provider, get_class
from optapy.types import Joiners, HardSoftScore
from domain import TimeTable, Lesson, Room
from datetime import datetime, date, timedelta
TimeTableClass = get_class(TimeTable)
LessonClass = get_class(Lesson)
RoomClass = get_class(Room)
today = date.today()
def within30Mins(lesson1, lesson2):
between = datetime.combine(today, lesson1.timeslot.endTime) - datetime.combine(today, lesson2.timeslot.startTime)
return timedelta(minutes=0) <= between <= timedelta(minutes=30)
1-Hard constraints and Soft constraints
@constraint_provider def defineConstraints(constraintFactory): return [
roomConflict(constraintFactory), teacherConflict(constraintFactory), #studentGroupConflict(constraintFactory), 2- Soft constraints teacherRoomStability(constraintFactory), teacherTimeEfficiency(constraintFactory), #studentGroupSubjectVariety(constraintFactory), # curriculum_needs_to_be_met(constraintFactory), ]
A room can accommodate at most one lesson at the same time.
def roomConflict(constraintFactory):
return constraintFactory \ .fromUniquePair(LessonClass, # ... in the same timeslot ... [Joiners.equal(lambda lesson: lesson.timeslot), # ... in the same room ... Joiners.equal(lambda lesson: lesson.room), Joiners.equal(lambda lesson: lesson.timeslot.dayOfWeek)])\ .penalize("Room conflict", HardSoftScore.ONE_HARD)
A teacher can teach at most one lesson at the same time.
def teacherConflict(constraintFactory):
return constraintFactory \ .fromUniquePair(LessonClass, [Joiners.equal(lambda lesson: lesson.timeslot), Joiners.equal(lambda lesson: lesson.teacher)]) \ .penalize("Teacher conflict", HardSoftScore.ONE_HARD)
A student can attend at most one lesson at the same time.
def studentGroupConflict(constraintFactory):
return constraintFactory \ .fromUniquePair(LessonClass, [Joiners.equal(lambda lesson: lesson.timeslot), Joiners.equal(lambda lesson: lesson.studentGroup)]) \ .penalize("Student group conflict", HardSoftScore.ONE_HARD)
A teacher prefers to teach in a single room.
def teacherRoomStability(constraintFactory):
return constraintFactory \ .fromUniquePair(LessonClass, [Joiners.equal(lambda lesson: lesson.teacher)]) \ .filter(lambda lesson1, lesson2: lesson1.room != lesson2.room) \ .penalize("Teacher room stability", HardSoftScore.ONE_SOFT)
** A teacher prefers to teach sequential lessons and dislikes gaps between lessons.**
def teacherTimeEfficiency(constraintFactory):
return constraintFactory.from_(LessonClass)\ .join(LessonClass, [Joiners.equal(lambda lesson: lesson.teacher), Joiners.equal(lambda lesson: lesson.timeslot.dayOfWeek)]) \ .filter(within30Mins) \ .reward("Teacher time efficiency", HardSoftScore.ONE_SOFT)
A student group dislikes sequential lessons on the same subject.
def studentGroupSubjectVariety(constraintFactory):
return constraintFactory.from_(LessonClass) \ .join(LessonClass, [Joiners.equal(lambda lesson: lesson.subject), Joiners.equal(lambda lesson: lesson.studentGroup), Joiners.equal(lambda lesson: lesson.timeslot.dayOfWeek)]) \ .filter(within30Mins) \ .penalize("Student group subject variety", HardSoftScore.ONE_SOFT)