def to_tree_obj(self, spanning_tree, k, resp): """Computes a Tree object from the spanning tree. Categorical distributions are computed from the samples and responsibilities Parameters: spanning_tree -- List of tuples (v_i, v_j weight) k -- Index of tree we're updating resp -- Responsibility matrix (num_samples, num_trees) Returns: Tree object with first vertex in the spanning tree as root and remaining nodes organised as a Tree, each node with its MLE q distribution """ tree = Tree() tree.root = Node(0, []) tree.k = 2 visit_list = [tree.root] remaining_nodes = spanning_tree while len(visit_list) != 0:# and len(remaining_nodes): tree.num_nodes += 1 tree.num_leaves += 1 cur_node = visit_list[0] # We're going to separate the remaining nodes in those that are connected # to the current and those that aren't connected = [edge for edge in remaining_nodes if edge[0] == int(cur_node.name) or edge[1] == int(cur_node.name)] not_connected = [edge for edge in remaining_nodes if edge[0] != int(cur_node.name) and edge[1] != int(cur_node.name)] # We create a Node for the connected nodes and add them as children to current node for edge in connected: other = edge[0] if edge[0] != int(cur_node.name) else edge[1] child = Node(other, []) child.ancestor = cur_node cur_node.descendants.append(child) visit_list = visit_list[1:] + cur_node.descendants remaining_nodes = not_connected # Keep only nodes that aren't connected yet # Now we built a tree. We traverse it again to set the correct node names and # categorical distributions visit_list = [tree.root] cont = 0 while len(visit_list) != 0: cur_node = visit_list[0] # TODO: Why does it work if I dont't rename the nodes? #cur_node.name = cont cat = [] if cur_node.ancestor == None: cat = [self.q_marginal(k, cur_node.name, 0, resp), self.q_marginal(k, cur_node.name, 1, resp)] else: parent_idx = int(cur_node.ancestor.name) child_idx = int(cur_node.name) for p in [0, 1]: # For possible values of parent q_given_parent = [0, 0] for c in [0, 1]: # For possible values of child q_given_parent[c] = self.q(k, parent_idx, child_idx, p, c, resp) q_given_parent /= self.q_marginal(k, parent_idx, p, resp) cat.append(q_given_parent) cont += 1 cur_node.cat = cat visit_list = visit_list[1:] + cur_node.descendants return tree