Skip to content

Commit 7923fee

Browse files
committed
Clean up core specializer
1 parent 068c413 commit 7923fee

1 file changed

Lines changed: 24 additions & 52 deletions

File tree

src/main/nluas/language/core_specializer.py

Lines changed: 24 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ def __init__(self, analyzer):
4949

5050
self.fs = None
5151
UtilitySpecializer.__init__(self, analyzer)
52-
self.parameter_templates = OrderedDict() #self.read_templates(path+"parameter_templates.json")
53-
self.mood_templates = OrderedDict() #self.read_templates(path+"mood_templates.json")
52+
self.parameter_templates = OrderedDict()
53+
self.mood_templates = OrderedDict()
5454
self.descriptor_templates = OrderedDict()
5555
self.initialize_templates()
5656

@@ -62,7 +62,6 @@ def __init__(self, analyzer):
6262

6363
self.spans = None
6464

65-
#self.read_templates
6665

6766
def set_spans(self, spans):
6867
""" Sets the current constructional spans to input spans. These are used for referent resolution. (TODO)."""
@@ -82,8 +81,8 @@ def specialize_fragment(self, fs):
8281
return self.get_headingDescriptor(fs.m)
8382
elif self.analyzer.issubtype("SCHEMA", fs.m.type(), "PropertyModifier"):
8483
return self.get_property(fs.m)
85-
#elif self.analyzer.issubtype("SCHEMA", fs.m.type(), "EventDescriptor"): # Testing...
86-
# return self.specialize_event(fs.m)
84+
elif self.analyzer.issubtype("SCHEMA", fs.m.type(), "EventDescriptor"):
85+
return self.specialize_event(fs.m)
8786
elif self.analyzer.issubtype("SCHEMA", fs.m.type(), "Process"):
8887
return self.fill_parameters(fs.m)
8988
elif self.analyzer.issubtype("SCHEMA", fs.m.type(), "SPG"):
@@ -96,7 +95,6 @@ def specialize_fragment(self, fs):
9695
"objectDescriptor": self.get_objectDescriptor(fs.m.landmark)}}
9796
else:
9897
raise Exception("Unable to specialize fragment with meaning of {}.".format(fs.m.type()))
99-
#print("Unable to specialize fragment with meaning of {}.".format(fs.m.type()))
10098

10199
def initialize_templates(self):
102100
""" Initializes templates from path, set above. """
@@ -107,11 +105,9 @@ def initialize_templates(self):
107105

