@@ -31,14 +31,14 @@ def join(rooted_trees, label_attribute=None):
31
31
return join_trees (rooted_trees , label_attribute = label_attribute )
32
32
33
33
34
- def join_trees (rooted_trees , label_attribute = None ):
34
+ def join_trees (rooted_trees , * , label_attribute = None , first_label = 0 ):
35
35
"""Returns a new rooted tree made by joining `rooted_trees`
36
36
37
37
Constructs a new tree by joining each tree in `rooted_trees`.
38
38
A new root node is added and connected to each of the roots
39
39
of the input trees. While copying the nodes from the trees,
40
- relabeling to integers occurs and the old name stored as an
41
- attribute of the new node in the returned graph .
40
+ relabeling to integers occurs. If the `label_attribute` is provided,
41
+ the old node labels will be stored in the new tree under this attribute .
42
42
43
43
Parameters
44
44
----------
@@ -50,17 +50,20 @@ def join_trees(rooted_trees, label_attribute=None):
50
50
51
51
label_attribute : str
52
52
If provided, the old node labels will be stored in the new tree
53
- under this node attribute. If not provided, the node attribute
54
- ``'_old'`` will store the original label of the node in the
55
- rooted trees given in the input.
53
+ under this node attribute. If not provided, the original labels
54
+ of the nodes in the input trees are not stored.
55
+
56
+ first_label : int, optional (default=0)
57
+ Specifies the label for the new root node. If provided, the root node of the joined tree
58
+ will have this label. If not provided, the root node will default to a label of 0.
56
59
57
60
Returns
58
61
-------
59
62
NetworkX graph
60
- The rooted tree whose subtrees are the given rooted trees . The
61
- new root node is labeled 0. Each non-root node has an attribute,
62
- as described under the keyword argument `` label_attribute``,
63
- that indicates the label of the original node in the input tree.
63
+ The rooted tree resulting from joining the provided `rooted_trees` . The new tree has a root node
64
+ labeled as specified by `first_label` (defaulting to 0 if not provided). Subtrees from the input
65
+ `rooted_trees` are attached to this new root node. Each non-root node, if the ` label_attribute`
66
+ is provided, has an attribute that indicates the original label of the node in the input tree.
64
67
65
68
Notes
66
69
-----
@@ -86,42 +89,38 @@ def join_trees(rooted_trees, label_attribute=None):
86
89
True
87
90
88
91
"""
89
- if len ( rooted_trees ) == 0 :
92
+ if not rooted_trees :
90
93
return nx .empty_graph (1 )
91
94
92
95
# Unzip the zipped list of (tree, root) pairs.
93
96
trees , roots = zip (* rooted_trees )
94
97
95
- # The join of the trees has the same type as the type of the first
96
- # tree.
98
+ # The join of the trees has the same type as the type of the first tree.
97
99
R = type (trees [0 ])()
98
100
99
- # Relabel the nodes so that their union is the integers starting at 1.
100
- if label_attribute is None :
101
- label_attribute = "_old"
101
+ lengths = (len (tree ) for tree in trees [:- 1 ])
102
+ first_labels = list (accumulate (lengths , initial = first_label + 1 ))
103
+
104
+ new_roots = []
105
+ for tree , root , first_node in zip (trees , roots , first_labels ):
106
+ new_root = first_node + list (tree .nodes ()).index (root )
107
+ new_roots .append (new_root )
108
+
109
+ # Relabel the nodes so that their union is the integers starting at first_label.
102
110
relabel = partial (
103
111
nx .convert_node_labels_to_integers , label_attribute = label_attribute
104
112
)
105
- lengths = (len (tree ) for tree in trees [:- 1 ])
106
- first_labels = chain ([0 ], accumulate (lengths ))
107
- trees = [
108
- relabel (tree , first_label = first_label + 1 )
113
+ new_trees = [
114
+ relabel (tree , first_label = first_label )
109
115
for tree , first_label in zip (trees , first_labels )
110
116
]
111
117
112
- # Get the relabeled roots.
113
- roots = [
114
- next (v for v , d in tree .nodes (data = True ) if d .get (label_attribute ) == root )
115
- for tree , root in zip (trees , roots )
116
- ]
117
-
118
118
# Add all sets of nodes and edges, attributes
119
- for tree in trees :
119
+ for tree in new_trees :
120
120
R .update (tree )
121
121
122
- # Finally, join the subtrees at the root. We know 0 is unused by the
123
- # way we relabeled the subtrees.
124
- R .add_node (0 )
125
- R .add_edges_from ((0 , root ) for root in roots )
122
+ # Finally, join the subtrees at the root. We know first_label is unused by the way we relabeled the subtrees.
123
+ R .add_node (first_label )
124
+ R .add_edges_from ((first_label , root ) for root in new_roots )
126
125
127
126
return R
0 commit comments