Exemplo n.º 1
0
def dmrs_query(dmrs_iter, search_dmrs_graphlang, results_as_dict=False, results_per_dmrs=False):
    """
    Queries DMRS graphs for an underspecified (sub)graph pattern and returns the values of named wildcards (of the form "?[Identifier]") as they are specified in the queried graph.
    :param dmrs_iter An iterator of DMRS graphs to query.
    :param search_dmrs_graphlang The query DMRS (sub)graph, given as a GraphLang string.
    :param results_as_dict True if a query result should be a dictionary, mapping identifiers to values.
    :param results_per_dmrs True if a (possibly empty) list per DMRS should be returned.
    :return Iterator of dicts containing the matching node ids.
    """
    queries = {}
    search_dmrs = parse_graphlang(search_dmrs_graphlang, queries=queries)
    queries = [(key, queries[key]) for key in sorted(queries)]
    for dmrs in dmrs_iter:
        assert isinstance(dmrs, Dmrs), 'Object in dmrs_iter is not a Dmrs.'
        # perform an exact matching of search_dmrs against dmrs
        matchings = dmrs_exact_matching(search_dmrs, dmrs)
        if results_per_dmrs:
            results = []
        for matching in matchings:
            # extract matched values
            if results_as_dict:
                result = {key: query(matching, dmrs) for key, query in queries}
            else:
                result = tuple(query(matching, dmrs) for _, query in queries)
            if results_per_dmrs:
                results.append(result)
            else:
                yield result
        if results_per_dmrs:
            yield results
Exemplo n.º 2
0
def dmrs_mapping(dmrs, search_dmrs, replace_dmrs, copy_dmrs=True, iterative=True, all_matches=True, require_connected=True):
    """
    Performs an exact DMRS (sub)graph matching of a (sub)graph against a containing graph.
    :param dmrs DMRS graph to map.
    :param search_dmrs DMRS subgraph to replace.
    :param replace_dmrs DMRS subgraph to replace with.
    :param copy_dmrs True if DMRS graph argument should be copied before being mapped.
    :param iterative True if all possible mappings should be performed iteratively to the same DMRS graph, instead of a separate copy per mapping (iterative=False requires copy_dmrs=True).
    :param all_matches True if all possible matches should be returned, instead of only the first (or None).
    :param require_connected True if mappings resulting in a disconnected DMRS graph should be ignored.
    :return Mapped DMRS graph (resp. a list of graphs in case of iterative=False and all_matches=True)
    """
    assert copy_dmrs or iterative, 'Invalid argument combination.'

    # extract anchor node mapping between search_dmrs and replace_dmrs
    sub_mapping = {}
    for search_node in search_dmrs.iter_nodes():
        if not isinstance(search_node, AnchorNode):
            continue
        for replace_node in replace_dmrs.iter_nodes():
            if not isinstance(replace_node, AnchorNode) or replace_node.anchor != search_node.anchor:
                continue
            sub_mapping[search_node.nodeid] = replace_node.nodeid
            break
        else:
            assert False, 'Un-matched anchor node.'

    # set up variables according to settings
    if iterative:
        result_dmrs = copy.deepcopy(dmrs) if copy_dmrs else dmrs
    else:
        matchings = dmrs_exact_matching(search_dmrs, dmrs)
    if not iterative and all_matches:
        result = []

    # continue while there is a match for search_dmrs
    while True:
        if iterative:
            matchings = dmrs_exact_matching(search_dmrs, result_dmrs)
        else:
            result_dmrs = copy.deepcopy(dmrs) if copy_dmrs else dmrs

        # return mapping(s) if there are no more matches left
        try:
            search_matching = next(matchings)
        except StopIteration:
            if not all_matches:
                return None
            elif iterative:
                return result_dmrs
            else:
                return result

        # remove nodes in the matched search_dmrs if they are no anchor nodes, otherwise perform mapping()
        # mapping() performs the mapping process (with whatever it involves) specific to this node type (e.g. fill underspecified values)
        replace_matching = {}
        for nodeid in search_matching:
            if isinstance(search_dmrs[nodeid], AnchorNode):
                replace_dmrs[sub_mapping[nodeid]].mapping(result_dmrs, search_matching[nodeid])
                replace_matching[sub_mapping[nodeid]] = search_matching[nodeid]
            elif search_matching[nodeid] is not None:
                result_dmrs.remove_node(search_matching[nodeid])

        # add copies of the non-anchor nodes for the matched replace_dmrs
        for nodeid in replace_dmrs:
            if nodeid in replace_matching:
                continue
            node = copy.deepcopy(replace_dmrs[nodeid])
            node.nodeid = result_dmrs.free_nodeid()
            result_dmrs.add_node(node)
            replace_matching[nodeid] = node.nodeid

        # set top/index if specified in replace_dmrs
        if replace_dmrs.top is not None:
            result_dmrs.top = result_dmrs[replace_matching[replace_dmrs.top.nodeid]]
        if replace_dmrs.index is not None:
            result_dmrs.index = result_dmrs[replace_matching[replace_dmrs.index.nodeid]]

        # remove all links in the matched search_dmrs
        links = []
        matching_values = set(search_matching.values())
        for link in result_dmrs.iter_links():
            if link.start in matching_values and link.end in matching_values:
                links.append(link)
        result_dmrs.remove_links(links)

        # add all links for the matched replace_dmrs
        for link in replace_dmrs.iter_links():
            link = Link(replace_matching[link.start], replace_matching[link.end], link.rargname, link.post)
            result_dmrs.add_link(link)

        # add/return result
        if not require_connected or result_dmrs.is_connected():
            if all_matches and not iterative:
                result.append(result_dmrs)
            elif not all_matches:
                return result_dmrs
