def build_join_tree(self, triangulatedGraph): # The Triangulated Graph is really a graph of cliques. cliques = triangulatedGraph.cliques # We start by creating a forest of trees, one for each clique. forest = [JoinTree(clique) for clique in cliques] sepsetHeap = self.create_sepset_priority_queue(cliques) # Join n - 1 sepsets together forming (hopefully) a single tree. for n in range(len(forest) - 1): while sepsetHeap: sepset = heapq.heappop(sepsetHeap) # Find out which tree each clique is from joinTreeX = GraphUtilities.getTree(forest, sepset.cliqueX) joinTreeY = GraphUtilities.getTree(forest, sepset.cliqueY) if not joinTreeX == joinTreeY: # If the cliques are on different trees, then join to make a larger one. joinTreeX.merge(sepset, joinTreeY) forest.remove(joinTreeY) break if len(forest) > 1: raise BadTreeStructure( "Inference on a forest of Junction Trees is not yet supported") else: tree = forest[0] tree.init_clique_potentials(self.bnet.nodes) return tree
def global_propagation(self): self.joinTree.initialized = False # Arbitrarily pick a clique to be the root node, could be OPTIMIZED startClique = self.joinTree.nodes.pop() # Seems very awkward, but with sets there is no # way that I know of to get an element without popping it off. self.joinTree.nodes.add(startClique) GraphUtilities.unmark_all_nodes(self.joinTree) # We use 0 to denote that there was no prevCluster self.collect_evidence(0, startClique, 0, True) GraphUtilities.unmark_all_nodes(self.joinTree) self.distribute_evidence(startClique)
def __init__(self, moral): Graph.__init__(self, moral.nodes) heap = GraphUtilities.ClusterBinaryHeap() # Copy the graph so that we can destroy the copy as we insert it into heap. # Deep copy isn't working, need to trace down bug but for now use hack. for i, node in enumerate(moral.deep_copy_nodes()): heap.insert(node) inducedCliques = [] nodes = list(self.nodes) # Want nodes in their index order nodes.sort for (node, edges) in heap: realnode = nodes[node.index] for edge in edges: # We need to make sure we reference the nodes in the actual graph, # not the copied ones that were inserted into the heap. node1 = nodes[edge[0].index] node2 = nodes[edge[1].index] self.connect_nodes(node1, node2) clique = Clique(realnode.neighbors.union([realnode])) # We only add clique to inducedCliques if is not contained in a previously added clique GraphUtilities.addClique(inducedCliques, clique) self.cliques = inducedCliques
def build_join_tree (self, triangulatedGraph): # The Triangulated Graph is really a graph of cliques. cliques = triangulatedGraph.cliques # We start by creating a forest of trees, one for each clique. forest = [JoinTree(clique) for clique in cliques] sepsetHeap = self.create_sepset_priority_queue(cliques) # Join n - 1 sepsets together forming (hopefully) a single tree. for n in range(len(forest) - 1): while sepsetHeap: sepset = heapq.heappop(sepsetHeap) # Find out which tree each clique is from joinTreeX = GraphUtilities.getTree(forest, sepset.cliqueX) joinTreeY = GraphUtilities.getTree(forest, sepset.cliqueY) if not joinTreeX == joinTreeY: # If the cliques are on different trees, then join to make a larger one. joinTreeX.merge(sepset, joinTreeY) forest.remove(joinTreeY) break if len(forest) > 1: raise BadTreeStructure("Inference on a forest of Junction Trees is not yet supported") else: tree = forest[0] tree.init_clique_potentials(self.bnet.nodes) return tree