Пример #1
0
 def create(nodes, mapping):
     nonlocal max_happiness
     nonlocal ret
     nonlocal k
     if nodes == []:
         mm = convert_dictionary(mapping)
         #if mapping not in rooms and is_valid_solution(mm, G, s, len(mapping)):
             #rooms.append(mapping)
         room_k = len(mapping)
         if is_valid_solution(mm, G, s, room_k):
             happiness = calculate_happiness(mm, G)
             if happiness > max_happiness:
                 max_happiness = happiness
                 ret = mm
                 k = room_k
         return
     pp = nodes[0]
     r = 0
     n = copy.deepcopy(nodes)
     n.remove(pp)
     for room in mapping:
         m = copy.deepcopy(mapping)
         m[room] = m[room] + [pp]
         mm = convert_dictionary(m)
         if is_valid_solution(mm, G, s, len(m)):
             create(n, m)
         r += 1
     m = copy.deepcopy(mapping)
     m[r] = [pp]
     create(n, m)
Пример #2
0
def solve_happy(G, s, prob):
    """
    Args:
        G: networkx.Graph
        s: stress_budget
    Returns:
        D: Dictionary mapping for student to breakout room r e.g. {0:2, 1:0, 2:1, 3:2}
        k: Number of breakout rooms
    """

    # TODO: your code here!
    best_D_so_far = {}
    best_k_so_far = 1
    best_H_so_far = 0.0
    n = nx.number_of_nodes(G)
    
    for k in range(1, n + 1):
        curr_D = {}
        smax = s/k
        G_happy = G.copy()
        while nx.number_of_nodes(G_happy) > k:  
            i = np.random.geometric(p=prob, size = 1).item(0)
            # sort edges by decreasing happiness
            sorted_happiness = sorted(G_happy.edges(data=True), key=lambda y: (y[2]["happiness"], -y[2]["stress"]), reverse=True)
            #i = random.randint(0, len(sorted_happiness))
            if len(sorted_happiness) == 0:
                break
            #need to merge nodes A and B
            i = i % len(sorted_happiness)
            n1, n2, _ = sorted_happiness[i]
            if G_happy.nodes[n1].get("stress", 0) + G_happy.nodes[n2].get("stress", 0) + G_happy.edges[n1, n2]["stress"] <= smax:
                merge(G_happy, n1, n2)
                
            else:
                G_happy.remove_edge(n1,n2)
                

        if nx.number_of_nodes(G_happy) == k:
            room = 0
            for node in list(G_happy.nodes):
                if isinstance(node, int):
                    temp = [node]
                else:
                    temp = node.split(' ')
                    temp = [int(x) for x in temp]
                curr_D[room] = temp
                room += 1
            curr_D = convert_dictionary(curr_D)
            
        else:
            continue
       
        if is_valid_solution(curr_D, G, s, k):
            if calculate_happiness(curr_D, G) > best_H_so_far:
                best_D_so_far = curr_D
                best_k_so_far = k
                best_H_so_far = calculate_happiness(curr_D, G)
            #
    # pass
    return best_D_so_far, best_k_so_far
Пример #3
0
def read_output_file(path, G, s):
    """
    Parses and validates an output file

    :param path: str, a path
    :param G: the input graph corresponding to this output
    :return: networkx Graph is the output is well formed, AssertionError thrown otherwise
    """
    with open(path, "r") as fo:
        nodes = set()
        rooms = set()
        D = {}
        lines = fo.read().splitlines()
        fo.close()

        for line in lines:
            tokens = line.split()
            assert len(tokens) == 2
            #validate node
            node = int(tokens[0])
            assert tokens[0].isdigit() and 0 <= node < len(G)
            nodes.add(node)
            #validate rooms
            room = int(tokens[1])
            assert tokens[0].isdigit() and 0 <= room < len(G)
            rooms.add(room)

            D[node] = room

        assert len(nodes) == len(G)
        assert utils.is_valid_solution(D, G, s, len(rooms))

    return D
Пример #4
0
def solve(G, s):
    """
    Args:
        G: networkx.Graph
        s: stress_budget
    Returns:
        D: Dictionary mapping for student to breakout room r e.g. {0:2, 1:0, 2:1, 3:2}
        k: Number of breakout rooms
    """
    D = {}
    for i in G.nodes:
        D[i] = 0
    rooms = 1
    while not is_valid_solution(D, G, s, rooms):
        # print(rooms)
        for i in range(rooms):
            people_in_room_i = [
                person for person in D.keys() if D[person] == i
            ]
            while calculate_stress_for_room(people_in_room_i, G) > s / rooms:
                person_to_take_out = people_in_room_i[random.randrange(
                    0,
                    len(people_in_room_i) - 1, 1)]
                D[person_to_take_out] = i + 1
                if (i + 1) > rooms - 1:
                    rooms = rooms + 1
                people_in_room_i.remove(person_to_take_out)
    return D, rooms
Пример #5
0
def solve(G, s):
    """
    Args:
        G: networkx.Graph
        s: stress_budget
    Returns:
        D: Dictionary mapping for student to breakout room r e.g. {0:2, 1:0, 2:1, 3:2}
        k: Number of breakout rooms
    """
    if G.size(weight='stress') <= s:
        return {t: 0 for t in list(G.nodes)}, 1

    max_happiness = 0.0
    best_d = {}
    for node in list(G.nodes):
        best_d[node] = node

    # Write out every single solution. Check each solution's validity. If valid, compute happiness.
    n = len(list(G.nodes))
    for a in range(n):
        for b in range(n):
            for c in range(n):
                for d in range(n):
                    for e in range(n):
                        for f in range(n):
                            for g in range(n):
                                for h in range(n):
                                    for i in range(n):
                                        for j in range(n):

                                            sol = {
                                                0: a,
                                                1: b,
                                                2: c,
                                                3: d,
                                                4: e,
                                                5: f,
                                                6: g,
                                                7: h,
                                                8: i,
                                                9: j
                                            }

                                            k = len(set(sol.values()))

                                            if is_valid_solution(sol, G, s, k):
                                                happy = calculate_happiness(
                                                    sol, G)
                                                if happy > max_happiness:
                                                    max_happiness = happy
                                                    best_d = sol
                                                    print(max_happiness)

    return best_d, len(set(best_d.values()))
Пример #6
0
def repeatedly_solve(path):
    G, s = read_input_file("inputs/" + path + ".in")
    solutions = []
    happiness = []
    for i in range(5):
        D, k = solve_helper(G, s, 12, 0, 0)
        assert is_valid_solution(D, G, s, k)
        # write_output_file(D, "outputs_manual/" + str(path) + "_ratio_" + str(i) + ".out")
        solutions.append(D)
        happiness.append(calculate_happiness(D, G))
    print("i'm done with 5 only ratio")
    for i in range(5):
        D, k = solve_helper(G, s, 0, 12, 0)
        assert is_valid_solution(D, G, s, k)
        # write_output_file(D, "outputs_manual/" + str(path) + "_happiness_" + str(i) + ".out")
        solutions.append(D)
        happiness.append(calculate_happiness(D, G))
    print("i'm done with 5 only happiness")
    for i in range(5):
        D, k = solve_helper(G, s, 0, 0, 12)
        assert is_valid_solution(D, G, s, k)
        # write_output_file(D, "outputs_manual/" + str(path) + "_stress_" + str(i) + ".out")
        solutions.append(D)
        happiness.append(calculate_happiness(D, G))
    print("i'm done with 5 only stress")
    for i in range(5):
        D, k = solve_helper(G, s, 5, 5, 5)
        assert is_valid_solution(D, G, s, k)
        # write_output_file(D, "outputs_manual/" + str(path) + "_all_3_" + str(i) + ".out")
        solutions.append(D)
        happiness.append(calculate_happiness(D, G))
    print("i'm done with 5 all 3")
    print(happiness)
    max_happiness = max(happiness)
    best_index = 0
    print(max_happiness)
    for i in range(20):
        if happiness[i] == max_happiness:
            best_index = i
    print(best_index)
    write_output_file(solutions[best_index], "out_manual/" + str(path) + ".out")
Пример #7
0
def single_file(lol):
    path = 'inputs/small/small-' + str(lol) + '.in'
    # path = 'test.in'
    # path = 'inputs/medium/medium-' + str(lol) +  '.in'
    # path = 'inputs/large/large-' + str(lol) +  '.in'
    G = read_input_file(path)
    print(G.nodes)
    # c, k = solve2(G)
    c, k = solve2(G)
    assert is_valid_solution(G, c, k)
    print("Shortest Path Difference: {}".format(calculate_score(G, c, k)))
    write_output_file(G, c, k, 'small-test.out')
Пример #8
0
def use_greedy_happystress(G, s):
    best = {}
    i = 1
    while i <= len(G.nodes):
        G_cop = G.copy()
        possible = greedy_happystress(G, G_cop, s, i)
        if is_valid_solution(possible, G, s, i) and not list(G_cop.nodes):
            if not best or calculate_happiness(best, G) < calculate_happiness(
                    possible, G):
                best = possible
        i += 1
    return best
