%PDF- %PDF-
Direktori : /lib/python3/dist-packages/pythran/ |
Current File : //lib/python3/dist-packages/pythran/graph.py |
''' Minimal directed graph replacement for networkx.DiGraph This has the sole advantage of being a standalone file that doesn't bring any dependency with it. ''' class DiGraph(object): def __init__(self): # adjacency[i][j] = True means j is a successor of i self._adjacency = {} self._edges = {} def successors(self, node): return (n for n in self._adjacency[node]) def predecessors(self, node): return (k for k, v in self._adjacency.items() if node in v) def add_node(self, node): self._adjacency.setdefault(node, set()) def add_edge(self, src, dest, **props): self.add_node(dest) self._adjacency.setdefault(src, set()).add(dest) self._edges[(src, dest)] = props @property def edges(self): return self._edges def remove_edge(self, src, dest): self._adjacency[src].remove(dest) del self._edges[(src, dest)] def __len__(self): return len(self._adjacency) def __iter__(self): return iter(self._adjacency.keys()) def __contains__(self, value): return value in self._adjacency def __getitem__(self, node): return self._adjacency[node] class Unfeasible(RuntimeError): pass def has_path(graph, src, dest): visited = set() worklist = [src] while worklist: current = worklist.pop() if current in visited: continue visited.add(current) if dest in graph.successors(current): return True worklist.extend(graph.successors(current)) return False # Copied verbatim from NetworkX 2.6.1 # # NetworkX is distributed with the 3-clause BSD license. # # :: # # Copyright (C) 2004-2021, NetworkX Developers # Aric Hagberg <hagberg@lanl.gov> # Dan Schult <dschult@colgate.edu> # Pieter Swart <swart@lanl.gov> # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # # * Neither the name of the NetworkX Developers nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. def _all_simple_paths_graph(G, source, targets, cutoff): visited = dict.fromkeys([source]) stack = [iter(G[source])] while stack: children = stack[-1] child = next(children, None) if child is None: stack.pop() visited.popitem() elif len(visited) < cutoff: if child in visited: continue if child in targets: yield list(visited) + [child] visited[child] = None if targets - set(visited.keys()): # expand stack until find all targets stack.append(iter(G[child])) else: visited.popitem() # maybe other ways to child else: # len(visited) == cutoff: for target in (targets & (set(children) | {child})) - set(visited.keys()): yield list(visited) + [target] stack.pop() visited.popitem() def all_simple_paths(graph, src, target): return _all_simple_paths_graph(graph, src, {target}, len(graph) - 1)