示例#1
0
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
示例#2
0
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
示例#3
0
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
示例#7
0
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
示例#8
0
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
示例#9
0
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
示例#10
0
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
示例#11
0
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
示例#12
0
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
示例#14
0
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
示例#16
0
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