@GeoffreyDeSmet
by Geoffrey De Smet
Timefold
Expected: -1% driving time
Result: -25% driving time
⇒ -10 million kg CO² emission per year
⇒ -100 million $ cost per year
public 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;
}
for (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);
}
Greedy algorithm
Greedy | ||
---|---|---|
Fast | ||
Scalable | ||
Far from optimal |
long 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)
...
Brute Force
Search space for n lessons: nn
Search space for 400 lessons: 101040
Greedy | Brute Force | |
---|---|---|
Fast | Slow | |
Scalable | Not scalable | |
Far from optimal | Optimal |
+ advanced subsystem algorithms
public 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);
}
Metaheuristics
Greedy | Brute Force | Metaheuristics |
---|---|---|
Fast | Slow | Fast |
Scalable | Not scalable | Scalable |
Far from optimal | Optimal | (Near) Optimal |
Humans | Greedy | Brute Force | Meta heuristics |
---|---|---|---|
Slow | Fast | Slow | Fast |
Scalable | Scalable | Not scalable | Scalable |
Far from optimal | Far from optimal | Optimal | (Near) Optimal |
Live coding
$ git clone https://github.com/TimefoldAI/timefold-quickstarts.git
...
$ cd timefold-quickstarts/java/maintenance-scheduling
$ mvn quarkus:dev
...
Learn more | timefold.ai |
---|---|
Feedback |
@GeoffreyDeSmet @GeoffreyDeSmet@mastodon.social |
Get started |