Пример #9
0
def main():
    already_done = [
        1, 2, 4, 6, 7, 9, 10, 12, 14, 15, 16, 17, 18, 19, 20, 26, 29, 30, 33,
        34, 35, 38, 39, 40, 41, 43, 46, 47, 50, 51, 52, 53, 54, 55, 56, 58, 59,
        60, 63, 64, 70, 73, 74, 76, 77, 79, 81, 83, 84, 85, 88, 89, 90, 96,
        100, 101, 103, 105, 109, 110, 111, 112, 113, 114, 115, 117, 119, 121,
        122, 123, 125, 128, 129, 131, 132, 134, 136, 137, 140, 141, 143, 145,
        147, 151, 152, 156, 157, 158, 159, 160, 161, 162, 166, 167, 169, 172,
        174, 175, 177, 178, 181, 184, 187, 196, 199, 201, 202, 203, 206, 207,
        208, 209, 213, 216, 217, 218, 220, 222, 223, 226, 227, 230, 233, 235,
        237, 238, 240, 241
    ]
    # already_done = [7, 18, 33, 43, 51, 54, 56, 65, 69, 73, 77, 81, 91, 112, 114, 121, 123, 127, 131, 134, 151, 169, 171, 174, 178, 184, 187, 201, 202, 207, 213, 215, 222]
    """
    inputs = glob.glob('compinputslarge/*')
    couldnt = []
    done = 0
    for i in range(len(inputs)):
        input_path = inputs[i]
        
        done += 1
        print("doing #" + str(done) + ": " + input_path)
        output_path = 'comp2large/' + basename(normpath(input_path))[:-3] + '.out'
        G, s = read_input_file(input_path)
        D, k = solve(G, s)
        if k != -1:
            assert is_valid_solution(D, G, s, k)
            write_output_file(D, output_path)
            # print("done, used " + str(k) + " rooms")
        else:
            couldnt += [input_path]
    
    """
    num = int(sys.argv[1])
    moves = int(sys.argv[2])
    print("Doing #" + str(num))
    if num not in already_done:
        input_path = "compinputsmed/medium-" + str(num) + ".in"
        current_sol_path = "comp1med/medium-" + str(num) + ".out"
        output_path = "comp2med/medium-" + str(num) + ".out"
        G, s = read_input_file(input_path)
        D, k = solve(G, s, load=current_sol_path, moves=moves)
        if k != -1:
            assert is_valid_solution(D, G, s, k)
            write_output_file(D, output_path)
Пример #10
0
def gamble_solve(G, s, num_open_rooms, reps=100, limit = -1):
    """
    Gambles by randomly assigning students to rooms and checking optimality and stress levels
    Works specifically for input #1 type
     - can be modified by changin num_open_rooms to randint
     - can be modified adding checks before h > best_h to check stress_max val per room
    ToDo:
     - Refactor to use methods in utils.py
     - Make sure truly gamble solution
    """

    students = list(G.nodes)
    #num_open_rooms = int(math.ceil(len(students)/2))
    best_h = -1
    best_rooms = []


    count = 0
    while (count < reps):
        rooms = []
        for _ in range(num_open_rooms):
            rooms.append([])
        temp_students = students.copy()



        rooms = random_assign(temp_students, rooms, limit)

        temp_d = utils.convert_list_to_dictionary(rooms)
        dict = utils.convert_dictionary(temp_d)

        valid = utils.is_valid_solution(dict, G, s, num_open_rooms)

        h = utils.calculate_happiness(dict, G)

        if ((valid) and (h > best_h)):
            best_rooms = []
            room_temp = rooms.copy()
            for i in range(len(rooms)):
                best_rooms += [rooms[i].copy()]
            best_h = h
        elif (not valid):
            count = count - 1
        count = count + 1
    return best_rooms.copy(), best_h
Пример #11
0
    def dfs(curAssignment, numAssigned, numRooms):
        nonlocal bestAssignment, bestNumRooms, bestScore
        # End early if timed out and return best solution
        if timeoutInSeconds and time.time() > start + timeoutInSeconds:
            return -1

        # Ignore assignments with more than "numStudents" rooms.
        if numRooms >= numStudents:
            return 0

        # If all students are assigned check if assignment is better
        if numAssigned >= numStudents:
            curScore = calculate_happiness(curAssignment, G)
            if curScore > bestScore:
                bestAssignment = copy.deepcopy(curAssignment)
                bestNumRooms = numRooms
                bestScore = curScore
            return 0

        # Go through all possible room assignments for the next student
        for room in range(numRooms + 1):
            curAssignment[numAssigned] = room
            newNumRooms = max(numRooms, room + 1)

            # # Check if assignment is valid so far
            # roomAssignments = {}
            # for i in range(numAssigned + 1):
            #     curRoom = curAssignment[i]
            #     if curRoom not in roomAssignments:
            #         roomAssignments[curRoom] = [i]
            #     else:
            #         roomAssignments[curRoom].append(i)
            #
            # maxRoomStress = s / newNumRooms
            # isValid = True
            # print(roomAssignments)
            # for breakoutRoom in roomAssignments:
            #     isValid &= maxRoomStress < calculate_stress_for_room(breakoutRoom, G)

            if is_valid_solution(curAssignment, G, s, newNumRooms):
                dfs(curAssignment, numAssigned + 1, newNumRooms)

        del curAssignment[numAssigned]
Пример #12
0
def solve(G):
    """
    Args:
        G: networkx.Graph
    Returns:
        c: list of cities to remove
        k: list of edges to remove
    """
    random.seed(datetime.now())
    iterations = 0
    best_c, best_k = [], []
    if len(list(G.nodes)) <= 30:
        iterations = 500
    elif len(list(G.nodes)) <= 50:
        iterations = 200
    elif len(list(G.nodes)) <= 100:
        iterations = 15
    first_time, best_score, is_medium_or_large = True, 0.0, False
    for i in range(iterations):
        m = 0
        t = len(list(G.nodes)) - 1
        if len(list(G.nodes)) <= 30:
            max_k, max_c, m = 15, 1, 100
        elif len(list(G.nodes)) <= 50:
            max_k, max_c, m = 50, 3, 100
            is_medium_or_large = True
        elif len(list(G.nodes)) <= 100:
            max_k, max_c, m = 100, 5, 500
            is_medium_or_large = True
        else:
            max_k, max_c = 0, 0
        c, k, m, max_c, max_k, first_time = helper(G, m, t, max_c, max_k,
                                                   first_time,
                                                   is_medium_or_large)
        first_time = False
        if is_valid_solution(G, c, k, t):
            curr_score = calculate_score(G, c, k, t)
            if curr_score > best_score:
                best_score = curr_score
                best_c, best_k = c, k
    print("END")
    return best_c, best_k
def solve(G, s):

    max_happiness = 0.0
    best_sol = {}

    num_students = len(list(G.nodes))
    for num_rooms in range(1, num_students + 1):
        all_sols = construct_sol(list(range(num_students)), num_rooms)

        for sol in all_sols:
            k = len(set(sol.values()))

            if is_valid_solution(sol, G, s, k):
                happy = calculate_happiness(sol, G)
                if happy > max_happiness:
                    max_happiness = happy
                    best_sol = sol
                    print(max_happiness)

    return best_sol, len(set(best_sol.values()))
Пример #14
0
def check(size):
    output = "smallresult.txt"
    output = size + "result.txt"
    print(output, file=open(output, "w"))
    directory = "small/"
    directory = size + "/"
    for filename in os.listdir(directory):
        #print(filename)
        if (filename.endswith(".in")):
            file = filename[:-3]
            inpath = os.path.join(directory, file + ".in")
            outpath = os.path.join(directory, file + ".out")
            G, s = parse.read_input_file(inpath)
            x = parse.read_output_file(outpath, G, s)
            uniqueValues = set(x.values())
            k = len(uniqueValues)
            valid = utils.is_valid_solution(x, G, s, k)
            if (valid == False):
                print("false output @", file)
                break
            happy = utils.calculate_happiness(x, G)
            print(file, "\tyields", happy, file=open(output, "a"))
Пример #15
0
def kcluster_beef(G, s):
    best = {}
    best_happiness = 0
    for i in range(1, len(G.nodes)):
        local_best = {}
        j = 0
        valid = 0
        total_combos = []
        while j <= 1000:
            if (not valid) and j >= 100:
                j = 1000
            init_centroids = random.sample(range(0, len(list(G.nodes))), i)
            if (len(total_combos) < comb(len(G.nodes), i)):
                while (init_centroids in total_combos):
                    init_centroids = random.sample(
                        range(0, len(list(G.nodes))), i)
            total_combos.append(init_centroids)
            classes = making_classes_beef(init_centroids, G, s / i)
            for c in classes:
                d = making_dic(c)
                dic = convert_dictionary(d)
                if is_valid_solution(dic, G, s, i):
                    valid = 1
                    local_best[calculate_happiness(dic, G)] = dic
                if len(local_best) != 0:
                    local = max(local_best.keys())
                    if len(best) != 0:
                        if best_happiness < local:
                            best_happiness = local
                            best = local_best[local]
                    else:
                        best_happiness = local
                        best = local_best[local]
            j += 1
    h = calculate_happiness(best, G)
    return best
