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
Esempio n. 6
0
 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))