Exemple #1
0
def multi_root_forest_arborescence(g, nodes):
    #Input: 1. An undirected graph 2. Subset of nodes
    #Output: An undirected graph containing collection of arborescence rooted at the given subset of nodes and the set of
    # nodes partitioned according to shortest distance to the root nodes (ties handled in the order of rooted node indices supplied)
    #NOTE: Assumes edge length in both directions is same  TODO: Relax this assumption
    h = nx.DiGraph()
    h.add_nodes_from(nodes)
    for i in h.nodes():
        h.node[i] = g.node[i]
    n = len(g.nodes())
    lens = []
    paths = []
    for i in nodes:
        l, p = nxsh.single_source_dijkstra(g, i, weight='length')
        lens.append(l)
        paths.append(p)
    for k in range(n):
        min_len = np.inf
        min_id = n
        for i in range(len(lens)):
            if lens[i][k] < min_len:
                min_len = lens[i][k]
                min_id = i
        path = paths[min_id][k]
        if len(path) > 1:
            for j in range(len(path) - 1):
                h.add_edge(path[j], path[j + 1])
                h.edge[path[j]][path[j + 1]] = g.edge[path[j]][path[j + 1]]
                h.edge[path[j + 1]][path[j]] = g.edge[path[j + 1]][path[j]]

    return h
Exemple #2
0
def find_shortest_path(g, src, target):
    try:
        path_sum, sp = single_source_dijkstra(g, src, target, weight='weight')
    except:
        raise ValueError("No such path exists, try different nodes") from None
    print("Found shortest path between {} and {}!".format(src, target))
    path = ""
    for node in sp:
        path += node + "->"
    print("Path (displayed in red): {}".format(path[:-2]))
    print("Path weight: {}".format(path_sum))
    return sp
Exemple #3
0
def get_arborescence(g, node):
    h = nx.DiGraph()
    h.add_nodes_from(g)
    for i in g.nodes():
        h.node[i] = g.node[i]
    _, paths = nxsh.single_source_dijkstra(g, node, weight='length')
    for p in paths:
        if len(paths[p]) > 1:
            for i in range(len(paths[p]) - 1):
                h.add_edge(paths[p][i], paths[p][i + 1])
                h.edge[paths[p][i]][paths[p][i + 1]] = g.edge[paths[p][i]][
                    paths[p][i + 1]]
                h.add_edge(paths[p][i + 1], paths[p][i])
                h.edge[paths[p][i + 1]][paths[p][i]] = g.edge[paths[p][i + 1]][
                    paths[p][i]]
    return h
Exemple #4
0
def puzzle_1(field, portals, portal_map, graph):
    final_graph = nx.Graph()

    for p1 in portals:
        for p2 in portals:
            if p1 != p2:
                for p1_pos in portal_map[p1]:
                    for p2_pos in portal_map[p2]:

                        # Combine the two portals by using the same name and create a new graph that removes the "portal" and
                        # directly connects all nodes to each other. Just a normal graph now, that we can throw Dijkstra on.
                        if nx.has_path(graph, p1_pos, p2_pos) and not final_graph.has_edge(p1, p2):
                            final_graph.add_edge(p1, p2, weight=nx.shortest_path_length(graph, p1_pos, p2_pos))

    step_count, steps = single_source_dijkstra(final_graph, "AA", "ZZ")

    return step_count + len(steps)-2
Exemple #5
0
    def find_reachable(self, source, node_list):
        """

        :param source: starting node hash local env
        :param node_list: list of nodes from local env that we want to find shortest path to
        :return: A list of the the same size as node_list containing  the shortest path in local env from start
                or None if doesn't exist
        """
        # get the subgraph
        # I choose here a random node, but other options will be better and slower
        passable_subgraph = self.local_environment.get_passable_subgraph(
            keep_nodes=[source])
        shortest_paths = single_source_dijkstra(passable_subgraph, source)[1]
        shortest_paths = {
            node: path
            for node, path in shortest_paths.items() if node in set(node_list)
        }
        return shortest_paths
Exemple #6
0
    def test_shortestPathCompare6(self):
        """Runs the shortestPath method from this project's algo, and runs it also through
        netWorkX, to compare results and performance. runs on graph: G_30000_240000_1.json """

        print("reading from file...",
              self.algo.load_from_json("G_30000_240000_1.json"))
        graphnx6 = nx.DiGraph()
        for nodeKey in self.algo.myGraph._nodes.keys():
            graphnx6.add_node(nodeKey)
        for src in self.algo.myGraph._edges.keys():
            for dest in self.algo.myGraph._edges.get(src).keys():
                graphnx6.add_edge(
                    src,
                    dest,
                    weight=self.algo.myGraph._edges.get(src).get(dest))
        self.startTime = time.time()
        print("shortestPath is ", self.algo.shortest_path(0, 4))
        print("Networx: ")
        print(single_source_dijkstra(graphnx6, 0, 4))
