-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGreedy.py
171 lines (133 loc) · 5.9 KB
/
Greedy.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import os
import json
from copy import deepcopy
from time import time
# from Dataset import Dataset
class Greedy:
def __init__(self, dataset, threshold):
self.dataset = dataset
self.threshold = threshold
def update_learner_profile(self, learner, course):
"""Update the learner profile with the skills and levels provided by the course
Args:
learner (list): list of skills and mastery level of the learner
course (list): list of required (resp. provided) skills and mastery level of the course
"""
# Update the learner profile with the skills and levels provided by the course (course [1] is the list of skills and levels provided by the course)
for cskill, clevel in course[1]:
found = False
i = 0
while not found and i < len(learner):
lskill, llevel = learner[i]
if cskill == lskill:
learner[i] = (lskill, max(llevel, clevel))
found = True
i += 1
if not found:
learner.append((cskill, clevel))
def get_course_recommendation(self, learner, enrollable_courses):
"""Return the greedy recommendation for the learner
Args:
learner (list): list of skills and mastery level of the learner
enrollable_courses (dict): dictionary of courses that the learner can enroll in
Returns:
int: the id of the course recommended
"""
course_recommendation = None
max_nb_applicable_jobs = 0
max_attractiveness = 0
for id_c, course in enrollable_courses.items():
tmp_learner = deepcopy(learner)
self.update_learner_profile(tmp_learner, course)
nb_applicable_jobs = self.dataset.get_nb_applicable_jobs(
tmp_learner, self.threshold
)
attractiveness = self.dataset.get_learner_attractiveness(tmp_learner)
# Select the course that maximizes the number of applicable jobs
if nb_applicable_jobs > max_nb_applicable_jobs:
max_nb_applicable_jobs = nb_applicable_jobs
course_recommendation = id_c
max_attractiveness = attractiveness
# If there are multiple courses that maximize the number of applicable jobs,
# select the one that maximizes the attractiveness of the learner
elif nb_applicable_jobs == max_nb_applicable_jobs:
if attractiveness > max_attractiveness:
max_attractiveness = attractiveness
course_recommendation = id_c
return course_recommendation
def recommend_and_update(self, learner):
"""Recommend a course to the learner and update the learner profile
Args:
learner (list): list of skills and mastery level of the learner
Returns:
int: the id of the course recommended
"""
enrollable_courses = self.dataset.get_all_enrollable_courses(
learner, self.threshold
)
# print(f"{len(enrollable_courses)} courses are enrollable for this learner")
# print(f"{enrollable_courses.keys()}")
course_recommendation = self.get_course_recommendation(
learner, enrollable_courses
)
self.update_learner_profile(
learner, self.dataset.courses[course_recommendation]
)
return course_recommendation
def greedy_recommendation(self, k, run):
"""Make k greedy recommendations for each learner and save the results in a json file
Args:
k (int): number of recommendations to make for each learner
run (int): run number
"""
results = dict()
avg_l_attrac = self.dataset.get_avg_learner_attractiveness()
print(f"The average attractiveness of the learners is {avg_l_attrac:.2f}")
results["original_attractiveness"] = avg_l_attrac
avg_app_j = self.dataset.get_avg_applicable_jobs(self.threshold)
print(f"The average nb of applicable jobs per learner is {avg_app_j:.2f}")
results["original_applicable_jobs"] = avg_app_j
time_start = time()
recommendations = dict()
for i, learner in enumerate(self.dataset.learners):
index = self.dataset.learners_index[i]
recommendation_sequence = []
for _ in range(k):
recommendation_sequence.append(
self.recommend_and_update(self.dataset.learners[i])
)
recommendations[index] = [
self.dataset.courses_index[course_id]
for course_id in recommendation_sequence
]
time_end = time()
avg_recommendation_time = (time_end - time_start) / len(self.dataset.learners)
print(f"Average Recommendation Time: {avg_recommendation_time:.2f} seconds")
results["avg_recommendation_time"] = avg_recommendation_time
avg_l_attrac = self.dataset.get_avg_learner_attractiveness()
print(f"The new average attractiveness of the learners is {avg_l_attrac:.2f}")
results["new_attractiveness"] = avg_l_attrac
avg_app_j = self.dataset.get_avg_applicable_jobs(self.threshold)
print(f"The new average nb of applicable jobs per learner is {avg_app_j:.2f}")
results["new_applicable_jobs"] = avg_app_j
results["recommendations"] = recommendations
filename = (
"greedy_nbskills_"
+ str(len(self.dataset.skills))
+ "_k_"
+ str(k)
+ "_run_"
+ str(run)
+ ".json"
)
json.dump(
results,
open(
os.path.join(
self.dataset.config["results_path"],
filename,
),
"w",
),
indent=4,
)