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_induced_functions(): """ Test evaluating a model with an ontology which has induced functions. """ fake_scene = { "objects": ["foo", "bar"], } types = TypeSystem(["a"]) functions = [ types.new_function("test", ("a", "a"), lambda x: True), types.new_function("test2", ("a", "a"), Expression.fromstring(r"\x.test(test(x))")), ] ontology = Ontology(types, functions, []) model = Model(scene=fake_scene, ontology=ontology) cases = [ ("Test basic call of an abstract function", r"\a.test2(a)", {"foo": True, "bar": True}), ("Test embedded call of an abstract function", r"\a.test(test2(a))", {"foo": True, "bar": True}), ] def test(msg, expr, expected): eq_(model.evaluate(Expression.fromstring(expr)), expected) for msg, expr, expected in cases: yield test, msg, expr, expected
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_stored_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) ontology.add_functions([types.new_function("partial", ("obj", "obj"), Expression.fromstring(r"lotsofargs(obj2)"))]) scene = {"objects": []} model = Model(scene, ontology) eq_(model.evaluate(Expression.fromstring(r"partial(obj1)")), "obj1")
def _make_mock_ontology(): 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"]) functions = [ types.new_function("left_of", ("object", "object", "boolean"), lambda a, b: a["x"] < b["x"]), types.new_function("unique", (("object", "boolean"), "object"), fn_unique), types.new_function("cube", ("object", "boolean"), lambda x: x["shape"] == "cube"), types.new_function("sphere", ("object", "boolean"), lambda x: x["shape"] == "sphere"), types.new_function("and_", ("boolean", "boolean", "boolean"), lambda x, y: x and y), ] constants = [] ontology = Ontology(types, functions, constants) return ontology
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
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)} the => N/N {\x.unique(x)} the => S/N {\x.x} the => N/N {\x.x} object => N {scene} objects => N {scene}