def calc_score(courses, rooms, course_names, matrix): """ Score calculation. """ # iterate through courses and set all scores to zero for course in courses: course.goodbad = 0 # calculate points for all categories and add them points = 0 points += sc.matrix_checker(courses, course_names, matrix) + sc.order_checker(courses) points += sc.student_checker(rooms, courses, course_names) dist_bonus, dist_malus = sc.distribution_checker(courses) points += dist_bonus + dist_malus points += sc.evening_checker(rooms, courses, course_names) return points
def initial_population(): """ Initial population. """ # store different schedules scheduled_rooms = [[] for i in range(5)] scheduled_courses = [[] for i in range(5)] scheduled_students = [[] for i in range(5)] scores = [0 for i in range(5)] matrix = [] course_names = [] matrixfile = open("data/matrix.csv", 'r') coursenamefile = open("data/vakken.txt", 'r') # read matrix for line in matrixfile: matrix.append(line.split(";")) for line in coursenamefile: course_names.append(line.split(";")[0]) # schedule 5 times for i in range(5): #read files coursefile = open("data/vakken.txt", 'r') roomfile = open("data/lokalen.txt", 'r') studentfile = open("data/studentenenvakken.csv", 'r', errors='ignore') for line in coursefile: info = line.split(";") scheduled_courses[i].append(inf.Course(info[0], int(info[1]), int(info[2]), int(info[3]),\ int(info[4]), int(info[5]), int(info[7]))) for line in roomfile: info = line.split(",") scheduled_rooms[i].append(inf.Room_info(info[0], int(info[1]))) # create evening timeslot in largest room big_room_cap = 0 for room in scheduled_rooms[i]: if room.cap > big_room_cap: big_room_cap = room.cap big_room = room for day in big_room.days: day.hours.append(inf.Hour()) for line in studentfile: student_info = line.strip("\n").split(";") student_courses = [] for coursename in student_info[3:]: if len(coursename) > 2: student_courses.append(coursename) scheduled_students[i].append( inf.Student(student_info[0], student_info[1], student_info[2], student_courses)) # remove headers in students scheduled_students[i] = scheduled_students[i][1:] # schedule day_sch.total_schedule(scheduled_rooms[i], scheduled_courses[i], course_names, matrix) # calculate score and apply hillclimber scores[i] = sc.matrix_checker(scheduled_courses[i], course_names, matrix) + sc.order_checker( scheduled_courses[i]) scores[i] += sc.student_checker(scheduled_rooms[i], scheduled_courses[i], course_names) bonus, malus = sc.distribution_checker(scheduled_courses[i]) scores[i] += bonus + malus scores[i] += sc.evening_checker(scheduled_rooms[i], scheduled_courses[i], course_names) scores[i] = hill.random_climber(scheduled_courses[i], scheduled_rooms[i], course_names, 1000, scores[i], matrix) # schedule students stu.distribute_all_students(scheduled_students[i], scheduled_rooms[i], scheduled_courses[i], course_names) # Save score for hillclimber student_bonus, student_malus = sc.student_score(scheduled_students[i]) student_score = student_bonus + student_malus # pre filter the relevant courses student_courses = [] for course in scheduled_courses[i]: poss_group_ids = [] for activity in course.activities: if activity.group_id not in poss_group_ids and activity.group_id != "x": poss_group_ids.append(activity.group_id) if len(poss_group_ids) > 1: student_courses.append([course, poss_group_ids]) # student hillclimber scores[i] += sthl.students_hillclimber(student_courses, scheduled_students[i], student_score, 100) return scheduled_rooms, scheduled_courses, scheduled_students, scores, course_names, matrix
def mutate_schedule(rooms, courses, students, score, matrix, course_names): """ Mutate a fit schedule to 10 different schedules. Keep the orignal schedule. Furthermore, for 9 times: unschedule a random subset of the courses and reschedule this subset. """ # store mutated schedules new_rooms = [[inf.Room_info(room.name, room.cap) for room in rooms] \ for j in range(10)] new_courses = [[inf.Course(course.name, course.hoorcolleges, \ course.werkcolleges, course.max_werkcolleges, course.practica, \ course.max_practica, course.e_students) for course in courses] \ for j in range(10)] new_students = [[inf.Student(student.surname, student.name, \ student.student_number, student.courses) for student in students] \ for j in range(10)] new_scores = [0 for j in range(10)] # create evening timeslot in largest room for n_rooms in new_rooms: big_room_cap = 0 for room in n_rooms: if room.cap > big_room_cap: big_room_cap = room.cap big_room = room for day in big_room.days: day.hours.append(inf.Hour()) # copy orignal schedule onto mutations for k in range(10): new_rooms[k], new_courses[k], new_students[k] = bas_sch.copy_schedule(rooms, \ courses, students, new_rooms[k], new_courses[k], new_students[k]) # keep original schedule new_scores[0] = score # mutate 9 times for i in range(1, 10): # select random subset of scheduled courses indices = rd.sample(range(len(new_courses[i])), rd.randint(0, \ len(new_courses[i]) - 7)) # store names of subset unsched_names = [] # unschedule subset for j in indices: unsched_names.append(new_courses[i][j].name) clear_schedule_of_course(new_rooms[i], new_courses[i][j], \ new_students[i]) # schedule all required classes schedulings = 0 for j in indices: schedulings += day_sch.course_scheduler(new_courses[i][j], new_rooms[i],\ new_courses[i], course_names, matrix) print("Schedulings:", schedulings) # schedule students' unscheduled groups for student in new_students[i]: for coursename in student.courses: if coursename in unsched_names: course = new_courses[i][course_names.index(coursename)] poss_group_ids = [] student_id = "" # get possible groups of course for student and choose one randomly for activity in course.activities: if activity.group_id != "x" and len( activity.students) < activity.capacity: poss_group_ids.append(activity.group_id) if len(poss_group_ids) > 0: student_id = rd.choice(poss_group_ids) student.group_id[student.courses.index( course.name)] = student_id # schedule student for activity in course.activities: if activity.id == "Hoorcollege" or activity.group_id == student_id: activity.students.append(student.student_number) student.dates[student.courses.index( coursename)].append(activity.date) # calculate score new_scores[i] = sc.matrix_checker(new_courses[i], course_names, \ matrix) + sc.order_checker(new_courses[i]) new_scores[i] += sc.student_checker(new_rooms[i], new_courses[i], course_names) bonus, malus = sc.distribution_checker(new_courses[i]) new_scores[i] += bonus + malus + sc.evening_checker(new_rooms[i], \ new_courses[i], course_names) student_bonus, student_malus = sc.student_score(new_students[i]) new_scores[i] += student_bonus + student_malus return new_rooms, new_courses, new_students, new_scores
big_room_cap = room.cap big_room = room for day in big_room.days: day.hours.append(inf.Hour()) course_names = [course.name for course in courses] # return total score of schedule using the score calculator day_sch.total_schedule(rooms, courses, course_names, matrix) score = sc.matrix_checker(courses, course_names, matrix) + sc.order_checker(courses) score += sc.student_checker(rooms, courses, course_names) bonus, malus = sc.distribution_checker(courses) score += bonus + malus score += sc.evening_checker(rooms, courses, course_names) # print scores before hillclimber if not course_optim_type == "none": print("Courses score before optimization:", score) # for course in courses: # if course.goodbad < - 1000: # score = hill.course_climber(courses[0], courses, rooms, course_names, 1000, score, matrix) # print("Score after 1 course_climb: ", score) # run hillclimber if specified by user if course_optim_type == "hillclimber": score = hill.random_climber(courses, rooms, course_names, c_max_iterations, score, matrix)
def search(rooms, courses, course_names, students, matrix): """ Searches for painpoints in the case. """ student_numbers = [student.student_number for student in students] student_weakness = [0 for number in student_numbers] course_weakness = [0 for coursename in course_names] for i in range(100): # schedule day_sch.total_schedule(rooms, courses, course_names, matrix) # calculate score and apply hillclimber score = sc.matrix_checker(courses, course_names, matrix) + sc.order_checker(courses) score += sc.student_checker(rooms, courses, course_names) bonus, malus = sc.distribution_checker(courses) score += bonus + malus score += sc.evening_checker(rooms, courses, course_names) score = hill.random_climber(courses, rooms, course_names, 1000, score, matrix) # schedule students stu.distribute_all_students(students, rooms, courses, course_names) # save score for hillclimber student_bonus, student_malus = sc.student_score(students) student_score = student_bonus + student_malus # pre filter the relevant courses student_courses = [] for course in courses: poss_group_ids = [] for activity in course.activities: if activity.group_id not in poss_group_ids and activity.group_id != "x": poss_group_ids.append(activity.group_id) if len(poss_group_ids) > 1: student_courses.append([course, poss_group_ids]) # student hillclimber student_climb_score = sthl.students_hillclimber( student_courses, students, student_score, 100) # update statistics for course in courses: if course.goodbad < 0: course_weakness[course_names.index(course.name)] += 1 for student in students: if student.goodbad < -12: student_weakness[student_numbers.index( student.student_number)] += 1 bas_sch.print_schedule(rooms) bas_sch.clear_schedule(rooms, courses) bas_sch.clear_students(students) cprint(i, "blue") # print painpoints for f in range(len(student_numbers)): print(student_numbers[f] + ":", student_weakness[f]) for j in range(len(course_names)): print(course_names[j] + ":", course_weakness[j])