Exemple #1
0
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:]))
Exemple #2
0
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))
Exemple #3
0
 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
Exemple #4
0
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:]))
Exemple #5
0
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
Exemple #6
0
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))
Exemple #7
0
 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)
Exemple #8
0
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
Exemple #10
0
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
Exemple #11
0
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"))
Exemple #12
0
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")
Exemple #13
0
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')
Exemple #15
0
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))
Exemple #16
0
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
Exemple #17
0
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
Exemple #18
0
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
Exemple #19
0
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
Exemple #21
0
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))
Exemple #22
0
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
Exemple #23
0
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)
Exemple #24
0
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}")
Exemple #25
0
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
Exemple #26
0
        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))
Exemple #27
0
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))
Exemple #28
0
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:
Exemple #29
0
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]
Exemple #30
0
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))