@staticmethod
def _compute_generic_dominators(head, reachable_cb, prev_cb, next_cb):
    """Generic algorithm to compute either the dominators or postdominators
        of the graph.
        @head: the head/leaf of the graph
        @reachable_cb: sons/parents of the head/leaf
        @prev_cb: return predecessors/successors of a node
        @next_cb: return successors/predecessors of a node
        """
    nodes = set(reachable_cb(head))
    dominators = {}
    for node in nodes:
        dominators[node] = set(nodes)
    dominators[head] = set([head])
    todo = set(nodes)
    while todo:
        node = todo.pop()
        if node == head:
            continue
        new_dom = None
        for pred in prev_cb(node):
            if not pred in nodes:
                continue
            if new_dom is None:
                new_dom = set(dominators[pred])
            new_dom.intersection_update(dominators[pred])
        assert new_dom is not None
        new_dom.update(set([node]))
        if new_dom == dominators[node]:
            continue
        dominators[node] = new_dom
        for succ in next_cb(node):
            todo.add(succ)
    return dominators
