Beispiel #1
0
def construct_junction_tree(cliques):
    "Construct a junction tree from a sequence of cliques."
    # construct a complete graph which has the clique intersections as edge weights
    g = bgl.Graph()
    clusters = g.add_vertex_property(type='object')
    for clique in cliques:
        clusters[g.add_vertex()] = set(clique)
    weights = g.add_edge_property(type='float')
    separators = g.add_edge_property(type='object')
    for v1 in g.vertices:
        for v2 in g.vertices:
            if v1 != v2 and None == g.edge(v1, v2):
                intersection = clusters[v1].intersection(clusters[v2])
                if intersection:
                    e = g.add_edge(v1, v2)
                    separators[e] = intersection
                    weights[e] = 1.0 / len(intersection)
    maximal_tree_edges = bgl.kruskal_minimum_spanning_tree(g, weights)
    # remove edges not in maximal tree
    for e in g.edges:
        if e not in maximal_tree_edges:
            g.remove_edge(e)
    return g, clusters, separators
Beispiel #2
0
# Copyright 2005 The Trustees of Indiana University.

# Use, modification and distribution is subject to the Boost Software
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http:#www.boost.org/LICENSE_1_0.txt)

#  Authors: Douglas Gregor
#           Andrew Lumsdaine
import boost.graph as bgl

# Load a graph from the GraphViz file 'mst.dot'
graph = bgl.read_graphviz('mst.dot')

# Compute the minimum spanning tree of the graph
mst_edges = bgl.kruskal_minimum_spanning_tree(graph, graph.edge_properties['weight'])

# Compute the weight of the minimum spanning tree 
print 'MST weight =',sum([e.weight for e in mst_edges])

# Put the weights into the label. Make MST edges solid while all other
# edges remain dashed.
for e in graph.edges:
    e.label = e.weight
    if e in mst_edges:
        e.style = 'solid'
    else:
        e.style = 'dashed'

# Write out the graph in GraphViz DOT format
graph.write_graphviz('mst-out.dot')
Beispiel #3
0
    def build_tree(self, mi_threshold = 0.0):
        """
        Builds a tree from the mutual information between the base distributions
        """
        import boost.graph as bgl
        # first build an (undirected) graph of the (negative) mutual informations
        g = bgl.Graph()
        vertices = [ g.add_vertex() for i in xrange(self.K) ]
        weight_map = g.add_edge_property('weight', 'float')
        joint_probabilities = g.add_edge_property('joints')
        marginal_probabilities = g.add_vertex_property('marginals')

        # add the edges and marginal probs
        for i in xrange(self.K):
            marginal_probabilities[vertices[i]] = self.marginal[i]

        # add the edges and conditional probs
        for i in xrange(self.K):
            for j in xrange(i+1,self.K):
                if self.mutual_information[i,j] > mi_threshold:
                    e = g.add_edge(vertices[i],vertices[j])
                    weight_map[e] = -self.mutual_information[i,j]
                    joint_probabilities[e] = self.joint[i,j]

        # find the minimum spanning tree and remove those edges not in it
        spanning_tree = bgl.kruskal_minimum_spanning_tree(g,weight_map)
        for e in g.edges:
            if e not in spanning_tree:
                g.remove_edge(e)

        def index_of(v):
            for i in xrange(self.K):
                if vertices[i] == v:
                    return i
            raise RuntimeError( 'Could not find vertex: ' + v )

        # build a directed forest from the (undirected) graph
        def build_forest(g, root_idx = None):
            "Take a forest and build an isomorphic Digraph"
            import boost.graph as bgl

            vertices_visited = set()
            diforest = bgl.Digraph()
            edge_label = diforest.add_edge_property( 'label', 'string' )
            di_conditionals = diforest.add_edge_property( 'conditionals' )
            di_marginals = diforest.add_vertex_property( 'marginals' )
            di_vertices = [ diforest.add_vertex() for i in xrange(self.K) ]

            def visit(i):
                if i in vertices_visited: return
                vertices_visited.add(i)
                v = vertices[i]
                di_v = di_vertices[i]
                di_marginals[di_v] = marginal_probabilities[v]
                for neighbour in g.adjacent_vertices(v):
                    j = index_of(neighbour)
                    if j not in vertices_visited:
                        e = diforest.add_edge(di_v, di_vertices[j])
                        edge_label[e] = '%.3f' % (-weight_map[g.edge(v,vertices[j])])
                        joint = joint_probabilities[g.edge(v,neighbour)]
                        if index_of(neighbour) < index_of(v): joint = joint.T # make sure we have correct orientation of joint
                        di_conditionals[e] = joint_to_conditional(joint)
                        visit(j) # recurse

            # visit all the vertices - starting with root if given
            if None != root_idx: visit(root_idx)
            for i in xrange(self.K): visit(i)

            # check each node has max one parent
            for v in diforest.vertices: assert diforest.in_degree(v) < 2

            return diforest

        # set the root to have the highest MI
        root_idx = self.mutual_information.argmax() % self.mutual_information.shape[0]
        self.d = build_forest(g, root_idx = root_idx)
