def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ g = GraphSolver(G) start = g.find_leaf_path() if start is None: start = first_heuristic(g) graph_choices = [] for v in g.neighbors(start): newG = G.copy() new_g = GraphSolver(newG) new_g.visit(start) new_g.visit(v, (start, v)) graph_choices.append(new_g) minT = G minCost = float('inf') for g_option in graph_choices: g_option.dijkstra_solve_graph(start, calculate_heuristic, first_heuristic) optimize_sorted(g_option, g_option.T, cycle_killer_fn=kill_cycle) cost = average_pairwise_distance(g_option.T) if cost < minCost: minCost = cost minT = g_option.T return minT
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ # TODO: your code here! g = GraphSolver(G) T = g.dijkstra_solve_graph() return T
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ g = GraphSolver(G) start = g.find_leaf_path() T = g.dijkstra_solve_graph(start, calculate_heuristic, first_heuristic) return T
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ g = GraphSolver(G) start = g.find_leaf_path() T = g.dijkstra_solve_graph(start, calculate_heuristic, first_heuristic) optimize_sorted(g, T, kill_cycle_all_paths) return T
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ g = GraphSolver(G) T = g.dijkstra_solve_graph(None, calculate_heuristic, first_heuristic) if average_pairwise_distance(T) == 0: return T optimize_sorted(g, T, cycle_killer_fn=kill_cycle) return T
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ g = GraphSolver(G) start = g.find_leaf_path() T = g.dijkstra_solve_graph(start, calculate_heuristic, first_heuristic) if average_pairwise_distance(T) == 0: return T optimize(g, T) return T
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ g = GraphSolver(G) single_node = process(g) if single_node >= 0: return g.T g.visit(first_heuristic(g)) T = g.mst_solve_graph(heuristic) optimize_sorted(g, T, cycle_killer_fn=kill_cycle) return T
def kill_cycle(solver: GraphSolver, cycle: list, orig_cost: float): """ Returns the first edge found in the cycle which, if removed from tree, leads to a decrease in cost (average pairwise distance). :param tree: tree (with 1 extra edge) to consider :param cycle: list of edges to consider (which form a cycle, removal of any restores tree) :param orig_cost: original cost :return: """ tree = solver.T for edge in cycle: solver.remove_edge(edge) new_cost = average_pairwise_distance(tree) still_valid = is_valid_network(solver.G, solver.T) solver.add_edge(edge) if new_cost < orig_cost and still_valid: return edge, new_cost return None, orig_cost
def optimize_removal(solver: GraphSolver, tree: Graph, orig_cost: float): candidates = [ v for v in tree.nodes if not solver.is_required(v) and is_leaf(tree, v) ] while candidates: # print(candidates) # random.seed(0) node = random.choice(candidates) candidates.remove(node) edge = (node, list(tree.neighbors(node))[0]) solver.unvisit(node) new_cost = average_pairwise_distance(tree) if new_cost < orig_cost: # print('removed', node) return optimize_removal(solver, tree, new_cost) else: solver.add_edge(edge) return orig_cost
def kill_cycle_all_paths(solver: GraphSolver, cycle: list, orig_cost: float): """ Returns the first edge found in the cycle which, if removed from tree, leads to a decrease in cost (average pairwise distance). :param tree: tree (with 1 extra edge) to consider :param cycle: list of edges to consider (which form a cycle, removal of any restores tree) :param orig_cost: original cost :return: """ tree = solver.T weights = [0] * len(cycle) # Count the number of times each edge in the cycle appears in the paths for n, (dist, path) in all_pairs_dijkstra(solver.G): for target in path.keys(): for v in range(1, len(path[target])): path_edge = (path[target][v - 1], path[target][v]) if path_edge in cycle: weights[cycle.index(path_edge)] += 1 # Multiply by the edge weight to get the contributing weight weights = [ weights[i] * weight(solver.G, cycle[i]) for i in range(len(weights)) ] edge = cycle[argmin(weights)] # print('weights for', cycle, 'are', weights) # cycle.sort(key= lambda x: weight(solver.T, x), reverse = True) # edge = cycle[0] solver.remove_edge(edge) new_cost = average_pairwise_distance(tree) solver.add_edge(edge) if new_cost < orig_cost: # print('nice') return edge, new_cost else: # print('removing', edge, 'from cycle', cycle, "didn't decrease cost because", new_cost, '>=', orig_cost) # print(weight(solver.T, edge), 'from', [weight(solver.T, e) for e in cycle]) pass return None, orig_cost
def optimize_removal_sorted(solver: GraphSolver, tree: Graph, orig_cost: float): candidates = [ v for v in tree.nodes if not solver.is_required(v) and is_leaf(tree, v) ] while candidates: # print(candidates) # random.seed(0) candidates.sort(key=lambda x: closeness_centrality(solver.T, x)) node = candidates.pop(0) edge = (node, list(tree.neighbors(node))[0]) solver.unvisit(node) new_cost = average_pairwise_distance(tree) if new_cost < orig_cost: # print('removed', node) return optimize_removal_sorted(solver, tree, new_cost) else: solver.add_edge(edge) return orig_cost
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ t = most_between(G) solver = GraphSolver(G) for node in t.nodes: solver.visit(node) for edge in t.edges: solver.add_edge(edge) optimize_sorted(solver, solver.T, kill_cycle_all_paths) return solver.T
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ t = find_shortest_paths(G) solver = GraphSolver(G) for node in t.nodes: solver.visit(node) for edge in t.edges: solver.add_edge(edge) optimize_sorted(solver, solver.T, kill_cycle_all_paths) check = is_valid_network(G, solver.T) if not check: raise Exception('invalid') return solver.T
def solve(G): global saved_costs, solver_filenames g = GraphSolver(G) for v in list(g.G.nodes): if len( list(g.neighbors(v)) ) == g.n - 1: # Special case when one vertex is connected to all of them g.visit(v) return g.T solvers = [ import_module(solver_filename) for solver_filename in solver_filenames ] skipped_costs = [] skipped_solvers = [] # Don't calculate for inputs we already know costs for deterministically skip = [] if cacher is not None: for i in range(len(solvers)): # It turns out all of our algorithms are not deterministic so that condition is going to be deleted if cacher.is_cached(input_filename, solver_filenames[i]): # if getattr(solvers[i], 'isDeterministic', False) and cacher.is_cached(input_filename, solver_filenames[i]): skipped_costs.append( cacher.get_cost(input_filename, solver_filenames[i])) skip.append(i) skipped_solvers.append(solver_filenames[i]) solver_filenames = [ f for i, f in enumerate(solver_filenames) if i not in skip ] solvers = [s for i, s in enumerate(solvers) if i not in skip] trees = [] # to be populated ############### Parallelizing ######################## if len(solvers) > 0: pool = Pool(len(solvers)) async_solvers = [ pool.apply_async(solver.solve, [G]) for solver in solvers ] trees = [ async_solver.get(1000000000) for async_solver in async_solvers ] pool.close() pool.join() ################ Non - parallelizing #################### # trees = [solver.solve(G) for solver in solvers] ######################################################### # Cache costs costs = [average_pairwise_distance(t) for t in trees] if cacher is not None: for i in range(len(trees)): cacher.cache_if_better_or_none(input_filename, solver_filenames[i], costs[i], None, trees[i]) # Create lists with the same length all_trees = [None] * len(skipped_costs) + trees all_costs = skipped_costs + costs solver_filenames = skipped_solvers + solver_filenames # Sort all_trees = [ tree for c, tree in sorted(zip(all_costs, all_trees), key=lambda pair: pair[0]) ] solver_filenames = [ filename for c, filename in sorted(zip(all_costs, solver_filenames), key=lambda pair: pair[0]) ] all_costs = sorted(all_costs) # Print saved costs second_smallest = all_costs[1] individual_saved_costs = [ second_smallest - cost if second_smallest - cost > 0 else 0 for cost in all_costs ] saved_costs = [sum(x) for x in zip(saved_costs, individual_saved_costs)] print(saved_costs) # Get the tree to return min_tree = all_trees[0] if min_tree is None: out_file = join(OUTPUT_DIRECTORY, input_filename[:-3], solver_filenames[0] + '.out') if isfile(out_file): print('read outfile', out_file) min_tree = read_output_file(out_file, G) else: print( "WARNING: all_prev_outputs.txt is probably out of sync. {} was not found." .format(out_file)) print('Recalculating for input {}'.format(input_filename)) # Recalculate for this input prev_type = cacher.set_cache_type('none') min_tree = solve(G) cacher.set_cache_type(prev_type) return min_tree
def solve(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ g = GraphSolver(G) start = g.find_leaf_path() T = g.dijkstra_solve_graph(start, calculate_heuristic, first_heuristic) optimize_sorted(g, T) rebuilder = Rebuilder(g) min_T = T.copy() min_cost = average_pairwise_distance(T) # print('*', min_cost) for _ in range(50): if rebuilder.rebuild(): g = GraphSolver(G) for v in min_T.nodes: g.visit(v) for e in min_T.edges: g.add_edge(e) # print('reset') g.dijkstra_solve_graph(start, calculate_heuristic, first_heuristic) optimize_sorted(g, g.T) cost = average_pairwise_distance(g.T) # print(cost) if cost < min_cost: min_cost = cost min_T = g.T.copy() return min_T
def optimize_additions(solver: GraphSolver, tree: Graph, orig_cost: float = None): graph = solver.G if orig_cost is None: orig_cost = average_pairwise_distance(tree) # get all edges to consider edges = [] for node in tree.nodes: for neighbor in graph.neighbors(node): if not edge_exists(tree.edges, (node, neighbor)) and not edge_exists( edges, (node, neighbor)): edges.append((node, neighbor)) # for each edge (consider order randomly) while edges: # random.seed(0) added_edge = random.choice(edges) edges.remove(added_edge) weight = graph[added_edge[0]][added_edge[1]]['weight'] # if added edge creates a cycle if added_edge[1] in tree.nodes: solver.add_edge(added_edge) while (True): try: cycle: list = find_cycle(tree, added_edge[0]) except: # No cycle break try: cycle.remove(added_edge) except ValueError: cycle.remove(added_edge[::-1]) replaced_edge, new_cost = kill_cycle(solver, cycle, orig_cost) # print("replaced_edge:", replaced_edge) # print("cost:", new_cost) if replaced_edge: orig_cost = new_cost solver.remove_edge(replaced_edge) else: solver.remove_edge(added_edge) # if other vertex not in tree else: v = added_edge[1] solver.visit(v, added_edge) # add_edge(tree, added_edge, weight) new_cost = average_pairwise_distance(tree) if new_cost < orig_cost: orig_cost = new_cost add_neighbors(solver, edges, v) else: solver.unvisit(v) # remove considered edge return orig_cost