def beam_path_length(G, source, target, heuristic=None, weight='weight'): """Returns the length of the shortest path between source and target using the Beam Stack Search algorithm. Parameters ---------- G : NetworkX graph source : node Starting node for path target : node Ending node for path heuristic : function A function to evaluate the estimate of the distance from the a node to the target. The function takes two nodes arguments and must return a number. Raises ------ NetworkXNoPath If no path exists between source and target. See Also ------- """ if source not in G or target not in G: msg = f"Either source {source} or target {target} is not in G" raise nx.NodeNotFound(msg) weight = _weight_function(G, weight) path = beam_path(G, source, target, heuristic, weight) return sum(weight(u, v, G[u][v]) for u, v in zip(path[:-1], path[1:]))
def single_source_shortest_path_length(G, source, cutoff=None): if source not in G: raise nx.NodeNotFound('Source {} is not in G'.format(source)) if cutoff is None: cutoff = float('inf') nextlevel = {source: 1} return dict(_single_shortest_path_length(G.adj, nextlevel, cutoff))
def _dijkstra(G, node): """使用dijkstra算法计算 node 与 图中其它节点 之间的最短路径""" G_succ = {k: list(G._adj[k].keys()) for k in G._adj.keys()} for u,v in G.edges(): G_succ[v] += [u] # 保存全部邻接关系 push = heappush pop = heappop dist = {} # dictionary of final distances seen = {} fringe = [] if node not in G: raise nx.NodeNotFound(f"Node {node} not in G") seen[node] = 0 push(fringe, (0, node)) while fringe: (d, v) = pop(fringe) if v in dist: continue # already searched this node. dist[v] = d for u in G_succ[v]: vu_dist = dist[v] + 1 if u in dist: if vu_dist < dist[u]: raise ValueError('Contradictory paths found:','negative weights?') elif u not in seen or vu_dist < seen[u]: seen[u] = vu_dist push(fringe, (vu_dist, u)) return dist
def astar_path_length(G, source, target, heuristic=None, weight='weight'): """Return the length of the shortest path between source and target using the A* ("A-star") algorithm. Parameters ---------- G : NetworkX graph source : node Starting node for path target : node Ending node for path heuristic : function A function to evaluate the estimate of the distance from the a node to the target. The function takes two nodes arguments and must return a number. Raises ------ NetworkXNoPath If no path exists between source and target. See Also -------- astar_path """ 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)) path = astar_path(G, source, target, heuristic, weight) return sum(G[u][v].get(weight, 1) for u, v in zip(path[:-1], path[1:]))
def BFS(G=nx.Graph(), source=None, depth=None): if source not in G: msg = 'source {} is not in G' raise nx.NodeNotFound(msg.format(source)) level = list() explored = list() this_level = list() explored.append(source) this_level.append(source) while this_level.__len__() is not 0: level.append(this_level) next_level = list() for node in this_level: for adj_node in G.adj[node]: if adj_node not in explored: explored.append(adj_node) next_level.append(adj_node) this_level = next_level if depth is not None and level.__len__() > depth: break # convert list to dict level = {index: set(nodes) for index, nodes in enumerate(level)} return level
def greedy_path(G, source, target, heuristic = None, weight = "weight"): #if source or target is not in G -> error msg if source not in G or target not in G: msg = f"Either source {source} or target {target} is not in G" raise nx.NodeNotFound(msg) #if heuristic is none -> define the default heuristic function: h = 0 if heuristic is None: def heuristic(u, v): return 0 #assegno a push la funzione heappush e a pop la funzione heappop. #A wieght invece assegno la funzione _weight_function(G, weight) #passando come parametro G e weight (input della funzione greedy_search) push = heappush pop = heappop getWeight = _weight_function(G, weight) #variabile di gestione dell'euristica nell'ordinamento (in caso di parità) c = count() #la fringe mantiene: priorità, nodo corrente (nel caso base è la radice), varibaile di gestione e il parent fringe = [(0, next(c), source, None)] #struttura dati che memorizza i parent dei nodi visitati explored = {} #struttura che mantiene i pesi dei cammini parziali weights = {} while queue: _, __, curNode, parent = pop(fringe) #caso base: target raggiunto. Costruzione del path tramite i parent if curNode == target: path = [curNode] node = parent while node is not None: path.append(node) node = explored[node] path.reverse() return path curWeight = weights[parent] + getWeight(parent, curNode, weight) if curNode in explored: if explored[curNode] is None: continue if curWeight > weights[curNode]: continue explored[curNode] = parent weights[curNode] = curWeight for neighbor, _ in G[curNode].items(): if neighbor not in explored: weights[neighbor] = weights[curNode] + getWeight(curnNode, neighbor, weight) heuristicValue = heuristic(neighbor, target) push(fringe, (heuristicValue, next(c), neighbor, curNode))
def mod_all_simple_paths(self, source, target, cutoff=None): if source not in self.G: raise nx.NodeNotFound(f"source node {source} not in graph") if target in self.G: targets = {target} else: try: targets = set(target) except TypeError as e: raise nx.NodeNotFound( f"target node {target} not in graph") from e if cutoff is None: cutoff = len(self.G) - 1 if cutoff < 1: return self.empty_generator() else: return self._mod_all_simple_paths_graph(source, targets, cutoff)
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_multisource(G, iniciales, pesos, pred=None, caminos=None, limite=None, final=None): G_succ = G._succ if G.is_directed() else G._adj push = heappush pop = heappop distancia = {} visitado = {} #Sirve para evitar comparciones dobles entre dos vertices, a causa de un vertice ya visitado c = count() # Tripleta con valores (distancia, c, vertice) valores_x_vertice = [] for vertice_inicial in iniciales: if vertice_inicial not in G: raise nx.NodeNotFound( f"El vertice origen {vertice_inicial}no es parte del grafo") visitado[vertice_inicial] = 0 push(valores_x_vertice, (0, next(c), vertice_inicial)) while valores_x_vertice: (dist, contador, verti) = pop(valores_x_vertice) if verti in distancia: continue distancia[verti] = dist if verti == final: break for u, e in G_succ[verti].items(): cost = pesos(verti, u, e) if cost is None: continue vu_dist = distancia[verti] + cost if limite is not None: if vu_dist > limite: continue if u in distancia: u_dist = distancia[u] if vu_dist < u_dist: raise ValueError("Camino incorrecto:", "pesos negativos invalidos") elif pred is not None and vu_dist == u_dist: pred[u].append(verti) elif u not in visitado or vu_dist < visitado[u]: visitado[u] = vu_dist push(valores_x_vertice, (vu_dist, next(c), u)) if caminos is not None: caminos[u] = caminos[verti] + [u] if pred is not None: pred[u] = [verti] elif vu_dist == visitado[u]: if pred is not None: pred[u].append(verti) return distancia
def single_source_shortest_path(G,source,cutoff=None): """Compute shortest path between source and all other nodes reachable from source. Parameters ---------- G : NetworkX graph source : node label Starting node for path cutoff : integer, optional Depth to stop the search. Only paths of length <= cutoff are returned. Returns ------- lengths : dictionary Dictionary, keyed by target, of shortest paths. Examples -------- >>> G=nx.path_graph(5) >>> path=nx.single_source_shortest_path(G,0) >>> path[4] [0, 1, 2, 3, 4] Notes ----- The shortest path is not necessarily unique. So there can be multiple paths between the source and each target node, all of which have the same 'shortest' length. For each target node, this function returns only one of those paths. See Also -------- shortest_path """ if source not in G: raise nx.NodeNotFound("Source {} not in G".format(source)); level=0 # the current level nextlevel={source:1} # list of nodes to check at next level paths={source:[source]} # paths dictionary (paths to key from source) if cutoff==0: return paths while nextlevel: thislevel=nextlevel nextlevel={} for v in thislevel: for w in G[v]: if w not in paths: paths[w]=paths[v]+[w] nextlevel[w]=1 level=level+1 if (cutoff is not None and cutoff <= level): break return paths
def progressive_widening_search(a: nx.classes.graph.Graph, s: int, v, con: Callable[[int], bool], initial_width: int = 1) -> int: if con(s): return s log_m = math.ceil(math.log2((len(a)))) for i in range(log_m): width = initial_width * pow(2, i) for u, v in nx.bfs_beam_edges(a, s, v, width): if con(v): return v print(nx.NodeNotFound("no node"))
def progressive_widening_search(G, source, value, condition, initial_width=1): if condition(source): return source log_m = math.ceil(math.log2(len(G))) for i in range(log_m): width = initial_width * pow(2, i) for u, v in nx.bfs_beam_edges(G, source, value, width): if condition(v): return v raise nx.NodeNotFound("no node satisfied the termination condition")
def astar_path_length(G, source, target, heuristic=None, weight='weight'): import networkx as nx 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)) path = astar_path(G, source, target, heuristic, weight) return sum(G[u][v].get(weight, 1) for u, v in zip(path[:-1], path[1:]))
def progressive_widening_search(G, source, value, condition, initial_width=1): """Progressive widening beam search to find a node. The progressive widening beam search involves a repeated beam search, starting with a small beam width then extending to progressively larger beam widths if the target node is not found. This implementation simply returns the first node found that matches the termination condition. `G` is a NetworkX graph. `source` is a node in the graph. The search for the node of interest begins here and extends only to those nodes in the (weakly) connected component of this node. `value` is a function that returns a real number indicating how good a potential neighbor node is when deciding which neighbor nodes to enqueue in the breadth-first search. Only the best nodes within the current beam width will be enqueued at each step. `condition` is the termination condition for the search. This is a function that takes a node as input and return a Boolean indicating whether the node is the target. If no node matches the termination condition, this function raises :exc:`NodeNotFound`. `initial_width` is the starting beam width for the beam search (the default is one). If no node matching the `condition` is found with this beam width, the beam search is restarted from the `source` node with a beam width that is twice as large (so the beam width increases exponentially). The search terminates after the beam width exceeds the number of nodes in the graph. """ # Check for the special case in which the source node satisfies the # termination condition. if condition(source): return source # The largest possible value of `i` in this range yields a width at # least the number of nodes in the graph, so the final invocation of # `bfs_beam_edges` is equivalent to a plain old breadth-first # search. Therefore, all nodes will eventually be visited. # # TODO In Python 3.3+, this should be `math.log2(len(G))`. log_m = math.ceil(math.log(len(G), 2)) for i in range(log_m): width = initial_width * pow(2, i) # Since we are always starting from the same source node, this # search may visit the same nodes many times (depending on the # implementation of the `value` function). for u, v in nx.bfs_beam_edges(G, source, value, width): if condition(v): return v # At this point, since all nodes have been visited, we know that # none of the nodes satisfied the termination condition. raise nx.NodeNotFound('no node satisfied the termination condition')
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 dijkstra(G, sources, weight, pred=None, paths=None, cutoff=None, target=None, mode='drive'): G_succ = G._succ if G.is_directed() else G._adj push = heappush pop = heappop dist = {} # dictionary of final distances seen = {} # fringe is heapq with 3-tuples (distance,c,node) # use the count c to avoid comparing nodes (may not be able to) from itertools import count c = count() fringe = [] for source in sources: if source not in G: raise nx.NodeNotFound("Source {} not in G".format(source)) seen[source] = 0 push(fringe, (0, next(c), source)) while fringe: (d, _, v) = pop(fringe) if v in dist: continue # already searched this node. dist[v] = d if v == target: break for u, e in G_succ[v].items(): #pdb.set_trace() if not valid_edge(e[0], mode): continue #import pdb;pdb.set_trace() cost = weight(v, u, e) if cost is None: continue vu_dist = dist[v] + cost if cutoff is not None: if vu_dist > cutoff: continue if u in dist: if vu_dist < dist[u]: raise ValueError('Contradictory paths found:', 'negative weights?') elif u not in seen or vu_dist < seen[u]: seen[u] = vu_dist push(fringe, (vu_dist, next(c), u)) if paths is not None: paths[u] = paths[v] + [u] if pred is not None: pred[u] = [v] elif vu_dist == seen[u]: if pred is not None: pred[u].append(v) # The optional predecessor and path dictionaries can be accessed # by the caller via the pred and paths objects passed as arguments. return dist
def bidirectional_shortest_path(G, source, target): """Returns a list of nodes in a shortest path between source and target. Parameters ---------- G : NetworkX graph source : node label starting node for path target : node label ending node for path Returns ------- path: list List of nodes in a path from source to target. Raises ------ NetworkXNoPath If no path exists between source and target. See Also -------- shortest_path Notes ----- This algorithm is used by shortest_path(G, source, target). """ 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)) # call helper to do the real work results = _bidirectional_pred_succ(G, source, target) pred, succ, w = results # build path from pred+w+succ path = [] # from source to w while w is not None: path.append(w) w = pred[w] path.reverse() # from w to target w = succ[path[-1]] while w is not None: path.append(w) w = succ[w] return path
def all_simple_paths(G,source,target,cutoff): if source not in G: raise nx.NodeNotFound('source node %s not in graph' % source) if target in G: targets = {target} else: try: targets = set(target) except TypeError: raise nx.NodeNotFound('target node %s not in graph' % target) if source in targets: return [] if cutoff is None: cutoff = len(G) - 1 if cutoff < 1: return [] if G.is_multigraph(): return _all_simple_paths_multigraph(G, source, targets, cutoff) else: return None
def probability_dijkstra_multisource(G, sources, weight, pred=None, paths=None, target=None, min_prob=-10**10): """Uses Dijkstra's algorithm to find shortest weighted paths when all values are negative (shortest path is closest to 0) modified from Network X """ G_succ = G._succ if G.is_directed() else G._adj push = heappush pop = heappop dist = {} # dictionary of final distances seen = {} # fringe is heapq with 3-tuples (distance,c,node) # use the count c to avoid comparing nodes (may not be able to) c = count() fringe = [] for source in sources: if source not in G: raise nx.NodeNotFound("Source {} not in G".format(source)) seen[source] = 0 push(fringe, (0, next(c), source)) while fringe: (d, _, v) = pop(fringe) if v in dist: continue # already searched this node. dist[v] = d if v == target: break for u, e in G_succ[v].items(): cost = weight(v, u, e) if cost is None: continue vu_dist = dist[v] + cost if u not in seen or vu_dist > seen[u]: # vu_dist < seen[u]: seen[u] = vu_dist push(fringe, (vu_dist, next(c), u)) if paths is not None: paths[u] = paths[v] + [u] if pred is not None: pred[u] = [v] elif vu_dist == seen[u]: if pred is not None: pred[u].append(v) # The optional predecessor and path dictionaries can be accessed # by the caller via the pred and paths objects passed as arguments. return dist
def _dijkstra_multisource(G, sources, weight, pred=None, paths=None, cutoff=None, target=None): G_succ = G._succ if G.is_directed() else G._adj push = heappush pop = heappop dist = {} # dictionary of final distances seen = {} # fringe is heapq with 3-tuples (distance,c,node) # use the count c to avoid comparing nodes (may not be able to) c = itertools.count() fringe = [] for source in sources: if source not in G: raise nx.NodeNotFound("Source {} not in G".format(source)) seen[source] = 0 push(fringe, (0, next(c), source)) while fringe: (d, _, v) = pop(fringe) if v in dist: continue # already searched this node. dist[v] = d if v == target: break for u, e in G_succ[v].items(): cost = weight(v, u, e) if cost is None: continue vu_dist = dist[v] + cost if cutoff is not None: if vu_dist > cutoff: continue if u in dist: if vu_dist < dist[u]: raise ValueError('Contradictory paths found:', 'negative weights?') elif u not in seen or vu_dist < seen[u]: seen[u] = vu_dist push(fringe, (vu_dist, next(c), u)) if paths is not None: paths[u] = paths[v] + [u] if pred is not None: pred[u] = [v] elif vu_dist == seen[u]: if pred is not None: pred[u].append(v) return dist
def single_source_shortest_path(G, source, cutoff=None): if source not in G: raise nx.NodeNotFound("Source {} not in G".format(source)) def join(p1, p2): return p1 + p2 if cutoff is None: cutoff = float('inf') nextlevel = {source: 1} paths = {source: [source]} return dict(_single_shortest_path(G.adj, nextlevel, paths, cutoff, join))
def single_source_shortest_path_length(G, source, cutoff=None): """Compute the shortest path lengths from source to all reachable nodes. Parameters ---------- G : NetworkX graph source : node Starting node for path cutoff : integer, optional Depth to stop the search. Only paths of length <= cutoff are returned. Returns ------- lengths : iterator (target, shortest path length) iterator Examples -------- >>> G = nx.path_graph(5) >>> length = dict(nx.single_source_shortest_path_length(G, 0)) >>> length[4] 4 >>> for node in [0, 1, 2, 3, 4]: ... print('{}: {}'.format(node, length[node])) 0: 0 1: 1 2: 2 3: 3 4: 4 See Also -------- shortest_path_length """ if source not in G: raise nx.NodeNotFound('Source {} is not in G'.format(source)) seen = {} # level (number of hops) when seen in BFS level = 0 # the current level nextlevel = {source: 1} # dict of nodes to check at next level while nextlevel: thislevel = nextlevel # advance to next level nextlevel = {} # and start a new list (fringe) for v in thislevel: if v not in seen: seen[v] = level # set the level of vertex v nextlevel.update(G[v]) # add neighbors of v yield (v, level) if (cutoff is not None and cutoff <= level): break level = level + 1 del seen
def shortest_path_BFS(G=nx.Graph(), source=None, target=None, depth=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)) level = BFS(G, source, depth) if target not in level: return Path(False) else: for this_level, nodes in level: if target in nodes: return Path(True, this_level)
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 astar_path_length( graph: nx.Graph, source: Node, target: Node, heuristic: Optional[HeuristicFunction] = None, weight: Union[str, WeightFunction] = "weight", ) -> float: """Returns the length of the shortest path between source and target using the A* ("A-star") algorithm. Parameters ---------- graph : NetworkX graph source : node Starting node for path target : node Ending node for path heuristic : function A function to evaluate the estimate of the distance from the a node to the target. The function takes two nodes arguments and must return a number. Raises ------ NetworkXNoPath If no path exists between source and target. See Also -------- astar_path """ if source not in graph or target not in graph: msg = f"Either source {source} or target {target} is not in graph" raise nx.NodeNotFound(msg) weight = _weight_function(graph, weight) path = astar_path(graph, source, target, heuristic, weight) # The weight function looks at the current and the previous edge. # Since, when we visit our first edge, we haven't visited any other edge beforehand. # This is indicated by an edge with the value `None`. path_edges = list(chain([None], list(zip(path[:-1], path[1:])))) # ignoring type: we manually added a node and that node will only be passed in as u, which is valid return sum( weight(graph, u, v) for u, v in zip(path_edges[:-1], path_edges[1:])) # type: ignore
def single_source_paths_filter(G, source, cutoff=None): if source not in G: raise nx.NodeNotFound("Source {} not in G".format(source)) def join(p1, p2): return p1 + p2 if cutoff is None: cutoff = float('inf') nextlevel = {source: 1} # list of nodes to check at next level # paths dictionary (paths to key from source) paths = {source: [source]} return dict( _single_source_paths_filter(G, nextlevel, paths, cutoff, join))
def single_target_shortest_path(G, target, cutoff=None): """Compute shortest path to target from all nodes that reach target. Parameters ---------- G : NetworkX graph target : node label Target node for path cutoff : integer, optional Depth to stop the search. Only paths of length <= cutoff are returned. Returns ------- lengths : dictionary Dictionary, keyed by target, of shortest paths. Examples -------- >>> G = nx.path_graph(5, create_using=nx.DiGraph()) >>> path = nx.single_target_shortest_path(G, 4) >>> path[0] [0, 1, 2, 3, 4] Notes ----- The shortest path is not necessarily unique. So there can be multiple paths between the source and each target node, all of which have the same 'shortest' length. For each target node, this function returns only one of those paths. See Also -------- shortest_path, single_source_shortest_path """ if target not in G: raise nx.NodeNotFound("Target {} not in G".format(target)) def join(p1, p2): return p2 + p1 # handle undirected graphs adj = G.pred if G.is_directed() else G.adj if cutoff is None: cutoff = float('inf') nextlevel = {target: 1} # list of nodes to check at next level paths = {target: [target]} # paths dictionary (paths to key from source) return dict(_single_shortest_path(adj, nextlevel, paths, cutoff, join))
def tarjan(G, root=None, pairs=None): """ LCA for graph G with Tarjan's algorithm tarjan. """ if len(G) == 0: raise nx.NetworkXPointlessConcept("LCA meaningless on null graphs.") elif None in G: raise nx.NetworkXError("None is not a valid node.") # Index pairs of interest for efficient lookup from either side. if pairs is not None: pair_dict = defaultdict(set) # See note on all_pairs_lowest_common_ancestor. if not isinstance(pairs, (Mapping, Set)): pairs = set(pairs) for u, v in pairs: for n in (u, v): if n not in G: msg = "The node %s is not in the digraph." % str(n) raise nx.NodeNotFound(msg) pair_dict[u].add(v) pair_dict[v].add(u) if root is None: for n, deg in G.in_degree: if deg == 0: if root is not None: msg = "No root specified and tree has multiple sources." raise nx.NetworkXError(msg) root = n elif deg > 1: msg = "Tree LCA only defined on trees; use DAG routine." raise nx.NetworkXError(msg) if root is None: raise nx.NetworkXError("Graph contains a cycle.") uf = UnionFind() ancestors = {} for node in G: ancestors[node] = uf[node] colors = defaultdict(bool) for node in nx.dfs_postorder_nodes(G, root): colors[node] = True for v in (pair_dict[node] if pairs is not None else G): if colors[v]: # If the user requested both directions of a pair, give it. # Otherwise, just give one. if pairs is not None and (node, v) in pairs: yield (node, v), ancestors[uf[v]] if pairs is None or (v, node) in pairs: yield (v, node), ancestors[uf[v]] if node != root:
def getSimplePaths(G, source, target, cutoff=None): if source not in G: raise nx.NodeNotFound(f"source node {source} not in graph") if target in G: targets = {target} else: try: targets = set(target) except TypeError as e: raise nx.NodeNotFound(f"target node {target} not in graph") from e if source in targets: return empty_generator() if cutoff is None: cutoff = len(G) - 1 if cutoff < 1: return empty_generator() for simp_path in _all_simple_paths_graph(G, source, targets, cutoff): tag = '' scores = [] for i in range(len(simp_path) - 1): tag += G.edges[simp_path[i], simp_path[i+1]]['aa'] scores.append(round(1 * G.edges[simp_path[i], simp_path[i+1]]['inte'], 2)) yield [tag, round(sum(scores)/sqrt(len(simp_path) - 1), 5), simp_path, scores]
def single_source_shortest_path(G, source, cutoff=None): """Compute shortest path between source and all other nodes reachable from source. Parameters ---------- G : NetworkX graph source : node label Starting node for path cutoff : integer, optional Depth to stop the search. Only paths of length <= cutoff are returned. Returns ------- lengths : dictionary Dictionary, keyed by target, of shortest paths. Examples -------- >>> G = nx.path_graph(5) >>> path = nx.single_source_shortest_path(G, 0) >>> path[4] [0, 1, 2, 3, 4] Notes ----- The shortest path is not necessarily unique. So there can be multiple paths between the source and each target node, all of which have the same 'shortest' length. For each target node, this function returns only one of those paths. See Also -------- shortest_path """ if source not in G: raise nx.NodeNotFound("Source {} not in G".format(source)) def join(p1, p2): return p1 + p2 if cutoff is None: cutoff = float('inf') nextlevel = {source: 1} # list of nodes to check at next level paths = {source: [source]} # paths dictionary (paths to key from source) return dict(_single_shortest_path(G.adj, nextlevel, paths, cutoff, join))