def abstract_atoms(tree): check_tree_top_level(tree) new_tree = HypergraphTree(node=tree.node, children=[abstract_atoms(t) for t in tree]) check_tree_top_level(new_tree) for t_id in tree.node.terminal_ids(): # this modifies the tree.node object too new_child = abstract_atom(tree.node, t_id) child_tree = HypergraphTree(node=new_child) new_tree.append(child_tree) check_tree_top_level(new_tree) return new_tree
def dict_tree_to_graph_tree(tree): out_children = [] if 'children' in tree: for child in tree['children'].values(): out_children.append(dict_tree_to_graph_tree(child)) out_tree = HypergraphTree(node=tree['node'], children=out_children) return out_tree
def dict_tree_to_graph_tree(tree): out_children = [] if "children" in tree: for child in tree["children"].values(): out_children.append(dict_tree_to_graph_tree(child)) out_tree = HypergraphTree(node=tree["node"], children=out_children) return out_tree
def abstract_atoms(tree): check_tree_top_level(tree) new_tree = HypergraphTree(node=tree.node, children=[abstract_atoms(t) for t in tree]) check_tree_top_level(new_tree) for t_id in tree.node.terminal_ids(): # this modifies the tree.node object too new_child = abstract_atom(tree.node, t_id) child_tree = HypergraphTree(node=new_child) new_tree.append(child_tree) check_tree_top_level(new_tree) return new_tree # check that the number of a tree's children still equals the number of nonterminals in its node, # and the number of edges match (should also check edge type) return new_tree
def abstract_ring_atoms(tree): new_children = [abstract_ring_atoms(x) for x in tree] if len(tree.node.terminal_ids()) >= 2: for t_id in tree.node.terminal_ids(): # this modifies the tree.node object too, appending a nonterminal at the end, instead of the abstracted atom new_child, subtree_inds = abstract_ring_atom(tree.node, t_id) if new_child is not None: grandchildren = [ ] # the abstracted node takes over some children for ind in subtree_inds: grandchildren.append(new_children.pop(ind)) child_tree = HypergraphTree(node=new_child, children=grandchildren) new_children.append(child_tree) new_tree = HypergraphTree(node=tree.node, children=new_children) return new_tree
def normalize_tree(self, tree): # as we're replacing the original hypergraph from the parser with an equivalent node from our rules list, # which could have a different order of nonterminals, need to reorder subtrees to match new_subtrees = [self.normalize_tree(subtree) for subtree in tree] child_id_to_subtree = {child_id: subtree for child_id, subtree in zip(tree.node.child_ids(), new_subtrees)} rule_id, node_id_map = self.rule_to_index(tree.node) reordered_subtrees = [child_id_to_subtree[node_id_map[child_id]] for child_id in self.rules[rule_id].child_ids()] new_tree = HypergraphTree(node=self.rules[rule_id], children=reordered_subtrees) new_tree.node.rule_id = rule_id self.last_tree_processed = new_tree return new_tree
def _remove_largest_clique(cliques, tree): hypergraph = tree.node clique = sorted(cliques, key=lambda x: len(x))[-1] clique_nodes = [] clique_children = [] clique_idxs = [] for i, node_id in enumerate(hypergraph.child_ids()): if node_id in clique: clique_nodes.append(hypergraph.node[node_id]) clique_children.append(tree[i]) clique_idxs.append(i) # Clean parent for node_id in clique: del hypergraph.node[node_id] for idx in sorted(clique_idxs, reverse=True): hypergraph.child_ids tree.pop(idx) # Add new non-terminal # Find external edges from clique clique_edges = set() for node in clique_nodes: clique_edges.update(set(node.edge_ids)) external_edge_ids = [] external_edges = [] for node in hypergraph.node.values(): for edge_id, edge in zip(node.edge_ids, node.edges): if edge_id in clique_edges: external_edge_ids.append(edge_id) external_edges.append(edge) new_nt = Node(edge_ids=external_edge_ids, edges=external_edges) hypergraph.add_node(new_nt) remaining_clique_edges = clique_edges - set(external_edge_ids) for edge_id in remaining_clique_edges: hypergraph.edges.pop(edge_id) hypergraph.validate() # Make new child from clique external_edges_ids_cpy = copy.deepcopy(external_edge_ids) external_edges_cpy = copy.deepcopy(external_edges) new_nt_child = Node(edge_ids=external_edges_ids_cpy, edges=external_edges_cpy) new_child = HyperGraph() new_child.add_parent_node(new_nt_child) edge_id_map = {} for node in clique_nodes: new_child.add_node(node) for i, (edge_id, edge) in enumerate(zip(node.edge_ids, node.edges)): new_id = edge_id_map.get(edge_id) if not new_id: new_id = new_child.add_edge(edge) edge_id_map[edge_id] = new_id node.edge_ids[i] = new_id if edge_id in external_edge_ids: idx = external_edge_ids.index(edge_id) new_nt_child.edge_ids[idx] = new_id new_child.validate() child_graph = new_child.to_nx() child_graph.remove_node(new_child.parent_node_id) assert len(make_max_clique_graph(child_graph)) == 1 tree.append(HypergraphTree(new_child, clique_children))