Пример #16
0
def remove_c(G, c, V):
    ret = []
    nodes = list(G.nodes())
    nodes.remove(0)
    nodes.remove(V - 1)
    #ret has node
    while len(ret) < c:
        temp = -1
        curr = -1
        for j in nodes:
            H = G.copy()
            H.remove_node(j)
            if nx.is_connected(H):
                score = calculate_score(G, [j], [])
                if score > curr:
                    temp = j
                    curr = score
        if len(nodes) == 0 or temp == -1:
            return ret
        #print(temp)
        nodes.remove(temp)
        if is_valid_solution(G, ret + [temp], []):
            ret.append(temp)
    return ret
Пример #17
0
def solve(G, s):
    """
    Args:
        G: networkx.Graph
        s: stress_budget
    Returns:
        D: Dictionary mapping for student to breakout room r e.g. {0:2, 1:0, 2:1, 3:2}
        k: Number of breakout rooms
    """

    # TODO: your code here!
    rooms = {}
    numRooms = 1
    used = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    edgeCount = 0
    maxHap = 0
    maxRooms = {}
    maxNumRooms = 1
    # for i in G.edges(data=True):
    #     print (i[2])
    # edges = list(G.edges(data=True))
    # edges.sort(key=lambda x: x[2]["happiness"], reverse=True)
    # while used < G.number_of_nodes():
    #     edges[edgeCount]
    # # print(len(list(G.edges)))
    # print(temp)
    # for perm in itertools.permutations([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]):
    # for i in range(500):
    #     perm = np.random.permutation(50)
    #     currRoom = 0
    #     for student in perm:
    #
    #     # while numRooms <= 50:
    #         # studentsPerRoom = 50 // numRooms
    #         # studentCountPerRoom = 0
    #         # currRoom = 0
    #         # for student in perm:
            #     rooms[student] = currRoom
            #     studentCountPerRoom += 1
            #     if studentCountPerRoom >= studentsPerRoom:
            #         studentCountPerRoom = 0
            #         currRoom += 1
        #     if is_valid_solution(rooms, G, s, numRooms):
        #         temp = calculate_happiness(rooms, G)
        #         if temp > maxHap:
        #             maxHap = temp
        #             maxRooms = rooms
        #             maxNumRooms = numRooms
        #         print(perm, temp)
        #     rooms = {}
        #     numRooms += 1
        # # print(perm, maxHap)
        # rooms = {}
        # numRooms = 1
    numRooms = 1
    for student in range(10):
        rooms[student] = 0
    if is_valid_solution(rooms, G, s, numRooms):
            temp = calculate_happiness(rooms, G)
            if temp > maxHap:
                maxHap = temp
                maxRooms = dict(rooms)
                maxNumRooms = numRooms
    rooms = {}
    used = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    numRooms = 2
    for i in range(1, 10):
        for comb in itertools.combinations(used, i):
            for student in comb:
                rooms[student] = 0
                used.remove(student)
            for student in used:
                rooms[student] = 1
            if is_valid_solution(rooms, G, s, numRooms):
                    temp = calculate_happiness(rooms, G)
                    if temp > maxHap:
                        maxHap = temp
                        maxRooms = dict(rooms)
                        maxNumRooms = numRooms
            rooms = {}
            used = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    numRooms = 3
    for i in range(1, 10):
        for comb1 in itertools.combinations(used, i):
            for student in comb1:
                rooms[student] = 0
                used.remove(student)
            rooms1 = dict(rooms)
            used1 = set(used)
            for j in range(1, 10-i):
                for comb2 in itertools.combinations(used, j):
                    for student in comb2:
                        rooms[student] = 1
                        used.remove(student)
                    for student in used:
                        rooms[student] = 2
                    if is_valid_solution(rooms, G, s, numRooms):
                            temp = calculate_happiness(rooms, G)
                            if temp > maxHap:
                                maxHap = temp
                                maxRooms = dict(rooms)
                                maxNumRooms = numRooms
                    rooms = dict(rooms1)
                    used = set(used1)
            rooms = {}
            used = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    numRooms = 4
    for i in range(1, 10):
        for comb1 in itertools.combinations(used, i):
            for student in comb1:
                rooms[student] = 0
                used.remove(student)
            rooms1 = dict(rooms)
            used1 = set(used)
            for j in range(1, 10-i):
                for comb2 in itertools.combinations(used, j):
                    for student in comb2:
                        rooms[student] = 1
                        used.remove(student)
                    rooms2 = dict(rooms)
                    used2 = set(used)
                    for k in range(1, 10-i-j):
                        for comb3 in itertools.combinations(used, k):
                            for student in comb3:
                                rooms[student] = 2
                                used.remove(student)
                            for student in used:
                                rooms[student] = 3
                            if is_valid_solution(rooms, G, s, numRooms):
                                    temp = calculate_happiness(rooms, G)
                                    if temp > maxHap:
                                        maxHap = temp
                                        maxRooms = dict(rooms)
                                        maxNumRooms = numRooms
                            rooms = dict(rooms2)
                            used = set(used2)
                    rooms = dict(rooms1)
                    used = set(used1)
            rooms = {}
            used = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    if maxHap == 0:
        numRooms = 5
        for i in range(1, 10):
            for comb1 in itertools.combinations(used, i):
                for student in comb1:
                    rooms[student] = 0
                    used.remove(student)
                rooms1 = dict(rooms)
                used1 = set(used)
                for j in range(1, 10-i):
                    for comb2 in itertools.combinations(used, j):
                        for student in comb2:
                            rooms[student] = 1
                            used.remove(student)
                        rooms2 = dict(rooms)
                        used2 = set(used)
                        for k in range(1, 10-i-j):
                            for comb3 in itertools.combinations(used, k):
                                for student in comb3:
                                    rooms[student] = 2
                                    used.remove(student)
                                rooms3 = dict(rooms)
                                used3 = set(used)
                                for l in range(1, 10-i-j-k):
                                    for comb4 in itertools.combinations(used, l):
                                        for student in comb4:
                                            rooms[student] = 3
                                            used.remove(student)
                                        for student in used:
                                            rooms[student] = 4
                                        if is_valid_solution(rooms, G, s, numRooms):
                                                temp = calculate_happiness(rooms, G)
                                                if temp > maxHap:
                                                    maxHap = temp
                                                    maxRooms = dict(rooms)
                                                    maxNumRooms = numRooms
                                        rooms = dict(rooms3)
                                        used = set(used3)
                                rooms = dict(rooms2)
                                used = set(used2)
                        rooms = dict(rooms1)
                        used = set(used1)
                rooms = {}
                used = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    if maxHap == 0:
        numRooms = 6
        for i in range(1, 10):
            for comb1 in itertools.combinations(used, i):
                for student in comb1:
                    rooms[student] = 0
                    used.remove(student)
                rooms1 = dict(rooms)
                used1 = set(used)
                for j in range(1, 10-i):
                    for comb2 in itertools.combinations(used, j):
                        for student in comb2:
                            rooms[student] = 1
                            used.remove(student)
                        rooms2 = dict(rooms)
                        used2 = set(used)
                        for k in range(1, 10-i-j):
                            for comb3 in itertools.combinations(used, k):
                                for student in comb3:
                                    rooms[student] = 2
                                    used.remove(student)
                                rooms3 = dict(rooms)
                                used3 = set(used)
                                for l in range(1, 10-i-j-k):
                                    for comb4 in itertools.combinations(used, l):
                                        for student in comb4:
                                            rooms[student] = 3
                                            used.remove(student)
                                        rooms4 = dict(rooms)
                                        used4 = set(used)
                                        for m in range(1, 10-i-j-k-l):
                                            for comb5 in itertools.combinations(used, m):
                                                for student in comb5:
                                                    rooms[student] = 4
                                                    used.remove(student)
                                                for student in used:
                                                    rooms[student] = 5
                                                if is_valid_solution(rooms, G, s, numRooms):
                                                        temp = calculate_happiness(rooms, G)
                                                        if temp > maxHap:
                                                            maxHap = temp
                                                            maxRooms = dict(rooms)
                                                            maxNumRooms = numRooms
                                                rooms = dict(rooms4)
                                                used = set(used4)
                                        rooms = dict(rooms3)
                                        used = set(used3)
                                rooms = dict(rooms2)
                                used = set(used2)
                        rooms = dict(rooms1)
                        used = set(used1)
                rooms = {}
                used = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    # if maxHap == 0:
    #     numRooms = 7
    #     for i in range(1, 10):
    #         for comb1 in itertools.combinations(used, i):
    #             for student in comb1:
    #                 rooms[student] = 0
    #                 used.remove(student)
    #             rooms1 = dict(rooms)
    #             used1 = set(used)
    #             for j in range(1, 10-i):
    #                 for comb2 in itertools.combinations(used, j):
    #                     for student in comb2:
    #                         rooms[student] = 1
    #                         used.remove(student)
    #                     rooms2 = dict(rooms)
    #                     used2 = set(used)
    #                     for k in range(1, 10-i-j):
    #                         for comb3 in itertools.combinations(used, k):
    #                             for student in comb3:
    #                                 rooms[student] = 2
    #                                 used.remove(student)
    #                             rooms3 = dict(rooms)
    #                             used3 = set(used)
    #                             for l in range(1, 10-i-j-k):
    #                                 for comb4 in itertools.combinations(used, l):
    #                                     for student in comb4:
    #                                         rooms[student] = 3
    #                                         used.remove(student)
    #                                     rooms4 = dict(rooms)
    #                                     used4 = set(used)
    #                                     for m in range(1, 10-i-j-k-l):
    #                                         for comb5 in itertools.combinations(used, m):
    #                                             for student in comb5:
    #                                                 rooms[student] = 4
    #                                                 used.remove(student)
    #                                             rooms5 = dict(rooms)
    #                                             used5 = set(used)
    #                                             for n in range(1, 10-i-j-k-l-m):
    #                                                 for comb6 in itertools.combinations(used, n):
    #                                                     for student in comb6:
    #                                                         rooms[student] = 5
    #                                                         used.remove(student)
    #                                                     for student in used:
    #                                                         rooms[student] = 6
    #                                                     if is_valid_solution(rooms, G, s, numRooms):
    #                                                             temp = calculate_happiness(rooms, G)
    #                                                             if temp > maxHap:
    #                                                                 maxHap = temp
    #                                                                 maxRooms = dict(rooms)
    #                                                                 maxNumRooms = numRooms
    #                                                     rooms = dict(rooms5)
    #                                                     used = set(used5)
    #                                             rooms = dict(rooms4)
    #                                             used = set(used4)
    #                                     rooms = dict(rooms3)
    #                                     used = set(used3)
    #                             rooms = dict(rooms2)
    #                             used = set(used2)
    #                     rooms = dict(rooms1)
    #                     used = set(used1)
    #             rooms = {}
    #             used = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}


    # for dict in dicts:
    #     if is_valid_solution(dict[0], G, s, dict[1]):
    #             temp = calculate_happiness(dict[0], G)
    #             if temp > maxHap:
    #                 maxHap = temp
    #                 maxRooms = dict[0]
    #                 maxNumRooms = dict[1]
    # print(maxRooms, maxNumRooms)
    return (maxRooms, maxNumRooms)
