def _encode_eds(e, properties, lnk, show_status, indent): # do something predictable for empty EDS if len(e.nodes) == 0: return '{:\n}' if indent else '{:}' # determine if graph is connected g = {node.id: set() for node in e.nodes} for node in e.nodes: for target in node.edges.values(): g[node.id].add(target) g[target].add(node.id) nidgrp = _bfs(g, start=e.top) status = '' if show_status and nidgrp != set(g): status = ' (fragmented)' delim = '\n' if indent else ' ' connected = ' ' if indent else '' disconnected = '|' if show_status else ' ' ed_list = [] for node in e.nodes: membership = connected if node.id in nidgrp else disconnected ed_list.append(membership + _encode_node(node, properties, lnk)) return '{{{top}{status}{delim}{ed_list}{enddelim}}}'.format( top=e.top + ':' if e.top is not None else ':', status=status, delim=delim, ed_list=delim.join(ed_list), enddelim='\n' if indent else '')
def is_connected(m: mrs.MRS) -> bool: """ Return `True` if *m* is a fully-connected MRS. A connected MRS is one where, when viewed as a graph, all EPs are connected to each other via regular (non-scopal) arguments, scopal arguments (including qeqs), or label equalities. """ ids = {ep.id for ep in m.rels} g: Dict[Identifier, Set[Identifier]] = {id: set() for id in ids} # first establish links from labels and intrinsic variables to EPs for ep in m.rels: id, lbl, iv = ep.id, ep.label, ep.iv g[id].update((lbl, iv)) g.setdefault(lbl, set()).add(id) if iv: g.setdefault(iv, set()).add(id) # arguments may link EPs with IVs or labels (or qeq) as targets hcmap = {hc.hi: hc.lo for hc in m.hcons} for id, roleargs in m.arguments().items(): for role, value in roleargs: value = hcmap.get(value, value) # resolve qeq if any if value in g: g[id].add(value) g[value].add(id) return ids.issubset(util._bfs(g))
def _serialize_eds(e, properties, pretty_print, show_status, predicate_modifiers): if not isinstance(e, Eds): e = Eds.from_xmrs(e, predicate_modifiers=predicate_modifiers) # do something predictable for empty EDS if len(e.nodeids()) == 0: return '{:\n}' if pretty_print else '{:}' # determine if graph is connected g = {n: set() for n in e.nodeids()} for n in e.nodeids(): for tgt in e.edges(n).values(): g[n].add(tgt) g[tgt].add(n) nidgrp = _bfs(g, start=e.top) status = '' if show_status and nidgrp != set(e.nodeids()): status = ' (fragmented)' delim = '\n' if pretty_print else ' ' connected = ' ' if pretty_print else '' disconnected = '|' if show_status else ' ' return eds.format( top=e.top + ':' if e.top is not None else ':', flag=status, delim=delim, ed_list=delim.join( ed.format( membership=connected if n.nodeid in nidgrp else disconnected, id=n.nodeid, pred=n.pred.short_form(), lnk=str(n.lnk) if n.lnk else '', carg=carg.format(constant=n.carg) if n.carg else '', props=proplist.format( varsort=n.cvarsort + ' ' if n.cvarsort else '', proplist=', '.join( '{} {}'.format(k, v) for k, v in sorted(n.properties.items()) ) ) if properties and n.sortinfo else '', dep_list=(', '.join( '{} {}'.format(rargname, tgt) for rargname, tgt in sorted( e.edges(n.nodeid).items(), key=lambda x: rargname_sortkey(x[0]) ) )), ) for n in e.nodes() ), enddelim='\n' if pretty_print else '' )
def to_triples(d, properties=True, lnk=True): """ Encode *d* as triples suitable for PENMAN serialization. """ # determine if graph is connected g = {node.id: set() for node in d.nodes} for link in d.links: g[link.start].add(link.end) g[link.end].add(link.start) main_component = _bfs(g, start=d.top) complete = True idmap = {} quantifiers = {node.id for node in d.nodes if d.is_quantifier(node.id)} for i, node in enumerate(d.nodes, 1): if node.id in quantifiers: idmap[node.id] = 'q' + str(i) else: idmap[node.id] = '{}{}'.format(node.type or '_', i) # sort the nodes so the top node appears first nodes = sorted(d.nodes, key=lambda n: d.top != n.id) triples = [] for node in nodes: if node.id in main_component: _id = idmap[node.id] triples.append((_id, ':instance', node.predicate)) if lnk and node.lnk is not None: triples.append((_id, ':lnk', '"{}"'.format(str(node.lnk)))) if node.carg is not None: triples.append((_id, ':carg', '"{}"'.format(node.carg))) if node.type: triples.append((_id, ':' + CVARSORT, node.type)) if properties: for key in sorted(node.properties, key=property_priority): value = node.properties[key] triples.append((_id, ':' + key.lower(), value)) else: complete = False # if d.top is not None: # triples.append((None, 'top', d.top)) for link in d.links: if link.start in main_component and link.end in main_component: start = idmap[link.start] end = idmap[link.end] relation = ':{}-{}'.format(link.role.upper(), link.post) triples.append((start, relation, end)) if not complete: logger.warning('disconnected graph cannot be completely encoded: %r', d) return triples
def is_connected(self): """ Return `True` if the Xmrs represents a connected graph. Subgraphs can be connected through things like arguments, QEQs, and label equalities. """ nids = set(self._nodeids) # the nids left to find if len(nids) == 0: raise XmrsError('Cannot compute connectedness of an empty Xmrs.') # build a basic dict graph of relations edges = [] # label connections for lbl in self.labels(): lblset = self.labelset(lbl) edges.extend((x, y) for x in lblset for y in lblset if x != y) # argument connections _vars = self._vars for nid in nids: for rarg, tgt in self.args(nid).items(): if tgt not in _vars: continue if IVARG_ROLE in _vars[tgt]['refs']: tgtnids = list(_vars[tgt]['refs'][IVARG_ROLE]) elif tgt in self._hcons: tgtnids = list(self.labelset(self.hcon(tgt)[2])) elif 'LBL' in _vars[tgt]['refs']: tgtnids = list(_vars[tgt]['refs']['LBL']) else: tgtnids = [] # connections are bidirectional edges.extend((nid, t) for t in tgtnids if nid != t) edges.extend((t, nid) for t in tgtnids if nid != t) g = {nid: set() for nid in nids} for x, y in edges: g[x].add(y) connected_nids = _bfs(g) if connected_nids == nids: return True elif connected_nids.difference(nids): raise XmrsError('Possibly bogus nodeids: {}'.format(', '.join( connected_nids.difference(nids)))) return False
def to_triples(e, properties=True, lnk=True): """ Encode the Eds as triples suitable for PENMAN serialization. """ # determine if graph is connected g = {node.id: set() for node in e.nodes} for node in e.nodes: for target in node.edges.values(): g[node.id].add(target) g[target].add(node.id) main_component = _bfs(g, start=e.top) complete = True triples = [] # sort node ids just so top var is first nodes = sorted(e.nodes, key=lambda n: n.id != e.top) for node in nodes: nid = node.id if nid in main_component: triples.append((nid, ':instance', node.predicate)) if lnk and node.lnk: triples.append((nid, ':lnk', '"{}"'.format(str(node.lnk)))) if node.carg: triples.append((nid, ':carg', '"{}"'.format(node.carg))) if node.type is not None: triples.append((nid, ':type', node.type)) if properties: for prop in sorted(node.properties, key=property_priority): rel = ':' + prop.lower() triples.append((nid, rel, node.properties[prop])) for role in sorted(node.edges, key=role_priority): triples.append((nid, ':' + role, node.edges[role])) else: complete = False if not complete: logger.warning( 'disconnected graph cannot be completely encoded: %r', e) return triples