2017-05-23 17:04:10 +00:00
|
|
|
from .modifiable_property import (
|
2017-05-22 18:20:53 +00:00
|
|
|
ModifiableProperty,
|
|
|
|
ModifiablePropertyWithAst,
|
|
|
|
is_modifiable_property,
|
|
|
|
)
|
2017-05-11 18:24:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
def resolve(knowledge_base, elements, value):
|
2017-05-11 17:54:02 +00:00
|
|
|
if isinstance(value, int):
|
|
|
|
return elements[value]
|
2017-05-11 18:36:49 +00:00
|
|
|
elif isinstance(value, tuple) or isinstance(value, list):
|
2017-05-11 18:24:29 +00:00
|
|
|
return integrate_information(knowledge_base, {
|
|
|
|
"elements": elements,
|
|
|
|
"parsed": value,
|
|
|
|
})
|
2017-05-11 17:54:02 +00:00
|
|
|
return value
|
2017-05-10 23:09:39 +00:00
|
|
|
|
|
|
|
|
2017-05-15 14:51:39 +00:00
|
|
|
# TODO: improve typing
|
|
|
|
def infer_type(result):
|
|
|
|
if isinstance(result, bool):
|
|
|
|
return "bool"
|
|
|
|
elif isinstance(result, int):
|
|
|
|
return "int"
|
|
|
|
|
|
|
|
else:
|
|
|
|
raise Exception("Unknown type for value: {}".format(result))
|
|
|
|
|
|
|
|
|
|
|
|
def get_subquery_type(knowledge_base, atom):
|
|
|
|
subquery_result = integrate_information(knowledge_base,
|
|
|
|
{
|
|
|
|
"parsed": atom,
|
|
|
|
"elements": [],
|
|
|
|
})
|
|
|
|
assert (subquery_result is not None)
|
|
|
|
result = subquery_result.getter()
|
|
|
|
|
|
|
|
result_type = infer_type(result)
|
|
|
|
return result_type
|
|
|
|
|
|
|
|
|
2017-05-11 17:54:02 +00:00
|
|
|
def property_for_value(knowledge_base, value):
|
2017-05-23 21:24:44 +00:00
|
|
|
if value in knowledge_base:
|
|
|
|
# Annotate the property as property
|
2017-05-23 21:29:34 +00:00
|
|
|
groups = knowledge_base[value].get('groups', {'property'})
|
2017-05-23 21:24:44 +00:00
|
|
|
groups.add('property')
|
|
|
|
knowledge_base[value]['groups'] = groups
|
2017-05-23 21:16:19 +00:00
|
|
|
|
2017-05-23 21:24:44 +00:00
|
|
|
# And find the property "name"
|
|
|
|
if 'as_property' in knowledge_base[value]:
|
|
|
|
return knowledge_base[value]['as_property']
|
|
|
|
|
2017-05-23 21:29:34 +00:00
|
|
|
return knowledge_base[value].get('groups', {'property'})
|
2017-05-23 21:24:44 +00:00
|
|
|
else:
|
|
|
|
# Consider that any property is... a property
|
|
|
|
knowledge_base[value] = {'groups': {'property'}}
|
|
|
|
return {'property'}
|
2017-05-10 23:09:39 +00:00
|
|
|
|
|
|
|
|
2017-05-11 18:24:29 +00:00
|
|
|
def modifiable_property_from_property(prop, path, value):
|
|
|
|
def getter():
|
|
|
|
nonlocal prop, path, value
|
2017-05-23 21:16:19 +00:00
|
|
|
if isinstance(path, set):
|
|
|
|
# If the property is from a set, it's true if any possible
|
|
|
|
# path has a element as true
|
|
|
|
return any(map(lambda possible_path: ((possible_path in prop)
|
|
|
|
and
|
|
|
|
(prop[possible_path] == value)),
|
|
|
|
path))
|
|
|
|
else:
|
|
|
|
return (path in prop) and prop[path] == value
|
2017-05-11 18:24:29 +00:00
|
|
|
|
|
|
|
def setter():
|
|
|
|
nonlocal prop, path, value
|
2017-05-23 21:16:19 +00:00
|
|
|
if isinstance(path, set):
|
|
|
|
for possible_path in path:
|
|
|
|
prop[possible_path] = value
|
|
|
|
else:
|
|
|
|
prop[path] = value
|
2017-05-11 18:24:29 +00:00
|
|
|
|
2017-05-15 14:51:39 +00:00
|
|
|
return ModifiableProperty(
|
|
|
|
getter=getter,
|
|
|
|
setter=setter,
|
|
|
|
)
|
|
|
|
|
2017-05-11 18:24:29 +00:00
|
|
|
|
2017-05-11 17:54:02 +00:00
|
|
|
def exists_property_with_value(knowledge_base, elements, subj, value):
|
2017-05-11 18:24:29 +00:00
|
|
|
subj = resolve(knowledge_base, elements, subj)
|
|
|
|
value = resolve(knowledge_base, elements, value)
|
2017-05-11 17:54:02 +00:00
|
|
|
|
|
|
|
if subj not in knowledge_base:
|
|
|
|
knowledge_base[subj] = {}
|
2017-05-10 23:09:39 +00:00
|
|
|
|
2017-05-11 18:24:29 +00:00
|
|
|
return modifiable_property_from_property(
|
|
|
|
prop=knowledge_base[subj],
|
|
|
|
path=property_for_value(knowledge_base, value),
|
|
|
|
value=value
|
|
|
|
)
|
2017-05-10 23:09:39 +00:00
|
|
|
|
|
|
|
|
2017-05-11 18:24:29 +00:00
|
|
|
def modifiable_element_for_existance_in_set(container, set_name, element):
|
|
|
|
def getter():
|
|
|
|
nonlocal container, set_name, element
|
|
|
|
return (set_name in container) and (element in container[set_name])
|
|
|
|
|
|
|
|
def setter():
|
|
|
|
nonlocal container, set_name, element
|
|
|
|
return container[set_name].add(element)
|
2017-05-15 14:51:39 +00:00
|
|
|
|
2017-05-11 18:24:29 +00:00
|
|
|
return ModifiableProperty(
|
|
|
|
getter=getter,
|
|
|
|
setter=setter,
|
|
|
|
)
|
|
|
|
|
2017-05-24 20:05:46 +00:00
|
|
|
def modifiable_element_for_existance_in_group(container, element, backlink, set_name='groups'):
|
|
|
|
def getter():
|
|
|
|
nonlocal container, element, backlink, set_name
|
|
|
|
return (set_name in container) and (element in container[set_name])
|
|
|
|
|
|
|
|
def setter():
|
|
|
|
nonlocal container, set_name, element
|
|
|
|
backlink['groups'].add(set_name)
|
|
|
|
return container[set_name].add(element)
|
|
|
|
|
|
|
|
return ModifiableProperty(
|
|
|
|
getter=getter,
|
|
|
|
setter=setter,
|
|
|
|
)
|
|
|
|
|
2017-05-11 17:54:02 +00:00
|
|
|
def pertenence_to_group(knowledge_base, elements, subj, group):
|
2017-05-11 18:24:29 +00:00
|
|
|
subj = resolve(knowledge_base, elements, subj)
|
|
|
|
group = resolve(knowledge_base, elements, group)
|
2017-05-11 17:54:02 +00:00
|
|
|
|
|
|
|
if subj not in knowledge_base:
|
2017-05-24 20:25:53 +00:00
|
|
|
knowledge_base[subj] = {'groups': set()}
|
2017-05-11 17:54:02 +00:00
|
|
|
|
|
|
|
if "groups" not in knowledge_base[subj]:
|
|
|
|
knowledge_base[subj]["groups"] = set()
|
2017-05-11 18:24:29 +00:00
|
|
|
|
2017-05-24 20:02:32 +00:00
|
|
|
if group not in knowledge_base:
|
2017-05-24 20:25:53 +00:00
|
|
|
knowledge_base[group] = {'groups': set()}
|
2017-05-24 20:02:32 +00:00
|
|
|
|
|
|
|
if "groups" not in knowledge_base[group]:
|
|
|
|
knowledge_base[group]["groups"] = set()
|
|
|
|
|
|
|
|
return modifiable_element_for_existance_in_group(
|
2017-05-11 18:24:29 +00:00
|
|
|
container=knowledge_base[subj],
|
2017-05-24 20:02:32 +00:00
|
|
|
element=group,
|
|
|
|
backlink=knowledge_base[group],
|
2017-05-11 18:24:29 +00:00
|
|
|
)
|
2017-05-10 23:09:39 +00:00
|
|
|
|
2017-05-11 17:54:02 +00:00
|
|
|
def has_capacity(knowledge_base, elements, subj, capacity):
|
2017-05-11 18:24:29 +00:00
|
|
|
subj = resolve(knowledge_base, elements, subj)
|
|
|
|
capacity = resolve(knowledge_base, elements, capacity)
|
2017-05-11 17:54:02 +00:00
|
|
|
|
|
|
|
if subj not in knowledge_base:
|
|
|
|
knowledge_base[subj] = {}
|
|
|
|
|
2017-05-10 23:09:39 +00:00
|
|
|
if "capacities" not in knowledge_base[subj]:
|
2017-05-11 17:54:02 +00:00
|
|
|
knowledge_base[subj]["capacities"] = set()
|
2017-05-11 18:24:29 +00:00
|
|
|
|
|
|
|
return modifiable_element_for_existance_in_set(
|
|
|
|
container=knowledge_base[subj],
|
|
|
|
set_name="capacities",
|
|
|
|
element=capacity
|
|
|
|
)
|
2017-05-10 23:09:39 +00:00
|
|
|
|
|
|
|
|
2017-05-11 18:36:49 +00:00
|
|
|
def question(knowledge_base, elements, subj):
|
|
|
|
subj = resolve(knowledge_base, elements, subj)
|
|
|
|
|
2017-05-22 18:20:53 +00:00
|
|
|
if is_modifiable_property(subj):
|
2017-05-11 18:36:49 +00:00
|
|
|
return subj.getter()
|
|
|
|
return subj
|
|
|
|
|
2017-05-24 18:13:42 +00:00
|
|
|
def implies(knowledge_base, elements, precedent, consequent):
|
|
|
|
precedent = resolve(knowledge_base, elements, precedent)
|
|
|
|
consequent = resolve(knowledge_base, elements, consequent)
|
|
|
|
|
|
|
|
if precedent not in knowledge_base:
|
2017-05-24 20:25:53 +00:00
|
|
|
knowledge_base[precedent] = {'groups': set()}
|
2017-05-24 18:13:42 +00:00
|
|
|
|
|
|
|
if "implications" not in knowledge_base[precedent]:
|
|
|
|
knowledge_base[precedent]["implications"] = set()
|
|
|
|
|
|
|
|
return modifiable_element_for_existance_in_set(
|
|
|
|
container=knowledge_base[precedent],
|
|
|
|
set_name="implications",
|
|
|
|
element=consequent
|
|
|
|
)
|
|
|
|
|
2017-05-11 18:36:49 +00:00
|
|
|
|
2017-05-24 18:42:15 +00:00
|
|
|
def property_has_value(knowledge_base, elements, subj, prop, value):
|
|
|
|
subj = resolve(knowledge_base, elements, subj)
|
|
|
|
prop = resolve(knowledge_base, elements, prop)
|
|
|
|
value = resolve(knowledge_base, elements, value)
|
|
|
|
|
|
|
|
if subj not in knowledge_base:
|
2017-05-24 20:25:53 +00:00
|
|
|
knowledge_base[subj] = {'groups': set()}
|
2017-05-24 18:42:15 +00:00
|
|
|
|
|
|
|
if prop not in knowledge_base[subj]:
|
|
|
|
knowledge_base[subj][prop] = set()
|
|
|
|
|
|
|
|
return modifiable_element_for_existance_in_set(
|
|
|
|
container=knowledge_base[subj],
|
|
|
|
set_name=prop,
|
|
|
|
element=value
|
|
|
|
)
|
|
|
|
|
2017-05-24 21:54:56 +00:00
|
|
|
def perform_verb_over_object(knowledge_base, elements, subj, verb, obj):
|
|
|
|
subj = resolve(knowledge_base, elements, subj)
|
|
|
|
verb = resolve(knowledge_base, elements, verb)
|
|
|
|
obj = resolve(knowledge_base, elements, obj)
|
|
|
|
|
|
|
|
if subj not in knowledge_base:
|
|
|
|
knowledge_base[subj] = {'groups': set()}
|
|
|
|
|
|
|
|
if 'performs-over' not in knowledge_base[subj]:
|
|
|
|
knowledge_base[subj]['performs-over'] = {}
|
|
|
|
|
|
|
|
if verb not in knowledge_base[subj]['performs-over']:
|
|
|
|
knowledge_base[subj]['performs-over'][verb] = set()
|
|
|
|
|
|
|
|
return modifiable_element_for_existance_in_set(
|
|
|
|
container=knowledge_base[subj]['performs-over'],
|
|
|
|
set_name=verb,
|
|
|
|
element=obj
|
|
|
|
)
|
|
|
|
|
2017-05-24 18:42:15 +00:00
|
|
|
|
2017-05-10 23:09:39 +00:00
|
|
|
knowledge_ingestion = {
|
|
|
|
"exists-property-with-value": exists_property_with_value,
|
|
|
|
"pertenence-to-group": pertenence_to_group,
|
|
|
|
"has-capacity": has_capacity,
|
2017-05-11 18:36:49 +00:00
|
|
|
"question": question,
|
2017-05-24 18:13:42 +00:00
|
|
|
"implies": implies,
|
2017-05-24 18:42:15 +00:00
|
|
|
"property-has-value": property_has_value,
|
2017-05-24 21:54:56 +00:00
|
|
|
"perform-verb-over-object": perform_verb_over_object,
|
2017-05-10 23:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-22 18:20:53 +00:00
|
|
|
def tagged_with_ast(ast, elements, modifiable_property):
|
|
|
|
if not isinstance(modifiable_property, ModifiableProperty):
|
|
|
|
return modifiable_property
|
|
|
|
|
|
|
|
return ModifiablePropertyWithAst(modifiable_property.getter,
|
|
|
|
modifiable_property.setter,
|
|
|
|
ast, elements)
|
|
|
|
|
|
|
|
|
2017-05-11 17:54:02 +00:00
|
|
|
def integrate_information(knowledge_base, example):
|
2017-05-22 18:20:53 +00:00
|
|
|
ast = example['parsed']
|
|
|
|
method = ast[0]
|
|
|
|
args = ast[1:]
|
2017-05-11 17:54:02 +00:00
|
|
|
elements = example.get('elements', None)
|
|
|
|
|
2017-05-22 18:20:53 +00:00
|
|
|
return tagged_with_ast(
|
|
|
|
ast, elements,
|
|
|
|
knowledge_ingestion[method](knowledge_base, elements, *args))
|