Пример #18
0
    return result


# For testing a folder of inputs to create a folder of outputs, you can use glob (need to import it)
if __name__ == '__main__':
    inputs = glob.glob('inputs/*')
    solved = 0
    defaulted = 0
    for input_path in inputs:
        output_path = 'outputs/' + basename(normpath(input_path))[:-3] + '.out'
        G, s = read_input_file(input_path)
        n = len(G)
        best_sol, best_happiness = None, 0
        for i in range(1, n + 1):
            D, k = solve(G, s, i)
            if len(D) == n and is_valid_solution(D, G, s, k):
                happiness = calculate_happiness(D, G)
                if happiness > best_happiness:
                    best_sol = D
            else:
                continue
        if not best_sol:
            defaulted += 1
            print("Was not able to solve {}".format(input_path))
            best_sol = dummy_solution(n)
            write_output_file(best_sol, output_path)
        else:
            # Find highest happiness solution and write to file
            solved += 1
            print("Successfully solved {}".format(input_path))
            write_output_file(best_sol, output_path)
Пример #19
0
    print(G.nodes)
    # c, k = solve2(G)
    c, k = solve2(G)
    assert is_valid_solution(G, c, k)
    print("Shortest Path Difference: {}".format(calculate_score(G, c, k)))
    write_output_file(G, c, k, 'small-test.out')


if __name__ == '__main__':
    # single_file(62)
    for i in range(1, 301):
        print("INPUT: ", i)
        path = 'inputs/medium/medium-' + str(i) + '.in'
        G = read_input_file(path)
        c, k = solve2(G)
        assert is_valid_solution(G, c, k)
        print("Shortest Path Difference: {}".format(calculate_score(G, c, k)))
        output_path = 'outputs/medium-' + str(i) + '.out'
        write_output_file(G, c, k, output_path)

# For testing a folder of inputs to create a folder of outputs, you can use glob (need to import it)
# if __name__ == '__main__':
#     inputs = glob.glob('inputs/*')
#     for input_path in inputs:
#         output_path = 'outputs/' + basename(normpath(input_path))[:-3] + '.out'
#         G = read_input_file(input_path)
#         c, k = solve(G)
#         assert is_valid_solution(G, c, k)
#         distance = calculate_score(G, c, k)
#         write_output_file(G, c, k, output_path)
Пример #20
0
def solve(G, s, swap):
    """
    Args:
        G: networkx.Graph
        s: stress_budget
    Returns:
        D: Dictionary mapping for student to breakout room r e.g. {0:2, 1:0, 2:1, 3:2}
        k: Number of breakout rooms
    """

    # TODO: your code here!
    rooms = [list(G.nodes)]

    def move(index):
        room = rooms[index]
        # if room satisfies stress requirement
        if calculate_stress_for_room(room, G) <= s / len(rooms):
            return
 
        # person to be removed
        kick = process(index)
        # remove person
        rooms[index].remove(kick)
        # create new room if necessary
        if index == len(rooms) - 1:
            rooms.append([])
        # add person to new room
        rooms[index + 1].append(kick)
        # check next room for validity
        move(index + 1)
        
         
    def process(index):
        r = rooms[index]
        ret = {}
        for i in r:
            ret[i] = 0
            for j in r:
                if i == j:
                    continue
                if swap == 0:
                    ret[i] += G.edges[i,j]["happiness"] - G.edges[i,j]["stress"]
                elif swap == 1:
                    ret[i] += G.edges[i,j]["happiness"]
                else:
                    ret[i] -= G.edges[i,j]["stress"]
        return min(ret, key = lambda x: ret[x])


    finished = False
    while not finished:
        finished = True
        for i in range(len(rooms)):
            room = rooms[i]
            if calculate_stress_for_room(room, G) > s / len(rooms):
                move(i)
                finished = False
                break

    D = {}
    for i in range(len(rooms)):
        r = rooms[i]
        for n in r:
            D[n] = i
    k = len(rooms)
    ret = D

    max_happiness = calculate_happiness(ret, G)
    improved = True
    # print("before", max_happiness)

    # def search_local(depth):
    #     nonlocal D
    #     nonlocal k
    #     nonlocal improved
    #     nonlocal max_happiness
    #     nonlocal ret
    #     if depth == 0:
    #         return
    #     for i in D:
    #         for j in D:
    #             if i == j:
    #                 continue
    #             D[i], D[j] = D[j], D[i]
    #             kkk = len(set(D.values()))
    #             if is_valid_solution(D, G, s, kkk):
    #                 happy = calculate_happiness(D, G)
    #                 if happy > max_happiness:
    #                     k = kkk
    #                     max_happiness = happy
    #                     ret = {}
    #                     for key in D:
    #                         ret[key] = D[key]
    #                     improved = True
    #                 search_local(depth - 1)
    #             D[i], D[j] = D[j], D[i]

    #             temp, D[i] = D[i], D[j]
    #             kkk = len(set(D.values()))
    #             if is_valid_solution(D, G, s, kkk):
    #                 happy = calculate_happiness(D, G)
    #                 if happy > max_happiness:
    #                     k = kkk
    #                     max_happiness = happy
    #                     ret = {}
    #                     for key in D:
    #                         ret[key] = D[key]
    #                     improved = True
    #                 search_local(depth - 1)
    #             D[i] = temp

    while improved:
        improved = False
        # search_local(2)
        # D = ret
        for i in D:
            for j in D:
                if i == j:
                    continue
                D[i], D[j] = D[j], D[i]
                kkk = len(set(D.values()))
                if is_valid_solution(D, G, s, kkk):
                    if calculate_happiness(D, G) > max_happiness:
                        max_happiness = calculate_happiness(D, G)
                        ret = {}
                        for key in D:
                            ret[key] = D[key]
                        improved = True
                        k = kkk
                D[i], D[j] = D[j], D[i]

                temp, D[i] = D[i], D[j]
                kkk = len(set(D.values()))
                if is_valid_solution(D, G, s, kkk):
                    if calculate_happiness(D, G) > max_happiness:
                        max_happiness = calculate_happiness(D, G)
                        ret = {}
                        for key in D:
                            ret[key] = D[key]
                        improved = True
                        k = kkk
                D[i] = temp
        D = ret
    # print("after:", max_happiness)
    return ret, k, max_happiness
Пример #21
0
 for i in range(1, 243):
     path = 'inputs/medium/medium-'
     path += str(i)
     path += '.in'
     try:
         test = open(path, 'r')
         test.close()
     except:
         continue
     G, s = read_input_file(path)
     #D, k = complete_solve(G, s)
     # D, k = solve(G, s)
     D1, k1, h1 = solve(G, s, 0)
     D2, k2, h2 = solve(G, s, 1)
     D3, k3, h3 = solve(G, s, 2)
     assert is_valid_solution(D1, G, s, k1)
     assert is_valid_solution(D2, G, s, k2)
     assert is_valid_solution(D3, G, s, k3)
     best = max([h1, h2, h3])
     if h1 == best:
         D = D1
     elif h2 == best:
         D = D2
     elif h3 == best:
         D = D3
     print("Total Happiness: {}".format(calculate_happiness(D, G)))
     out_path = 'out/'
     out_path += path.split('/')[-2]
     out_path += '/'
     out_path += path.split('/')[-1]
     out_path = out_path.split('.')[0]
