Juggling commited on
Commit
c010d15
·
verified ·
1 Parent(s): a2aebf8

Trying to make the code faster

Browse files
Files changed (1) hide show
  1. workshops.py +41 -31
workshops.py CHANGED
@@ -43,6 +43,13 @@ class Schedule:
43
  self.timeslots[time].remove(person)
44
 
45
 
 
 
 
 
 
 
 
46
  # Returns True if the person can teach during the slot, and False otherwise
47
  def can_teach(person: str, slot: list, capacity: int) -> bool:
48
  if len(slot) == capacity or len(slot) > capacity:
@@ -103,10 +110,13 @@ def initialize_timeslots(df) -> dict:
103
 
104
 
105
  # Recursive function that generates all possible schedules
106
- def find_all_schedules(people: list, availability: dict, schedule_obj: Schedule, capacity: int, schedules: list, max_list: list) -> None:
107
- if schedule_obj.num_timeslots_filled > max_list[0] or schedule_obj.num_timeslots_filled == max_list[0]:
108
  schedules.append(copy.deepcopy(schedule_obj))
109
- max_list[0] = schedule_obj.num_timeslots_filled
 
 
 
110
 
111
  # Base case
112
  if len(people) == 0:
@@ -123,21 +133,20 @@ def find_all_schedules(people: list, availability: dict, schedule_obj: Schedule,
123
 
124
  # Explore (assign everyone else to timeslots based on that decision)
125
  if len(people) == 1:
126
- find_all_schedules([], availability, schedule_obj, capacity, schedules, max_list)
127
 
128
  else:
129
- find_all_schedules(people[1:len(people)], availability, schedule_obj, capacity, schedules, max_list)
130
 
131
  # Unchoose (remove that person from the timeslot)
132
  schedule_obj.remove(person, time)
133
  # NOTE: this will not generate a full timeslot, but could still lead to a good schedule
134
  else:
135
  if len(people) == 1:
136
- find_all_schedules([], availability, schedule_obj, capacity, schedules, max_list)
137
  else:
138
- find_all_schedules(people[1:len(people)], availability, schedule_obj, capacity, schedules, max_list)
139
-
140
-
141
  return
142
 
143
 
@@ -256,8 +265,10 @@ def classify_schedules(people: list, schedules: list, partial_names: list, total
256
 
257
  all_names = pref_dict.keys()
258
 
259
- # Evaluate each schedule
260
- overall_max = 0
 
 
261
  for sched in schedules:
262
  if sched.num_timeslots_filled != max_timeslots_filled:
263
  continue
@@ -307,27 +318,25 @@ def classify_schedules(people: list, schedules: list, partial_names: list, total
307
 
308
 
309
  # Parameters: schedules that have the max number of timeslots filled
 
310
  # Returns: a list of all schedules that have the max number of workshops
311
  # To make it less overwhelming, it will return {cutoff} randomly
312
- def get_best_schedules(schedules: list, cutoff: str) -> list:
313
  cutoff = int(cutoff)
314
- overall_max = 0
315
- best_schedules = {}
316
  for sched in schedules:
317
- if sched.total_num_workshops not in best_schedules:
318
- best_schedules[sched.total_num_workshops] = []
319
- best_schedules[sched.total_num_workshops].append(sched.timeslots)
320
- if sched.total_num_workshops > overall_max:
321
- overall_max = sched.total_num_workshops
322
- all_best_schedules = best_schedules[overall_max]
323
  if cutoff == -1:
324
- return all_best_schedules
325
  else:
326
- if len(all_best_schedules) > cutoff:
327
  # Sample without replacement
328
- return random.sample(all_best_schedules, cutoff)
329
  else:
330
- return all_best_schedules
331
 
332
 
333
  # Big wrapper function that calls the other functions
@@ -338,6 +347,7 @@ def main(df, capacity:int, num_results: int, og_slots: list):
338
  res = convert_df(df)
339
  people = res[0]
340
  availability = res[1]
 
341
 
342
  partial_names = []
343
 
@@ -345,21 +355,22 @@ def main(df, capacity:int, num_results: int, og_slots: list):
345
 
346
  schedules = []
347
  schedule_obj = Schedule(timeslots)
348
- max_list = [0]
 
349
 
350
- find_all_schedules(people, availability, schedule_obj, capacity, schedules, max_list)
351
 
352
  total_timeslots = len(timeslots)
353
 
354
 
355
- res = classify_schedules(people, schedules, partial_names, total_timeslots, max_list[0])
356
  valid_schedules = res[0]
357
  decent_schedules = res[1]
358
 
359
 
360
  # Return schedules
361
  if len(valid_schedules) > 0:
362
- best_schedules = get_best_schedules(valid_schedules, num_results)
363
  res = make_df(best_schedules, descrip_dict, og_slots)
364
  new_df = res[0]
365
  count = res[1]
@@ -369,11 +380,11 @@ def main(df, capacity:int, num_results: int, og_slots: list):
369
  results = "Good news! I was able to make multiple complete schedules."
370
 
371
  else:
372
- best_schedules = get_best_schedules(decent_schedules, num_results)
373
  res = make_df(best_schedules, descrip_dict, og_slots)
374
  new_df = res[0]
375
  count = res[1]
376
- beginning = "I wasn't able to make a complete schedule, but here"
377
  if count == 1:
378
  results = f"{beginning} is the best option."
379
  else:
@@ -387,7 +398,6 @@ def main(df, capacity:int, num_results: int, og_slots: list):
387
  new_df.to_csv(path, index=False)
388
  return results, new_df, path
389
 
390
-
391
 
392
 
393
 
 
43
  self.timeslots[time].remove(person)
44
 
45
 
46
+ def print(self):
47
+ print(f"# timeslots filled: {self.num_timeslots_filled}")
48
+ print(f"# workshops: {self.total_num_workshops}")
49
+ for time,instructors in self.timeslots.items():
50
+ print(f"{time}: {', '.join(instructors)}")
51
+
52
+
53
  # Returns True if the person can teach during the slot, and False otherwise
54
  def can_teach(person: str, slot: list, capacity: int) -> bool:
55
  if len(slot) == capacity or len(slot) > capacity:
 
110
 
111
 
112
  # Recursive function that generates all possible schedules
113
+ def find_all_schedules(people: list, availability: dict, schedule_obj: Schedule, capacity: int, schedules: list, max_timeslots_list: list, max_workshops_list: list) -> None:
114
+ if schedule_obj.num_timeslots_filled > max_timeslots_list[0] or schedule_obj.num_timeslots_filled == max_timeslots_list[0]:
115
  schedules.append(copy.deepcopy(schedule_obj))
116
+ max_timeslots_list[0] = schedule_obj.num_timeslots_filled
117
+ # Keep track of total number of workshops taught
118
+ if schedule_obj.total_num_workshops > max_workshops_list[0] or schedule_obj.total_num_workshops == max_workshops_list[0]:
119
+ max_workshops_list[0] = schedule_obj.total_num_workshops
120
 
121
  # Base case
122
  if len(people) == 0:
 
133
 
134
  # Explore (assign everyone else to timeslots based on that decision)
135
  if len(people) == 1:
136
+ find_all_schedules([], availability, schedule_obj, capacity, schedules, max_timeslots_list, max_workshops_list)
137
 
138
  else:
139
+ find_all_schedules(people[1:len(people)], availability, schedule_obj, capacity, schedules, max_timeslots_list, max_workshops_list)
140
 
141
  # Unchoose (remove that person from the timeslot)
142
  schedule_obj.remove(person, time)
143
  # NOTE: this will not generate a full timeslot, but could still lead to a good schedule
144
  else:
145
  if len(people) == 1:
146
+ find_all_schedules([], availability, schedule_obj, capacity, schedules, max_timeslots_list, max_workshops_list)
147
  else:
148
+ find_all_schedules(people[1:len(people)], availability, schedule_obj, capacity, schedules, max_timeslots_list, max_workshops_list)
149
+
 
150
  return
151
 
152
 
 
265
 
266
  all_names = pref_dict.keys()
267
 
268
+
269
+ ## Evaluate each schedule ##
270
+ overall_max = 0 # changes throughout the function
271
+
272
  for sched in schedules:
273
  if sched.num_timeslots_filled != max_timeslots_filled:
274
  continue
 
318
 
319
 
320
  # Parameters: schedules that have the max number of timeslots filled
321
+ # Max number of workshops taught in filled timeslots
322
  # Returns: a list of all schedules that have the max number of workshops
323
  # To make it less overwhelming, it will return {cutoff} randomly
324
+ def get_best_schedules(schedules: list, cutoff: str, max_workshops: int) -> list:
325
  cutoff = int(cutoff)
326
+ best_schedules = []
 
327
  for sched in schedules:
328
+ if sched.total_num_workshops != max_workshops:
329
+ continue
330
+ best_schedules.append(sched.timeslots)
331
+
 
 
332
  if cutoff == -1:
333
+ return best_schedules
334
  else:
335
+ if len(best_schedules) > cutoff:
336
  # Sample without replacement
337
+ return random.sample(best_schedules, cutoff)
338
  else:
339
+ return best_schedules
340
 
341
 
342
  # Big wrapper function that calls the other functions
 
347
  res = convert_df(df)
348
  people = res[0]
349
  availability = res[1]
350
+ print(availability)
351
 
352
  partial_names = []
353
 
 
355
 
356
  schedules = []
357
  schedule_obj = Schedule(timeslots)
358
+ max_timeslots_list = [0]
359
+ max_workshops_list = [0]
360
 
361
+ find_all_schedules(people, availability, schedule_obj, capacity, schedules, max_timeslots_list, max_workshops_list)
362
 
363
  total_timeslots = len(timeslots)
364
 
365
 
366
+ res = classify_schedules(people, schedules, partial_names, total_timeslots, max_timeslots_list[0])
367
  valid_schedules = res[0]
368
  decent_schedules = res[1]
369
 
370
 
371
  # Return schedules
372
  if len(valid_schedules) > 0:
373
+ best_schedules = get_best_schedules(valid_schedules, num_results, max_workshops_list)
374
  res = make_df(best_schedules, descrip_dict, og_slots)
375
  new_df = res[0]
376
  count = res[1]
 
380
  results = "Good news! I was able to make multiple complete schedules."
381
 
382
  else:
383
+ best_schedules = get_best_schedules(decent_schedules, num_results, max_workshops_list)
384
  res = make_df(best_schedules, descrip_dict, og_slots)
385
  new_df = res[0]
386
  count = res[1]
387
+ beginning = "Here"
388
  if count == 1:
389
  results = f"{beginning} is the best option."
390
  else:
 
398
  new_df.to_csv(path, index=False)
399
  return results, new_df, path
400
 
 
401
 
402
 
403