108106
def read_templates(self, filename):
109107
""" Sets each template to ordered dict."""
110-
#print("Parsing " + filename)
111108
base = OrderedDict()
112109
# Add basic information from templates
113110
with open(filename, "r") as data_file:
114-
#data = json.loads(data_file.read())
115111
data = json.load(data_file, object_pairs_hook=OrderedDict)
116112
for name, template in data['templates'].items():
117113
setattr(self, name, template)
@@ -124,25 +120,20 @@ def read_templates(self, filename):
124120
if parent in base:
125121
template = self.unify_templates(template, base[parent])
126122
else:
127-
raise TemplateException("Formatting issue with template definition for '{}'. Listed parent '{}' does not exist.".format(name, parent))
128123
# Throw exception
124+
raise TemplateException("Formatting issue with template definition for '{}'.\
125+
Listed parent '{}' does not exist.".format(name, parent))
129126
template.pop("parents")
130127
return base
131128

132129
def unify_templates(self, child, parent):
133-
""" Unifies a child and parent template. Adds all parent key-value pairs
130+
""" Unifies a child and parent template. Adds all parent key-value pairs
134131
unless the key already exists in the child. """
135132
child.update({key:value for (key, value) in parent.items() if key not in child})
136133
return child
137-
"""
138-
for k, v in parent.items():
139-
if k not in child:
140-
child.update({k: v})
141-
return child
142-
"""
143134

144135
def specialize_event(self, content):
145-
""" Takes in an EventDescriptor, and uses event_templates to drive specialization.
136+
""" Takes in an EventDescriptor, and uses event_templates to drive specialization.
146137
Calls fill_value for each item in the corresponding event template. """
147138
ed = content.type()
148139
if ed in self.event_templates:
@@ -154,10 +145,8 @@ def specialize_event(self, content):
154145
eventDescriptor[k] = self.fill_value(k, v, content)
155146
return eventDescriptor
156147

157-
158-
159148
def specialize(self, fs):
160-
""" Takes in a FeatureStruct (fs), produces an ntuple.
149+
""" Takes in a FeatureStruct (fs), produces an ntuple.
161150
Currently requires that the FS be a discourse utterance with a mood ("Declarative", etc.),
162151
and an associated EventDescriptor. However, this could be generalized to route
163152
specialized n-tuples for other types of input, like an NP.
@@ -168,7 +157,7 @@ def specialize(self, fs):
168157
self.fs = fs
169158
mood = str(fs.m.mood).replace("-", "_").lower()
170159
if hasattr(fs.m, "addressee"):
171-
addressee = self.get_objectDescriptor(fs.m.addressee) # and fs.m.addressee.has_filler()
160+
addressee = self.get_objectDescriptor(fs.m.addressee)
172161
if "referent" in addressee:
173162
self.addressees.append({'objectDescriptor': addressee})
174163
content = fs.m.content
@@ -181,15 +170,14 @@ def specialize(self, fs):
181170
parameters = ntuple['eventDescriptor']['eventProcess']
182171
if mood == "wh_question":
183172
ntuple['return_type'], ntuple['eventDescriptor']['eventProcess']['specificWh'] = self.get_return_type(parameters)
184-
173+
185174
if ntuple:
186175
ntuple = self.map_ontologies(ntuple)
187176

188177
if self.debug_mode:
189178
pprint.pprint(ntuple)
190179
return dict(ntuple)
191180

192-
193181
def get_return_type(self, parameters):
194182
""" If sentence is a wh-sentence, returns the corresponding return_type. """
195183
return_type, specificWh = "", ""
@@ -214,9 +202,8 @@ def get_return_type(self, parameters):
214202
return r, w
215203
return return_type, specificWh
216204

217-
218205
def fill_parameters(self, eventProcess):
219-
""" Identifies the corresponding parameter template ("MotionPath", etc.).
206+
""" Identifies the corresponding parameter template ("MotionPath", etc.).
220207
If none are found, it chooses a parent template ("Motion", "Process", etc.).
221208
For each item in the template, it calls fill_value. """
222209
process = eventProcess.type()
@@ -259,16 +246,13 @@ def get_process_modifiers(self, eventProcess):
259246
returned["instrument"] = self.get_objectDescriptor(modifier.instrument)
260247
return returned
261248

262-
263-
264249
def check_parameter_subtypes(self, process, templates):
265250
""" Finds the parent type of the input process among the template list. """
266251
for key in templates:
267252
if self.analyzer.issubtype("SCHEMA", process, key):
268253
return key
269254
return None
270255

271-
272256
def get_headingDescriptor(self, headingSchema):
273257
""" Returns a heading for a headingDescriptor. Could be more complex depending on domain,
274258
in which case the method would be overridden. """
@@ -314,7 +298,7 @@ def fill_value(self, key, value, input_schema):
314298
return attribute.type()
315299
elif attribute.__value__ != "None":
316300
return attribute.__value__
317-
301+
318302
#return value # TODO: Which one to return? Default or None?
319303
return final_value
320304

@@ -324,7 +308,9 @@ def get_negated(self, value):
324308

325309
def get_scaleDescriptor(self, scale):
326310
""" Returns a scaleDescriptor, with unit type, the actual value, and the associated property. """
327-
return {'units': scale.extras.quantity.units.type(), 'value': float(scale.extras.quantity.amount.value), 'property': scale.extras.quantity.property.type()}
311+
return {'units': scale.extras.quantity.units.type(),
312+
'value': float(scale.extras.quantity.amount.value),
313+
'property': scale.extras.quantity.property.type()}
328314

329315
def get_property(self, pm):
330316
""" Returns the relevant property values for a PropertyModifier. """
@@ -348,7 +334,6 @@ def get_property(self, pm):
348334
returned['direction'] = 'decrease'
349335
return returned
350336

351-
352337
def get_state(self, eventProcess):
353338
""" Returns the state for a Stasis Process. """
354339
predication = {}
@@ -400,7 +385,7 @@ def get_spgValue(self, spg, valueType):
400385
final = {}
401386
value = getattr(spg, valueType)
402387
if value.type() == "home":
403-
return {'location':"home"}
388+
return {'location':"home"}
404389
elif value.ontological_category.type() == "location":
405390
return {'location': (float(value.xCoord), float(value.xCoord))}
406391
elif value.ontological_category.type() == "region":
@@ -452,14 +437,12 @@ def get_eventFeatures(self, e_features):
452437
return final
453438

454439
def get_relationDescriptor(self, relation):
455-
""" Returns a relation descriptor, describing in a high-level way the relation between several entities.
440+
""" Returns a relation descriptor, describing in a high-level way the relation between several entities.
456441
The Problem Solver then uses the relation in the application domain's context to determine the actual meaning. """
457442
returned = dict()
458443
template = self.descriptor_templates["relationDescriptor"] if "relationDescriptor" in self.descriptor_templates else dict()
459444
for k, v in template.items():
460-
#if hasattr(relation, v) and getattr(relation, v).has_filler():
461445
value = self.fill_value(k, v, relation)
462-
#print(value)
463446
if value:
464447
returned[k] = value
465448
return returned
@@ -470,22 +453,19 @@ def get_conjRDDescriptor(self, item, resolving=False):
470453
first=self.get_objectDescriptor(item.rd1),
471454
second=self.get_objectDescriptor(item.rd2))
472455