Пример #22
0
def gamble_solve_with_greedy(G, s, i, limit=-1, reps=100):

    """
    Gambles by randomly assigning students to rooms and checking optimality and stress levels
    Works specifically for input #1 type
     - can be modified by changin num_open_rooms to randint
     - can be modified adding checks before h > best_h to check stress_max val per room
    Methods to use:
     - random_assign(students, rooms, limit_per_room = -1):

    """

    students = list(G.nodes)
    #num_open_rooms = int(math.ceil(len(students)/2))
    best_h = -1
    best_rooms = []


    count = 0
    while (count < reps):
        rooms = []
        for _ in range(i):
            rooms.append([])
        temp_students = students.copy()

        rooms = random_assign(temp_students, rooms, limit)

        room_to_students = utils.convert_list_to_dictionary(rooms)


        G_copy = nx.Graph(G)
        assigned_students = [i+1 for i in range(50)]
        happy_dict = {}
        happy_edgeList = [] #sorted(G_copy.edges, key=lambda x: G_copy.edges[x]["happiness"], reverse = True)


        happy_edgeList = greedy_solver_2.remove_students_greedy(G, G_copy, s, room_to_students, happy_dict, assigned_students, happy_edgeList)



        #ToDo: Modify greedy_2 to take in optional parameters of rooms, other stuff thats initialized @ start
        room_to_students = greedy_solver_2.greedy_solve_2(G, s, assigned_students, room_to_students, happy_edgeList)


        dict = utils.convert_dictionary(room_to_students)


        valid = utils.is_valid_solution(dict, G, s, num_open_rooms)

        h = utils.calculate_happiness(dict, G)

        if ((valid) and (h > best_h)):
            best_rooms = []
            room_temp = rooms.copy()
            for i in range(len(rooms)):
                best_rooms += [rooms[i].copy()]
            best_h = h
        #elif (not valid):
            #count = count - 1
        count = count + 1
    return best_rooms.copy(), best_h