Exemplo n.º 3
0
def dmrs_mapping(dmrs, search_dmrs, replace_dmrs, equalities=(), hierarchy=None, copy_dmrs=True, iterative=True, all_matches=True, require_connected=True, max_matches=100):
    """
    Performs an exact DMRS (sub)graph matching of a (sub)graph against a containing graph.
    :param dmrs DMRS graph to map.
    :param search_dmrs DMRS subgraph to replace.
    :param replace_dmrs DMRS subgraph to replace with.
    :param equalities
    :param hierarchy An optional predicate hierarchy.
    :param copy_dmrs True if DMRS graph argument should be copied before being mapped.
    :param iterative True if all possible mappings should be performed iteratively to the same DMRS graph, instead of a separate copy per mapping (iterative=False requires copy_dmrs=True).
    :param all_matches True if all possible matches should be returned, instead of only the first (or None).
    :param require_connected True if mappings resulting in a disconnected DMRS graph should be ignored.
    :param max_matches: Maximum number of matches.
    :return Mapped DMRS graph (resp. a list of graphs in case of iterative=False and all_matches=True)
    """
    assert copy_dmrs or iterative, 'Invalid argument combination.'

    # extract anchor node mapping between search_dmrs and replace_dmrs
    sub_mapping = {}
    optional_nodeids = []
    for search_node in search_dmrs.iter_nodes():
        if not isinstance(search_node, AnchorNode):
            continue
        if not search_node.required:
            optional_nodeids.append(search_node.nodeid)
        for replace_node in replace_dmrs.iter_nodes():
            if not isinstance(replace_node, AnchorNode) or all(anchor not in replace_node.anchors for anchor in search_node.anchors):
                continue
            assert search_node.nodeid not in sub_mapping, 'Node matches multiple nodes.' + str(search_node)
            sub_mapping[search_node.nodeid] = replace_node.nodeid
        if search_node.nodeid not in sub_mapping:
            assert not search_node.requires_target, 'Un-matched anchor node.'

    # set up variables according to settings
    if iterative:
        result_dmrs = copy.deepcopy(dmrs) if copy_dmrs else dmrs
        matchings = dmrs_exact_matching(search_dmrs, dmrs, optional_nodeids=optional_nodeids, equalities=equalities, hierarchy=hierarchy, match_top_index=True)
    else:
        matchings = dmrs_exact_matching(search_dmrs, dmrs, optional_nodeids=optional_nodeids, equalities=equalities, hierarchy=hierarchy, match_top_index=True)
    if not iterative and all_matches:
        result = []

    # continue while there is a match for search_dmrs
    count = 0
    for _ in range(max_matches):
        if iterative:
            pass
            # matchings = dmrs_exact_matching(search_dmrs, result_dmrs, optional_nodeids=optional_nodeids, equalities=equalities, hierarchy=hierarchy, match_top_index=True)
        else:
            result_dmrs = copy.deepcopy(dmrs) if copy_dmrs else dmrs

        # return mapping(s) if there are no more matches left
        try:
            search_matching = next(matchings)
            count += 1
        except StopIteration:
            if not all_matches:
                if copy_dmrs:
                    return None
                else:
                    return False
            elif iterative:
                if not require_connected or result_dmrs.is_connected():
                    if copy_dmrs:
                        return result_dmrs
                    else:
                        return count > 0
                else:
                    if copy_dmrs:
                        return None
                    else:
                        return False
            else:
                return result

        # remove nodes in the matched search_dmrs if they are no anchor nodes, otherwise perform mapping()
        # mapping() performs the mapping process (with whatever it involves) specific to this node type (e.g. fill underspecified values)
        for nodeid in search_dmrs:
            search_node = search_dmrs[nodeid]
            if isinstance(search_node, AnchorNode):
                search_node.before_map(result_dmrs, search_matching[nodeid])
        replace_matching = {}
        for nodeid in search_matching:
            if nodeid in sub_mapping:
                replace_dmrs[sub_mapping[nodeid]].map(result_dmrs, search_matching[nodeid], hierarchy=hierarchy)
                replace_dmrs[sub_mapping[nodeid]].after_map(result_dmrs, search_matching[nodeid])
                replace_matching[sub_mapping[nodeid]] = search_matching[nodeid]
            elif search_matching[nodeid] is not None:
                result_dmrs.remove_node(search_matching[nodeid])

        # add copies of the non-anchor nodes for the matched replace_dmrs
        for nodeid in replace_dmrs:
            if nodeid in replace_matching:
                continue
            node = copy.deepcopy(replace_dmrs[nodeid])
            node.nodeid = result_dmrs.free_nodeid()
            result_dmrs.add_node(node)
            replace_matching[nodeid] = node.nodeid

        # set top/index if specified in replace_dmrs
        if replace_dmrs.top is not None:
            result_dmrs.top = result_dmrs[replace_matching[replace_dmrs.top.nodeid]]
        if replace_dmrs.index is not None:
            result_dmrs.index = result_dmrs[replace_matching[replace_dmrs.index.nodeid]]

        # remove all links in the matched search_dmrs
        links = []
        matching_values = set(search_matching.values())
        for link in result_dmrs.iter_links():
            if link.start in matching_values and link.end in matching_values:
                links.append(link)
        result_dmrs.remove_links(links)

        # add all links for the matched replace_dmrs
        for link in replace_dmrs.iter_links():
            link = Link(replace_matching[link.start], replace_matching[link.end], link.rargname, link.post)
            result_dmrs.add_link(link)

        # add/return result
        if not require_connected or result_dmrs.is_connected():
            if all_matches and not iterative:
                result.append(result_dmrs)
            elif not all_matches:
                if copy_dmrs:
                    return result_dmrs
                else:
                    return True

    raise Exception('More than {} matches!'.format(max_matches))
