@@ -257,7 +257,13 @@ def breadth_first(tree, children=iter, maxdepth=-1):
257257
258258
259259def edge_closure (tree , children = iter , maxdepth = - 1 , verbose = False ):
260- """Yield the edges of a graph in breadth-first order,
260+ """
261+ :param tree: the tree root
262+ :param children: a function taking as argument a tree node
263+ :param maxdepth: to limit the search depth
264+ :param verbose: to print warnings when cycles are discarded
265+
266+ Yield the edges of a graph in breadth-first order,
261267 discarding eventual cycles.
262268 The first argument should be the start node;
263269 children should be a function taking as argument a graph node
@@ -295,13 +301,13 @@ def edge_closure(tree, children=iter, maxdepth=-1, verbose=False):
295301def edges2dot (edges , shapes = None , attr = None ):
296302 """
297303 :param edges: the set (or list) of edges of a directed graph.
298-
299- :return dot_string: a representation of 'edges' as a string in the DOT
300- graph language, which can be converted to an image by the 'dot' program
301- from the Graphviz package, or nltk.parse.dependencygraph.dot2img(dot_string).
302-
303304 :param shapes: dictionary of strings that trigger a specified shape.
304305 :param attr: dictionary with global graph attributes
306+ :return: a representation of 'edges' as a string in the DOT graph language.
307+
308+ Returns dot_string: a representation of 'edges' as a string in the DOT
309+ graph language, which can be converted to an image by the 'dot' program
310+ from the Graphviz package, or nltk.parse.dependencygraph.dot2img(dot_string).
305311
306312 >>> import nltk
307313 >>> from nltk.util import edges2dot
@@ -337,8 +343,12 @@ def edges2dot(edges, shapes=None, attr=None):
337343
338344def unweighted_minimum_spanning_digraph (tree , children = iter , shapes = None , attr = None ):
339345 """
346+ :param tree: the tree root
347+ :param children: a function taking as argument a tree node
348+ :param shapes: dictionary of strings that trigger a specified shape.
349+ :param attr: dictionary with global graph attributes
340350
341- Build a Minimum Spanning Tree (MST) of an unweighted graph,
351+ Build a Minimum Spanning Tree (MST) of an unweighted graph,
342352 by traversing the nodes of a tree in breadth-first order,
343353 discarding eventual cycles.
344354
@@ -377,8 +387,16 @@ def unweighted_minimum_spanning_digraph(tree, children=iter, shapes=None, attr=N
377387##########################################################################
378388
379389
380- def acyclic_breadth_first (tree , children = iter , maxdepth = - 1 ):
381- """Traverse the nodes of a tree in breadth-first order,
390+ def acyclic_breadth_first (tree , children = iter , maxdepth = - 1 , verbose = False ):
391+ """
392+ :param tree: the tree root
393+ :param children: a function taking as argument a tree node
394+ :param maxdepth: to limit the search depth
395+ :param verbose: to print warnings when cycles are discarded
396+ :return: the tree in breadth-first order
397+
398+ Adapted from breadth_first() above, to discard cycles.
399+ Traverse the nodes of a tree in breadth-first order,
382400 discarding eventual cycles.
383401
384402 The first argument should be the tree root;
@@ -389,14 +407,16 @@ def acyclic_breadth_first(tree, children=iter, maxdepth=-1):
389407 queue = deque ([(tree , 0 )])
390408 while queue :
391409 node , depth = queue .popleft ()
410+ if node in traversed :
411+ continue
392412 yield node
393413 traversed .add (node )
394414 if depth != maxdepth :
395415 try :
396416 for child in children (node ):
397417 if child not in traversed :
398418 queue .append ((child , depth + 1 ))
399- else :
419+ elif verbose :
400420 warnings .warn (
401421 "Discarded redundant search for {} at depth {}" .format (
402422 child , depth + 1
@@ -407,12 +427,22 @@ def acyclic_breadth_first(tree, children=iter, maxdepth=-1):
407427 pass
408428
409429
410- def acyclic_depth_first (tree , children = iter , depth = - 1 , cut_mark = None , traversed = None ):
411- """Traverse the nodes of a tree in depth-first order,
430+ def acyclic_depth_first (
431+ tree , children = iter , depth = - 1 , cut_mark = None , traversed = None , verbose = False
432+ ):
433+ """
434+ :param tree: the tree root
435+ :param children: a function taking as argument a tree node
436+ :param depth: the maximum depth of the search
437+ :param cut_mark: the mark to add when cycles are truncated
438+ :param traversed: the set of traversed nodes
439+ :param verbose: to print warnings when cycles are discarded
440+ :return: the tree in depth-first order
441+
442+ Traverse the nodes of a tree in depth-first order,
412443 discarding eventual cycles within any branch,
413444 adding cut_mark (when specified) if cycles were truncated.
414-
415- The first argument should be the tree root;
445+ The first argument should be the tree root;
416446 children should be a function taking as argument a tree node
417447 and returning an iterator of the node's children.
418448
@@ -454,12 +484,13 @@ def acyclic_depth_first(tree, children=iter, depth=-1, cut_mark=None, traversed=
454484 )
455485 ]
456486 else :
457- warnings .warn (
458- "Discarded redundant search for {} at depth {}" .format (
459- child , depth - 1
460- ),
461- stacklevel = 3 ,
462- )
487+ if verbose :
488+ warnings .warn (
489+ "Discarded redundant search for {} at depth {}" .format (
490+ child , depth - 1
491+ ),
492+ stacklevel = 3 ,
493+ )
463494 if cut_mark :
464495 out_tree += [f"Cycle({ child } ,{ depth - 1 } ,{ cut_mark } )" ]
465496 except TypeError :
@@ -470,9 +501,19 @@ def acyclic_depth_first(tree, children=iter, depth=-1, cut_mark=None, traversed=
470501
471502
472503def acyclic_branches_depth_first (
473- tree , children = iter , depth = - 1 , cut_mark = None , traversed = None
504+ tree , children = iter , depth = - 1 , cut_mark = None , traversed = None , verbose = False
474505):
475- """Traverse the nodes of a tree in depth-first order,
506+ """
507+ :param tree: the tree root
508+ :param children: a function taking as argument a tree node
509+ :param depth: the maximum depth of the search
510+ :param cut_mark: the mark to add when cycles are truncated
511+ :param traversed: the set of traversed nodes
512+ :param verbose: to print warnings when cycles are discarded
513+ :return: the tree in depth-first order
514+
515+ Adapted from acyclic_depth_first() above, to
516+ traverse the nodes of a tree in depth-first order,
476517 discarding eventual cycles within the same branch,
477518 but keep duplicate paths in different branches.
478519 Add cut_mark (when defined) if cycles were truncated.
@@ -527,12 +568,13 @@ def acyclic_branches_depth_first(
527568 )
528569 ]
529570 else :
530- warnings .warn (
531- "Discarded redundant search for {} at depth {}" .format (
532- child , depth - 1
533- ),
534- stacklevel = 3 ,
535- )
571+ if verbose :
572+ warnings .warn (
573+ "Discarded redundant search for {} at depth {}" .format (
574+ child , depth - 1
575+ ),
576+ stacklevel = 3 ,
577+ )
536578 if cut_mark :
537579 out_tree += [f"Cycle({ child } ,{ depth - 1 } ,{ cut_mark } )" ]
538580 except TypeError :
@@ -543,15 +585,22 @@ def acyclic_branches_depth_first(
543585
544586
545587def acyclic_dic2tree (node , dic ):
546- """Convert acyclic dictionary 'dic', where the keys are nodes, and the
588+ """
589+ :param node: the root node
590+ :param dic: the dictionary of children
591+
592+ Convert acyclic dictionary 'dic', where the keys are nodes, and the
547593 values are lists of children, to output tree suitable for pprint(),
548594 starting at root 'node', with subtrees as nested lists."""
549595 return [node ] + [acyclic_dic2tree (child , dic ) for child in dic [node ]]
550596
551597
552598def unweighted_minimum_spanning_dict (tree , children = iter ):
553599 """
554- Output a dictionary representing a Minimum Spanning Tree (MST)
600+ :param tree: the tree root
601+ :param children: a function taking as argument a tree node
602+
603+ Output a dictionary representing a Minimum Spanning Tree (MST)
555604 of an unweighted graph, by traversing the nodes of a tree in
556605 breadth-first order, discarding eventual cycles.
557606
@@ -593,7 +642,10 @@ def unweighted_minimum_spanning_dict(tree, children=iter):
593642
594643def unweighted_minimum_spanning_tree (tree , children = iter ):
595644 """
596- Output a Minimum Spanning Tree (MST) of an unweighted graph,
645+ :param tree: the tree root
646+ :param children: a function taking as argument a tree node
647+
648+ Output a Minimum Spanning Tree (MST) of an unweighted graph,
597649 by traversing the nodes of a tree in breadth-first order,
598650 discarding eventual cycles.
599651
0 commit comments