def subnet_tree(self, subnets=None): """Get a hierarchy tree of non-trivial subnets In this tree root is the current Pnet itself And one subnet is the child of another if child subnet is fully contained in parent subnet Tree has an additional labels on nodes and egdes For nodes, label 'inner' contains tuple with keys of edges from starting node of the subnet, that are a part of this subnet (some start node's outgoing edges may be not a part of the subnet) For edges, label 'keys' contains tuple with keys of edges from start of the parent subnet, that lead to the start node of child subnet (or childs' 'inner' label, if child and parent start from the same node) Parameters ---------- subnets : container of (int,int), optional list or other container with all non-trivial subnets of current Pnet if not given, it will be calculated automatically Returns ------- tree : networkx.DiGraph Subnet hierarchy tree with additional labels See Also -------- subnets, envelope_subnet """ subnets = subnets if subnets is not None else self.subnets() tree = nx.DiGraph() for subnet in subnets: subnet_start, subnet_end = subnet envelope_subnet = self.envelope_subnet(subnet, subnets=subnets) inner_paths = nx.all_simple_edge_paths(self, subnet_start, subnet_end) inner_keys = tuple(set(k for (_, _, k), *_ in inner_paths)) if envelope_subnet is None: tree.add_node(subnet, inner=inner_keys) else: envelop_start = envelope_subnet[0] if subnet_start == envelop_start: paths = nx.all_simple_edge_paths(self, envelop_start, subnet_end) else: paths = nx.all_simple_edge_paths(self, envelop_start, subnet_start) keys = tuple(set(k for (_, _, k), *_ in paths)) tree.add_node(subnet, inner=inner_keys) tree.add_edge(envelope_subnet, subnet, keys=keys) return tree
def test_all_simple_edge_paths_cutoff(): G = nx.complete_graph(4) paths = nx.all_simple_edge_paths(G, 0, 1, cutoff=1) assert {tuple(p) for p in paths} == {((0, 1), )} paths = nx.all_simple_edge_paths(G, 0, 1, cutoff=2) assert {tuple(p) for p in paths} == {((0, 1), ), ((0, 2), (2, 1)), ((0, 3), (3, 1))}
def test_all_simple_edge_paths_on_non_trivial_graph(): """ you may need to draw this graph to make sure it is reasonable """ G = nx.path_graph(5, create_using=nx.DiGraph()) G.add_edges_from([(0, 5), (1, 5), (1, 3), (5, 4), (4, 2), (4, 3)]) paths = nx.all_simple_edge_paths(G, 1, [2, 3]) assert {tuple(p) for p in paths} == { ((1, 2), ), ((1, 3), (3, 4), (4, 2)), ((1, 5), (5, 4), (4, 2)), ((1, 3), ), ((1, 2), (2, 3)), ((1, 5), (5, 4), (4, 3)), ((1, 5), (5, 4), (4, 2), (2, 3)), } paths = nx.all_simple_edge_paths(G, 1, [2, 3], cutoff=3) assert {tuple(p) for p in paths} == { ((1, 2), ), ((1, 3), (3, 4), (4, 2)), ((1, 5), (5, 4), (4, 2)), ((1, 3), ), ((1, 2), (2, 3)), ((1, 5), (5, 4), (4, 3)), } paths = nx.all_simple_edge_paths(G, 1, [2, 3], cutoff=2) assert {tuple(p) for p in paths} == {((1, 2), ), ((1, 3), ), ((1, 2), (2, 3))}
def all_routes(): for start, end in itertools.combinations(G.nodes(), 2): for path in nx.all_simple_edge_paths(G, start, end): if len(path) == len(G.nodes()) - 1: yield path for path in nx.all_simple_edge_paths(G, end, start): if len(path) == len(G.nodes()) - 1: yield path
def test_all_simple_edge_paths_multigraph(): G = nx.MultiGraph([(1, 2), (1, 2)]) paths = nx.all_simple_edge_paths(G, 1, 1) assert list(paths) == [] nx.add_path(G, [3, 1, 10, 2]) paths = list(nx.all_simple_edge_paths(G, 1, 2)) assert len(paths) == 3 assert {tuple(p) for p in paths} == { ((1, 2, 0),), ((1, 2, 1),), ((1, 10, 0), (10, 2, 0)) }
def test_all_simple_edge_paths_with_two_targets_emits_two_paths(): G = nx.path_graph(4) G.add_edge(2, 4) paths = nx.all_simple_edge_paths(G, 0, [3, 4]) assert {tuple(p) for p in paths} == { ((0, 1), (1, 2), (2, 3)), ((0, 1), (1, 2), (2, 4)) }
def sents(self, start=None, end=None, maxlen=None): """Generate sentences from paths between start and end nodes Parameters ---------- start : int, default self.start node to start sentence from end : int, default self.end node where the sentence ends maxlen : int, default None maximum length (in the number of keys) of sentences to return, unlimited if equals to None Yields ------- sent: list of str sentence as list of edges labels/keys See Also -------- add_sents """ start = start if start is not None else self.start end = end if end is not None else self.end paths = nx.all_simple_edge_paths(self, start, end, cutoff=maxlen) for path in paths: sent = [] for _, _, word in path: sent += word yield sent
def length(self, start=None, end=None): start = start if start is not None else self.start end = end if end is not None else self.end return len( max(list(nx.all_simple_edge_paths(self, start, end)), key=len, default=[]))
def test_series_diagram_construction(): head_block = DirectFormI.from_model( signal.dlti(1, [1, 1, 0.5])) tail_block = DirectFormI.from_model( signal.dlti(2, [1, -0.5])) x, y = sympy.symbols('x y') diagram = series_diagram([ head_block, tail_block ], input_=x, output=y) paths = list(nx.all_simple_edge_paths( diagram, source=x, target=y)) assert len(paths) == 1 path = paths[0] assert len(path) == 2 u, v, i = path[0] assert u is x assert i == 0 assert diagram[u][v][i]['block'] is head_block w, z, i = path[1] assert v is w assert z is y assert i == 0 assert diagram[w][z][i]['block'] is tail_block
def test_digraph_all_simple_edge_paths_with_two_targets_cutoff(): G = nx.path_graph(4, create_using=nx.DiGraph()) G.add_edge(2, 4) paths = nx.all_simple_edge_paths(G, 0, [3, 4], cutoff=3) assert {tuple(p) for p in paths} == { ((0, 1), (1, 2), (2, 3)), ((0, 1), (1, 2), (2, 4)) }
def hamiltonian_edge_path(G, source): source = arbitrary_element(G) neighbors = set(G[source]) - {source} n = len(G) for target in neighbors: for path in nx.all_simple_edge_paths(G, source, target): if len(path) == n - 1: yield path
def check_explicit_flow(rda_graph, source, target): paths = nx.all_simple_edge_paths(rda_graph, source=source, target=target) for path in paths: valid = True for edge in path: if rda_graph.get_edge_data(edge[0],edge[1])['type'] == 1: valid = False break if valid: return path return None
def get_causal_paths(self, as_edge_list: bool = False) -> List[List[Tuple]]: if self.treatment is None or self.outcome is None: return [] if as_edge_list: paths = nx.all_simple_edge_paths(self._graph, self.treatment, self.outcome) else: paths = nx.all_simple_paths(self._graph, self.treatment, self.outcome) return list(paths)
def getAllPaths(self, terminalNodes): paths = [] for t in terminalNodes: for p in nx.all_simple_edge_paths( self.dot, source=self.root, target=t): #get all paths to that termIndice newPath = [] for edge in range(len(p)): #iterate through edges node0 = p[edge][0] node1 = p[edge][1] if edge + 1 == len(p): #last edge pair lbl = self.dot.nodes[node0]['label'].split('\\n') var0 = lbl[0] lbl2 = self.dot.nodes[node1]['label'].split('\\n') cls = lbl2[-1].replace("class = ", "") cls = cls.replace("\"", "") relop, param = self.dot.get_edge_data( node0, node1)['label'].split(" ") op = '==>' newPath.append(var0) newPath.append(relop) newPath.append(param) newPath.append(op) newPath.append(cls) else: lbl = self.dot.nodes[node0]['label'].split('\\n') var0 = lbl[0] relop, param = self.dot.get_edge_data( node0, node1)['label'].split(" ") if self.dot.get_edge_data(node0, node1)['style'] == 'solid': op = 'AND' else: op = 'OR' newPath.append(var0) newPath.append(relop) newPath.append(param) newPath.append(op) paths.append(newPath) return paths
def get_row_indices(self, table: LinkedTable, source_node: Union[int, str], target_node: Union[int, str], links: Tuple[str, str]): assert isinstance(source_node, int) or isinstance( target_node, int), "Can only get row index for at least one column" if isinstance(source_node, str): if table.context.page_qnode == source_node: # TODO: get context node id, is there any better way to do it? source_id = f"ent:{source_node}" else: source_id = f"ent:{source_node}" else: source_id = f"column-{source_node}" if isinstance(target_node, str): # TODO: fix me after we fix the data graph if table.context.page_qnode == target_node: # TODO: get context node id, is there any better way to do it? target_id = f"ent:{target_node}" else: target_id = f"ent:{target_node}" else: target_id = f"column-{target_node}" dg, sg = self.table2g[table.id] rows = set() for paths in nx.all_simple_edge_paths(sg, source_id, target_id, cutoff=2): assert len(paths) == 2 uid, sid, eid = paths[0] _, vid, peid = paths[1] if not (eid == links[0] and peid == links[1]): continue stmt: SGStatementNode = sg.nodes[sid]['data'] for (source_flow, target_flow), stmt2prov in stmt.flow.items(): if target_flow.sg_target_id == vid and target_flow.edge_id == peid: dv = dg.nodes[target_flow.dg_target_id]['data'] if dv.is_cell: rows.add(dv.row) else: du = dg.nodes[source_flow.dg_source_id]['data'] assert du.is_cell rows.add(du.row) return rows
def compounds(self) -> List[str]: """ For this example, we define compounds as linear sub-graphs (paths) of any length. """ if hasattr(self, "_compounds"): return self._compounds else: self._compounds = [] for a1, a2 in product(self.atoms, self.atoms): new_compounds = [SETCompound(self.G.edge_subgraph(p), self.G, self.id) for p in list(nx.all_simple_edge_paths( self.G, source=a1, target=a2)) if p] self._compounds += new_compounds # otherwise we will double count subgraphs self._compounds = set(self._compounds) for c in self._compounds: self.compounds_by_type[str(c)].append(c) return self._compounds
def _getShortestPathInMultigraph(G, Source, Target): edges = [] if not (G.has_node(Source) and G.has_node(Target)): return edges try: # pathLength = nx.shortest_path_length(G, Source, Target) Node_path = nx.shortest_path(G, Source, Target) if len(Node_path) == 0: return edges for index in range(len(Node_path) - 1): edge_path = nx.all_simple_edge_paths(G, Node_path[index], Node_path[index + 1], 1) edges.append(next(edge_path)[0]) # all_edge_paths = nx.all_simple_edge_paths(G, Source, Target, pathLength) # edges = next(all_edge_paths) except: edges = [] return edges
def tree_to_leaf_row_values( tree: nx.DiGraph, row_value_fn: Callable, default_row_values: Dict[str, Number]) -> Dict[str, Dict[str, Number]]: """ Return, for list of leaf nodes, a dictionary mapping column name to value to generate. Note: not implemented for recurring instances of the same feature along a single path to a leaf. """ leaf_row_values = {} # Get root name root_name = [n for (n, d) in tree.in_degree() if d == 0][0] # Get criteria for each leaf for node in tree: if tree.out_degree(node) == 0: # leaf node criteria = {} for path in next( nx.all_simple_edge_paths(tree, root_name, node) ): # only one path, so calling next() once gets it (math.stackexchange.com/a/1523566/440173) criteria[path[0]] = tree.edges[path]["criterion"] # Translate criteria to row value dict leaf_row_values[node] = row_value_fn(criteria, default_row_values) return leaf_row_values
def _subnet_to_rule(net, subnet, subnet_tree, non_terms): sub_children = list(subnet_tree.successors(subnet)) s_to_e = {} for s, e in sub_children: if s not in s_to_e: s_to_e[s] = [e] else: s_to_e[s].append(e) paths = nx.all_simple_edge_paths(net, subnet[0], subnet[1]) res = set() for path in paths: subnet_s = None variant = '' for s, e, k in path: if subnet_s is not None and s in s_to_e[subnet_s]: variant += ' ' + non_terms[(subnet_s, s)] subnet_s = None if s in s_to_e: subnet_s = s if subnet_s is not None: continue variant += ' ' + f"'{k}'" # if child subnet ends on the same node as parent if subnet_s is not None: variant += ' ' + non_terms[(subnet_s, subnet[1])] res.add(variant) rule = non_terms[subnet] + ' ->' + ' |'.join(res) return rule
def _schema_fields_from_dag( graph: nx.DiGraph, is_key_schema: bool ) -> List[SchemaField]: generations: List = list(nx.algorithms.dag.topological_generations(graph)) fields: Dict = {} if generations and generations[0]: roots = generations[0] leafs: List = [] for node in graph: if graph.out_degree(node) == 0: leafs.append(node) type_of_nodes: Dict = nx.get_node_attributes(graph, "node_type") for root in roots: root_type = type_of_nodes[root] for leaf in leafs: paths = list(nx.all_simple_edge_paths(graph, root, leaf)) if paths: for path in paths: stack: List[str] = ["[version=2.0]"] if is_key_schema: stack.append("[key=True]") stack.append(root_type) if len(roots) > 1: stack.append(re.sub(r"^.*\.", "", root)) root_path = ".".join(stack) fields[root_path] = SchemaField( fieldPath=root_path, nativeDataType="message", type=SchemaFieldDataType(type=RecordTypeClass()), ) for field in _traverse_path(graph, path, stack): fields[field.path] = field.field return sorted(fields.values(), key=lambda sf: sf.fieldPath)
def test_all_simple_edge_paths(): G = nx.path_graph(4) paths = nx.all_simple_edge_paths(G, 0, 3) assert {tuple(p) for p in paths} == {((0, 1), (1, 2), (2, 3))}
def test_edge_target_missing(): with pytest.raises(nx.NodeNotFound): G = nx.Graph() nx.add_path(G, [1, 2, 3]) list(nx.all_simple_edge_paths(nx.MultiGraph(G), 1, 4))
def test_all_simple_edge_paths_ignores_cycle(): G = nx.cycle_graph(3, create_using=nx.DiGraph()) G.add_edge(1, 3) paths = nx.all_simple_edge_paths(G, 0, 3) assert {tuple(p) for p in paths} == {((0, 1), (1, 3))}
def test_all_simple_edge_paths_with_two_targets_inside_cycle_emits_two_paths(): G = nx.cycle_graph(3, create_using=nx.DiGraph()) G.add_edge(1, 3) paths = nx.all_simple_edge_paths(G, 0, [2, 3]) assert {tuple(p) for p in paths} == {((0, 1), (1, 2)), ((0, 1), (1, 3))}
def test_edge_cutoff_zero(): G = nx.complete_graph(4) paths = nx.all_simple_edge_paths(G, 0, 3, cutoff=0) assert list(list(p) for p in paths) == [] paths = nx.all_simple_edge_paths(nx.MultiGraph(G), 0, 3, cutoff=0) assert list(list(p) for p in paths) == []
def test_all_simple_edge_paths_corner_cases(): assert list(nx.all_simple_edge_paths(nx.empty_graph(2), 0, 0)) == [] assert list(nx.all_simple_edge_paths(nx.empty_graph(2), 0, 1)) == [] assert list(nx.all_simple_edge_paths(nx.path_graph(9), 0, 8, 0)) == []
def test_all_simple_edge_paths_empty(): G = nx.path_graph(4) paths = nx.all_simple_edge_paths(G, 0, 3, cutoff=2) assert list(paths) == []
def test_all_simple_edge_paths_directed(): G = nx.DiGraph() nx.add_path(G, [1, 2, 3]) nx.add_path(G, [3, 2, 1]) paths = nx.all_simple_edge_paths(G, 1, 3) assert {tuple(p) for p in paths} == {((1, 2), (2, 3))}
def test_all_simple_edge_paths_multigraph_with_cutoff(): G = nx.MultiGraph([(1, 2), (1, 2), (1, 10), (10, 2)]) paths = list(nx.all_simple_edge_paths(G, 1, 2, cutoff=1)) assert len(paths) == 2 assert {tuple(p) for p in paths} == {((1, 2, 0), ), ((1, 2, 1), )}
def test_all_simple_edge_paths_source_target(): G = nx.path_graph(4) paths = nx.all_simple_edge_paths(G, 1, 1) assert list(paths) == []