-
Notifications
You must be signed in to change notification settings - Fork 29
Description
In the new delphin.scope module I had a function tree_fragments() which constructed the partial scope trees and allowed inspection of immediately lower scopes (lheqs) and indirectly lower scopes (qeqs) for each scope label. In the end I needed per-predicate granularity when looking at scopal descendants (rather than the descendants of the whole scope) for representative node selection, so I started finding other ways of doing this. With scope.descendants() I no longer need the UnderspecifiedScope class or the tree_fragments() function. They may still be useful in the future for enumerating scope readings (see #221) so I copy those bits of code here. Re-adding the same functionality to PyDelphin might not use the code directly; they are just copied for reference.
class UnderspecifiedScope(tuple):
"""
Quantifier scope with underspecified constraints.
This class serves as the nodes in the scope tree fragments used by
MRS (and transformations of DMRS). It combines three data
structures:
* the ids of predications in the immediate scope
* a mapping of labels to :class:`UnderspecifiedScope` objects for
scopes directly under the current scope
* a mapping of labels to :class:`UnderspecifiedScope` objects for
scopes qeq from the current scope
This class is not meant to be instantiated directly, but rather is
used in the return value of functions such as
:func:`tree_fragments`.
Attributes:
ids: ids of predications in the immediate scope
lheqs: mapping of labels to underspecified scopes directly
under the current scope
qeqs: mapping of labels to underspecified scopes qeq from
the current scope
"""
__slots__ = ()
def __new__(cls,
ids: Container[Identifier],
lheqs: UnderspecifiedFragments = None,
qeqs: UnderspecifiedFragments = None):
if lheqs is None:
lheqs = {}
if qeqs is None:
qeqs = {}
return super().__new__(cls, (set(ids), dict(lheqs), dict(qeqs)))
ids = property(
itemgetter(0), doc='set of ids of predicates in the immediate scope')
lheqs = property(
itemgetter(1), doc='directly lower scopes')
qeqs = property(
itemgetter(2), doc='indirectly lower scopes')
def __repr__(self):
return 'UnderspecifiedScope({!r}, {!r}, {!r})'.format(*self)
def __contains__(self, id):
return (id in self.ids
or any(id in lower for lower in self.lheqs.values())
or any(id in lower for lower in self.qeqs.values()))def tree_fragments(x: ScopingSemanticStructure,
prune=True) -> UnderspecifiedFragments:
"""
Return a mapping of scope labels to underspecified tree fragments.
Each fragment is an :class:`UnderspecifiedScope` object.
By default the top-level mapping only includes the fragments that
are not specified as being under another scope. By setting the
*prune* parameter to `False` all scope labels are included in the
mapping, which may be helpful for applications needing direct
access to lower scopes.
Args:
x: an MRS or DMRS
prune: if `True` only include top-level scopes in the mapping
"""
scopes = x.scopes()
fragments = {x.top: UnderspecifiedScope([])}
for label, ps in scopes.items():
fragments[label] = UnderspecifiedScope(ps)
nested = set()
for src, sc_roleargs in x.scopal_arguments(scopes).items():
for _, rel, label in sc_roleargs:
if rel == LHEQ:
fragments[src].lheqs[tgt] = fragments[tgt]
nested.add(tgt)
elif rel == QEQ:
fragments[src].qeqs[tgt] = fragments[tgt]
nested.add(tgt)
if prune:
for label in nested:
del fragments[label]
return fragments