def make_ontology(self, anonymous_constants=False): """Construct a pyccg-compatible ontology system based on the type definitions and signatures.""" types = TypeSystem(list(set(self.parameter_types).union(set(self.variable_types)).union(set(self.return_types)))) functions = list() constants = list() for fname, parameter_inputs, variable_inputs, return_type in self.operation_signatures: if len(parameter_inputs) == 0 and len(variable_inputs) == 0: function = types.new_function(self.escape_funcname(fname), (return_type, ), None) functions.append(function) # constants.append(types.new_constant(fname, return_type)) else: all_inputs = tuple(variable_inputs + parameter_inputs) function = types.new_function(self.escape_funcname(fname), all_inputs + (return_type, ), None) functions.append(function) for concept_category, concept_list in zip( ['concept', 'attribute', 'relational_concept'], [self.all_attribute_concepts, self.all_attributes, self.all_relational_concepts] ): for i, v in enumerate(concept_list): constants.append(types.new_constant( v if not anonymous_constants else '{}_{:06d}'.format(concept_category, i + 1), concept_category )) for i in range(5): constants.append(types.new_constant( '{}_{:06d}'.format(concept_category, len(concept_list) + i), concept_category )) ontology = Ontology(types, functions, constants) return ontology
def test_model_constants(): """ Test evaluating with constant values. """ types = TypeSystem(["num"]) functions = [ types.new_function("add", ("num", "num", "num"), lambda a, b: str(int(a) + int(b))) ] constants = [types.new_constant("1", "num"), types.new_constant("2", "num")] ontology = Ontology(types, functions, constants) model = Model(scene={"objects": []}, ontology=ontology) cases = [ ("Test basic constant evaluation", r"1", "1"), ("Test constants as arguments to functions", r"add(1,1)", "2"), ] def test(msg, expr, expected): print("ret", model.evaluate(Expression.fromstring(expr))) eq_(model.evaluate(Expression.fromstring(expr)), expected) for msg, expr, expected in cases: yield test, msg, expr, expected
def test_model_partial_application(): types = TypeSystem(["obj"]) functions = [ types.new_function("lotsofargs", ("obj", "obj", "obj"), lambda a, b: b), ] constants = [ types.new_constant("obj1", "obj"), types.new_constant("obj2", "obj"), ] ontology = Ontology(types, functions, constants) scene = {"objects": []} model = Model(scene, ontology) eq_(model.evaluate(Expression.fromstring(r"(lotsofargs(obj1))(obj2)")), "obj2")
def _make_mock_lexicon(): types = TypeSystem(["obj", "boolean"]) functions = [ types.new_function("unique", (("obj", "boolean"), "obj"), lambda x: x[0]), types.new_function("twoplace", ("boolean", ("obj", "boolean"), "obj"), lambda a, b: b[0]), types.new_function("dog", ("obj", "boolean"), lambda x: x["dog"]), types.new_function("not_", ("boolean", "boolean"), lambda a: not a), types.new_function("enlarge", ("obj", "obj"), lambda x: x), ] constants = [types.new_constant("true", "boolean")] ontology = Ontology(types, functions, constants) lex = Lexicon.fromstring(r""" :- S, N the => N/N {\x.unique(x)} thee => N\N {\x.unique(x)} twoplace => N/N {\x.twoplace(true,x)} twoplacee => N\N {\x.twoplace(true,x)} abc => N/N {\a.not_(a)} def => N/N {\b.not_(b)} qrs => N/N {\a.enlarge(a)} tuv => N/N {\b.enlarge(b)} twoarg => N/N/N {\a b.twoplace(a,b)} doggish => N/N {\x.dog(x)} dog => N {dog} # NB, won't typecheck cat => N {unique} """, ontology=ontology, include_semantics=True) # TODO hack: this needs to be integrated into lexicon construction.. for w in ["the", "twoplace", "thee", "twoplacee"]: e = lex._entries[w][0] sem = e.semantics() tx = lex.ontology.infer_type(sem, "x") sem.variable.type = tx lex.ontology.typecheck(sem) return lex
dummy_fn_1 = lambda x: x dummy_fn_2 = lambda x, y: x types = TypeSystem(["object", "boolean", "shape", "size"]) functions = [ types.new_function("has_shape", ("object", "shape", "boolean"), dummy_fn_2), types.new_function("unique", (("object", "boolean"), "object"), dummy_fn_1), types.new_function("object_exists", (("object", "boolean"), "boolean"), dummy_fn_1), ] constants = [ types.new_constant("sphere", "shape"), types.new_constant("cube", "shape"), types.new_constant("cylinder", "shape"), types.new_constant("true", "boolean"), ] ontology = Ontology(types, functions, constants) ####### # Lexicon: defines an initial set of word -> (syntax, meaning) mappings. # Weights are initialized uniformly by default. lexicon = Lexicon.fromstring(r""" :- S, N the => S/N {\x.unique(x)}
fn_max_in_dir), types.new_function("is_edge", ("object", "boolean"), fn_is_edge), ] def make_obj_fn(obj): return lambda o: o["type"] == obj functions.extend([ types.new_function(obj, ("object", "boolean"), make_obj_fn(obj)) for obj in obj_dict.values() ]) constants = [ types.new_constant("true", "boolean"), types.new_constant("left", "direction"), types.new_constant("right", "direction"), types.new_constant("up", "direction"), types.new_constant("down", "direction"), types.new_constant("1", "int"), types.new_constant("2", "int"), ] ontology = Ontology(types, functions, constants) # Add model-typed versions of function for EC. ec_functions = functions ec_functions.extend([ types.new_function("ec_unique", ("model", ("object", "boolean"), "object"), ec_fn_unique)
def fn_unique(xs): true_xs = [x for x, matches in xs.items() if matches] assert len(true_xs) == 1 return true_xs[0] types = TypeSystem(["object", "boolean", "shape", "size"]) functions = [ types.new_function("has_shape", ("object", "shape", "boolean"), lambda x, s: x.shape == s), types.new_function("unique", (("object", "boolean"), "object"), fn_unique), ] constants = [ types.new_constant("sphere", "shape"), types.new_constant("cube", "shape"), types.new_constant("cylinder", "shape"), ] ontology = Ontology(types, functions, constants) ####### # Lexicon: defines an initial set of word -> (syntax, meaning) mappings. # Weights are initialized uniformly by default. lex = Lexicon.fromstring(r""" :- N the => N/N {\x.unique(x)} ball => N {\x.has_shape(x,sphere)}