def max_independent_set(tree, root, weight_attribute='w'): ''' Finds the maximum independent set in rooted tree. The weight of every node is taken from each node's weight_attribute attribute. Returns (|MIS|, {MIS}), where |MIS| is the total weight of nodes in the set and {MIS} is the set of nodes. ''' if tree.is_directed(): raise NotUndirectedGraph("Tree must be undirected graph!") f_plus, f_minus = {}, {} max_set = set() children, levels, _ = _get_children(tree, root) weight = lambda u: tree.nodes[u][weight_attribute] for level in levels[::-1]: for u in level: if u in children: f_plus[u] = weight(u) + sum(f_minus[v] for v in children[u]) f_minus[u] = sum(max(f_plus[v], f_minus[v]) for v in children[u]) else: f_plus[u], f_minus[u] = weight(u), 0 def node_is_added(predecessor_is_added, node): return (not predecessor_is_added and f_plus[node] >= f_minus[node]) stack = deque([(root, node_is_added(False, root))]) while stack: u, added = stack.pop() if added: max_set.add(u) if u not in children: continue for v in children[u]: stack.append((v, node_is_added(added, v))) return max(f_plus[root], f_minus[root]), max_set
def _assign_level_labels(tree, root): ''' Assings labels to each node. Yeilds the different labels on each level of the tree. For more information, search for AHU algorithm for three isomorphism. ''' labels = {u: 0 for u in tree if tree.degree(u) == 1 and u != root} children_labels = {} children, levels, height = _get_children(tree, root) sort = lambda x: tuple(sorted(x)) # helper for level in levels[:-1][::-1]: nodes_with_label = defaultdict(list) different_labels = set() for node in level: if node in children: # if node has children for child in children[node]: # for each children if node in children_labels: children_labels[node] += (labels[child],) else: children_labels[node] = (labels[child],) children_labels[node] = sort(children_labels[node]) # map the children labels to the node nodes_with_label[children_labels[node]].append(node) # to compute different labels on the current level different_labels.add(children_labels[node]) different_labels = list(different_labels) _tuple_sort(different_labels) yield different_labels for k, node_children_label in enumerate(different_labels): for node in nodes_with_label[node_children_label]: labels[node] = k # k-th distinct tuple