Exemple #7
0
def puzzle_2(field, portals, portal_map, graph):
    final_graph = nx.Graph()

    # If using all levels we can at maximum go down half of all portals and half up again...?
    # Could be wrong, then remove the //2, but seems to work for this problem.
    for level in range(len(portals)//2):
        for p1 in portals:
            for p2 in portals:
                if p1 != p2:
                    # Only the first level has AA and ZZ.
                    if level > 0 and (p1 in ["AA", "ZZ"] or p2 in ["AA", "ZZ"]):
                        continue

                    for p1_pos in portal_map[p1]:

                        # The name is now unique for portals depending on level and inner/outer status!
                        outer_p1 = is_outer(field, p1_pos)
                        new_name_p1 = p1 + ("o" if outer_p1 else "i") + ("-" * level)

                        for p2_pos in portal_map[p2]:

                            # The name is now unique for portals depending on level and inner/outer status!
                            outer_p2 = is_outer(field, p2_pos)
                            new_name_p2 = p2 + ("o" if outer_p2 else "i") + ("-" * level)

                            if nx.has_path(graph, p1_pos, p2_pos):
                                final_graph.add_edge(new_name_p1, new_name_p2, weight=nx.shortest_path_length(graph, p1_pos, p2_pos))

                            # Portals going up
                            if outer_p1 and level > 0:
                                final_graph.add_edge(new_name_p1, new_name_p1.replace("o", "i")[:-1], weight=1)

                            # Portals going down
                            if not outer_p1 and p1 not in ["AA", "ZZ"]:
                                final_graph.add_edge(new_name_p1, new_name_p1.replace("i", "o") + "-", weight=1)


    # Go from the outer ports (though there are no inner) from AA to ZZ.
    step_count, steps = single_source_dijkstra(final_graph, "AAo", "ZZo")
    return step_count
Exemple #8
0
def single_flip_contiguous(partition):
    """
    Check if swapping the given node from its old assignment disconnects the
    old assignment class.

    :parition: Current :class:`.Partition` object.

    :flips: Dictionary of proposed flips, with `(nodeid: new_assignment)`
            pairs. If `flips` is `None`, then fallback to the
            :func:`.contiguous` check.

    :returns: True if contiguous, and False otherwise.

    We assume that `removed_node` belonged to an assignment class that formed a
    connected subgraph. To see if its removal left the subgraph connected, we
    check that the neighbors of the removed node are still connected through
    the changed graph.

    """
    parent = partition.parent
    flips = partition.flips
    if not flips or not parent:
        return contiguous(partition)

    graph = partition.graph
    assignment_dict = parent.assignment

    def proposed_assignment(node):
        """Return the proposed assignment of the given node."""
        if node in flips:
            return flips[node]

        return assignment_dict[node]

    def partition_edge_weight(start_node, end_node, edge_attrs):
        """
        Compute the district edge weight, which is 1 if the nodes have the same
        assignment, and infinity otherwise.
        """
        if proposed_assignment(start_node) != proposed_assignment(end_node):
            return float("inf")

        return 1

    for changed_node, _ in flips.items():
        old_neighbors = []
        old_assignment = assignment_dict[changed_node]

        for node in graph.neighbors(changed_node):
            if proposed_assignment(node) == old_assignment:
                old_neighbors.append(node)

        if not old_neighbors:
            # Under our assumptions, if there are no old neighbors, then the
            # old_assignment district has vanished. It is trivially connected.
            return True

        start_neighbor = random.choice(old_neighbors)

        for neighbor in old_neighbors:
            try:
                distance, _ = nx_path.single_source_dijkstra(
                    graph,
                    start_neighbor,
                    neighbor,
                    weight=partition_edge_weight)
                if not (distance < float("inf")):
                    return False
            except NetworkXNoPath:
                return False

    # All neighbors of all changed nodes are connected, so the new graph is
    # connected.
    return True
Exemple #9
0
 def _update_path(self):
     dist, path = single_source_dijkstra(
         self.G, source=self.current_path[-1], target=self.current_node
     )
     self.current_path += path[1:]
     return dist
Exemple #10
0
        flattened_list.append(y)

#clean up the path and add up the weights of the set of nodes
res_path = [x[0] for x in groupby(flattened_list)]
res_weight = sum(res_weight)
print("The shortest route from " + list_of_nodes_to_dest[0] + " to " +
      list_of_nodes_to_dest[-1] + " is:\n" + str(res_path))
print("The total weight is " + str(res_weight))

# <h2> Validate the result </h2>

#use networkx to create an edgelist (for validating the results)
G = nx.from_pandas_edgelist(df, 'source', 'target', edge_attr='weight')

#run the below function to find the shortest path for a set of nodes(for validating the results)
single_source_dijkstra(G, '21', '22')

# <h2> Visualization of the graph </h2>

#read the node informtion data
df_data = pd.read_csv('node_information_file.csv')

#convert the latitudes and logitudes in proper format by dividing them by 1000000
#store the latitude and logitude of the source, must-pass and destination nodes in a list
location_latlongs = []
for x in list_of_nodes_to_dest:
    location_latlong = []
    location_latlong.append(
        float(df_data["Longitude"].iloc[int(x) - 1]) / 1000000)
    location_latlong.append(
        float(df_data["Latitude"].iloc[int(x) - 1]) / 1000000)