예제 #1
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
예제 #2
0
def take_both(word, num):
    G, s = read_input_file('inputs/' + word + '-' + str(num) + '.in')
    sree = kcluster_beef(G, s)
    m = max([use_greedy_happystress(G, s) for i in range(100)],
            key=lambda x: calculate_happiness(x, G))
    if calculate_happiness(sree, G) > calculate_happiness(m, G):
        print(calculate_happiness(sree, G))
        write_output_file(sree, 'outputs/' + word + '-' + str(num) + '.out')
    else:
        print(calculate_happiness(m, G))
        write_output_file(m, 'outputs/' + word + '-' + str(num) + '.out')
예제 #3
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
예제 #4
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)
예제 #5
0
def solve_naive(G, s):
    vertex_list = list(G.nodes)
    N = len(vertex_list)

    best_happiness = 0
    config = {}
    numRooms = 0

    for n, p in enumerate(partition(list(range(20))), 1):
        isValid = True
        for room in p:
            if calculate_stress_for_room(room, G) > s / len(p):
                isValid = False
                break
        print(n)
        if not isValid:
            continue
        
        D = {}
        for i in range(len(p)):
            for j in p[i]:
                D[j] = i

        happiness = calculate_happiness(D, G)
        if happiness > best_happiness:
            best_happiness = happiness
            config = D
            numRooms = len(p)

    return config, numRooms
예제 #6
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()))
예제 #7
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")
예제 #8
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
예제 #9
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
예제 #10
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]
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()))
예제 #12
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"))
예제 #13
0
def solve_kinda(G,s,n=40):
    curMax = 0
    dMax, kMax = 0,0
    for i in range(15):
        d1, k1 = solve_happy(G,s, 0.7)
        d2, k2 = solve_stress(G,s, 0.7)
        h1 = calculate_happiness(d1, G)
        h2 = calculate_happiness(d2, G)
        if max(h1, h2) >  curMax:
            if h1 > h2:
                curMax = h1
                dMax, kMax = d1, k1 
            else:
                curMax = h2 
                dMax, kMax = d2, k2

    for i in range(15):
        d1, k1 = solve_happy(G,s, 0.35)
        d2, k2 = solve_stress(G,s, 0.35)
        h1 = calculate_happiness(d1, G)
        h2 = calculate_happiness(d2, G)
        if max(h1, h2) >  curMax:
            if h1 > h2:
                curMax = h1
                dMax, kMax = d1, k1 
            else:
                curMax = h2 
                dMax, kMax = d2, k2

    for i in range(15):
        d1, k1 = solve_happy(G,s, 0.1)
        d2, k2 = solve_stress(G,s, 0.1)
        h1 = calculate_happiness(d1, G)
        h2 = calculate_happiness(d2, G)
        if max(h1, h2) >  curMax:
            if h1 > h2:
                curMax = h1
                dMax, kMax = d1, k1 
            else:
                curMax = h2 
                dMax, kMax = d2, k2
                
    return dMax, kMax
예제 #14
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
예제 #15
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
예제 #16
0
#     G, s = read_input_file(path)
#     D, k = solve(G, s)
#     assert is_valid_solution(D, G, s, k)
#     print("Total Happiness: {}".format(calculate_happiness(D, G)))
#     write_output_file(D, 'outputs/small-1.out')

# print("output dict,", d)
# print("k:", k)
# print("Valid solution? ", is_valid_solution(d, G, s, k))
# print("Happiness: ", calculate_happiness(d, G))

# """4
# 3
# 0 1 50 1
# 0 2 10 1
# 0 3 1 1
# 1 2 10 1
# 1 3 1 1
# 2 3 30 1"""
# good 4.in example?  greedy without dp will make [0,1,2],[3], because it doesnt look at going from [0,1] to [0,1],[2,3].
# 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, s = read_input_file(input_path)
        D, k = solve(G, s)
        assert is_valid_solution(D, G, s, k)
        happiness = calculate_happiness(D, G)
        write_output_file(D, output_path)
