-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstudentOptimization.py
executable file
·98 lines (84 loc) · 4.72 KB
/
studentOptimization.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""
Author: Corneel den Hartogh
Course: Heuristics
Description: Local search help to ensure that students have no unneccesary double rosters
"""
import copy
def studentOptimization(roster):
# select per student timeslots in which they are double rostered
for student in roster.studentsActiveFirst:
timeslots = []
for activity in student.activities:
timeslots.append(activity.slot[0:2])
timeslotsDouble = copy.copy(timeslots)
for x in set(timeslots):
timeslots.remove(x)
altActivities = []
# select the activities that are double rostered and can be replaced (so only the ones that have multiple groups)
for activity in student.activities:
for x in set(timeslots):
if (activity.slot[0:2] == x and activity.kind == "WorkLecture") or \
(activity.slot[0:2] == x and activity.kind == "Practicum"):
altActivities.append(activity)
for altActivity in altActivities:
for activity in roster.activities:
if activity.kind == altActivity.kind and activity.subject == altActivity.subject and \
activity.slot[0:2] not in timeslotsDouble and activity.group is not altActivity.group:
# if other group is not full, put the student there
if activity.maxStud > len(activity.students):
changeStudent(student,activity, altActivity)
activity.amountStud += 1
altActivity.amountStud -= 1
break
elif activity.maxStud == activity.amountStud:
# if other group is full, but in it are students that are unlikely to have conflicts (since they have only subject) switch
# first check students with less subjects
activity.studentsReversed = sorted(activity.students, key=lambda x:len(x.subjects))
suboptimalStudent = None
for studentSwitch in activity.studentsReversed:
if len(studentSwitch.subjects) == 1:
changeStudent(student,activity, altActivity)
switchStudent(studentSwitch,activity, altActivity)
break
elif len(studentSwitch.subjects) > 1:
# try other students (but not the ones with more subjects, since they are altready optimalized
timeslotsSwitch = []
for activ in studentSwitch.activities:
timeslotsSwitch.append(activ.slot[0:2])
for timeslot in timeslotsSwitch:
if altActivity.slot[0:2] == timeslot:
# when we have a student with less subjects but still conflicting schedules, we remember the student
#if activity == roster.activities[len(roster.activities)-1] and \
if len(studentSwitch.subjects) <= len(student.subjects) and suboptimalStudent == None:
suboptimalStudent = studentSwitch
break
else:
changeStudent(student,activity, altActivity)
switchStudent(studentSwitch,activity, altActivity)
suboptimalStudent = None
break
continue
else:
continue
# switch students, maybe we are able to optimalize the other student's roster better
if suboptimalStudent != None:
changeStudent(student,activity, altActivity)
switchStudent(suboptimalStudent,activity, altActivity)
break
else:
continue
break
else:
continue
break
return roster
def changeStudent(student, activity, altActivity):
student.activities.remove(altActivity)
altActivity.students.remove(student)
student.activities.append(activity)
activity.students.append(student)
def switchStudent(studentSwitch, activity, altActivity):
studentSwitch.activities.remove(activity)
activity.students.remove(studentSwitch)
studentSwitch.activities.append(altActivity)
altActivity.students.append(studentSwitch)