Beispiel #4
0
    def build_tree(self, mi_threshold=0.0):
        """
        Builds a tree from the mutual information between the base distributions
        """
        import boost.graph as bgl
        # first build an (undirected) graph of the (negative) mutual informations
        g = bgl.Graph()
        vertices = [g.add_vertex() for i in xrange(self.K)]
        weight_map = g.add_edge_property('weight', 'float')
        joint_probabilities = g.add_edge_property('joints')
        marginal_probabilities = g.add_vertex_property('marginals')

        # add the edges and marginal probs
        for i in xrange(self.K):
            marginal_probabilities[vertices[i]] = self.marginal[i]

        # add the edges and conditional probs
        for i in xrange(self.K):
            for j in xrange(i + 1, self.K):
                if self.mutual_information[i, j] > mi_threshold:
                    e = g.add_edge(vertices[i], vertices[j])
                    weight_map[e] = -self.mutual_information[i, j]
                    joint_probabilities[e] = self.joint[i, j]

        # find the minimum spanning tree and remove those edges not in it
        spanning_tree = bgl.kruskal_minimum_spanning_tree(g, weight_map)
        for e in g.edges:
            if e not in spanning_tree:
                g.remove_edge(e)

        def index_of(v):
            for i in xrange(self.K):
                if vertices[i] == v:
                    return i
            raise RuntimeError('Could not find vertex: ' + v)

        # build a directed forest from the (undirected) graph
        def build_forest(g, root_idx=None):
            "Take a forest and build an isomorphic Digraph"
            import boost.graph as bgl

            vertices_visited = set()
            diforest = bgl.Digraph()
            edge_label = diforest.add_edge_property('label', 'string')
            di_conditionals = diforest.add_edge_property('conditionals')
            di_marginals = diforest.add_vertex_property('marginals')
            di_vertices = [diforest.add_vertex() for i in xrange(self.K)]

            def visit(i):
                if i in vertices_visited: return
                vertices_visited.add(i)
                v = vertices[i]
                di_v = di_vertices[i]
                di_marginals[di_v] = marginal_probabilities[v]
                for neighbour in g.adjacent_vertices(v):
                    j = index_of(neighbour)
                    if j not in vertices_visited:
                        e = diforest.add_edge(di_v, di_vertices[j])
                        edge_label[e] = '%.3f' % (
                            -weight_map[g.edge(v, vertices[j])])
                        joint = joint_probabilities[g.edge(v, neighbour)]
                        if index_of(neighbour) < index_of(v):
                            joint = joint.T  # make sure we have correct orientation of joint
                        di_conditionals[e] = joint_to_conditional(joint)
                        visit(j)  # recurse

            # visit all the vertices - starting with root if given
            if None != root_idx: visit(root_idx)
            for i in xrange(self.K):
                visit(i)

            # check each node has max one parent
            for v in diforest.vertices:
                assert diforest.in_degree(v) < 2

            return diforest

        # set the root to have the highest MI
        root_idx = self.mutual_information.argmax(
        ) % self.mutual_information.shape[0]
        self.d = build_forest(g, root_idx=root_idx)
    # which will be converted into Boost.Graph property maps.
    # In this case, we're only interested in the edge weights.
    bgl_graph, translation_map = graphviz_graph.to_bgl(edge_properties = ['weight'])
    
    # the returned translation_map is used to translate between the two
    # graph formats:
    #   translation_map[boost_vertex]  => corresponding yapgvb node
    #   translation_map[boost_edge]    => corresponding yapgvb edge
    #   translation_map[yapgvb_node]   => corresponding boost vertex
    #   translation_map[yapgvb_edge]   => corresponding boost edge
    
    weight_map = bgl_graph.edge_properties['weight']

    # Compute the minimum spanning tree of the graph
    # Returns a list of boost edges
    mst_edges = bgl.kruskal_minimum_spanning_tree(bgl_graph, weight_map)

    # Color the minimum spanning tree edges red in the graphviz representation
    for bgl_edge in mst_edges:

        # Get the yapgvb edge corresponding to the boost edge
        graphviz_edge = translation_map[bgl_edge]
        
        graphviz_edge.color = yapgvb.colors.red
    
    print "Using dot for layout..."
    graphviz_graph.layout(yapgvb.engines.dot)

    print "Rendering mst.png..."
    graphviz_graph.render('mst.png')