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()
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)
def remove(rel: InstrumentedList, table: Base, value: dict): try: item = table.query.filter_by(**value).one() rel.remove(item) except NoResultFound: pass