Пример #23
0
def greedy_solve_5(G, s, alpha, beta, pop_limit=5):
    """
    Probably open 1 room, add as many possible students w/o exceeding stress level, then
    if s_level exceeded, remove students that cause most stress, open 2 room, repeat
     - Remember to sort students (or sort edgelist or somt) and break ties by happiness
     - Will probably need algo to determine which student causes most stress in given room
    Helpful Utils:
     - utils.calculate_stress_for_room(arr, G)
    """
    #Iterate by opening 1 breakout room at a time, up to n breakout rooms
    room_to_students_to_return = {}
    max_happy = -1
    assigned_students = []
    i = 1
    room_to_students = {}
    for j in range(i):
        room_to_students[j] = []

    #print("room_to_students: ", room_to_students)
    #Make copy of graph (so we can use actual graph later on as reference)
    G_copy = nx.Graph(G)

    #Create edgeList pairs of students sorted by stress/happiness
    stress_edgeList = sorted(G_copy.edges,
                             key=lambda x: G_copy.edges[x]["stress"])
    happy_edgeList = sorted(G_copy.edges,
                            key=lambda x: G_copy.edges[x]["happiness"],
                            reverse=True)
    value_edgeList = sorted(G_copy.edges,
                            key=lambda x: alpha * G_copy.edges[x]["happiness"]
                            - beta * G_copy.edges[x]["stress"],
                            reverse=True)
    #Todo: Maybe sort/solve based on some values/prioerities i.e. a * happy - b * stress, a & b can be constants passed in or randInts

    #dictionary of happiness values to list of all students that have same happiness value
    value_dict = {}
    for edge in value_edgeList:
        #print("edge: ", edge)
        #print("happiness: ", G_copy.edges[edge]["happiness"])
        val = alpha * G_copy.edges[edge]["happiness"] - beta * G_copy.edges[
            edge]["stress"]
        if val in value_dict:
            value_dict[val] += [edge]
        else:
            value_dict[val] = []
            value_dict[val] += [edge]

    while (len(assigned_students) < len(list(G.nodes))):

        stress_edgeList = sorted(stress_edgeList,
                                 key=lambda x: G_copy.edges[x]["stress"],
                                 reverse=True)
        happy_edgeList = sorted(happy_edgeList,
                                key=lambda x: G_copy.edges[x]["happiness"],
                                reverse=True)
        value_edgeList = sorted(
            G_copy.edges,
            key=lambda x: alpha * G_copy.edges[x][
                "happiness"] - beta * G_copy.edges[x]["stress"],
            reverse=True)

        #dictionary of happiness values to list of all students that have same happiness value
        value_dict = {}
        for edge in value_edgeList:
            #print("edge: ", edge)
            #print("happiness: ", G_copy.edges[edge]["happiness"])
            val = alpha * G_copy.edges[edge][
                "happiness"] - beta * G_copy.edges[edge]["stress"]
            if val in value_dict:
                value_dict[val] += [edge]
            else:
                value_dict[val] = []
                value_dict[val] += [edge]

        #Assign students until all pairings are broken or assigned (i.e. all students in rooms)
        while (len(assigned_students) < len(list(G.nodes))):

            #Take happiest pair and try to assign them to rooms to maximize happiness
            #print(happy_dict)
            student_pair = None
            """
            for key in sorted(happy_dict.keys()):
                #print("key: ", key)
                #print("happy_dict[key]: ", happy_dict[key])
                if (len(happy_dict[key]) > 0):

                    student_pair = random.sample(happy_dict[key], 1)
                    #print(student_pair[0])
                    happy_dict[key].remove(student_pair[0])

            #student_pair = happy_edgeList.pop(0)

            # No more student pairs – shouldn't really hit this point tho??
            if (not student_pair):
                print("here")
                #for key in sorted(happy_dict.keys()):
                    #print("key: ", key)
                    #if (len(happy_dict[key]) > 0):

                        #print("happy_dict[key]: ", happy_dict[key])

                break

            student_pair = student_pair[0]
            """
            #Todo: Does this always pick happiest?
            pop_amt = min(len(value_edgeList), pop_limit)
            if (pop_amt <= 0):
                break
            #print("assigned_students: ", assigned_students)
            #print("room_to_students: ", room_to_students)
            #print("happy_edgeList: ", happy_edgeList)
            student_pair = value_edgeList.pop(random.randint(
                0, pop_amt - 1))  # ToDo: Maybe increase this value to 5 - 10?
            #print("num assigend students: ", len(assigned_students))
            #print("student_pair: ", student_pair)
            #print("happy val: ", G_copy.edges[student_pair]["happiness"])
            student0 = student_pair[0]
            student1 = student_pair[1]

            #Check if students have been assigned
            student0_assigned = (student0 in assigned_students)
            student1_assigned = (student1 in assigned_students)
            #If students are already assigned (whether in same or diff room), go to next happiest pair
            if (student0_assigned and student1_assigned):
                #print("here0")
                continue

            #Check which room the students are in, if they have already been asigned to a room
            room_of_student0 = -1
            room_of_student1 = -1
            for room in room_to_students:
                if student0 in room_to_students[room]:
                    room_of_student0 = room
                if student1 in room_to_students[room]:
                    room_of_student1 = room

            #If student0 assigned, try to put student1 in same room, else put in room that causes least stress
            if (student0_assigned):
                #print("here1")
                #print("room_of_student0: ", room_of_student0)
                room_to_students[room_of_student0] += [student1]

                assigned_students += [student1]
                valid0 = utils.is_valid_solution(
                    utils.convert_dictionary(room_to_students), G, s, i)
                if (valid0):
                    continue

                #Can't put student1 in same room, so try to put in diff room
                room_to_students[room_of_student0].remove(student1)
                assigned_students.remove(student1)

                min_stress1 = float('inf')
                min_room1 = -1
                for room in room_to_students:
                    room_to_students[room] += [student1]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress1 = utils.calculate_stress_for_room(
                        room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid1 = utils.is_valid_solution(
                        utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress1 < min_stress1 and valid1):
                        min_stress1 = temp_stress1
                        min_room1 = room

                    room_to_students[room].remove(student1)

                if (min_room1 >= 0):
                    room_to_students[min_room1] += [student1]
                    assigned_students += [student1]
                else:
                    # at this point, student1 cant be assigned to any room without causing excess stress,
                    # so this solution/number of breakout rooms cannot work, so try opening more rooms
                    #print("I got here2, assigned_students = ", assigned_students)
                    #break
                    value_edgeList = remove_students_greedy(
                        G, G_copy, s, room_to_students, value_dict,
                        assigned_students, value_edgeList, alpha, beta)
                    continue

            #If student1 assigned, try to put student0 in same room, else put in room that causes least stress
            if (student1_assigned):
                #print("here2")
                #print("room_of_student1: ", room_of_student1)
                room_to_students[room_of_student1] += [student0]
                assigned_students += [student0]
                valid1 = utils.is_valid_solution(
                    utils.convert_dictionary(room_to_students), G, s, i)
                if (valid1):
                    continue

                #Can't put student1 in same room, so try to put in diff room
                room_to_students[room_of_student1].remove(student0)
                assigned_students.remove(student0)

                min_stress0 = float('inf')
                min_room0 = -1
                for room in room_to_students:
                    room_to_students[room] += [student0]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress0 = utils.calculate_stress_for_room(
                        room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid0 = utils.is_valid_solution(
                        utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress0 < min_stress0 and valid0):
                        min_stress0 = temp_stress0
                        min_room0 = room

                    room_to_students[room].remove(student0)

                if (min_room0 >= 0):
                    room_to_students[min_room0] += [student0]
                    assigned_students += [student0]
                else:
                    # at this point, student1 cant be assigned to any room without causing excess stress,
                    # so this solution/number of breakout rooms cannot work, so try opening more rooms
                    #print("I got here4, assigned_students = ", assigned_students)
                    #break
                    value_edgeList = remove_students_greedy(
                        G, G_copy, s, room_to_students, value_dict,
                        assigned_students, value_edgeList, alpha, beta)
                    continue

            if (not student1_assigned and not student0_assigned):
                #print("here5")

                #If neither student assigned, put both into the breakout room that creates least stress
                #If putting them into a breakout room together always creates invalid solution, consider putting them into seperate rooms
                min_stress = float('inf')
                min_room = -1
                for room in room_to_students:
                    room_to_students[room] += [student0]
                    room_to_students[room] += [student1]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress = utils.calculate_stress_for_room(
                        room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid = utils.is_valid_solution(
                        utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress < min_stress and valid):
                        min_stress = temp_stress
                        min_room = room

                    room_to_students[room].remove(student0)
                    room_to_students[room].remove(student1)

                if (min_room >= 0):
                    room_to_students[min_room] += [student0]
                    room_to_students[min_room] += [student1]
                    assigned_students += [student0]
                    assigned_students += [student1]
                    continue

                #if putting students together in breakout room still causes excess stress, put them in diff rooms
                min_stress0 = float('inf')
                min_room0 = -1

                for room in room_to_students:
                    room_to_students[room] += [student0]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress0 = utils.calculate_stress_for_room(
                        room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid0 = utils.is_valid_solution(
                        utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress0 < min_stress0 and valid0):
                        min_stress0 = temp_stress0
                        min_room0 = room

                    room_to_students[room].remove(student0)

                min_stress1 = float('inf')
                min_room1 = -1

                for room in room_to_students:
                    room_to_students[room] += [student1]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress1 = utils.calculate_stress_for_room(
                        room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid1 = utils.is_valid_solution(
                        utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress1 < min_stress1 and valid1):
                        min_stress1 = temp_stress1
                        min_room1 = room

                    room_to_students[room].remove(student1)

                if (min_room1 >= 0):
                    room_to_students[min_room1] += [student1]
                    assigned_students += [student1]
                if (min_room0 >= 0):
                    room_to_students[min_room0] += [student0]
                    assigned_students += [student0]
                else:
                    #continue
                    # at this point, student0 cant be assigned to any room without causing excess stress,
                    # so this solution/number of breakout rooms cannot work, so remove students
                    # that cause stress level to exceed room stress level, put them back into
                    # happiness edgelist and dictionary, and then continue from there

                    value_edgeList = remove_students_greedy(
                        G, G_copy, s, room_to_students, value_dict,
                        assigned_students, value_edgeList, alpha, beta)

                    #print("I got here, assigned_students = ", assigned_students)
                    #break
                    continue

        #print("here3")

        valid_sol = utils.is_valid_solution(
            utils.convert_dictionary(room_to_students), G, s,
            len(room_to_students))
        happy = utils.calculate_happiness(
            utils.convert_dictionary(room_to_students), G)
        if (len(assigned_students) < len(list(G.nodes))):
            #print(room_to_students)
            happy = float('-inf')

        #print("room_to_students: ", room_to_students)

        #print("room_to_students: ", room_to_students)
        #print("happy: ", happy)
        if (happy > max_happy and valid_sol):
            max_happy = happy
            room_to_students_to_return = {}
            for room in room_to_students:
                room_to_students_to_return[room] = room_to_students[room].copy(
                )
        elif (not valid_sol):
            value_edgeList = remove_students_greedy(
                G, G_copy, s, room_to_students, value_dict, assigned_students,
                value_edgeList, alpha, beta)
        #elif ((happy < max_happy) and (len(room_to_students) < 50)):
        #happy_dict = remove_students_greedy(G, G_copy, s, room_to_students, happy_dict, assigned_students, happy_edgeList)
        #else:
        #break

        if (len(value_edgeList) <= 0):
            break

    #print("here4")
    print("happy for ", len(room_to_students), " rooms: ", max_happy)
    return room_to_students_to_return
Пример #24
0
def remove_students_greedy(G, G_copy, s, room_to_students, value_dict,
                           assigned_students, value_edgeList, alpha, beta):
    # Check which rooms exceed stress limit
    #print("in remove_students_greedy")
    counter = 0
    while True:
        #print("here: ", counter)
        room_numbers_that_exceed_stress = []
        for room in room_to_students:
            s_room = utils.calculate_stress_for_room(room_to_students[room], G)
            if (s_room >= (s / (len(room_to_students)))
                ):  #ToDo: should this be i or i+1? Think of 50 room case
                room_numbers_that_exceed_stress += [room]

        # From the rooms that exceed stress limit, remove students until all stress limit not exceeded
        removed_students = []
        for room in room_numbers_that_exceed_stress:
            s_room = utils.calculate_stress_for_room(room_to_students[room], G)
            while (s_room >= (s / (len(room_to_students)))):
                min_stress = float("inf")
                student_to_remove = -1
                for i in range(len(room_to_students[room])):

                    student = room_to_students[room].pop(i)
                    if (utils.calculate_stress_for_room(
                            room_to_students[room], G) < min_stress):
                        min_stress = utils.calculate_stress_for_room(
                            room_to_students[room], G)
                        student_to_remove = student
                    room_to_students[room].insert(i, student)

                room_to_students[room].remove(student_to_remove)
                removed_students += [student_to_remove]
                s_room = utils.calculate_stress_for_room(
                    room_to_students[room], G)

        for i in range(len(removed_students) - 1):
            for j in range(i + 1, len(removed_students)):
                edge = (removed_students[i], removed_students[j])
                if (edge[0] == edge[1]):
                    continue
                #print(edge)
                value_edgeList += [edge]
                val = alpha * G_copy.edges[edge][
                    "happiness"] - beta * G_copy.edges[edge]["happiness"]
                if val in value_dict:
                    value_dict[val] += [edge]
                else:
                    value_dict[val] = []
                    value_dict[val] += [edge]

        value_edgeList = sorted(
            value_edgeList,
            key=lambda x: alpha * G_copy.edges[x][
                "happiness"] - beta * G_copy.edges[x]["happiness"],
            reverse=True)

        for student in removed_students:
            assigned_students.remove(student)

        #open another room
        if (len(room_to_students) < 50):
            room_to_students[len(room_to_students)] = []

        counter += 1
        if (utils.is_valid_solution(utils.convert_dictionary(room_to_students),
                                    G, s, len(room_to_students))):
            #print("why you always breakin")
            #print("This is valid? wyd: ", room_to_students)
            #print("How did you get this kinda happiness?: ", utils.calculate_happiness(utils.convert_dictionary(room_to_students), G))
            #print("Did you assign everyone tho: ", assigned_students)
            #print("Did you assign everyone tho pt 2: ", len(assigned_students))
            break
    #print("done with remove_students_greedy")
    return value_edgeList
Пример #25
0
            output_path = 'outputs/medium/' + basename(normpath(input_path))[:-3] + '.out'
            G = read_input_file(input_path)
            num_nodes = G.number_of_nodes()
            num_edges = G.number_of_edges()
            if 20 <= num_nodes <= 30:
                MAX_EDGES_REMOVED = 15
                MAX_NODES_REMOVED = 1
            elif 31 <= num_nodes <= 50:
                MAX_EDGES_REMOVED = 50
                MAX_NODES_REMOVED = 3
            elif 51 <= num_nodes <= 100:
                MAX_EDGES_REMOVED = 100
                MAX_NODES_REMOVED = 5
            resultc, resultk, largest = None, None, 0
            for i in range(5):
                c, k = solve(G)
                if not is_valid_solution(G, c, k):
                    continue
                currentScore = calculate_score(G, c, k)
                if largest < currentScore:
                    resultc, resultk = c, k
                    largest = currentScore

            existingSol = read_output_file(G, output_path)
            if largest > existingSol:
                write_output_file(G, resultc, resultk, output_path)
                print("enhanced by: " + str((largest - existingSol)/existingSol))
            print(str(count) + " out of " +str(len(inputs)) + " Done.")
            count += 1
        
Пример #26
0
def helper(G, m, t, max_c, max_k, first_time, is_medium_or_large):
    c, k = [], []
    if m <= 0:  # if there's nothing else to remove, return
        return c, k, m, max_c, max_k, first_time
    if max_c <= 0 and max_k <= 0:
        return c, k, m, max_c, max_k, first_time
    m = m - 1
    edges = list(G.edges)
    shortest_path_vertices = nx.dijkstra_path(G, 0, t)
    shortest_path_vertices_count = len(shortest_path_vertices)
    shortest_path_edges_weights = []
    shortest_path_vertices_weights = []
    sum_edges_weight = 0.0
    sum_vertices_weight = 0.0
    for i in range(shortest_path_vertices_count):
        if i + 1 < shortest_path_vertices_count:  # Safety check for i+1 case for edges
            c1, k1 = [], []
            k1.append(
                (shortest_path_vertices[i], shortest_path_vertices[i + 1]))
            if is_valid_solution(
                    G, c1, k1,
                    t):  # Note this returns true when a node is disconnected
                edge_weight = G[shortest_path_vertices[i]][
                    shortest_path_vertices[i + 1]]['weight']
                shortest_path_edges_weights.append(
                    (shortest_path_vertices[i], shortest_path_vertices[i + 1],
                     edge_weight))
                if is_medium_or_large:
                    sum_edges_weight += (edge_weight / 100.0) * (edge_weight /
                                                                 100.0)
                else:
                    sum_edges_weight += edge_weight
        # Looping through edges in Dijkstras to get edge weights + calculate heuristic
        v = shortest_path_vertices[i]
        if v == 0:
            continue
        if v == t:
            continue
        c2, k2 = [], []
        c2.append(v)
        if not is_valid_solution(
                G, c2, k2,
                t):  # Note this returns true when a node is disconnected
            continue
        vertex_weight, count = 0, 0
        for edge in edges:
            if edge[0] == v or edge[1] == v:
                vertex_weight += G[edge[0]][edge[1]]['weight']
                count += 1
        if count > 0:
            if is_medium_or_large:
                vertex_weight = 0.01 * vertex_weight * 0.01 * vertex_weight
            else:
                vertex_weight = 0.9 * vertex_weight
        shortest_path_vertices_weights.append((v, vertex_weight))
        sum_vertices_weight += vertex_weight
    if (max_k <= 0):
        sum_edges_weight = 0.0
    if (max_c <= 0):
        sum_vertices_weight = 0.0
    remove_edge = True
    r = (sum_edges_weight + sum_vertices_weight) * random.random()
    if (r < sum_vertices_weight):
        remove_edge = False
    s = 0
    if max_k > 0 and remove_edge:
        rand_prob_edges = sum_edges_weight * random.random()
        for A, B, weight in shortest_path_edges_weights:
            s += weight
            G_copy = G.copy()
            if rand_prob_edges < s:
                G_copy.remove_edge(A, B)
                k.append((A, B))
                max_k = max_k - 1
                new_c, new_k, m, max_c, max_k, first_time = helper(
                    G_copy, m, t, max_c, max_k, first_time, is_medium_or_large)
                c += new_c
                k += new_k
                break
    else:
        rand_prob_vertices = sum_vertices_weight * random.random()
        for A, weight in shortest_path_vertices_weights:
            s += weight
            G_copy = G.copy()
            if rand_prob_vertices < s:
                G_copy.remove_node(A)
                c.append(A)
                max_c = max_c - 1
                new_c, new_k, m, max_c, max_k, first_time = helper(
                    G_copy, m, t, max_c, max_k, first_time, is_medium_or_large)
                c += new_c
                k += new_k
                break
    return c, k, m, max_c, max_k, first_time
Пример #27
0
def solver_loop(input_dir="inputs",
                output_dir="outputs",
                input_type=None,
                team_number=None,
                max_timeout=None,
                target_delta=None):
    inputs = get_all_inputs(input_dir, input_type, team_number)
    to_run_heap = []
    non_optimal_count = 0
    total_gaps = 0
    for input_path, max_cities, max_edges in inputs:
        cached = get_cached_run(input_path)
        if cached == None:
            heapq.heappush(
                to_run_heap,
                PrioritizedItem({
                    "in_path":
                    input_path,
                    "out_path":
                    f"{output_dir}/" + input_path[6:][:-3] + '.out',
                    "existing_solution":
                    None,
                    "max_cities":
                    max_cities,
                    "max_edges":
                    max_edges,
                    "last_timeout":
                    1,
                    "is_optimal_new":
                    False,
                    "best_gap":
                    100,
                    "gap_change":
                    0,
                    "timeout_change":
                    0
                }))
            non_optimal_count += 1
            total_gaps += 100
        elif ("is_optimal_new"
              not in cached) or (not cached["is_optimal_new"]):
            if "gap_change" not in cached:
                cached["gap_change"] = 0
            if "timeout_change" not in cached:
                cached["timeout_change"] = cached["last_timeout"] / 2
            if "is_optimal_new" not in cached:
                cached["is_optimal_new"] = False
            # if "known_nonoptimal" in cached and cached["known_nonoptimal"]:
            #   cached["last_timeout"] = 60
            heapq.heappush(to_run_heap, PrioritizedItem(cached))
            non_optimal_count += 1
            total_gaps += cached["best_gap"]
        else:
            total_gaps += 0

    if target_delta:
        assert len(to_run_heap) == 1

    while len(to_run_heap) > 0:
        next_task_wrap = heapq.heappop(to_run_heap)
        next_task = next_task_wrap.item
        if not next_task["is_optimal_new"]:
            G = read_input_file(next_task["in_path"])
            next_timeout = next_task_wrap.estimated_timeout_to_complete
            if max_timeout:
                next_timeout = min(next_timeout, max_timeout)
            target_distance = None
            if target_delta:
                original_min_dist = networkx.dijkstra_path_length(
                    G, 0,
                    len(G) - 1)
                target_distance = original_min_dist + target_delta

            timeout_delta = next_timeout - next_task["last_timeout"]
            last_progress = next_task["gap_change"]
            in_path = next_task["in_path"]
            print()
            print()
            print(
                "-----------------------------------------------------------")
            print()
            print()
            print(
                f"Remaining non-optimal: {non_optimal_count}/{len(inputs)}, average gap: {(total_gaps / non_optimal_count) * 100:.2f}%"
            )
            print(
                f"Running {in_path} with timeout {next_timeout}, last iteration progress {last_progress*100:.2f}%"
            )
            print()
            solve_result = solve(G, next_task["max_cities"],
                                 next_task["max_edges"], next_timeout,
                                 next_task["existing_solution"],
                                 target_distance)

            prev_score = 0
            if next_task["existing_solution"]:
                prev_score = calculate_score(G,
                                             next_task["existing_solution"][0],
                                             next_task["existing_solution"][1])
            new_score = 0
            if solve_result:
                assert is_valid_solution(G, solve_result[0], solve_result[1])
                new_score = calculate_score(G, solve_result[0],
                                            solve_result[1])

            better_result = solve_result and (new_score - prev_score) >= 0.0001
            if better_result:
                write_output_file(G, solve_result[0], solve_result[1],
                                  next_task["out_path"])
                print(f"Shortest Path Difference: {new_score}")
            if solve_result and solve_result[2]:
                non_optimal_count -= 1
            new_gap = solve_result[3] if solve_result else 100
            total_gaps -= next_task["best_gap"]
            total_gaps += new_gap
            if next_task["existing_solution"] and next_task[
                    "best_gap"] != 100 and new_gap > next_task["best_gap"]:
                orig_best = next_task["best_gap"]
                print(
                    f"WARNING WARNING WARNING WARNING: new gap {new_gap} was larger than previous best gap {orig_best}"
                )
                new_gap = orig_best

            if timeout_delta > 0 or better_result or (
                    new_gap > next_task["best_gap"]
            ) or "is_optimal_new" not in next_task:
                new_task = {
                    "in_path":
                    next_task["in_path"],
                    "out_path":
                    next_task["out_path"],
                    "existing_solution": (solve_result[0], solve_result[1])
                    if solve_result and new_score > prev_score else
                    next_task["existing_solution"],
                    "max_cities":
                    next_task["max_cities"],
                    "max_edges":
                    next_task["max_edges"],
                    "last_timeout":
                    next_timeout,
                    "is_optimal_new": (not target_distance)
                    and (solve_result != None) and solve_result[2],
                    "best_gap":
                    new_gap,
                    "gap_change":
                    new_gap - next_task["best_gap"] if
                    (next_task["existing_solution"]
                     and next_task["best_gap"] != 100) else 0,
                    "timeout_change":
                    max(timeout_delta, 0)
                }
                if "known_nonoptimal" in next_task and not better_result:
                    new_task["known_nonoptimal"] = True
                write_cached_run(new_task["in_path"], new_task)

                if not new_task["is_optimal_new"]:
                    heapq.heappush(to_run_heap, PrioritizedItem(new_task))
Пример #28
0
def greedy_solve_1(G, s):
    """
    Probably open 1 room, add as many possible students w/o exceeding stress level, then
    if s_level exceeded, remove all students, open 2 rooms, repeat
     - Remember to sort students (or sort edgelist or somt) and break ties by happiness

    Helpful utils:
        utils.is_valid_solution(D, G, s, rooms)
        utils.convert_dictionary(room_to_student)
        utils.calculate_stress_for_room(arr, G)
        utils.calculate_happiness_for_room(arr, G)
    """
    #Iterate by opening 1 breakout room at a time, up to n breakout rooms
    room_to_students_to_return = {}
    max_happy = -1
    for i in range(1, len(list(G.nodes)) + 1):

        room_to_students = {}
        for j in range(i):
            room_to_students[j] = []

        #print("room_to_students: ", room_to_students)
        #Make copy of graph (so we can use actual graph later on as reference)
        G_copy = nx.Graph(G)

        #Create edgeList pairs of students sorted by stress/happiness
        stress_edgeList = sorted(G_copy.edges, key=lambda x: G_copy.edges[x]["stress"], reverse = True)
        happy_edgeList = sorted(G_copy.edges, key=lambda x: G_copy.edges[x]["happiness"], reverse = True)

        #dictionary of happiness values to list of all students that have same happiness value
        happy_dict = {}
        for edge in happy_edgeList:
            #print("edge: ", edge)
            #print("happiness: ", G_copy.edges[edge]["happiness"])
            if G_copy.edges[edge]["happiness"] in happy_dict:
                happy_dict[G_copy.edges[edge]["happiness"]] += [edge]
            else:
                happy_dict[G_copy.edges[edge]["happiness"]] = []
                happy_dict[G_copy.edges[edge]["happiness"]] += [edge]

        assigned_students = []
        #Assign students until all pairings are broken or assigned (i.e. all students in rooms)
        while (len(assigned_students) < len(list(G.nodes))):


            #Take happiest pair and try to assign them to rooms to maximize happiness
            #print(happy_dict)
            student_pair = None

            """
            for key in sorted(happy_dict.keys()):
                #print("key: ", key)
                #print("happy_dict[key]: ", happy_dict[key])
                if (len(happy_dict[key]) > 0):

                    student_pair = random.sample(happy_dict[key], 1)
                    #print(student_pair[0])
                    happy_dict[key].remove(student_pair[0])

            #student_pair = happy_edgeList.pop(0)


            if (not student_pair):
                print("here")
                for key in sorted(happy_dict.keys()):
                    print("key: ", key)
                    if (len(happy_dict[key]) > 0):

                        print("happy_dict[key]: ", happy_dict[key])

                break

            student_pair = student_pair[0]
            """

            pop_amt = min(len(happy_edgeList), 10)
            if (pop_amt <= 0):
                break
            student_pair = happy_edgeList.pop(random.randint(0, pop_amt-1))
            #print("num assigend students: ", len(assigned_students))
            #print("student_pair: ", student_pair)
            #print("happy val: ", G_copy.edges[student_pair]["happiness"])
            student0 = student_pair[0]
            student1 = student_pair[1]


            #Check if students have been assigned
            student0_assigned = (student0 in assigned_students)
            student1_assigned = (student1 in assigned_students)
            #If students are already assigned (whether in same or diff room), go to next happiest pair
            if (student0_assigned and student1_assigned):
                #print("here0")
                continue





            #Check which room the students are in, if they have already been asigned to a room
            room_of_student0 = -1
            room_of_student1 = -1
            for room in room_to_students:
                if student0 in room_to_students[room]:
                    room_of_student0 = room
                if student1 in room_to_students[room]:
                    room_of_student1 = room

            #If student0 assigned, try to put student1 in same room, else put in room that causes least stress
            if (student0_assigned):
                #print("here1")
                room_to_students[room_of_student0] += [student1]
                assigned_students += [student1]
                valid0 = utils.is_valid_solution(utils.convert_dictionary(room_to_students), G, s, i)
                if (valid0):
                    continue

                #Can't put student1 in same room, so try to put in diff room
                room_to_students[room_of_student0].remove(student1)
                assigned_students.remove(student1)

                min_stress1 = float('inf')
                min_room1 = -1
                for room in room_to_students:
                    room_to_students[room] += [student1]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress1 = utils.calculate_stress_for_room(room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid1 = utils.is_valid_solution(utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress1 < min_stress1 and valid1):
                        min_stress1 = temp_stress1
                        min_room1 = room

                    room_to_students[room].remove(student1)

                if (min_room1 >= 0):
                    room_to_students[min_room1] += [student1]
                    assigned_students += [student1]
                else:
                # at this point, student1 cant be assigned to any room without causing excess stress,
                # so this solution/number of breakout rooms cannot work, so try opening more rooms
                    #print("I got here2, assigned_students = ", assigned_students)
                    break
                    #continue

            #If student1 assigned, try to put student0 in same room, else put in room that causes least stress
            if (student1_assigned):
                #print("here2")
                room_to_students[room_of_student1] += [student0]
                assigned_students += [student0]
                valid1 = utils.is_valid_solution(utils.convert_dictionary(room_to_students), G, s, i)
                if (valid1):
                    continue

                #Can't put student1 in same room, so try to put in diff room
                room_to_students[room_of_student1].remove(student0)
                assigned_students.remove(student0)

                min_stress0 = float('inf')
                min_room0 = -1
                for room in room_to_students:
                    room_to_students[room] += [student0]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress0 = utils.calculate_stress_for_room(room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid0 = utils.is_valid_solution(utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress0 < min_stress0 and valid0):
                        min_stress0 = temp_stress0
                        min_room0 = room

                    room_to_students[room].remove(student0)

                if (min_room0 >= 0):
                    room_to_students[min_room0] += [student0]
                    assigned_students += [student0]
                else:
                # at this point, student1 cant be assigned to any room without causing excess stress,
                # so this solution/number of breakout rooms cannot work, so try opening more rooms
                    #print("I got here4, assigned_students = ", assigned_students)
                    break
                    #continue


            if (not student1_assigned and not student0_assigned):
                #print("here5")

                #If neither student assigned, put both into the breakout room that creates least stress
                #If putting them into a breakout room together always creates invalid solution, consider putting them into seperate rooms
                min_stress = float('inf')
                min_room = -1
                for room in room_to_students:
                    room_to_students[room] += [student0]
                    room_to_students[room] += [student1]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress = utils.calculate_stress_for_room(room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid = utils.is_valid_solution(utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress < min_stress and valid):
                        min_stress = temp_stress
                        min_room = room

                    room_to_students[room].remove(student0)
                    room_to_students[room].remove(student1)

                if (min_room >= 0):
                    room_to_students[min_room] += [student0]
                    room_to_students[min_room] += [student1]
                    assigned_students += [student0]
                    assigned_students += [student1]
                    continue

                #if putting students together in breakout room still causes excess stress, put them in diff rooms
                min_stress0 = float('inf')
                min_room0 = -1

                for room in room_to_students:
                    room_to_students[room] += [student0]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress0 = utils.calculate_stress_for_room(room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid0 = utils.is_valid_solution(utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress0 < min_stress0 and valid0):
                        min_stress0 = temp_stress0
                        min_room0 = room

                    room_to_students[room].remove(student0)



                min_stress1 = float('inf')
                min_room1 = -1

                for room in room_to_students:
                    room_to_students[room] += [student1]

                    #check if adding students to this room causes minimum stress (disruption?)
                    temp_stress1 = utils.calculate_stress_for_room(room_to_students[room], G)
                    #check if solution is valid when adding students to this room
                    valid1 = utils.is_valid_solution(utils.convert_dictionary(room_to_students), G, s, i)
                    if (temp_stress1 < min_stress1 and valid1):
                        min_stress1 = temp_stress1
                        min_room1 = room

                    room_to_students[room].remove(student1)

                if (min_room1 >= 0):
                    room_to_students[min_room1] += [student1]
                    assigned_students += [student1]
                if (min_room0 >= 0):
                    room_to_students[min_room0] += [student0]
                    assigned_students += [student0]
                else:
                # at this point, student0 cant be assigned to any room without causing excess stress,
                # so this solution/number of breakout rooms cannot work, so try opening more rooms
                    #print("I got here, assigned_students = ", assigned_students)
                    break
                    #continue













        #print("here3")

        valid_sol = utils.is_valid_solution(utils.convert_dictionary(room_to_students), G, s, i)
        happy = utils.calculate_happiness(utils.convert_dictionary(room_to_students), G)
        if (len(assigned_students) < len(list(G.nodes))):
            #print(room_to_students)
            happy = float('-inf')

        #print("room_to_students: ", room_to_students)
        print("happy for ", i, " rooms: ", happy)

        if (happy > max_happy and valid_sol):
            max_happy = happy
            room_to_students_to_return = {}
            for room in room_to_students:
                room_to_students_to_return[room] = room_to_students[room].copy()

    #print("here4")
    return room_to_students_to_return
Пример #29
0
room += 1
D[25] = room
D[31] = room
room += 1
D[26] = room
D[29] = room
room += 1
D[27] = room
D[49] = room
room += 1
D[30] = room
D[48] = room
room += 1
D[32] = room
D[38] = room
room += 1
D[33] = room
D[45] = room
room += 1
D[35] = room
D[36] = room
room += 1
D[40] = room
D[42] = room
room += 1
k = len(set(D.values()))
assert is_valid_solution(D, G, s, k)
print("Total Happiness: {}".format(calculate_happiness(D, G)))
output_path = "out/other/large-169.out"
write_output_file(D, output_path)
Пример #30
0
        i += 1
        output_path_num = int(
            os.path.basename(os.path.normpath(input_path))[:-3].split("-")[1])
        if output_path_num in blacklist:
            print("Skipping Blacklist Num...")
            continue

        G, s = read_input_file(input_path, 100)
        output_path = 'medium_outputs/' + os.path.basename(
            os.path.normpath(input_path))[:-3] + '.out'
        D = read_output_file(output_path, G, s)
        output_happiness = calculate_happiness(D, G)
        print("Current Happiness:", output_happiness)

        D_new, k_new, val_new = verify(G, s, output_happiness)
        print("Returned Happiness", val_new)
        if D_new and round(val_new, 3) > round(output_happiness, 3):
            new_happiness = calculate_happiness(D_new, G)
            print(new_happiness, val_new)
            assert round(new_happiness, 3) == round(val_new, 3)
            assert is_valid_solution(D_new, G, s, k_new)
            print("New Happiness Found:", new_happiness)
            print()
            write_output_file(D_new, output_path)
            redo.append(input_path)
        else:
            print("Could not improve happiness (already optimal)")
        print()
    print("Inputs Improved:", redo)
    print("TLE", tle)