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
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')
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
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)
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
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()))
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")
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
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
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()))
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"))
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
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
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
# 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)
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
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
# 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
# #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:
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)
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')
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
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)")
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)
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))