473-
474-
475456
def get_objectDescriptor(self, item, resolving=False):
476457
""" Returns an object descriptor from descriptor template. Uses RD elements, as well as other things pointing to object. """
477458
returned = {}
478459
if "pointers" not in item.__dir__():
479460
item.pointers = self.invert_pointers(item)
480461
if self.analyzer.issubtype("SCHEMA", item.type(), "ConjRD"):
481462
returned = self.get_conjRDDescriptor(item, resolving)
482-
463+
483464
template = self.descriptor_templates['objectDescriptor'] if "objectDescriptor" in self.descriptor_templates else dict()
484465
allowed_pointers = template['pointers'] if 'pointers' in template else []
485-
466+
486467
for k, v in template.items():
487-
if k not in ["pointers", "description"] and hasattr(item, k):# and getattr(item, v).type():
488-
#attribute = getattr(item, v).type()
468+
if k not in ["pointers", "description"] and hasattr(item, k):
489469
attribute = self.fill_value(k, v, item)
490470
if k == "ontological_category":
491471
k = "type"
@@ -513,19 +493,16 @@ def get_objectDescriptor(self, item, resolving=False):
513493
return self.resolve_referents(returned, antecedents=self.addressees)['objectDescriptor']
514494
return returned
515495

516-
517496
def get_RDExtras(self, extras):
518497
""" RD Extras contain embedded RD information, like specificWh, Event-description, quantity. """
519498
template = self.descriptor_templates['RDExtras']
520499
returned = {}
521500
for key, value in template.items():
522-
#if hasattr(extras, value):
523501
final = self.fill_value(key, value, extras)
524502
if final:
525503
returned[key] = final
526504
return returned
527505

528-
529506
def get_eventRDDescriptor(self, item):
530507
""" Event RDs have an associated event description. """
531508
# TODO: Event/entity resolution?
@@ -541,7 +518,6 @@ def get_eventRDDescriptor(self, item):
541518
returned.update(eventDescription)
542519
return returned
543520

544-
545521
def fill_pointer(self, pointer, item):
546522
""" Fills pointers to an RD in a structured way. """
547523
if hasattr(pointer, "modifiedThing") and pointer.modifiedThing.index() != item.index():
@@ -553,9 +529,9 @@ def fill_pointer(self, pointer, item):
553529
elif hasattr(pointer, "possessed") and pointer.possessed.index() != item.index():
554530
return None
555531
else:
556-
#if self.analyzer.issubtype("SCHEMA", pointer.type(), "MetaphoricalScalarModification"):
557-
# value = float(pointer.value) if pointer.value.type() == "scalarValue" else pointer.value.type()
558-
# return {pointer.property.type(): value, "metaphor": {"source": pointer.met.source.type(), "name": pointer.met.name.type()}}
532+
if self.analyzer.issubtype("SCHEMA", pointer.type(), "MetaphoricalScalarModification"):
533+
value = float(pointer.value) if pointer.value.type() == "scalarValue" else pointer.value.type()
534+
return {pointer.property.type(): value, "metaphor": {"source": pointer.met.source.type(), "name": pointer.met.name.type()}}
559535
if self.analyzer.issubtype('SCHEMA', pointer.type(), "PropertyModifier"):
560536
if pointer.value.type() == "scalarValue":
561537
return {pointer.property.type(): float(pointer.value)}
@@ -584,14 +560,10 @@ def fill_pointer(self, pointer, item):
584560
elif self.analyzer.issubtype("SCHEMA", pointer.type(), "Relation") and pointer.entity1.index() == item.index():
585561
return dict(relationDescriptor=self.get_relationDescriptor(pointer))
586562

587-
588563
def get_processDescriptor(self, process, referent):
589564
""" Retrieves information about a process, according to existing templates. Meant to be implemented
590565
in specific extensions of this interface.
591566
592567
Can be overwritten as needed -- here, it calls the params_for_compound to gather essentially an embedded n-tuple.
593568
"""
594569
return self.fill_parameters(process)
595-
596-
597-

0 commit comments

Comments
 (0)