예제 #17
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
예제 #18
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
    """
    def getStress(s1, s2):
        return G.get_edge_data(s1, s2)['stress']

    def getHappiness(s1, s2):
        return G.get_edge_data(s1, s2)['happiness']

    def runSolver(k):
        # return dict, k
        m = Model(solver_name=CBC)

        #######################
        ###### Variables ######
        #######################
        """
        x[s1][r] = binary var if student s1 is in room r
        n x k matrix
        Room     0 1 2 3   Student
                [1 0 0 0]    0
                [1 1 0 1]    1
                [1 1 0 1]    2
        """
        x = [[
            m.add_var(name='x_{}_{}'.format(i, l), var_type='B')
            for l in range(k)
        ] for i in range(n)]
        """
        y[r][s1][s2] = binary var if s1 and s2 are in room r
        Each entry of s is a sqaure n x n matrix
                [(0, 0) ... (i, 0)]
                [ ...   ...   ... ]
                [(j, 0) ... (i, j)]
        all entries below the diagonal are repeated. 
        """
        y = []
        for l in range(k):
            y.append([[
                m.add_var(name='y_{}_{}_{}'.format(i, j, l), var_type='B')
                for i in range(n)
            ] for j in range(n)])

        #######################
        ##### Constraints #####
        #######################

        # https://cs.stackexchange.com/questions/12102/express-boolean-logic-operations-in-zero-one-integer-linear-programming-ilp?fbclid=IwAR0DTuP7zy4KUkgU_Vxip-21mMd0Gysw_EE1-BwGJtMz3BdPmDbTaAoPGI8
        for l in range(k):
            for i in range(n):
                for j in range(i + 1, n):
                    m += x[i][l] + x[j][l] - 1 <= y[l][i][j]
                    m += x[i][l] >= y[l][i][j]
                    m += x[j][l] >= y[l][i][j]

        # ensures each student can only be in 1 room
        for i in range(n):
            m += xsum(x[i][l] for l in range(k)) == 1

        # ensures that rooms have at least 1 person
        for l in range(k):
            m += xsum(x[i][l] for i in range(n)) >= 1

        # ensures each room meets stress requirement
        for l in range(k):
            m += xsum(y[l][i][j] * getStress(i, j) for i in range(n)
                      for j in range(i + 1, n)) <= S_MAX / k

        # optimize for happiness
        m.objective = maximize(
            xsum(y[l][i][j] * getHappiness(i, j) for l in range(k)
                 for i in range(n) for j in range(i + 1, n)))

        solution = {}
        m.max_gap = 0.05
        status = m.optimize(max_seconds=300)
        if status == OptimizationStatus.OPTIMAL:
            print('optimal solution cost {} found'.format(m.objective_value))
        elif status == OptimizationStatus.FEASIBLE:
            print('sol.cost {} found, best possible: {}'.format(
                m.objective_value, m.objective_bound))
        elif status == OptimizationStatus.NO_SOLUTION_FOUND:
            print('no feasible solution found, lower bound is: {}'.format(
                m.objective_bound))
        elif status == OptimizationStatus.INFEASIBLE:
            print('infeasible: ')
        if status == OptimizationStatus.OPTIMAL or status == OptimizationStatus.FEASIBLE:
            print('solution:')
            for v in m.vars:
                if abs(v.x) > 1e-6:  # only printing non-zeros
                    print('{} : {}'.format(v.name, v.x))
                    student_room = v.name.split('_')
                    if student_room[0] == 'x':
                        solution[int(student_room[1])] = int(student_room[2])

            solution = dict(sorted(solution.items(), key=lambda item: item[1]))
            return solution

    n = G.number_of_nodes()  # number of students
    S_MAX, K_LOWER, K_UPPER = s, 1, n - 1
    best_D, best_K, best_happiness = {}, K_LOWER, 0
    for k in range(K_LOWER, K_UPPER + 1):
        D = runSolver(k)
        if D:
            curr_happiness = calculate_happiness(D, G)
            if curr_happiness > best_happiness:
                best_D, best_K, best_happiness = D, k, curr_happiness
    print('BEST SOLUTION: {} rooms -'.format(best_K), best_D)
    return best_D, best_K
예제 #19
0
# The folders should have no subfolders
# The folders should have the same files (e.g. for file small-1, there should be inputs/small-1.in, comp1/small-1.out, comp2/small-1.out)
# Since this will overwrite the outputs in "comp1", you should make sure those are backed up (push them to Git or something)
if __name__ == '__main__':
    inputs = glob.glob('compinputslarge/*')
    done = 0
    changed = 0
    kept = 0
    improvement = 0
    for input_path in inputs:
        first_path = 'comp1large/' + basename(normpath(input_path))[:-3] + '.out'
        second_path = 'comp2large/' + basename(normpath(input_path))[:-3] + '.out'
        G, s = read_input_file(input_path)
        try:
            D1 = read_output_file(first_path, G, s)
            h1 = calculate_happiness(D1, G)
        except:
            h1 = 0
        try: 
            D2 = read_output_file(second_path, G, s)
            h2 = calculate_happiness(D2, G)
        except:
            h2 = 0
        if h1 + h2 > 0:
            done += 1
            # print("doing #" + str(done) + ": " + input_path)
            if h1 < h2:
                write_output_file(D2, first_path)
                # print("chose comp2: " + str(h2) + " vs. " + str(h1))
                changed += 1
                improvement += (h2 - h1) / h1
예제 #20
0
#     #write file
#     output_path = "outputs/" + number + ".out"
#     write_output_file(D, output_path)
#     D = read_output_file(output_path, G, s)
#     print("Total Happiness: {}".format(cost_t))

# 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, s = read_input_file(input_path)

        # Check output file
        savedrooms = read_output_file(output_path, G, s)
        savedhappiness = calculate_happiness(savedrooms, G)

        # Find the size of file
        t_end = 0
        size = basename(normpath(input_path)).split("-")[0]
        # print(size)
        if size == "small":
            t_end = 10
        elif size == "medium":
            t_end = 50
        elif size == "large":
            t_end = 120

        t_end = time.time() + t_end
        # Solving
        while time.time() < t_end:
예제 #21
0
파일: solver10.py 프로젝트: kellyruan/cs170
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)
예제 #22
0
def take_one(num):
    G, s = read_input_file('inputs/large-' + str(num) + '.in')
    m = max([use_greedy_happystress(G, s) for i in range(40)],
            key=lambda x: calculate_happiness(x, G))
    print(calculate_happiness(m, G))
    write_output_file(m, 'outputs/large-' + str(num) + '.out')
예제 #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
    num_inputs = len(inputs)
    for input_path in inputs[2:]:
        print("Filename:", input_path, "Input", i, "out of",
              str(num_inputs) + "...")
        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)")
예제 #25
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)
예제 #26
0
from parse import read_input_file, read_output_file
from utils import calculate_happiness
import sys

if __name__ == '__main__':
    assert len(sys.argv) == 3
    input_type = sys.argv[1]
    input_num = int(sys.argv[2])
    input_path = input_type + '/' + input_type + "-" + str(input_num) + '.in'
    output_path = input_type + '_outputs/' + input_type + "-" + str(
        input_num) + '.out'
    G, s = read_input_file(input_path, 100)
    D = read_output_file(output_path, G, s)
    print("Happiness:", calculate_happiness(D, G))