Source code for delphin.dmrs._operations


"""
Operations on DMRS structures
"""

import warnings
from typing import Callable, Dict, List, Optional, cast

from delphin import dmrs, mrs, scope, variable

_HCMap = Dict[str, mrs.HCons]
_IdMap = Dict[str, int]


[docs] def from_mrs( m: mrs.MRS, representative_priority: Optional[Callable] = None ) -> dmrs.DMRS: """ Create a DMRS by converting from MRS *m*. In order for MRS to DMRS conversion to work, the MRS must satisfy the intrinsic variable property (see :func:`delphin.mrs.has_intrinsic_variable_property`). Args: m: the input MRS representative_priority: a function for ranking candidate representative nodes; see :func:`scope.representatives` Returns: DMRS Raises: DMRSError when conversion fails. """ hcmap: _HCMap = {hc.hi: hc for hc in m.hcons} reps = scope.representatives(m, priority=representative_priority) # EP id to node id map; create now to keep ids consistent id_to_nid: _IdMap = {ep.id: i for i, ep in enumerate(m.rels, dmrs.FIRST_NODE_ID)} iv_to_nid: _IdMap = {ep.iv: id_to_nid[ep.id] for ep in m.rels if not ep.is_quantifier()} top = _mrs_get_top(m.top, hcmap, reps, id_to_nid) # some bad MRSs have an INDEX that isn't the ARG0 of any EP, so # make sure it exists first index = None if m.index and m.index in iv_to_nid: index = iv_to_nid[m.index] nodes = _mrs_to_nodes(m, id_to_nid) links = _mrs_to_links(m, hcmap, reps, iv_to_nid, id_to_nid) return dmrs.DMRS( top=top, index=index, nodes=nodes, links=links, lnk=m.lnk, surface=m.surface, identifier=m.identifier)
def _mrs_get_top( top_var: Optional[str], hcmap: _HCMap, reps: scope.ScopeMap, id_to_nid: _IdMap ) -> Optional[int]: top: Optional[int] if top_var is None: top = None else: lbl = hcmap[top_var].lo if top_var in hcmap else top_var if lbl in reps: rep = reps[lbl][0] assert isinstance(rep, mrs.EP) top = id_to_nid[rep.id] else: warnings.warn( f'unusable TOP: {top_var}', dmrs.DMRSWarning, stacklevel=2, ) top = None return top def _mrs_to_nodes(m: mrs.MRS, id_to_nid: _IdMap) -> List[dmrs.Node]: nodes = [] for ep in m.rels: node_id = id_to_nid[ep.id] properties, type = None, None if not ep.is_quantifier(): iv = ep.iv if iv is None: warnings.warn( f'missing intrinsic variable for {ep!r}; morphosemantic ' 'properties and node type information will be lost', dmrs.DMRSWarning, stacklevel=2, ) properties = {} type = variable.UNSPECIFIC else: properties = m.properties(iv) type = variable.type(iv) nodes.append( dmrs.Node(node_id, ep.predicate, type, properties, ep.carg, ep.lnk, ep.surface, ep.base)) return nodes def _mrs_to_links( m: mrs.MRS, hcmap: _HCMap, reps: scope.ScopeMap, iv_to_nid: _IdMap, id_to_nid: _IdMap ) -> List[dmrs.Link]: links = [] # links from arguments for src, roleargs in m.arguments().items(): start = id_to_nid[src] src_ep = cast(mrs.EP, m[src]) for role, tgt in roleargs: # non-scopal arguments if tgt in iv_to_nid: tgt_ep = cast(mrs.EP, m[tgt]) end = iv_to_nid[tgt] if src_ep.label == tgt_ep.label: post = dmrs.EQ_POST else: post = dmrs.NEQ_POST # scopal arguments else: if tgt in hcmap: lbl = hcmap[tgt].lo post = dmrs.H_POST if lbl not in reps: warnings.warn( f'broken handle constraint: {hcmap[tgt]}', dmrs.DMRSWarning, stacklevel=2, ) else: lbl = tgt post = dmrs.HEQ_POST if lbl in reps and len(reps[lbl]) > 0: ep = reps[lbl][0] assert isinstance(ep, mrs.EP) end = id_to_nid[ep.id] # BODY, dropped arguments, invalid, etc. else: continue links.append(dmrs.Link(start, end, role, post)) # MOD/EQ links for shared labels without argumentation for _label, eps in reps.items(): if len(eps) > 1: ep = eps[0] assert isinstance(ep, mrs.EP) end = id_to_nid[ep.id] for src in eps[1:]: start = id_to_nid[src.id] links.append( dmrs.Link(start, end, dmrs.BARE_EQ_ROLE, dmrs.EQ_POST)) return links