Esempio n. 1
0
def simulated_hardening(matrix, data, free, filled, groups_empty_space, teachers_empty_space, subjects_order, file):
    """
    Algorithm that uses simulated hardening with geometric decrease of temperature to optimize timetable by satisfying
    soft constraints as much as possible (empty space for groups and existence of an hour in which there is no classes).
    """
    # number of iterations
    iter_count = 2500
    # temperature
    t = 0.5
    _, _, curr_cost_group = empty_space_groups_cost(groups_empty_space)
    _, _, curr_cost_teachers = empty_space_teachers_cost(teachers_empty_space)
    curr_cost = curr_cost_group  # + curr_cost_teachers
    if free_hour(matrix) == -1:
        curr_cost += 1

    for i in range(iter_count):
        rt = random.uniform(0, 1)
        t *= 0.99                   # geometric decrease of temperature

        # save current results
        old_matrix = copy.deepcopy(matrix)
        old_free = copy.deepcopy(free)
        old_filled = copy.deepcopy(filled)
        old_groups_empty_space = copy.deepcopy(groups_empty_space)
        old_teachers_empty_space = copy.deepcopy(teachers_empty_space)
        old_subjects_order = copy.deepcopy(subjects_order)

        # try to mutate 1/4 of all classes
        for j in range(len(data.classes) // 4):
            index_class = random.randrange(len(data.classes))
            mutate_ideal_spot(matrix, data, index_class, free, filled, groups_empty_space, teachers_empty_space,
                              subjects_order)
        _, _, new_cost_groups = empty_space_groups_cost(groups_empty_space)
        _, _, new_cost_teachers = empty_space_teachers_cost(teachers_empty_space)
        new_cost = new_cost_groups  # + new_cost_teachers
        if free_hour(matrix) == -1:
            new_cost += 1

        if new_cost < curr_cost or rt <= math.exp((curr_cost - new_cost) / t):
            # take new cost and continue with new data
            curr_cost = new_cost
        else:
            # return to previously saved data
            matrix = copy.deepcopy(old_matrix)
            free = copy.deepcopy(old_free)
            filled = copy.deepcopy(old_filled)
            groups_empty_space = copy.deepcopy(old_groups_empty_space)
            teachers_empty_space = copy.deepcopy(old_teachers_empty_space)
            subjects_order = copy.deepcopy(old_subjects_order)
        if i % 100 == 0:
            print('Iteration: {:4d} | Average cost: {:0.8f}'.format(i, curr_cost))

    print('TIMETABLE AFTER HARDENING')
    show_timetable(matrix)
    print('STATISTICS AFTER HARDENING')
    show_statistics(matrix, data, subjects_order, groups_empty_space, teachers_empty_space)
    write_solution_to_file(matrix, data, filled, file, groups_empty_space, teachers_empty_space, subjects_order)
Esempio n. 2
0
def show_statistics(matrix, data, subjects_order, groups_empty_space,
                    teachers_empty_space):
    """
    Prints statistics.
    """
    cost_hard = check_hard_constraints(matrix, data)
    if cost_hard == 0:
        print('Hard constraints satisfied: 100.00 %')
    else:
        print('Hard constraints NOT satisfied, cost: {}'.format(cost_hard))
    print('Soft constraints satisfied: {:.02f} %\n'.format(
        subjects_order_cost(subjects_order)))

    empty_groups, max_empty_group, average_empty_groups = empty_space_groups_cost(
        groups_empty_space)
    print('TOTAL empty space for all GROUPS and all days: ', empty_groups)
    print('MAX empty space for GROUP in day: ', max_empty_group)
    print('AVERAGE empty space for GROUPS per week: {:.02f}\n'.format(
        average_empty_groups))

    empty_teachers, max_empty_teacher, average_empty_teachers = empty_space_teachers_cost(
        teachers_empty_space)
    print('TOTAL empty space for all TEACHERS and all days: ', empty_teachers)
    print('MAX empty space for TEACHER in day: ', max_empty_teacher)
    print('AVERAGE empty space for TEACHERS per week: {:.02f}\n'.format(
        average_empty_teachers))
Esempio n. 3
0
def write_solution_to_file(matrix, data, filled, filepath, groups_empty_space,
                           teachers_empty_space, subjects_order):
    """
    Writes statistics and schedule to file.
    """
    f = open('solution_files/sol_' + filepath, 'w')

    f.write(
        '-------------------------- STATISTICS --------------------------\n')
    cost_hard = check_hard_constraints(matrix, data)
    if cost_hard == 0:
        f.write('\nHard constraints satisfied: 100.00 %\n')
    else:
        f.write('Hard constraints NOT satisfied, cost: {}\n'.format(cost_hard))
    f.write('Soft constraints satisfied: {:.02f} %\n\n'.format(
        subjects_order_cost(subjects_order)))

    empty_groups, max_empty_group, average_empty_groups = empty_space_groups_cost(
        groups_empty_space)
    f.write('TOTAL empty space for all GROUPS and all days: {}\n'.format(
        empty_groups))
    f.write('MAX empty space for GROUP in day: {}\n'.format(max_empty_group))
    f.write('AVERAGE empty space for GROUPS per week: {:.02f}\n\n'.format(
        average_empty_groups))

    empty_teachers, max_empty_teacher, average_empty_teachers = empty_space_teachers_cost(
        teachers_empty_space)
    f.write('TOTAL empty space for all TEACHERS and all days: {}\n'.format(
        empty_teachers))
    f.write(
        'MAX empty space for TEACHER in day: {}\n'.format(max_empty_teacher))
    f.write('AVERAGE empty space for TEACHERS per week: {:.02f}\n\n'.format(
        average_empty_teachers))

    # f_hour = free_hour(matrix)
    # if f_hour != -1:
    #     f.write('Free term -> {}\n'.format(f_hour))
    # else:
    #     f.write('NO hours without classes.\n')

    groups_dict = {}
    for group_name, group_index in data.groups.items():
        if group_index not in groups_dict:
            groups_dict[group_index] = group_name
    days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
    hours = [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

    f.write(
        '\n--------------------------- SCHEDULE ---------------------------')
    for class_index, times in filled.items():
        c = data.classes[class_index]
        groups = ' '
        for g in c.groups:
            groups += groups_dict[g] + ', '
        f.write('\n\nClass {}\n'.format(class_index))
        f.write(
            'Teacher: {} \nSubject: {} \nGroups:{} \nType: {} \nDuration: {} hour(s)'
            .format(c.teacher, c.subject, groups[:len(groups) - 2], c.type,
                    c.duration))
        room = str(data.classrooms[times[0][1]])
        f.write('\nClassroom: {:2s}\nTime: {}'.format(room[:room.rfind('-')],
                                                      days[times[0][0] // 12]))
        for time in times:
            f.write(' {}'.format(hours[time[0] % 12]))
    f.close()
def simulated_hardening_utils(matrix, data, free, filled, groups_empty_space,
                              teachers_empty_space, subjects_order, result,
                              index):

    # create new data for parallel
    matrix_utils = copy.deepcopy(matrix)
    data_utils = copy.deepcopy(data)
    free_utils = copy.deepcopy(free)
    filled_utils = copy.deepcopy(filled)
    groups_empty_space_utils = copy.deepcopy(groups_empty_space)
    teachers_empty_space_utils = copy.deepcopy(teachers_empty_space)
    subjects_order_utils = copy.deepcopy(subjects_order)

    # number of iterations
    iter_count = 90
    # temperature
    t = 0.5 - index * 0.05
    _, _, curr_cost_group = empty_space_groups_cost(groups_empty_space)
    _, _, curr_cost_teachers = empty_space_teachers_cost(teachers_empty_space)
    curr_cost = curr_cost_group + curr_cost_teachers
    # if free_hour(matrix) == -1:
    #     curr_cost += 1

    for i in range(iter_count):
        rt = random.uniform(0, 1)
        t *= 0.99

        # save current results
        old_matrix = copy.deepcopy(matrix_utils)
        old_free = copy.deepcopy(free_utils)
        old_filled = copy.deepcopy(filled_utils)
        old_groups_empty_space = copy.deepcopy(groups_empty_space_utils)
        old_teachers_empty_space = copy.deepcopy(teachers_empty_space_utils)
        old_subjects_order = copy.deepcopy(subjects_order_utils)

        # try to mutate 1/4 of all classes
        for j in range(len(data.classes) // 4):
            index_class = random.randrange(len(data_utils.classes))
            mutate_ideal_spot(matrix_utils, data_utils, index_class,
                              free_utils, filled_utils,
                              groups_empty_space_utils,
                              teachers_empty_space_utils, subjects_order_utils)
        _, _, new_cost_groups = empty_space_groups_cost(
            groups_empty_space_utils)
        _, _, new_cost_teachers = empty_space_teachers_cost(
            teachers_empty_space_utils)
        new_cost = new_cost_groups + new_cost_teachers
        # if free_hour(matrix) == -1:
        #     new_cost += 1

        if new_cost < curr_cost or rt <= math.exp((curr_cost - new_cost) / t):
            # take new cost and continue with new data
            curr_cost = new_cost
        else:
            # return to previously saved data
            matrix_utils = copy.deepcopy(old_matrix)
            free_utils = copy.deepcopy(old_free)
            filled_utils = copy.deepcopy(old_filled)
            groups_empty_space_utils = copy.deepcopy(old_groups_empty_space)
            teachers_empty_space_utils = copy.deepcopy(
                old_teachers_empty_space)
            subjects_order_utils = copy.deepcopy(old_subjects_order)
        if i % 10 == 0:
            print('Iteration: {:4d} | Average cost: {:0.8f}'.format(
                i, curr_cost))

    result[index] = [
        curr_cost, matrix_utils, free_utils, filled_utils,
        groups_empty_space_utils, teachers_empty_space_utils,
        subjects_order_utils
    ]