Beispiel #1
0
    def get_subgraph(self, top):
        """

        :type top: Triple
        :param top:
        :return:
        """
        try:
            _span = self.span(top=top)
            possible_children = InstrumentedList(set(_span))
            not_instances = []
            instances = []
            for children in possible_children:
                if children.relation != 'instance':
                    not_instances.append(children)
                else:
                    instances.append(children)

            for not_instance in not_instances:
                if all(instance.source != not_instance.source and instance.
                       source != not_instance.target and not_instance != top
                       for instance in instances):
                    possible_children.remove(not_instance)

            possible_children = organize_triples_list(
                triples_list=possible_children, top=top)
            new_subgraph = AMRModel(
                top=top.source,
                triples=copy_triples_from_list(
                    possible_children)) if possible_children else None
            return new_subgraph
        except Exception as exc:
            PrintException()
Beispiel #2
0
class AMRModel(BaseModel):
    __tablename__ = 'amr_model'
    list_triples = db.relationship('Triple',
                                   backref='amr_model',
                                   lazy=True,
                                   cascade="all, delete-orphan")
    top = db.Column(db.String, nullable=False, default='')
    penman = db.Column(db.String, nullable=False, default='')
    sentence_id = db.Column(db.Integer, db.ForeignKey('sentence.id'))
    description_id = db.Column(db.Integer,
                               db.ForeignKey('description.id'),
                               nullable=True)

    def __init__(self, **kwargs):
        """

        :param kwargs:
            - string
            - triples
            - top

            - object

            -copy
        """
        if kwargs:
            if len(kwargs) == 3 and ('string' and 'triples'
                                     and 'top') in kwargs:
                self.penman = kwargs['string']
                self.list_triples = kwargs['graph']
                self.top = kwargs['top']

            elif len(kwargs) == 2 and ('triples' and 'top') in kwargs:
                self.top = kwargs['top']
                self.list_triples = kwargs['triples']
                self.penman = triple_model_list_to_penman(self.list_triples,
                                                          top_id=self.top)
                self.list_triples = self.delete_wiki()

            elif len(kwargs) == 1 and 'object' in kwargs:
                self.penman = pm.encode(kwargs['object'],
                                        top=kwargs['object'].top)
                self.list_triples, self.top = penman_to_model(kwargs['object'])
                self.list_triples = self.delete_wiki()

            elif len(kwargs) == 1 and 'copy' in kwargs:
                _source_amr: AMRModel = kwargs['copy']
                self.penman = _source_amr.get_penman(return_type='str')
                self.list_triples = InstrumentedList(
                    [Triple(copy=t) for t in _source_amr.get_triples()])
                self.list_triples = self.delete_wiki()
                self.top = _source_amr.get_top()
                self.penman = triple_model_list_to_penman(self.list_triples,
                                                          top_id=self.top)

    def __repr__(self):
        return self.penman

    def __str__(self):
        return self.penman

    def __eq__(self, other):
        if isinstance(other, AMRModel):
            return all(triple in other.get_triples()
                       for triple in self.list_triples) and all(
                           triple in self.list_triples
                           for triple in other.get_triples())
        elif isinstance(other, str):
            return self.penman == other

    def __hash__(self):
        return hash(self.penman)

    def get_variable_list(self):
        return [t.source for t in self.get_triples(relation='instance')]

    def has_variable(self, variable):
        return self.get_triples(src=variable, relation='instance')

    def add(self, other, tuple_ref):
        """

        :type tuple_ref: tuple
        :param tuple_ref:
        :type other: AMRModel
        :param other:
        :return:
        """
        old_penman = self.penman
        top = self.get_triple(src=self.top, relation='instance')
        if any(triple.target == top.target and triple.source != tuple_ref[1]
               for triple in other.list_triples):
            return self.list_triples
        try:
            other_top = other.get_top()
            old_triples = other.get_triples()
            change_variable_list = []
            if old_triples:
                new_triples = set()
                for old_triple in old_triples:
                    if old_triple.source == tuple_ref[1]:
                        if old_triple.relation != 'instance':
                            new_triple = Triple(src=tuple_ref[0],
                                                rel=old_triple.relation,
                                                tgt=old_triple.target)
                            new_triples.add(new_triple)
                    elif old_triple.target == tuple_ref[1]:
                        new_triple = Triple(src=old_triple.source,
                                            rel=old_triple.relation,
                                            tgt=tuple_ref[0])
                        new_triples.add(new_triple)
                    elif old_triple.is_instance() and old_triple.target:
                        old_source = old_triple.source
                        new_source = increase_variable(
                            old_triple.source, self.get_variable_list())
                        new_triple = Triple(src=new_source,
                                            rel=old_triple.relation,
                                            tgt=old_triple.target)
                        new_triples.add(new_triple)
                        change_variable_list.append((old_source, new_source))
                    elif not old_triple.is_instance() or not old_triple.target and old_triple.target != tuple_ref[1] and \
                            old_triple.source != tuple_ref[1]:
                        new_triple = Triple(src=old_triple.source,
                                            rel=old_triple.relation,
                                            tgt=old_triple.target)
                        new_triples.add(new_triple)

                newer_triples = set()
                if change_variable_list:
                    for old, new in change_variable_list:
                        for triple in new_triples:
                            if triple.source == old:
                                triple.source = new
                                newer_triples.add(triple)
                            else:
                                newer_triples.add(triple)

                else:
                    newer_triples = new_triples

                self.list_triples = InstrumentedList(
                    newer_triples.union(set(self.list_triples)))
                self.list_triples = organize_triples_list(
                    self.list_triples, top)
                self.penman = triple_model_list_to_penman(
                    self.list_triples, self.top)
            return self.list_triples
        except Exception as exc:
            print(old_penman)
            print(self.list_triples)
            PrintException()

    def delete(self, node_source):
        if isinstance(node_source, str):
            self.list_triples = _delete_nodes(self.list_triples, node_source)
        elif isinstance(node_source, Triple):
            self.list_triples = _delete_nodes(self.list_triples,
                                              node_source.source)

        return self.list_triples

    def delete_wiki(self):
        wikis = self.get_triples(relation='wiki')
        [self.list_triples.remove(wiki) for wiki in wikis]
        self.penman = triple_model_list_to_penman(self.list_triples,
                                                  top_id=self.top)
        [
            self.delete(node_source=wiki.target) for wiki in wikis
            if wiki.target != '-'
        ]
        return self.list_triples

    def get_top(self):
        return self.top

    def get_triples(self, src=None, relation=None, target=None):
        """

        :param src:
        :param relation:
        :param target:
        :return:
        """
        return triples(self.list_triples,
                       src=src,
                       relation=relation,
                       target=target)

    def get_penman(self, return_type='object', indent=None):
        if return_type == 'object':
            return pm.decode(self.penman)
        elif return_type == 'str':
            if indent is None:
                return self.penman
            else:
                return pm.encode(pm.decode(self.penman),
                                 top=self.top,
                                 indent=indent)

    def has_common_names(self, other):
        return _common_names(self, other)

    def has_common_person(self, other):
        return _common_persons(self, other)

    def set_top(self, new_top):
        """

        :type new_top: str
        :param new_top:
        :return:
        """
        self.top = new_top
        return new_top

    def get_parents(self, node):
        _src = ''
        if isinstance(node, str):
            _src = node
        elif isinstance(node, Triple):
            _src = node.source
        candidates = self.get_triples(target=_src)
        if candidates is not None and candidates:
            exists_candidates = [
                triple for triple in candidates if triple.target == _src
            ]
            if exists_candidates:
                candidate = [
                    triple for triple in candidates if triple.target == _src
                ][0]
                parent_node_candidate = self.get_triple(src=candidate.source,
                                                        relation='instance')
                if candidate and parent_node_candidate:
                    return [
                        Triple(copy=parent_node_candidate),
                        Triple(copy=candidate),
                        Triple(copy=node)
                    ]
        return []

    def is_instance(self, item):
        """

        :type item: str
        :param item:
        :return:
        """
        return any(item == triple.source and triple.is_instance()
                   for triple in self.list_triples)

    def get_names(self, name_src):
        ops = self.role(src=name_src)
        if ops:
            return " ".join([op.target for op in ops])
        return []

    def is_name(self, string):
        """

        :type string: str
        :param string:
        :return:
        """
        splitted_string = string.split()
        possible_names = self.get_triples(relation='instance', target='name')
        return_list = InstrumentedList([])
        for possible_name in possible_names:
            possible_name_string_list = self.get_triples(
                src=possible_name.source, relation='op')
            if possible_name_string_list and any(
                    any(ss in pns.target for ss in splitted_string)
                    for pns in possible_name_string_list):
                return_list.append(possible_name)

        return False if not return_list else return_list[0]

    def get_size(self):
        return len([
            triple for triple in self.list_triples
            if triple.is_relation('instance')
        ])

    def intersection(self, amr, focus=None):
        """

        :param focus:
        :type amr: AMRModel
        :param amr:
        :return:
        """
        return_list = set()
        if focus is None:
            _other_triples = amr.get_triples()
            for triple in _other_triples:
                if triple in self.list_triples:
                    return_list.add(triple)

        else:
            focus_is_name = amr.is_name(focus)
            if focus_is_name and self.is_name(focus):
                return_list.add(focus_is_name)
            else:
                _other_triples = amr.get_triples(relation='instance',
                                                 target=focus)
                for triple in _other_triples:
                    if triple in self.list_triples:
                        return_list.add(triple)

        return _filter_common(InstrumentedList(return_list),
                              self.has_common_person(amr),
                              self.has_common_names(amr))

    def get_instance(self, src=None):
        for triple in self.list_triples:
            if triple.source == src and triple.is_instance():
                return triple

    def get_sentence(self):
        return self.sentence

    def get_triple(self, src=None, relation=None, target=None):
        try:
            if src is None and relation is None and target is None:
                return None
            if target is not None:
                triple_is_name = self.is_name(target)
                if triple_is_name:
                    return triple_is_name
            return_list = []
            for triple in self.list_triples:
                if _match_triple(src, relation, target, triple):
                    return_list.append(triple)

            if return_list:
                if relation is not None and relation == 'instance':
                    return [
                        triple for triple in return_list
                        if triple.target is not None
                    ][0]
                else:
                    return return_list[0]
            else:
                return None
        except Exception as exc:
            PrintException()
            return None

    def role(self, src=None, target=None):
        return_list = InstrumentedList([])
        for triple in self.list_triples:
            is_instance = triple.relation == 'instance'
            if not is_instance and (
                (src is not None and triple.source == src) or
                (target is not None and triple.target == target)):
                return_list.append(triple)

        return return_list

    def path(self, src, target=None, only_roles=True):
        """
        DFS based
        :param src:
        :param target:
        :param only_roles:
        :return:
        """
        if src == target:
            return []
        _ways = self.role(src=src)
        for way in _ways:
            if way.target == target:
                return InstrumentedList(
                    [way] if only_roles else [self.get_instance(src=src)] +
                    [way] + [self.get_instance(src=target)])
            else:
                new_way = self.path(src=way.target,
                                    target=target,
                                    only_roles=only_roles)
                if new_way and new_way is not None:
                    return InstrumentedList([way]) + new_way

        return []

    def span(self, top):
        """

        :type top: Triple
        :param top:
        :return:
        """
        # base

        _ways = self.role(src=top.source)
        new_way = InstrumentedList([])
        for way in _ways:
            if self.is_instance(way.target):
                way_instance = self.get_instance(src=way.target)
                new_way += InstrumentedList([way
                                             ]) + self.span(top=way_instance)
            else:
                new_way.append(way)

        return InstrumentedList([top] + new_way)

    def root_distance(self, triple):
        """

        :type triple: Triple
        :param triple:
        :return:
        """
        path = self.path(src=self.top, target=triple.source, only_roles=True)
        return len(path)

    def get_subgraph(self, top):
        """

        :type top: Triple
        :param top:
        :return:
        """
        try:
            _span = self.span(top=top)
            possible_children = InstrumentedList(set(_span))
            not_instances = []
            instances = []
            for children in possible_children:
                if children.relation != 'instance':
                    not_instances.append(children)
                else:
                    instances.append(children)

            for not_instance in not_instances:
                if all(instance.source != not_instance.source and instance.
                       source != not_instance.target and not_instance != top
                       for instance in instances):
                    possible_children.remove(not_instance)

            possible_children = organize_triples_list(
                triples_list=possible_children, top=top)
            new_subgraph = AMRModel(
                top=top.source,
                triples=copy_triples_from_list(
                    possible_children)) if possible_children else None
            return new_subgraph
        except Exception as exc:
            PrintException()

    def __contains__(self, item):
        return any(item == triple for triple in self.list_triples)

    def save(self):
        [triple.save() for triple in self.list_triples]
        _add_session(self)
Beispiel #3
0
 def remove(rel: InstrumentedList, table: Base, value: dict):
     try:
         item = table.query.filter_by(**value).one()
         rel.remove(item)
     except NoResultFound:
         pass