def build_path(G, source, target, excluded_nodes, file_path): try: with open(file_path) as f: lines = f.read().splitlines() node_priorities = dict() for line in lines: match = re.fullmatch( r"(([A-Za-z0-9_@./#&+-])+{(([A-Za-z0-9_@./#&+-])+\b,*\b)+})", line) if match: sp1 = (match.string.split('{')) node = sp1[0] sp2 = (sp1[1].split('}')) priorities = (sp2[0].split(',')) if not G.has_node(node): raise nx.NetworkXNoPath(f"Node {node} not in graph") for priority in priorities: if not nodes_connected(G, priority, node): raise nx.NetworkXNoPath( f"Node {priority} not neighbor of {node}") if priority in excluded_nodes: priorities.remove(priority) if node not in excluded_nodes: node_priorities[node] = priorities else: raise ImportError('Import error: Wrong syntax!') path = list() if source in node_priorities: path.append(source) priorities = node_priorities[source] path.append(priorities[0]) else: raise nx.NetworkXNoPath( f"Source {source} not in the priority list") while True: if path[-1] == target: break if path[-1] in node_priorities: node = path[-1] nodes = node_priorities[node] path.append(nodes[0]) else: break if len(path) != len(set(path)): break return path except Exception as e: raise e
def k_shortest_paths(G, source, target, k=1, weight='weight'): if source == target: return ([0], [[source]]) length, path = nx.single_source_dijkstra(G, source, target, weight=weight) if target not in length: raise nx.NetworkXNoPath("node %s not reachable from %s" % (source, target)) lengths = [length[target]] paths = [path[target]] c = count() B = [] G_original = G.copy() for i in range(1, k): for j in range(len(paths[-1]) - 1): spur_node = paths[-1][j] root_path = paths[-1][:j + 1] edges_removed = [] for c_path in paths: if len(c_path) > j and root_path == c_path[:j + 1]: u = c_path[j] v = c_path[j + 1] if G.has_edge(u, v): edge_attr = G.edge[u][v] G.remove_edge(u, v) edges_removed.append((u, v, edge_attr)) for n in range(len(root_path) - 1): node = root_path[n] # out-edges for u, v, edge_attr in G.edges(node, data=True): G.remove_edge(u, v) edges_removed.append((u, v, edge_attr)) if G.is_directed(): # in-edges for u, v, edge_attr in G.in_edges_iter(node, data=True): G.remove_edge(u, v) edges_removed.append((u, v, edge_attr)) spur_path_length, spur_path = nx.single_source_dijkstra(G, spur_node, target, weight=weight) if target in spur_path and spur_path[target]: total_path = root_path[:-1] + spur_path[target] total_path_length = get_path_length(G_original, root_path, weight) + spur_path_length[target] heappush(B, (total_path_length, next(c), total_path)) for e in edges_removed: u, v, edge_attr = e G.add_edge(u, v, **edge_attr) if B: (l, _, p) = heappop(B) lengths.append(l) paths.append(p) else: break return (lengths, paths)
def reconstruir_caminos_por_padres(inicios, meta, padre): if meta not in padre: raise nx.NetworkXNoPath(f"Target {meta} cannot be reached" f"from given sources") seen = {meta} stack = [[meta, 0]] top = 0 while top >= 0: node, i = stack[top] if node in inicios: yield [p for p, n in reversed(stack[:top + 1])] if len(padre[node]) > i: stack[top][1] = i + 1 next = padre[node][i] if next in seen: continue else: seen.add(next) top += 1 if top == len(stack): stack.append([next, 0]) else: stack[top][:] = [next, 0] else: seen.discard(node) top -= 1
def shortest_path(G, sources=None, target=None, cutoff=None, weight=None, mode='drive'): #print("{}, {}".format(sources, target)) if not sources: raise ValueError('source must not be empty') if target in sources: return {'length': 0, 'nodes': [target]} weight = _weight_function(G, weight) paths = {source: [source] for source in sources} # dictionary of paths dist = _dijkstra_multisource(G, sources, weight, paths=paths, cutoff=cutoff, target=target, mode=mode) if target is None: return {'length': dist, 'nodes': [paths]} try: return {'length': dist[target], 'nodes': paths[target]} except KeyError: raise nx.NetworkXNoPath("No path to {}.".format(target))
def sympy_multisource_dijkstras(g, sources, f, accumulators=None, init=None, target=None, cutoff=None): if sources is None or not len(sources): raise ValueError("sources must not be empty") if target in sources: return (0, [target]) paths = {source: [source] for source in sources} # dictionary of paths dist = _multisource_dijkstra( g, sources, f, target=target, accumulators=accumulators, init=init, paths=paths, cutoff=cutoff, ) if target is None: return (dist, paths) try: return (dist[target], paths[target]) except KeyError: raise nx.NetworkXNoPath("No path to {}.".format(target))
def dijkstra_all_shortest_paths(G, source, target, weight=None): ''' This function is the networkX's implementation of the "all-shortest-paths-problem" algorithm and is used as ground truth for our implementation. It uses a modified version of the dijkstra algorithm that compute the shortest path length and predecessors on shortest paths.''' if weight is not None: pred,dist = nx.dijkstra_predecessor_and_distance(G,source,weight=weight) else: pred = nx.predecessor(G,source) if target not in pred: raise nx.NetworkXNoPath() stack = [[target,0]] top = 0 while top >= 0: node,i = stack[top] if node == source: yield [p for p,n in reversed(stack[:top+1])] if len(pred[node]) > i: top += 1 if top == len(stack): stack.append([pred[node][i],0]) else: stack[top] = [pred[node][i],0] else: stack[top-1][1] += 1 top -= 1
def _bidirectional_all_shortest_paths_multi(G, source, target): tree = [[(source, )], [(target, )]] found = 0 while not found and tree[0] and tree[1]: modus = len(tree[1]) < len(tree[0]) tree_source = tree[modus] tree_target = tree[modus ^ 1] temp_tree = [] for path_s in tree_source: for s in [v for u, v in G.edges([path_s[-1]])]: if s not in path_s: for path_t in tree_target: if s == path_t[-1]: if not set(path_t).intersection(path_s): found = 1 if modus: yield list(path_t + tuple(reversed(path_s))) else: yield list(path_s + tuple(reversed(path_t))) temp_tree.append(path_s + (s, )) tree[modus] = temp_tree if not found: raise nx.NetworkXNoPath("No path between %s and %s." % (source, target))
def Copy_all_shortest_paths_exclude_link(G, source, target, weight=None, color=None, color_exc_inc=None): if weight is not None: pred, dist = copy_dijkstra_predecessor_and_distance( G, source, weight=weight, color=color, color_exc_inc=color_exc_inc) else: pred = nx.predecessor(G, source) if target not in pred: raise nx.NetworkXNoPath() stack = [[target, 0]] top = 0 while top >= 0: node, i = stack[top] if node == source: yield [p for p, n in reversed(stack[:top + 1])] if len(pred[node]) > i: top += 1 if top == len(stack): stack.append([pred[node][i], 0]) else: stack[top] = [pred[node][i], 0] else: stack[top - 1][1] += 1 top -= 1
def dijkstra_path(G, source, target, weight='weight'): (length, path) = single_source_dijkstra(G, source, target=target, weight=weight) try: return path[target] except KeyError: raise nx.NetworkXNoPath("node %s not reachable from %s" % (source, target))
def dijkstra_path_length(G, source, target, weight='weight'): """Returns the shortest path length from source to target in a weighted graph. Parameters ---------- G : NetworkX graph source : node label starting node for path target : node label ending node for path weight: string, optional (default='weight') Edge data key corresponding to the edge weight Returns ------- length : number Shortest path length. Raises ------ NetworkXNoPath If no path exists between source and target. Examples -------- >>> G=nx.path_graph(5) >>> print(nx.dijkstra_path_length(G,0,4)) 4 Notes ----- Edge weight attributes must be numerical. Distances are calculated as sums of weighted edges traversed. See Also -------- bidirectional_dijkstra() """ if source == target: return 0 if G.is_multigraph(): get_weight = lambda u, v, data: min( eattr.get(weight, 1) for eattr in data.values()) else: get_weight = lambda u, v, data: data.get(weight, 1) length = _dijkstra(G, source, get_weight, target=target) try: return length[target] except KeyError: raise nx.NetworkXNoPath("node %s not reachable from %s" % (source, target))
def dijkstra_path(G, source, target, get_weight): """Returns the shortest path from source to target in a weighted graph G""" (length, path) = single_source_dijkstra(G, source, target, get_weight) try: return path[target] except KeyError: raise nx.NetworkXNoPath( "node %s not reachable from %s" % (source, target))
def _bidirectional_pred_succ(G, source, target, exclude): # does BFS from both source and target and meets in the middle # excludes nodes in the container "exclude" from the search if source is None or target is None: raise nx.NetworkXException( "Bidirectional shortest path called without source or target") if target == source: return ({target: None}, {source: None}, source) # handle either directed or undirected if G.is_directed(): Gpred = G.predecessors Gsucc = G.successors else: Gpred = G.neighbors Gsucc = G.neighbors # predecesssor and successors in search pred = {source: None} succ = {target: None} # initialize fringes, start with forward forward_fringe = [source] reverse_fringe = [target] level = 0 while forward_fringe and reverse_fringe: # Make sure that we iterate one step forward and one step backwards # thus source and target will only trigger "found path" when they are # adjacent and then they can be safely included in the container 'exclude' level += 1 if not level % 2 == 0: this_level = forward_fringe forward_fringe = [] for v in this_level: for w in Gsucc(v): if w in exclude: continue if w not in pred: forward_fringe.append(w) pred[w] = v if w in succ: return pred, succ, w # found path else: this_level = reverse_fringe reverse_fringe = [] for v in this_level: for w in Gpred(v): if w in exclude: continue if w not in succ: succ[w] = v reverse_fringe.append(w) if w in pred: return pred, succ, w # found path raise nx.NetworkXNoPath("No path between %s and %s." % (source, target))
def astar_path(G, source, target, percentage, max_ele=False): heuristic = None if source not in G or target not in G: msg = 'Either source {} or target {} is not in G' raise nx.NodeNotFound(msg.format(source, target)) if heuristic is None: # The default heuristic is h=0 - same as Dijkstra's algorithm def heuristic(u, v): return get_elevation_gain(G, u, v) push = heappush pop = heappop revPath = {} revPath[source] = None c = 1 queue = [(0, c, source, 0, None)] enqueued = {} explored = {} while queue: # Pop the smallest item from queue. _, _, curnode, dist, parent = pop(queue) if curnode == target: path = [curnode] node = parent while node is not None: path.append(node) node = explored[node] path.reverse() return path, get_path_length(G, path), get_path_elevation(G, path) if curnode in explored: continue explored[curnode] = parent for neighbor, w in G[curnode].items(): if neighbor in explored: continue # print(neighbor, w[0]) ncost = dist + w[0]['length'] if neighbor in enqueued: qcost, h = enqueued[neighbor] if qcost <= ncost: continue else: # print(neighbor, target) h = heuristic(neighbor, target) enqueued[neighbor] = ncost, h c += 1 push(queue, (ncost + h, c, neighbor, ncost, curnode)) raise nx.NetworkXNoPath("Node %s not reachable from %s" % (source, target))
def dijkstra_path(G, source, target, weight='weight', N="N"): """Returns the shortest path from source to target in a weighted graph G. parámetros ---------- G : NetworkX graph. source : node Nodo inicial del camino. target : node Nodo final del camino. weight: string, optional (default='weight') Edge data key corresponding to the edge weight. N : lista Lista con torres que pueden ser backhaul Retorna ------- path : list Lista de nodos con el camino más corto. Raises ------ NetworkXNoPath If no path exists between source and target. Ejemplos -------- >>> G=nx.path_graph(5) >>> print(nx.dijkstra_path(G,0,4)) [0, 1, 2, 3, 4] Nota ------ El peso del atributo debe ser numérico. Las distancias son calculados con la ponderación de los nodos atravesados. """ (length, path) = single_source_dijkstra(G, source, target=target, weight=weight, N=N) try: return path[target] except KeyError: raise nx.NetworkXNoPath("node %s not reachable from %s" % (source, target))
def astar_path(G, source, target, nodes_proj, heuristic=None, weight='weight'): if source not in G or target not in G: msg = 'Either source {} or target {} is not in G' raise nx.NodeNotFound(msg.format(source, target)) if heuristic is None: # The default heuristic is h=0 - same as Dijkstra's algorithm def heuristic(u, v): return 0 push = heappush pop = heappop c = count() queue = [(0, next(c), source, 0, None)] enqueued = {} # Maps explored nodes to parent closest to the source. explored = {} while queue: # Pop the smallest item from queue. _, __, curnode, dist, parent = pop(queue) if curnode == target: path = [curnode] node = parent while node is not None: path.append(node) node = explored[node] path.reverse() return path if curnode in explored: continue explored[curnode] = parent for neighbor, w in G[curnode].items(): if neighbor in explored: continue ncost = dist + w.get(weight, 1) if neighbor in enqueued: qcost, h = enqueued[neighbor] if qcost <= ncost: continue else: h = heuristic(G, neighbor, target, source, nodes_proj) enqueued[neighbor] = ncost, h push(queue, (ncost + h, next(c), neighbor, ncost, curnode)) raise nx.NetworkXNoPath("Node %s not reachable from %s" % (source, target))
def compute_cost_for_path(self, graph: nx.graph.Graph, path: List): """ compute the cost for the given path. This may raise nx.NetworkXNoPath if total_cost_from_start_to_dst returns None. E.g. if the CostAccumulator has limits on the fees or maximum number of hops this may return None""" cost = self.zero() for source, dst in zip(path, path[1:]): cost = self.total_cost_from_start_to_dst( cost, source, dst, graph.get_edge_data(source, dst)) if cost is None: raise nx.NetworkXNoPath("no path found") return cost
def multi_source_dijkstra(graph, sources, weight, target=None, price=0): if target in sources: return 0, [target] paths = {source: [source] for source in sources} push = heappush pop = heappop dist = {} seen = {} c = count() stack = [] if graph.is_directed(): graph_succ = graph._succ else: graph_succ = graph._adj for source in sources: seen[source] = 0 push(stack, (0, next(c), source)) while stack: (d, _, v) = pop(stack) if v in dist: continue dist[v] = d if v == target: break for u in graph_succ[v]: cost = weight(v, u) if cost is None: continue vu_dist = dist[v] + cost if u not in seen or (vu_dist < seen[u] and cost + price < 10000): seen[u] = vu_dist push(stack, (vu_dist, next(c), u)) if paths is not None: paths[u] = paths[v] + [u] if target is None: return dist, paths try: return dist[target], paths[target] except KeyError: raise nx.NetworkXNoPath("No path to {}.".format(target))
def _bidirectional_pred_succ(G, source, target): """Bidirectional shortest path helper. Returns (pred,succ,w) where pred is a dictionary of predecessors from w to the source, and succ is a dictionary of successors from w to the target. """ # does BFS from both source and target and meets in the middle if source is None or target is None: raise nx.NetworkXException(\ "Bidirectional shortest path called without source or target") if target == source: return ({target: None}, {source: None}, source) # handle either directed or undirected if G.is_directed(): Gpred = G.predecessors_iter Gsucc = G.successors_iter else: Gpred = G.neighbors_iter Gsucc = G.neighbors_iter # predecesssor and successors in search pred = {source: None} succ = {target: None} # initialize fringes, start with forward forward_fringe = [source] reverse_fringe = [target] while forward_fringe and reverse_fringe: if len(forward_fringe) <= len(reverse_fringe): this_level = forward_fringe forward_fringe = [] for v in this_level: for w in Gsucc(v): if w not in pred: forward_fringe.append(w) pred[w] = v if w in succ: return pred, succ, w # found path else: this_level = reverse_fringe reverse_fringe = [] for v in this_level: for w in Gpred(v): if w not in succ: succ[w] = v reverse_fringe.append(w) if w in pred: return pred, succ, w # found path raise nx.NetworkXNoPath("No path between %s and %s." % (source, target))
def dijkstra_path(G, source, target, weight='weight', N="N"): """Returns the shortest path from source to target in a weighted graph G. Parameters ---------- G : NetworkX graph source : node Starting node target : node Ending node weight: string, optional (default='weight') Edge data key corresponding to the edge weight Returns ------- path : list List of nodes in a shortest path. Raises ------ NetworkXNoPath If no path exists between source and target. Examples -------- >>> G=nx.path_graph(5) >>> print(nx.dijkstra_path(G,0,4)) [0, 1, 2, 3, 4] Notes ------ Edge weight attributes must be numerical. Distances are calculated as sums of weighted edges traversed. See Also -------- bidirectional_dijkstra() """ (length, path) = single_source_dijkstra(G, source, target=target, weight=weight, N=N) try: return path[target] except KeyError: raise nx.NetworkXNoPath("node %s not reachable from %s" % (source, target))
def dijkstra(graph, a, b, grid=None): def log_error(): id_grid_pd = grid.grid_pd.set_index("id") target_missing = b not in id_grid_pd.index if target_missing: logMsg = "Target node '{}' is not in grid".format(b) else: source_node = id_grid_pd.loc[a] target_node = id_grid_pd.loc[b] logMsg = ("Point ({}, {}) not reachable from point " "({}, {}), with node numbers {} and {}").format( target_node["x"], target_node["y"], source_node["x"], source_node["y"], b, a) module_logger.debug(logMsg) return if not graph.has_node(a): raise nx.NetworkXNoPath("node {} not in graph".format(a)) try: length, path = nx.single_source_dijkstra(graph, a, b) except nx.NetworkXNoPath: if grid is not None: log_error() raise nx.NetworkXNoPath("node {} not reachable from {}".format(b, a)) return length, path
def astar_path(G, source, target): if source not in G or target not in G: raise nx.NodeNotFound( f"Either source {source} or target {target} is not in G") push = heapq.heappush pop = heapq.heappop def weight(u, v, d): return min(attr.get(weight, 1) for attr in d.values()) c = count() queue = [(0, next(c), source, 0, None)] enqueued = {} explored = {} while queue: _, __, curnode, dist, parent = pop(queue) if curnode == target: path = [curnode] node = parent while node is not None: path.append(node) node = explored[node] path.reverse() return path if curnode in explored: if explored[curnode] is None: continue qcost, h = enqueued[curnode] if qcost < dist: continue explored[curnode] = parent for neighbor, w in G[curnode].items(): ncost = dist + weight(curnode, neighbor, w) if neighbor in enqueued: qcost, h = enqueued[neighbor] if qcost <= ncost: continue else: h = heuristic(G, neighbor, target) enqueued[neighbor] = ncost, h push(queue, (ncost + h, next(c), neighbor, ncost, curnode)) raise nx.NetworkXNoPath(f"Node {target} not reachable from {source}")
def _route_search(self, origin, destination): """ 去顶从起点到终点的最优距离 :param origin: carla.Location 类型 :param destination: :return: list类型,成员是图中节点id """ start_edge = self._find_location_edge(origin) # 获取起点所在边 end_edge = self._find_location_edge(destination) # 获取终点所在边 route = self._A_star(start_edge[0], end_edge[0]) if route is None: # 如果不可达就报错 raise nx.NetworkXNoPath(f"Node {start_edge[0]} not reachable from {end_edge[0]}") route.append(end_edge[1]) # 可达的话就将终点所在变得右端点加入路径 return route
def _bidirectional_pred_succ(G, source, target): """Bidirectional shortest path helper. Returns (pred, succ, w) where pred is a dictionary of predecessors from w to the source, and succ is a dictionary of successors from w to the target. """ # does BFS from both source and target and meets in the middle if target == source: return ({target: None}, {source: None}, source) # handle either directed or undirected if G.is_directed(): Gpred = G.pred Gsucc = G.succ else: Gpred = G.adj Gsucc = G.adj # predecesssor and successors in search pred = {source: None} succ = {target: None} # initialize fringes, start with forward forward_fringe = [source] reverse_fringe = [target] while forward_fringe and reverse_fringe: if len(forward_fringe) <= len(reverse_fringe): this_level = forward_fringe forward_fringe = [] for v in this_level: for w in Gsucc[v]: if w not in pred: forward_fringe.append(w) pred[w] = v if w in succ: # path found return pred, succ, w else: this_level = reverse_fringe reverse_fringe = [] for v in this_level: for w in Gpred[v]: if w not in succ: succ[w] = v reverse_fringe.append(w) if w in pred: # found path return pred, succ, w raise nx.NetworkXNoPath(f"No path between {source} and {target}.")
def un_inicio_bellman_ford(G, inicio, meta=None, peso="weight"): if inicio == meta: return (0, [inicio]) peso = extraer_pesos(G, peso) caminos = {inicio: [inicio]} dist = bellman_ford(G, [inicio], peso, caminos=caminos, meta=meta) if meta is None: return (dist, caminos) try: return (dist[meta], caminos[meta]) except KeyError as e: msg = f"Node {meta} not reachable from {inicio}" raise nx.NetworkXNoPath(msg) from e
def _bellman_ford_path(G, source, target, weight): "Returns shortest path using bellman_ford algorithm." pred, dist = nx.bellman_ford(G, source, weight) if target not in pred: raise nx.NetworkXNoPath("Node %s not reachable from %s." % (source, target)) # Since predecessors are given, build path backwards, then reverse. path = [] curr = target while curr != source: path.append(curr) curr = pred[curr] path.append(source) path.reverse() return path
def dijkstra_path_length(G, source, target, weight='weight'): """Returns the shortest path length from source to target in a weighted graph. Parameters ---------- G : NetworkX graph source : node label starting node for path target : node label ending node for path weight: string, optional (default='weight') Edge data key corresponding to the edge weight Returns ------- length : number Shortest path length. Raises ------ NetworkXNoPath If no path exists between source and target. Examples -------- >>> G=nx.path_graph(5) >>> print(nx.dijkstra_path_length(G,0,4)) 4 Notes ----- Edge weight attributes must be numerical. Distances are calculated as sums of weighted edges traversed. See Also -------- bidirectional_dijkstra() """ length = dict(single_source_dijkstra_path_length(G, source, weight=weight)) try: return length[target] except KeyError: raise nx.NetworkXNoPath("node %s not reachable from %s" % (source, target))
def rnd_walk(self, topo, node, steps, visited={}): i = 0 visited[node] = True # self.log.debug("rnd_walk %d %d" % (node, steps)) res = [node] if steps == 0: return res while i < self.MAX_ITER: i += 1 nnode = self.rng.choice(topo.graph.neighbors(node)) if nnode in visited: continue res.extend(self.rnd_walk(topo, nnode, steps - 1, visited)) return res self.log.debug("Giving up on random walk") raise nx.NetworkXNoPath("No random path from %s." % (node))
def multi_source_dijkstra(G, sources,neighborsDict, target=None, cutoff=None, weight='weight'): if not sources: raise ValueError('sources must not be empty') if target in sources: return (0, [target]) weight = _weight_function(G, weight) paths = {source: [source] for source in sources} # dictionary of paths dist = _dijkstra_multisource(G, sources, neighborsDict, weight, paths=paths, cutoff=cutoff, target=target) if target is None: return (dist, paths) try: return (dist[target], paths[target]) except KeyError: raise nx.NetworkXNoPath("No path to {}.".format(target))
def _least_cost_path_helper(graph: nx.graph.Graph, target_nodes: Set, queue: List, least_costs: Dict, backlinks: Dict, cost_fn: Callable, max_cost=None # node_filter, # edge_filter, ): graph_adj = graph.adj visited_nodes = set( ) # set of nodes, where we already found the minimal path while queue: cost_from_start_to_node, node = heapq.heappop(queue) if node in target_nodes: return cost_from_start_to_node, _build_path_from_backlinks( node, backlinks) if cost_from_start_to_node > least_costs[node]: continue # we already found a cheaper path to node visited_nodes.add(node) for dst, edge_data in graph_adj[node].items(): if dst in visited_nodes: continue cost_from_start_to_dst = cost_fn(cost_from_start_to_node, node, dst, edge_data) if cost_from_start_to_dst is None: # cost_fn decided this path is forbidden continue if max_cost is not None and max_cost < cost_from_start_to_dst: continue assert cost_from_start_to_dst >= cost_from_start_to_node least_cost_found_so_far_from_start_to_dst = least_costs.get(dst) if (least_cost_found_so_far_from_start_to_dst is None or cost_from_start_to_dst < least_cost_found_so_far_from_start_to_dst): heapq.heappush(queue, (cost_from_start_to_dst, dst)) least_costs[dst] = cost_from_start_to_dst backlinks[dst] = node raise nx.NetworkXNoPath("no path found")
def my_dijkstra_path(G, source, target, weight='weight', orient=None, stop_pt=None): (length, path) = my_single_source_dijkstra(G, source, target=target, weight=weight, orient=orient, stop_pt=stop_pt) try: return path[target] except KeyError: raise nx.NetworkXNoPath("node %s not reachable from %s" % (source, target))