def _print_forest(graph): """ Nice ascii representation of a forest Ignore: graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) _print_forest(graph) graph = CategoryTree.demo('coco').graph _print_forest(graph) """ assert nx.is_forest(graph) encoding = to_directed_nested_tuples(graph) def _recurse(encoding, indent=''): for idx, item in enumerate(encoding): node, data, children = item if idx == len(encoding) - 1: this_prefix = indent + '└── ' next_prefix = indent + ' ' else: this_prefix = indent + '├── ' next_prefix = indent + '│ ' label = graph.nodes[node].get('label', node) print(this_prefix + str(label)) _recurse(children, indent=next_prefix) _recurse(encoding)
def __init__(self, graph=None): """ Args: graph (nx.DiGraph): either the graph representing a category hierarchy """ if graph is None: graph = nx.DiGraph() else: if len(graph) > 0: if not nx.is_directed_acyclic_graph(graph): raise ValueError('The category graph must a DAG') if not nx.is_forest(graph): raise ValueError('The category graph must be a forest') if not isinstance(graph, nx.Graph): raise TypeError( 'Input to CategoryTree must be a networkx graph not {}'. format(type(graph))) self.graph = graph # :type: nx.Graph # Note: nodes are class names self.id_to_node = None self.node_to_id = None self.node_to_idx = None self.idx_to_node = None self.idx_groups = None self._build_index()
def add_edge(self, u, v, *args, **kwargs): changed = False if u == v: if self.flags['strict']: raise ValueError('Edge must be between two unique nodes!') return changed elif self._undirected.has_edge(u, v): self.remove_edges_from([[u, v], [v, u]]) elif len(self.nodes()) > 0: try: path = nx.shortest_path(self._undirected, u, v) if self.flags['strict']: raise ValueError( 'Multiple edge path exists between nodes!') self.disconnect_path(path) changed = True except (nx.NetworkXError, nx.NetworkXNoPath, nx.NetworkXException): pass self._undirected.add_edge(u, v) super(self.__class__, self).add_edge(u, v, *args, **kwargs) if self.flags['assert_forest']: # this is quite slow but makes very sure structure is correct # so is mainly used for testing assert nx.is_forest(nx.Graph(self)) return changed
def run_graph(graph): """ :param graph: :return: """ results = [] if nx.is_forest(graph): while len(leaves(graph)) > 0: current_leaves = leaves(graph) for n in current_leaves: for edge in graph.edges_iter(n): local_data = graph.node[n]['data'].copy() if 'data' not in graph.node[edge[1]]: graph.node[edge[1]]['data'] = apply_edge(local_data, graph.edge[edge[0]][edge[1]]['transformation']).copy() else: graph.node[edge[1]]['data'] = pd.merge( left=graph.node[edge[1]]['data'], right=apply_edge(local_data, graph.edge[edge[0]][edge[1]]['transformation']).copy(), how='left', left_on=graph.node[edge[1]]['match_keys'], right_on=graph.node[edge[1]]['match_keys'] ) if 'producer' in graph.node[n]: if graph.node[n]['producer']: results.append(graph.node[n]['data']) graph.remove_node(n) return results
def _print_forest(graph): """ Nice ascii representation of a forest Ignore: graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) _print_forest(graph) graph = CategoryTree.demo('coco').graph _print_forest(graph) """ if len(graph.nodes) == 0: print('--') return assert nx.is_forest(graph) def _recurse(node, indent='', islast=False): if islast: this_prefix = indent + '└── ' next_prefix = indent + ' ' else: this_prefix = indent + '├── ' next_prefix = indent + '│ ' label = graph.nodes[node].get('label', node) print(this_prefix + str(label)) graph.succ[node] children = graph.succ[node] for idx, child in enumerate(children, start=1): islast_next = (idx == len(children)) _recurse(child, indent=next_prefix, islast=islast_next) sources = [n for n in graph.nodes if graph.in_degree[n] == 0] for idx, node in enumerate(sources, start=1): islast_next = (idx == len(sources)) _recurse(node, indent='', islast=islast_next)
def edge_conditions(t, h, d): yield 0 <= d < N #yield (h, d) not in t.edges() #yield (d, h) not in t.edges() test_t = copy.deepcopy(t) test_t.add_edge(h, d) yield nx.is_forest(test_t)
def add_edge(self, u, v, *args, **kwargs): changed = False if u == v: if self.flags['strict']: raise ValueError('Edge must be between two unique nodes!') return changed if self._undirected.has_edge(u, v): self.remove_edges_from([[u, v], [v, u]]) elif len(self.nodes()) > 0: try: path = nx.shortest_path(self._undirected, u, v) if self.flags['strict']: raise ValueError( 'Multiple edge path exists between nodes!') self.disconnect_path(path) changed = True except (nx.NetworkXError, nx.NetworkXNoPath, nx.NetworkXException): pass self._undirected.add_edge(u, v) super(self.__class__, self).add_edge(u, v, *args, **kwargs) if self.flags['assert_forest']: # this is quite slow but makes very sure structure is correct # so is mainly used for testing assert nx.is_forest(nx.Graph(self)) return changed
def tree_depth(graph, root=None): """ Maximum depth of the forest / tree Example: >>> from kwcoco.category_tree import * >>> graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) >>> tree_depth(graph) 4 >>> tree_depth(nx.balanced_tree(r=2, h=0, create_using=nx.DiGraph)) 1 """ if len(graph) == 0: return 0 if root is not None: assert root in graph.nodes assert nx.is_forest(graph) def _inner(root): if root is None: return max(it.chain([0], (_inner(n) for n in source_nodes(graph)))) else: return max( it.chain([0], (_inner(n) for n in graph.successors(root)))) + 1 depth = _inner(root) return depth
def run_graph(graph): """ :param graph: :return: """ results = [] if nx.is_forest(graph): while len(leaves(graph)) > 0: current_leaves = leaves(graph) for n in current_leaves: for edge in graph.edges_iter(n): local_data = graph.node[n]['data'].copy() if 'data' not in graph.node[edge[1]]: graph.node[edge[1]]['data'] = apply_edge( local_data, graph.edge[edge[0]][edge[1]] ['transformation']).copy() else: graph.node[edge[1]]['data'] = pd.merge( left=graph.node[edge[1]]['data'], right=apply_edge( local_data, graph.edge[edge[0]][edge[1]] ['transformation']).copy(), how='left', left_on=graph.node[edge[1]]['match_keys'], right_on=graph.node[edge[1]]['match_keys']) if 'producer' in graph.node[n]: if graph.node[n]['producer']: results.append(graph.node[n]['data']) graph.remove_node(n) return results
def _validate_graph(self, graph): """Private: Validate a graph is suitable for visualizer.""" if not issubclass(type(graph), ScaffoldGraph): raise ValueError(f'{graph} must be a subclass of ScaffoldGraph') if self._requires_tree: if not nx.is_tree(graph) or nx.is_forest(graph): msg = '{} requires a tree/forest structured graph' msg.format(self.__class__.__name__) raise ValueError(msg) return graph
def tree_or_forest(graph): if nx.is_tree(graph): print( "The Minimum Spanning Tree Generated from this Network is a Tree") elif nx.is_forest(graph): print( "The Minimum Spanning Tree Generated from this Network is a Forest" ) else: print("Neither a Tree nor Forest")
def show_props(graph): print("Nodes: {}, Edges: {}".format(len(graph.nodes), len(graph.edges))) treewidth, decomp = approximation.treewidth_min_degree(graph) print("TreeWidth: {}".format(treewidth)) cluster_ceof = approximation.clustering_coefficient.average_clustering( graph) print("Average Clustering Coefficient: {}".format(cluster_ceof)) print("Is Acyclic: {}".format(nx.is_forest(graph))) node, degree = max([(n, d) for n, d in graph.degree()], key=lambda x: x[1]) print("Max degree: {}".format(degree))
def search_longest_path_efficient(G, weight='weight'): """ Info: Search algorithm to find longest path in a graph. Breadth first search (BFS) used twice for acyclic graphs. BFS over all endnodes used for cyclic graphs input: nx.Graph optional: edge paramater weight -> either 'weight' or 'thick' output: [list] of all paths between all nodes, [list] of length of each path """ def _bfs_tree(G): # twice BFS in undirected acyclic graph (Tree) to find endnodes # bfs for longest path is performed in Directed Tree endnodes = [x for x in G.nodes() if G.degree(x) == 1] DiTree1 = nx.traversal.bfs_tree(G, endnodes[0]) SG1 = G.subgraph(nx.dag_longest_path(DiTree1, weight=weight)) new_root = [ x for x in SG1.nodes() if G.degree(x) == 1 and x != endnodes[0] ][0] DiTree2 = nx.traversal.bfs_tree(SG1, new_root) SG2 = G.subgraph(nx.dag_longest_path(DiTree2, weight=weight)) return SG2, nx.dag_longest_path_length(DiTree2) def _exhaustive(G): # Finds longest shortest path by iterating over all endnodes path_list = [] path_length = [] # node_pairs = [] endnodes = [x for x in G.nodes() if G.degree(x) == 1] for source in endnodes: for target in endnodes: sh_p = nx.shortest_path(G, source, target, weight=weight) sh_p_l = nx.shortest_path_length(G, source, target, weight=weight) path_list.append(sh_p) path_length.append(sh_p_l) # node_pairs.append([source, target]) nbunch = path_list[np.argmax(path_length)] SG = G.subgraph(nbunch) return SG, np.max( path_length) #, nbunch, node_pairs[np.argmax(path_length)] if nx.tree.is_tree(G): #single connected acyclic graph return _bfs_tree(G) else: if nx.is_forest(G): #multiple disconnected trees #todo: loop over connected components (=trees), compare longest branches return _exhaustive(G) else: #cyclic graph return _exhaustive(G)
def freqCount(thread_map): dictionary = corpora.Dictionary.load("gensim_dictionary") maptofreq = dict() for head in sorted(thread_map): assert (nx.is_forest(thread_map[head])) thread_string = "" for node, data in thread_map[head].nodes_iter(data=True): thread_string += " " + data["body"] words_in_thread = re.findall(r"[\w'-]+", thread_string.lower()) word_vector = dictionary.doc2bow(words_in_thread) maptofreq[head] = word_vector return maptofreq
def is_merge_tree(M): acyclic = nx.is_forest(M) connected = nx.is_connected(M) red = reduced(M) print('---') print("M is acyclic: " + str(acyclic)) print("M is connected: " + str(connected)) print("M is reduced: " + str(red)) print('---') return acyclic and connected and red
def tree(self): rslt = {} rslt['is_tree'] = nx.is_tree(self.graph) rslt['is_forest'] = nx.is_forest(self.graph) if self.directed == 'directed': rslt['is_arborescence'] = nx.is_arborescence(self.graph) rslt['is_branching'] = nx.is_branching(self.graph) fname_tree = self.DIR + '/tree.json' with open(fname_tree, "w") as f: json.dump(rslt, f, cls=SetEncoder, indent=2) print(fname_tree)
def attempt(): result = nx.Graph() result.add_nodes_from(range(len(dl_seq) + 1)) for dl, k in dl_counter.items(): possibles = possible_edges_with_dl(result, dl) if not possibles: return None else: possible_sets = itertools.combinations(possibles, k) edge_set = random.choice(list(possible_sets)) result.add_edges_from(edge_set) if not nx.is_forest(result): return None return result
def is_tree(self) -> bool: """Returns whether neuron is a tree. Alsos returns True if neuron consists of multiple separate trees. See also -------- networkx.is_forest() Function used to test whether neuron is a tree. :attr:`TreeNeuron.cycles` If your neuron is not a tree, this will help you identify cycles. """ return nx.is_forest(self.graph)
def number_of_rforest(G, r1, r2): edge_list = G.edges() count = 0 for e in powerset(range(len(edge_list))): H = nx.Graph() H.add_nodes_from(range(len(G.nodes()))) #print H.nodes() for i in e: H.add_edge(*edge_list[i]) #print H.edges() if not nx.has_path(H, r1, r2) and nx.number_connected_components(H) == 2 and nx.is_forest(H): count += 1 #print H.edges() return count
def number_of_rforest(G, r1, r2): edge_list = G.edges() count = 0 for e in powerset(range(len(edge_list))): H = nx.Graph() H.add_nodes_from(range(len(G.nodes()))) #print H.nodes() for i in e: H.add_edge(*edge_list[i]) #print H.edges() if not nx.has_path(H, r1, r2) and nx.number_connected_components( H) == 2 and nx.is_forest(H): count += 1 #print H.edges() return count
def number_of_pathmatching(G): edge_list = G.edges() count = 0 for e in powerset(range(len(edge_list))): H = nx.Graph() H.add_nodes_from(range(len(G.nodes()))) #print H.nodes() for i in e: H.add_edge(*edge_list[i]) #print H.edges() is_pm = True for v in G.nodes(): if nx.degree(H, v) > 2: is_pm = False break if is_pm: if nx.is_forest(H): count += 1 #print H.edges() return count
def two_char_compatibility_test(c1,c2, ancestral_type_known = False, ancestral_type = (0,0)): ''' Takes two columns of equal length (representing characters on a phylogeny), and returns true if and only if they are compatible (in the sense that the number of mutations nessecary to place both characters on a single tree is the sum of the numbr of mutations nessecary to place each character on a tree individually) ''' if len(c1) != len(c2): raise(ValueError('Cannot compare characters of unequal length')) #convert input to list c1_list = list(c1) c2_list = list(c2) if ancestral_type_known: c1_list.append(ancestral_type[0]) c2_list.append(ancestral_type[1]) # G_dict = partition_intersection_graph([c1_list,c2_list]) # G_nx = nx.Graph(G_dict['E']) G_nx = partition_intersection_graph([c1_list,c2_list]) return nx.is_forest(G_nx)
def get_roots(tree: nx.DiGraph, g: nx.DiGraph) -> Iterable[Hashable]: """Iterate through the roots in the tree and any orphaned nodes in the graph :param tree: Hierarchical graph :type tree: nx.DiGraph :param g: [description] :type g: nx.DiGraph :return: [description] :rtype: Hashable :yield: [description] :rtype: Hashable """ if len(tree) == 0: # graph is empty return [] assert nx.is_forest( tree ), "The given hierarchy should be a NetworkX DiGraph that is also a Forest" for node, degree in tree.in_degree(): if degree == 0: yield node for node in g.nodes(): if node not in tree: yield node
def test_is_not_forest(self): assert_false(nx.is_forest(self.N4)) assert_false(nx.is_forest(self.N6)) assert_false(nx.is_forest(self.NF1))
def test_multidigraph_forest(self): assert_false(nx.is_forest(self.N3))
import matplotlib.pyplot as plt import networkx as nx from definition import G if nx.is_forest(G) : print('ffforest') def leaves(graph): return([n for n,d in graph.in_degree().items() if d==0]) while len(leaves(G)) > 0: for n in leaves(G): print(n) G.remove_node(n) # # for n,d in G.in_degree().items(): # print(n) # print(d) # print(nx.all_shortest_paths(G)) # print('ddd {here}'.format(here= G.number_of_nodes())) # nx.draw(G) # plt.show()
def maximum_common_ordered_tree_embedding(tree1, tree2, node_affinity='auto'): """ Finds the maximum common subtree-embedding between two ordered trees. A tree S is an embedded subtree of T if it can be obtained from T by a series of edge contractions. Note this produces a subtree embedding, which is not necessarilly a subgraph isomorphism (although a subgraph isomorphism is also an embedding.) The maximum common embedded subtree problem can be solved in in `O(n1 * n2 * min(d1, l1) * min(d2, l2))` time on ordered trees with n1 and n2 nodes, of depth d1 and d2 and with l1 and l2 leaves, respectively Implements algorithm described in [1]_. References: On the Maximum Common Embedded Subtree Problem for Ordered Trees https://pdfs.semanticscholar.org/0b6e/061af02353f7d9b887f9a378be70be64d165.pdf http://algo.inria.fr/flajolet/Publications/FlSiSt90.pdf Notes: Exact algorithms for computing the tree edit distance between unordered trees - https://pdf.sciencedirectassets.com/271538/1-s2.0-S0304397510X00299/1-s2.0-S0304397510005463/main.pdf ? Tree Edit Distance and Common Subtrees - https://upcommons.upc.edu/bitstream/handle/2117/97554/R02-20.pdf A Survey on Tree Edit Distance and Related Problems - https://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf Args: tree1 (nx.OrderedDiGraph): first ordered tree tree2 (nx.OrderedDiGraph): second ordered tree node_affinity (callable): function Example: >>> from netharn.initializers._nx_extensions import * # NOQA >>> from netharn.initializers._nx_extensions import _lcs, _print_forest >>> def random_ordered_tree(n, seed=None): >>> tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) >>> otree = nx.OrderedDiGraph() >>> otree.add_edges_from(tree.edges) >>> return otree >>> tree1 = random_ordered_tree(10, seed=1) >>> tree2 = random_ordered_tree(10, seed=2) >>> print('tree1') >>> _print_forest(tree1) >>> print('tree2') >>> _print_forest(tree2) >>> embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree1, tree2 ) >>> print('embedding1') >>> _print_forest(embedding1) >>> print('embedding2') >>> _print_forest(embedding2) """ if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree1)): raise nx.NetworkXNotImplemented( 'only implemented for directed ordered trees') if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree2)): raise nx.NetworkXNotImplemented( 'only implemented for directed ordered trees') # Convert the trees to balanced sequences sequence1, open_to_close, toks = tree_to_seq(tree1, open_to_close=None, toks=None) sequence2, open_to_close, toks = tree_to_seq(tree2, open_to_close, toks) seq1 = sequence1 seq2 = sequence2 open_to_tok = ub.invert_dict(toks) # Solve the longest common balanced sequence problem best, value = longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok=open_to_tok, node_affinity=node_affinity) subseq1, subseq2 = best # Convert the subsequence back into a tree embedding1 = seq_to_tree(subseq1, open_to_close, toks) embedding2 = seq_to_tree(subseq2, open_to_close, toks) return embedding1, embedding2
def maximum_common_ordered_subtree_isomorphism(tree1, tree2, node_affinity='auto'): """ Isomorphic version of `maximum_common_ordered_tree_embedding`. CommandLine: xdoctest -m /home/joncrall/code/netharn/netharn/initializers/_nx_extensions.py maximum_common_ordered_subtree_isomorphism:1 --profile && cat profile_output.txt Example: >>> from netharn.initializers._nx_extensions import * # NOQA >>> from netharn.initializers._nx_extensions import _lcs, _print_forest >>> def random_ordered_tree(n, seed=None): >>> tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) >>> otree = nx.OrderedDiGraph() >>> otree.add_edges_from(tree.edges) >>> return otree >>> tree1 = random_ordered_tree(10, seed=3) >>> tree2 = random_ordered_tree(10, seed=2) >>> tree1.add_edges_from(tree2.edges, weight=1) >>> tree1 = nx.minimum_spanning_arborescence(tree1) >>> tree2.add_edges_from(tree1.edges, weight=1) >>> tree2 = nx.minimum_spanning_arborescence(tree2) >>> tree1.remove_edge(4, 7) >>> tree1.remove_edge(4, 9) >>> tree1.add_edge(4, 10) >>> tree1.add_edge(10, 7) >>> tree1.add_edge(10, 9) >>> #tree1.add_edges_from([(9, 11), (11, 12), (12, 13), (13, 14)]) >>> #tree2.add_edges_from([(9, 11), (11, 12), (12, 13), (13, 14)]) >>> tree1.add_edges_from([(9, 11), (11, 12)]) >>> tree2.add_edges_from([(9, 11), (11, 12)]) >>> tree2.add_edge(100, 0) >>> tree1.add_edge(102, 100) >>> tree1.add_edge(100, 101) >>> tree1.add_edge(101, 0) >>> tree1.add_edge(5, 201) >>> tree1.add_edge(5, 202) >>> tree1.add_edge(5, 203) >>> tree1.add_edge(201, 2000) >>> tree1.add_edge(2000, 2001) >>> tree1.add_edge(2001, 2002) >>> tree1.add_edge(2002, 2003) >>> tree2.add_edge(5, 202) >>> tree2.add_edge(5, 203) >>> tree2.add_edge(5, 201) >>> tree2.add_edge(201, 2000) >>> tree2.add_edge(2000, 2001) >>> tree2.add_edge(2001, 2002) >>> tree2.add_edge(2002, 2003) >>> print('-----') >>> print('tree1') >>> _print_forest(tree1) >>> print('tree2') >>> _print_forest(tree2) >>> subtree1, subtree2 = maximum_common_ordered_subtree_isomorphism(tree1, tree2 ) >>> print('-----') >>> print('subtree1') >>> _print_forest(subtree1) >>> print('subtree2') >>> _print_forest(subtree2) >>> embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree1, tree2) >>> print('-----') >>> print('embedding1') >>> _print_forest(embedding1) >>> print('embedding2') >>> _print_forest(embedding2) >>> if 0: >>> ti = timerit.Timerit(6, bestof=2, verbose=2) >>> for timer in ti.reset('isomorphism'): >>> with timer: >>> maximum_common_ordered_subtree_isomorphism(tree1, tree2 ) >>> for timer in ti.reset('embedding'): >>> with timer: >>> maximum_common_ordered_tree_embedding(tree1, tree2 ) >>> from networkx import isomorphism >>> assert isomorphism.DiGraphMatcher(tree1, subtree1).subgraph_is_isomorphic() >>> assert isomorphism.DiGraphMatcher(tree2, subtree2).subgraph_is_isomorphic() >>> list(isomorphism.DiGraphMatcher(tree1, tree2).subgraph_isomorphisms_iter()) >>> list(isomorphism.DiGraphMatcher(tree1, tree2).subgraph_monomorphisms_iter()) >>> list(isomorphism.DiGraphMatcher(subtree1, subtree2).subgraph_isomorphisms_iter()) >>> list(isomorphism.DiGraphMatcher(tree1, subtree1).subgraph_isomorphisms_iter()) >>> list(isomorphism.DiGraphMatcher(tree2, subtree2).subgraph_isomorphisms_iter()) Example: >>> from netharn.initializers._nx_extensions import * # NOQA >>> from netharn.initializers._nx_extensions import _lcs, _print_forest >>> def random_ordered_tree(n, seed=None): >>> if n > 0: >>> tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) >>> otree = nx.OrderedDiGraph() >>> if n > 0: >>> otree.add_edges_from(tree.edges) >>> return otree >>> import random >>> rng = random.Random(90269698983701724775426457020022) >>> num = 1000 >>> def _gen_seeds(num): >>> for _ in range(num): >>> yield (rng.randint(0, 50), rng.randint(0, 50), rng.randint(0, 2 ** 64), rng.randint(0, 2 ** 64)) >>> for n1, n2, s1, s2 in ub.ProgIter(_gen_seeds(num=num), total=num, verbose=3): >>> tree1 = random_ordered_tree(n1, seed=s1) >>> tree2 = random_ordered_tree(n2, seed=s2) >>> #print('-----') >>> #print('tree1') >>> #_print_forest(tree1) >>> #print('tree2') >>> #_print_forest(tree2) >>> subtree1, subtree2 = maximum_common_ordered_subtree_isomorphism(tree1, tree2, node_affinity='auto') >>> #print('-----') >>> #print('subtree1') >>> #_print_forest(subtree1) >>> #print('subtree2') >>> #_print_forest(subtree2) >>> from networkx import isomorphism >>> assert isomorphism.DiGraphMatcher(tree1, subtree1).subgraph_is_isomorphic() >>> assert isomorphism.DiGraphMatcher(tree2, subtree2).subgraph_is_isomorphic() """ try: if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree1)): raise nx.NetworkXNotImplemented( 'only implemented for directed ordered trees') if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree2)): raise nx.NetworkXNotImplemented( 'only implemented for directed ordered trees') except nx.NetworkXPointlessConcept: subtree1 = nx.OrderedDiGraph() subtree2 = nx.OrderedDiGraph() return subtree1, subtree2 # Convert the trees to balanced sequences sequence1, open_to_close, toks = tree_to_seq(tree1, open_to_close=None, toks=None, mode='chr') sequence2, open_to_close, toks = tree_to_seq(tree2, open_to_close, toks, mode='chr') seq1 = sequence1 seq2 = sequence2 open_to_tok = ub.invert_dict(toks) # Solve the longest common balanced sequence problem best, value = longest_common_isomorphic_sequence( seq1, seq2, open_to_close, open_to_tok=open_to_tok, node_affinity=node_affinity) subseq1, subseq2 = best # Convert the subsequence back into a tree subtree1 = seq_to_tree(subseq1, open_to_close, toks) subtree2 = seq_to_tree(subseq2, open_to_close, toks) return subtree1, subtree2
def forest_str(graph, with_labels=True, sources=None, write=None): """ Creates a nice utf8 representation of a directed forest Parameters ---------- graph : nx.DiGraph | nx.Graph Graph to represent (must be a tree, forest, or the empty graph) with_labels : bool If True will use the "label" attribute of a node to display if it exists otherwise it will use the node value itself. Defaults to True. sources : List Mainly relevant for undirected forests, specifies which nodes to list first. If unspecified the root nodes of each tree will be used for directed forests; for undirected forests this defaults to the nodes with the smallest degree. write : callable Function to use to write to, if None new lines are appended to a list and returned. If set to the `print` function, lines will be written to stdout as they are generated. If specified, this function will return None. Defaults to None. Returns ------- str | None : utf8 representation of the tree / forest Example ------- >>> import networkx as nx >>> graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) >>> print(forest_str(graph)) ╙── 0 ├─╼ 1 │ ├─╼ 3 │ │ ├─╼ 7 │ │ └─╼ 8 │ └─╼ 4 │ ├─╼ 9 │ └─╼ 10 └─╼ 2 ├─╼ 5 │ ├─╼ 11 │ └─╼ 12 └─╼ 6 ├─╼ 13 └─╼ 14 >>> graph = nx.balanced_tree(r=1, h=2, create_using=nx.Graph) >>> print(forest_str(graph)) ╙── 0 └── 1 └── 2 """ import networkx as nx printbuf = [] if write is None: _write = printbuf.append else: _write = write if len(graph.nodes) == 0: _write("╙") else: if not nx.is_forest(graph): raise nx.NetworkXNotImplemented( "input must be a forest or the empty graph") is_directed = graph.is_directed() succ = graph.succ if is_directed else graph.adj if sources is None: if is_directed: # use real source nodes for directed trees sources = [n for n in graph.nodes if graph.in_degree[n] == 0] else: # use arbitrary sources for undirected trees sources = [ min(cc, key=lambda n: graph.degree[n]) for cc in nx.connected_components(graph) ] # Populate the stack with each source node, empty indentation, and mark # the final node. Reverse the stack so sources are popped in the # correct order. last_idx = len(sources) - 1 stack = [(node, "", (idx == last_idx)) for idx, node in enumerate(sources)][::-1] seen = set() while stack: node, indent, islast = stack.pop() if node in seen: continue seen.add(node) # Notes on available box and arrow characters # https://en.wikipedia.org/wiki/Box-drawing_character # https://stackoverflow.com/questions/2701192/triangle-arrow if not indent: # Top level items (i.e. trees in the forest) get different # glyphs to indicate they are not actually connected if islast: this_prefix = indent + "╙── " next_prefix = indent + " " else: this_prefix = indent + "╟── " next_prefix = indent + "╎ " else: # For individual forests distinguish between directed and # undirected cases if is_directed: if islast: this_prefix = indent + "└─╼ " next_prefix = indent + " " else: this_prefix = indent + "├─╼ " next_prefix = indent + "│ " else: if islast: this_prefix = indent + "└── " next_prefix = indent + " " else: this_prefix = indent + "├── " next_prefix = indent + "│ " if with_labels: label = graph.nodes[node].get("label", node) else: label = node _write(this_prefix + str(label)) # Push children on the stack in reverse order so they are popped in # the original order. children = [child for child in succ[node] if child not in seen] for idx, child in enumerate(children[::-1], start=1): islast_next = idx <= 1 try_frame = (child, next_prefix, islast_next) stack.append(try_frame) if write is None: # Only return a string if the custom write function was not specified return "\n".join(printbuf)
def test_is_not_forest(self): assert not nx.is_forest(self.N4) assert not nx.is_forest(self.N6) assert not nx.is_forest(self.NF1)
def test_is_forest(self): assert nx.is_forest(self.T2) assert nx.is_forest(self.T3) assert nx.is_forest(self.T5) assert nx.is_forest(self.F1) assert nx.is_forest(self.N5)
def test_null_forest2(self): with pytest.raises(nx.NetworkXPointlessConcept): nx.is_forest(self.multigraph())
m = 3 import networkx as nx trees = [] G = nx.grid_graph([m, m]) n = len(G.nodes()) sorted_edges = list(G.edges()) for i in range(5000): edge_list = [] T = nx.Graph() random.shuffle(sorted_edges) i = 0 while len(T.edges()) < n - 1: e = sorted_edges[i] T.add_edges_from([e]) if nx.is_forest(T) == False: T.remove_edges_from([e]) i += 1 trees.append(T) partitions = [] for tree in trees: for e in tree.edges(): partitions.append(R(G, tree, e)) print("now making histogram") histogram = make_histogram(list_of_partitions, partitions) total_variation = 0 for k in histogram.keys(): total_variation += np.abs(histogram[k] - 1 / len(list_of_partitions)) print(total_variation)
def test_is_forest(self): assert_true(nx.is_forest(self.T2)) assert_true(nx.is_forest(self.T3)) assert_true(nx.is_forest(self.T5)) assert_true(nx.is_forest(self.F1)) assert_true(nx.is_forest(self.N5))
def test_null_forest(self): nx.is_forest(self.graph()) nx.is_forest(self.multigraph())
# Part A: Analysis of Connected Components print("The Amount of Connected Components: ", nx.number_connected_components(ug)) ccs = [ len(c) for c in sorted(nx.connected_components(ug), key=len, reverse=True) ] print("Largest Connected Component: ", ccs[0]) print("Smallest Connected Component: ", ccs[-1]) # Part E: Euler Network print("Is subnetwork 1 Eularian? ", nx.is_eulerian(separate1)) print("Is subnetwork 2 Eularian? ", nx.is_eulerian(separate2)) # Part H: Minimum Spanning tree of network (ug) and largest CC (separate1) a = nx.minimum_spanning_tree(ug) print("Is tree?", nx.is_tree(a)) print("Is forest?", nx.is_forest(a)) separate1.remove_edge(3, 11) b = nx.minimum_spanning_tree(separate1) print("Removed edge from largest CC") print("Is tree?", nx.is_tree(b)) print("Is forest?", nx.is_forest(b)) flName = 'moreno_highschool\README.moreno_highschool' f = open(flName, 'r') lines = f.readlines() print('###################################################################') print('############### Directed weighted network: README #################') print('###################################################################') ## Reading the data flName = 'moreno_highschool\out.moreno_highschool_highschool'
def test_digraph_forest(self): assert_false(nx.is_forest(self.N1))