def test_Sortinfo_subclasses_dict(self): """ Dicts of sortinfo objects should map from features to values, including 'cvarsort' as a feature """ event = EventSortinfo('prop', 'past', 'indicative', '-', '-') event_dict = {'cvarsort':'e', 'sf':'prop', 'tense':'past', 'mood':'indicative', 'perf':'-', 'prog':'-'} self.assertEqual(event.as_dict(), event_dict) self.assertEqual(event, EventSortinfo.from_dict(event_dict)) instance = InstanceSortinfo('3', 'sg', 'f', '+', '+') instance_dict = {'cvarsort':'x', 'pers':'3', 'num':'sg', 'gend':'f', 'ind':'+', 'pt':'+'} self.assertEqual(instance.as_dict(), instance_dict) self.assertEqual(instance, InstanceSortinfo.from_dict(instance_dict))
def test_Sortinfo_subclasses_str(self): """ Strings of sortinfo objects should be of the form: cvarsort[feature1=value1, feature2=value2, ...] """ event = EventSortinfo('prop', 'past', 'indicative', '-', '-') event_string = 'e[sf=prop, tense=past, mood=indicative, perf=-, prog=-]' self.assertEqual(str(event), event_string) self.assertEqual(event, EventSortinfo.from_string(event_string)) instance = InstanceSortinfo('3', 'sg', 'f', '+', '+') instance_string = 'x[pers=3, num=sg, gend=f, ind=+, pt=+]' self.assertEqual(str(instance), instance_string) self.assertEqual(instance, InstanceSortinfo.from_string(instance_string))
def the_dog_chases_the_cat_and_the_mouse(): return DictDmrs(nodes=[ Node(nodeid=1, pred=RealPred('the', 'q')), Node(nodeid=2, pred=RealPred('dog', 'n', '1'), sortinfo=InstanceSortinfo(pers='3', num='sg', ind='+')), Node(nodeid=3, pred=RealPred('chase', 'v', '1'), sortinfo=EventSortinfo(sf='prop', tense='pres', mood='indicative')), Node(nodeid=4, pred=RealPred('the', 'q')), Node(nodeid=5, pred=RealPred('cat', 'n', '1'), sortinfo=InstanceSortinfo(pers='3', num='sg', ind='+')), Node(nodeid=6, pred=GPred('udef_q')), Node(nodeid=7, pred=RealPred('and', 'c'), sortinfo=InstanceSortinfo(pers='3', num='pl')), Node(nodeid=8, pred=RealPred('the', 'q')), Node(nodeid=9, pred=RealPred('mouse', 'n', '1'), sortinfo=InstanceSortinfo(pers='3', num='sg', ind='+')) ], links=[ Link(start=1, end=2, rargname='RSTR', post='H'), Link(start=3, end=2, rargname='ARG1', post='NEQ'), Link(start=3, end=7, rargname='ARG2', post='NEQ'), Link(start=4, end=5, rargname='RSTR', post='H'), Link(start=6, end=7, rargname='RSTR', post='H'), Link(start=7, end=5, rargname='L-INDEX', post='NEQ'), Link(start=7, end=9, rargname='R-INDEX', post='NEQ'), Link(start=8, end=9, rargname='RSTR', post='H') ], index=3, top=3)
def test_Sortinfo_subclasses_repr(self): """ Repr strings should evaluate to equivalent objects """ event = EventSortinfo('prop', 'past', 'indicative', '-', '-') self.assertEqual(event, eval(repr(event))) instance = InstanceSortinfo('3', 'sg', 'f', '+', '+') self.assertEqual(instance, eval(repr(instance)))
def test_Sortinfo_from_string(self): """ Initialise EventSortinfo or InstanceSortinfo as appropriate """ event_string = "e[tense=past]" self.assertEqual(Sortinfo.from_string(event_string), EventSortinfo.from_string(event_string)) instance_string = "x[num=pl]" self.assertEqual(Sortinfo.from_string(instance_string), InstanceSortinfo.from_string(instance_string))
def change_ref(self, old_ref, new_ref): if self.top_handle == old_ref: self.top_handle = new_ref if self.index_ref == old_ref: self.index_ref = new_ref if old_ref in self.eps: if new_ref not in self.eps: self.eps[new_ref] = {} for ep in self.eps.pop(old_ref).values(): ep.label = new_ref assert ep.intrinsic not in self.eps[new_ref] self.eps[new_ref][ep.intrinsic] = ep if old_ref in self.quant_eps: assert new_ref not in self.quant_eps self.quant_eps[new_ref] = self.quant_eps.pop(old_ref) self.quant_eps[new_ref].intrinsic = new_ref assert new_ref not in self.eps[self.quant_eps[new_ref].label] self.eps[self.quant_eps[new_ref].label][new_ref] = self.eps[self.quant_eps[new_ref].label].pop(old_ref) if old_ref in self.var_eps: assert new_ref not in self.var_eps self.var_eps[new_ref] = self.var_eps.pop(old_ref) self.var_eps[new_ref].intrinsic = new_ref assert new_ref not in self.eps[self.var_eps[new_ref].label] self.eps[self.var_eps[new_ref].label][new_ref] = self.eps[self.var_eps[new_ref].label].pop(old_ref) assert new_ref not in self.vars assert old_ref.is_sortinfo() self.vars.pop(old_ref) if new_ref.is_event(): self.vars[new_ref] = Variable(new_ref, EventSortinfo(None, None, None, None, None)) elif new_ref.is_instance(): self.vars[new_ref] = Variable(new_ref, InstanceSortinfo(None, None, None, None, None)) else: assert False for eps in self.eps.values(): for ep in eps.values(): for i, (role, arg) in enumerate(ep.args.items()): if arg == old_ref: ep.args[role] = new_ref for hole, label in self.hcons.items(): if hole == old_ref: self.hcons[new_ref] = label if label == old_ref: self.hcons[hole] = new_ref for i, (ref1, icon, ref2) in enumerate(self.icons): if ref1 == old_ref: self.icons[i] = (new_ref, icon, ref2) if ref2 == old_ref: self.icons[i] = (ref1, icon, new_ref) for i, (hole, label) in enumerate(self.icon_hcons): if hole == old_ref: self.icon_hcons[i] = (new_ref, label) if label == old_ref: self.icon_hcons[i] = (hole, new_ref)
def test_Sortinfo_subclasses_iter(self): """ Subclasses of Sortinfo should iter over feature names, including 'cvarsort' """ event = EventSortinfo('prop', 'past', 'indicative', '-', '-') instance = InstanceSortinfo('3', 'sg', 'f', '+', '+') self.assertEqual(list(iter(event)), ['cvarsort', 'sf', 'tense', 'mood', 'perf', 'prog']) self.assertEqual(event.features, ('sf', 'tense', 'mood', 'perf', 'prog')) self.assertEqual(list(iter(instance)), ['cvarsort', 'pers', 'num', 'gend', 'ind', 'pt']) self.assertEqual(instance.features, ('pers', 'num', 'gend', 'ind', 'pt'))
def test_EventSortinfo_init(self): """ Events have five features: 'sf', 'tense', 'mood', 'perf', 'prog' """ event = EventSortinfo('prop', 'past', 'indicative', '-', '-') self.assertEqual(event.cvarsort, 'e') self.assertEqual(event.sf, 'prop') self.assertEqual(event.tense, 'past') self.assertEqual(event.mood, 'indicative') self.assertEqual(event.perf, '-') self.assertEqual(event.prog, '-') self.assertEqual(event['cvarsort'], 'e') self.assertEqual(event['sf'], 'prop') self.assertEqual(event['tense'], 'past') self.assertEqual(event['mood'], 'indicative') self.assertEqual(event['perf'], '-') self.assertEqual(event['prog'], '-') event.tense = 'present' self.assertEqual(event['tense'], 'present') event['perf'] = '+' self.assertEqual(event.perf, '+') del event.perf self.assertIsNone(event['perf']) del event['sf'] self.assertIsNone(event.sf) with self.assertRaises((AttributeError, KeyError)): event['cvarsort'] = 'x' with self.assertRaises((AttributeError, KeyError)): event.cvarsort = 'x' with self.assertRaises(KeyError): event['num'] with self.assertRaises(AttributeError): event.num with self.assertRaises(TypeError): EventSortinfo('1','2','3','4','5','6')
def __str__(self): if self.cfrom is None or self.cto is None: span = '' else: span = '<{}:{}>'.format(self.cfrom, self.cto) if self.is_quantifier(): var = self.intrinsic if var.is_event(): # TODO: Hack for Chinese var = self.mrs.head_ep(label=self.mrs.hcons[self.mrs.var_eps[var].args['arg1']]).intrinsic elif self.is_icon(): var = Variable(self.intrinsic, EventSortinfo('prop', None, None, None, None)) else: var = self.mrs.vars[self.intrinsic] args_str = ''.join('{}: {} '.format(role.upper(), var if role == 'arg0' else self.args[role]) for role in ('arg1', 'arg2', 'arg3', 'arg4', 'arg', 'rstr', 'body', 'l-index', 'r-index', 'l-hndl', 'r-hndl') if role in self.args) if self.carg is None: return '[ {}_rel{} LBL: {} ARG0: {} {}]'.format(self.pred, span, self.label, var, args_str) else: return '[ {}_rel{} LBL: {} CARG: "{}" ARG0: {} {}]'.format(self.pred, span, self.label, self.carg, var, args_str)
def the_cat_chases_the_dog(): return DictDmrs(surface='the cat chases the dog', nodes=[ Node(nodeid=1, pred=RealPred('the', 'q'), cfrom=0, cto=3), Node(nodeid=2, pred=RealPred('cat', 'n', '1'), cfrom=4, cto=7, sortinfo=InstanceSortinfo(pers='3', num='sg', ind='+')), Node(nodeid=3, pred=RealPred('chase', 'v', '1'), cfrom=8, cto=14, sortinfo=EventSortinfo(sf='prop', tense='pres', mood='indicative')), Node(nodeid=4, pred=RealPred('the', 'q'), cfrom=15, cto=18), Node(nodeid=5, pred=RealPred('dog', 'n', '1'), cfrom=19, cto=22, sortinfo=InstanceSortinfo(pers='3', num='sg', ind='+')) ], links=[ Link(start=1, end=2, rargname='RSTR', post='H'), Link(start=3, end=2, rargname='ARG1', post='NEQ'), Link(start=3, end=5, rargname='ARG2', post='NEQ'), Link(start=4, end=5, rargname='RSTR', post='H') ], index=3, top=3)
def test_Sortinfo_from_dict(self): """ Initialise EventSortinfo or InstanceSortinfo as appropriate """ sortinfo_dict = {'cvarsort': 'i'} self.assertEqual(Sortinfo.from_dict(sortinfo_dict), Sortinfo()) event_dict = {'cvarsort': 'e', 'tense': 'past'} self.assertEqual(Sortinfo.from_dict(event_dict), EventSortinfo.from_dict(event_dict)) instance_dict = {'cvarsort': 'x', 'num': 'pl'} self.assertEqual(Sortinfo.from_dict(instance_dict), InstanceSortinfo.from_dict(instance_dict)) wrong_sort_sortinfo_dict = {'cvarsort': 'u'} self.assertEqual(Sortinfo.from_dict(wrong_sort_sortinfo_dict), Sortinfo.from_dict(sortinfo_dict)) wrong_sort_event_dict = {'cvarsort': 'i', 'tense': 'past'} self.assertEqual(Sortinfo.from_dict(wrong_sort_event_dict), Sortinfo.from_dict(event_dict)) wrong_sort_instance_dict = {'cvarsort': 'u', 'num': 'pl'} self.assertEqual(Sortinfo.from_dict(wrong_sort_instance_dict), Sortinfo.from_dict(instance_dict))
def map(self, dmrs, nodeid, hierarchy=None): """ Overrides the values of the target node if they are not underspecified in this anchor node. :param dmrs Target DMRS graph. :param nodeid Target node id. :param hierarchy: An optional predicate hierarchy. """ node = dmrs[nodeid] if self == node or self.is_less_specific(node, hierarchy=hierarchy): return if isinstance(self.pred, RealPred): if isinstance(node.pred, RealPred): node.pred = RealPred(node.pred.lemma if self.pred.lemma == '?' else self.pred.lemma, node.pred.pos if self.pred.pos in ('u', '?') else self.pred.pos, node.pred.sense if self.pred.sense in ('unknown', '?') else self.pred.sense) else: node.pred = copy.deepcopy(self.pred) elif isinstance(self.pred, GPred): if isinstance(node.pred, GPred): node.pred = GPred(node.pred.name if self.pred.name == '?' else self.pred.name) else: node.pred = copy.deepcopy(self.pred) elif not isinstance(self.pred, Pred): node.pred = None if isinstance(self.sortinfo, EventSortinfo): if isinstance(node.sortinfo, EventSortinfo): node.sortinfo = EventSortinfo(node.sortinfo.sf if self.sortinfo.sf in ('u', '?') else self.sortinfo.sf, node.sortinfo.tense if self.sortinfo.tense in ('u', '?') else self.sortinfo.tense, node.sortinfo.mood if self.sortinfo.mood in ('u', '?') else self.sortinfo.mood, node.sortinfo.perf if self.sortinfo.perf in ('u', '?') else self.sortinfo.perf, node.sortinfo.prog if self.sortinfo.prog in ('u', '?') else self.sortinfo.prog) else: node.sortinfo = copy.deepcopy(self.sortinfo) elif isinstance(self.sortinfo, InstanceSortinfo): if isinstance(node.sortinfo, InstanceSortinfo): node.sortinfo = InstanceSortinfo(node.sortinfo.pers if self.sortinfo.pers in ('u', '?') else self.sortinfo.pers, node.sortinfo.num if self.sortinfo.num in ('u', '?') else self.sortinfo.num, node.sortinfo.gend if self.sortinfo.gend in ('u', '?') else self.sortinfo.gend, node.sortinfo.ind if self.sortinfo.ind in ('u', '?') else self.sortinfo.ind, node.sortinfo.pt if self.sortinfo.pt in ('u', '?') else self.sortinfo.pt) else: node.sortinfo = copy.deepcopy(self.sortinfo) elif not isinstance(self.sortinfo, Sortinfo): node.sortinfo = None if self.carg != '?': node.carg = self.carg
def test_Node_underspecification(self): with self.assertRaises(TypeError): Node(pred='_the_q').is_more_specific(4) # complete underspecification self.assertFalse(Node().is_more_specific(Node())) self.assertFalse(Node().is_less_specific(Node())) # pred underspecification self.assertFalse(Node(pred=Pred()).is_more_specific(Node())) self.assertTrue(Node(pred=Pred()).is_less_specific(Node())) self.assertTrue(Node().is_more_specific(Node(pred=Pred()))) self.assertFalse(Node().is_less_specific(Node(pred=Pred()))) self.assertFalse(Node(pred=Pred()).is_more_specific(Node(pred=Pred()))) self.assertFalse(Node(pred=Pred()).is_less_specific(Node(pred=Pred()))) self.assertFalse( Node(pred=Pred()).is_more_specific(Node(pred=GPred(name='abc')))) self.assertTrue( Node(pred=Pred()).is_less_specific(Node(pred=GPred(name='abc')))) self.assertTrue( Node(pred=GPred(name='abc')).is_more_specific(Node(pred=Pred()))) self.assertFalse( Node(pred=GPred(name='abc')).is_less_specific(Node(pred=Pred()))) # carg underspecification self.assertFalse(Node(carg='?').is_more_specific(Node())) self.assertTrue(Node(carg='?').is_less_specific(Node())) self.assertTrue(Node().is_more_specific(Node(carg='?'))) self.assertFalse(Node().is_less_specific(Node(carg='?'))) self.assertFalse(Node(carg='?').is_more_specific(Node(carg='?'))) self.assertFalse(Node(carg='?').is_less_specific(Node(carg='?'))) self.assertFalse(Node(carg='?').is_more_specific(Node(carg='abc'))) self.assertTrue(Node(carg='?').is_less_specific(Node(carg='abc'))) self.assertTrue(Node(carg='abc').is_more_specific(Node(carg='?'))) self.assertFalse(Node(carg='abc').is_less_specific(Node(carg='?'))) # sortinfo underspecification self.assertFalse(Node(sortinfo=Sortinfo()).is_more_specific(Node())) self.assertTrue(Node(sortinfo=Sortinfo()).is_less_specific(Node())) self.assertTrue(Node().is_more_specific(Node(sortinfo=Sortinfo()))) self.assertFalse(Node().is_less_specific(Node(sortinfo=Sortinfo()))) self.assertFalse( Node(sortinfo=Sortinfo()).is_more_specific( Node(sortinfo=Sortinfo()))) self.assertFalse( Node(sortinfo=Sortinfo()).is_less_specific( Node(sortinfo=Sortinfo()))) self.assertFalse( Node(sortinfo=Sortinfo()).is_more_specific( Node(sortinfo=EventSortinfo(sf='abc')))) self.assertTrue( Node(sortinfo=Sortinfo()).is_less_specific( Node(sortinfo=EventSortinfo(sf='abc')))) self.assertTrue( Node(sortinfo=EventSortinfo(sf='abc')).is_more_specific( Node(sortinfo=Sortinfo()))) self.assertFalse( Node(sortinfo=EventSortinfo(sf='abc')).is_less_specific( Node(sortinfo=Sortinfo()))) # mixed specification self.assertFalse(Node(pred=Pred()).is_more_specific(Node(carg='?'))) self.assertFalse(Node(pred=Pred()).is_less_specific(Node(carg='?'))) self.assertFalse( Node(pred=Pred()).is_more_specific(Node(sortinfo=Sortinfo()))) self.assertFalse( Node(pred=Pred()).is_less_specific(Node(sortinfo=Sortinfo()))) self.assertFalse( Node(carg='?').is_more_specific(Node(sortinfo=Sortinfo()))) self.assertFalse( Node(carg='?').is_less_specific(Node(sortinfo=Sortinfo())))
def test_Sortinfo_cmp(self): """ Sortinfo objects should be equal if all features are equal. An underspecified Sortinfo should be less than a specified one. """ sortinfo = Sortinfo() event = EventSortinfo('prop', 'past', 'indicative', '-', None) event2 = EventSortinfo('prop', 'past', 'indicative', '-', None) instance = InstanceSortinfo('3', 'sg', 'f', '+', None) instance2 = InstanceSortinfo('3', 'sg', 'f', '+', None) underspec_event = EventSortinfo('?', 'u', 'indicative', '-', 'u') underspec_instance = InstanceSortinfo('?', 'u', 'f', '+', 'u') another_event = EventSortinfo('prop', 'past', 'indicative', '?', '?') another_instance = InstanceSortinfo('3', 'sg', 'f', '?', '?') self.assertEqual(event, event2) self.assertFalse(event.is_less_specific(event2)) self.assertFalse(event.is_more_specific(event2)) self.assertEqual(instance, instance2) self.assertFalse(instance.is_less_specific(instance2)) self.assertFalse(instance.is_less_specific(instance2)) self.assertNotEqual(event, underspec_event) self.assertNotEqual(event, sortinfo) self.assertNotEqual(instance, underspec_instance) self.assertNotEqual(instance, sortinfo) self.assertNotEqual(underspec_instance, sortinfo) self.assertNotEqual(underspec_instance, sortinfo) self.assertTrue(sortinfo.is_less_specific(underspec_event)) self.assertTrue(underspec_event.is_less_specific(event)) self.assertTrue(sortinfo.is_less_specific(underspec_instance)) self.assertTrue(underspec_instance.is_less_specific(instance)) self.assertFalse(underspec_event.is_less_specific(another_event)) self.assertFalse(underspec_event.is_more_specific(another_event)) self.assertFalse(underspec_instance.is_less_specific(another_instance)) self.assertFalse(underspec_instance.is_more_specific(another_instance))
def _read_variable(string, vs, rs, replace=True): if '[' not in string: ref = _read_reference(string, vs, rs, replace=replace) if replace: ref = rs.get(ref, ref) if ref in vs: return ref, vs.pop(ref) elif ref.sort == 'e': return ref, Variable(ref, EventSortinfo(None, None, None, None, None)) elif ref.sort == 'x': return ref, Variable( ref, InstanceSortinfo(None, None, None, None, None)) else: return ref, Variable(ref, Sortinfo()) assert string[-1] == ']' r = string.index('[') ref = _read_reference(string[:find_previous(string, end=r) + 1], vs, rs, replace=replace) if replace: ref = rs.get(ref, ref) l = find_next(string, start=r + 1) assert replace or string[l] == ref.sort l = find_next(string, start=l + 1) r = find_previous(string, end=len(string) - 1) + 1 attributes = _read_attributes(string[l:r]) if 'prontype' in attributes: assert 'pt' not in attributes attributes['pt'] = attributes.pop('prontype') if any(attr in ('sf', 'tense', 'mood', 'perf', 'prog') for attr in attributes): assert not any(attr in ('pers', 'num', 'gend', 'ind', 'pt') for attr in attributes) sf = attributes.pop('sf', None) tense = attributes.pop('tense', None) mood = attributes.pop('mood', None) perf = attributes.pop('perf', None) prog = attributes.pop('prog', None) assert sf in ('u', 'comm', 'prop', 'ques', 'prop-or-ques', 'prop-or-like'), 'Sentence force' assert tense in (None, 'u', 'untensed', 'tensed', 'pres', 'past', 'fut'), 'Tense' assert mood in (None, 'u', 'indicative', 'subjunctive'), 'Mood' assert perf in (None, 'u', '+', '-', 'plus', 'minus'), 'Perfect' assert prog in (None, 'u', '+', '-', 'plus', 'minus', 'bool'), 'Progressive' sortinfo = EventSortinfo(sf, tense, mood, perf, prog) elif any(attr in ('pers', 'num', 'gend', 'ind', 'pt') for attr in attributes): assert not any(attr in ('sf', 'tense', 'mood', 'perf', 'prog') for attr in attributes) pers = attributes.pop('pers', None) num = attributes.pop('num', None) gend = attributes.pop('gend', None) ind = attributes.pop('ind', None) pt = attributes.pop('pt', None) assert pers in (None, 'u', '1', '2', '3', '1-or-3'), 'Person' assert num in (None, 'u', 'sg', 'pl'), 'Number' assert gend in (None, 'u', 'f', 'm', 'n', 'm-or-f'), 'Gender' assert ind in (None, 'u', '+', '-', 'plus', 'minus'), 'Individuated' assert pt in (None, 'u', 'notpro', 'std', 'std_pron', 'zero', 'zero_pron', 'refl'), 'Pronoun type' sortinfo = InstanceSortinfo(pers, num, gend, ind, pt) else: if ref.sort == 'e': sortinfo = EventSortinfo(None, None, None, None, None) elif ref.sort == 'x': sortinfo = InstanceSortinfo(None, None, None, None, None) else: sortinfo = Sortinfo() assert not attributes, 'Invalid variable attributes: {}'.format(attributes) if ref.sort != sortinfo.cvarsort: if replace: var = None else: replace_ref = Reference(sortinfo.cvarsort, ref.index) rs[ref] = replace_ref var = Variable(replace_ref, sortinfo) else: var = Variable(ref, sortinfo) return ref, var
def sortinfo(self): if self.is_quantifier(): return None elif self.is_icon(): return EventSortinfo('prop', None, None, None, None) return self.mrs.vars[self.intrinsic].sortinfo