Exemplo n.º 4
0
from pydmrs.matching.exact_matching import dmrs_exact_matching
import examples.examples_dmrs as examples


if __name__ == '__main__':

    # "the" - "the dog chases the cat"
    assert len(list(dmrs_exact_matching(examples.the(), examples.the_dog_chases_the_cat()))) == 2

    # "the cat" - "the dog chases the cat"
    assert len(list(dmrs_exact_matching(examples.the_cat(), examples.the_dog_chases_the_cat()))) == 1

    # "dog cat" - "the dog chases the cat"
    assert len(list(dmrs_exact_matching(examples.dog_cat(), examples.the_dog_chases_the_cat()))) == 1

    # "the dog chases the cat" - "the dog chases the cat"
    assert len(list(dmrs_exact_matching(examples.the_dog_chases_the_cat(), examples.the_dog_chases_the_cat()))) == 1

    # "the cat chases the dog" - "the dog chases the cat"
    assert not len(list(dmrs_exact_matching(examples.the_cat_chases_the_dog(), examples.the_dog_chases_the_cat())))

    # "the dog chases the cat" - "the dog chases the cat and the mouse"
    assert not len(list(dmrs_exact_matching(examples.the_dog_chases_the_cat(), examples.the_dog_chases_the_cat_and_the_mouse())))

    # "the dog chases the cat" - "the dog chases the cat and the cat chases the mouse"
    assert len(list(dmrs_exact_matching(examples.the_dog_chases_the_cat(), examples.the_dog_chases_the_cat_and_the_cat_chases_the_mouse()))) == 1

    # "the cat" - "the dog chases the cat and the cat chases the mouse"
    assert len(list(dmrs_exact_matching(examples.the_cat(), examples.the_dog_chases_the_cat_and_the_cat_chases_the_mouse()))) == 2

    # "dog cat" - "the dog chases the cat and the cat chases the mouse"
Exemplo n.º 5
0
from pydmrs.matching.exact_matching import dmrs_exact_matching
import examples.examples_dmrs as examples

if __name__ == '__main__':

    # "the" - "the dog chases the cat"
    assert len(
        list(
            dmrs_exact_matching(examples.the(),
                                examples.the_dog_chases_the_cat()))) == 2

    # "the cat" - "the dog chases the cat"
    assert len(
        list(
            dmrs_exact_matching(examples.the_cat(),
                                examples.the_dog_chases_the_cat()))) == 1

    # "dog cat" - "the dog chases the cat"
    assert len(
        list(
            dmrs_exact_matching(examples.dog_cat(),
                                examples.the_dog_chases_the_cat()))) == 1

    # "the dog chases the cat" - "the dog chases the cat"
    assert len(
        list(
            dmrs_exact_matching(examples.the_dog_chases_the_cat(),
                                examples.the_dog_chases_the_cat()))) == 1

    # "the cat chases the dog" - "the dog chases the cat"
    assert not len(