示例#1
0
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
示例#2
0
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