@GeoffreyDeSmet
by Geoffrey De Smet
Expected: -1% driving time
Result: -25% driving time
⇒ -10 million kg CO² emission per year
⇒ -100 million $ cost per year
javapublic long calculateScore(TimeTable timeTable) {
long hardScore = 0;
for (Lesson lesson1 : timeTable.lessons) {
for (Lesson lesson2 : timeTable.lessons) {
if (lesson1.room == lesson2.room
&& lesson1.timeslot == lesson2.timeslot) {
hardScore--;
}
if (lesson1.teacher == lesson2.teacher
&& lesson1.timeslot == lesson2.timeslot) {
hardScore--;
}
if (lesson1.studentGroup == lesson2.studentGroup
&& lesson1.timeslot == lesson2.timeslot) {
hardScore--;
}
}
}
return hardScore;
}
pythondef calculate_score(time_table):
hard_score = 0
for lesson1 in time_table.lessons:
for lesson2 in time_table.lessons:
if (lesson1.room == lesson2.room
and lesson1.timeslot == lesson2.timeslot):
hard_score -= 1
if (lesson1.teacher == lesson2.teacher
and lesson1.timeslot == lesson2.timeslot):
hard_score -= 1
if (lesson1.student_group == lesson2.student_group
and lesson1.timeslot == lesson2.timeslot):
hard_score -= 1
return hard_score
javafor (Lesson lesson : timeTable.lessons) {
long bestScore = Long.MIN_VALUE;
Room bestRoom = null;
Timeslot bestTimeslot = null;
for (Timeslot timeslot : timeTable.timeslots) {
lesson.setTimeslot(timeslot);
for (Room room : timeTable.rooms) {
lesson.setRoom(room);
long score = calculateScore(timeTable);
if (score > bestScore) {
bestScore = score;
bestRoom = room;
bestTimeslot = timeslot;
}
}
}
lesson.setTimeslot(bestTimeslot);
lesson.setRoom(bestRoom);
}
pythonfor lesson in time_table.lessons:
best_score = float('-inf')
best_room = None
best_timeslot = None
for timeslot in time_table.timeslots:
lesson.timeslot = timeslot
for room in time_table.rooms:
lesson.room = room
score = calculate_score(time_table)
if score > best_score:
best_score = score
best_room = room
best_timeslot = timeslot
lesson.timeslot = best_timeslot
lesson.room = best_room
Greedy algorithm
Greedy | ||
---|---|---|
Fast | ||
Scalable | ||
Far from optimal |
javalong bestScore = Long.MIN_VALUE;
for (Timeslot timeslotLesson1 : timeslots) {
lesson1.setTimeslot(timeslotLesson1);
for (Room roomLesson1 : rooms) {
lesson1.setRoom(roomLesson1);
for (Timeslot timeslotLesson2 : timeslots) {
lesson2.setTimeslot(timeslotLesson2);
for (Room roomLesson2 : rooms) {
lesson2.setRoom(roomLesson2);
...
for (Timeslot timeslotLessonN : timeslots) {
lessonN.setTimeslot(timeslotLessonN);
for (Room roomLessonN : rooms) {
lessonN.setRoom(roomLessonN);
int score = calculateScore(timeTable);
if (score > bestScore)
...
pythonbest_score = float('-inf')
for timeslot_lesson_1 in timeslots:
lesson1.timeslot = timeslot_lesson_1
for room_lesson_1 in rooms:
lesson1.room = room_lesson_1
for timeslot_lesson_2 in timeslots:
lesson_2.timeslot = timeslot_lesson_2
for room_lesson_2 in rooms:
lesson_2.room = room_lesson_2
...
for timeslot_lesson_n in timeslots:
lesson_n.timeslot = timeslot_lesson_n
for room_lesson_n in rooms:
lesson_n.room = room_lesson_n
score = calculate_score(time_table)
if score > best_score:
...
Brute Force
Search space for n lessons: nn
Search space for 400 lessons: 101040
Atoms in observable universe: 1080
Greedy | Brute Force | |
---|---|---|
Fast | Slow | |
Scalable | Not scalable | |
Far from optimal | Optimal |
+ advanced subsystem algorithms
Planning optimization made easy
javapublic HardSoftScore calculateScore(TimeTable timeTable) {
long hardScore = 0;
for (Lesson lesson1 : timeTable.lessons) {
for (Lesson lesson2 : timeTable.lessons) {
if (lesson1.room == lesson2.room
&& lesson1.timeslot == lesson2.timeslot) {
hardScore--;
}
if (lesson1.teacher == lesson2.teacher
&& lesson1.timeslot == lesson2.timeslot) {
hardScore--;
}
if (lesson1.studentGroup == lesson2.studentGroup
&& lesson1.timeslot == lesson2.timeslot) {
hardScore--;
}
}
}
return HardSoftScore.of(hardScore, 0);
}
pythondef calculate_score(time_table) -> HardSoftScore:
hard_score = 0
for lesson1 in time_table.lessons:
for lesson2 in time_table.lessons:
if (lesson1.room == lesson2.room
and lesson1.timeslot == lesson2.timeslot):
hard_score -= 1
if (lesson1.teacher == lesson2.teacher
and lesson1.timeslot == lesson2.timeslot):
hard_score -= 1
if (lesson1.student_group == lesson2.student_group
and lesson1.timeslot == lesson2.timeslot):
hard_score -= 1
return HardSoftScore.of(hard_score, 0)
Metaheuristics
Greedy | Brute Force | Metaheuristics |
---|---|---|
Fast | Slow | Fast |
Scalable | Not scalable | Scalable |
Far from optimal | Optimal | (Near) Optimal |
Field Service Routing
app.timefold.ai
java$ git clone
https://github.com/TimefoldAI/timefold-quickstarts.git
$ cd timefold-quickstarts/java/school-timetabling
$ mvn quarkus:dev
python$ git clone
https://github.com/TimefoldAI/timefold-quickstarts.git
$ cd timefold-quickstarts/python/school-timetabling
$ pip install -e .
$ run-app
python$ git clone
https://github.com/TimefoldAI/timefold-notebooks.git
$ cd timefold-notebooks/python
Learn more | docs.timefold.ai |
---|---|
Feedback |
![]() ![]() |