.. Copyright (C) 2001-2010 NLTK Project .. For license information, see LICENSE.TXT ======================= Logic & Lambda Calculus ======================= The `nltk.logic` package allows expressions of First-Order Logic (FOL) to be parsed into ``Expression`` objects. In addition to FOL, the parser handles lambda-abstraction with variables of higher order. -------- Overview -------- >>> from nltk.sem.logic import * The default inventory of logical constants is the following: >>> boolean_ops() # doctest: +NORMALIZE_WHITESPACE negation - conjunction & disjunction | implication -> equivalence <-> >>> equality_preds() # doctest: +NORMALIZE_WHITESPACE equality = inequality != >>> binding_ops() # doctest: +NORMALIZE_WHITESPACE existential exists universal all lambda \ ---------------- Regression Tests ---------------- Untyped Logic +++++++++++++ Test for equality under alpha-conversion ======================================== >>> lp = LogicParser() >>> e1 = lp.parse('exists x.P(x)') >>> print e1 exists x.P(x) >>> e2 = e1.alpha_convert(Variable('z')) >>> print e2 exists z.P(z) >>> e1 == e2 True >>> l = lp.parse(r'\X.\X.X(X)(1)').simplify() >>> id = lp.parse(r'\X.X(X)') >>> l == id True Test numerals ============= >>> zero = lp.parse(r'\F x.x') >>> one = lp.parse(r'\F x.F(x)') >>> two = lp.parse(r'\F x.F(F(x))') >>> three = lp.parse(r'\F x.F(F(F(x)))') >>> four = lp.parse(r'\F x.F(F(F(F(x))))') >>> succ = lp.parse(r'\N F x.F(N(F,x))') >>> plus = lp.parse(r'\M N F x.M(F,N(F,x))') >>> mult = lp.parse(r'\M N F.M(N(F))') >>> pred = lp.parse(r'\N F x.(N(\G H.H(G(F)))(\u.x)(\u.u))') >>> v1 = ApplicationExpression(succ, zero).simplify() >>> v1 == one True >>> v2 = ApplicationExpression(succ, v1).simplify() >>> v2 == two True >>> v3 = ApplicationExpression(ApplicationExpression(plus, v1), v2).simplify() >>> v3 == three True >>> v4 = ApplicationExpression(ApplicationExpression(mult, v2), v2).simplify() >>> v4 == four True >>> v5 = ApplicationExpression(pred, ApplicationExpression(pred, v4)).simplify() >>> v5 == two True Overloaded operators also exist, for convenience. >>> print succ(zero).simplify() == one True >>> print plus(one,two).simplify() == three True >>> print mult(two,two).simplify() == four True >>> print pred(pred(four)).simplify() == two True >>> john = lp.parse(r'john') >>> man = lp.parse(r'\x.man(x)') >>> walk = lp.parse(r'\x.walk(x)') >>> man(john).simplify() >>> print -walk(john).simplify() -walk(john) >>> print (man(john) & walk(john)).simplify() (man(john) & walk(john)) >>> print (man(john) | walk(john)).simplify() (man(john) | walk(john)) >>> print (man(john) > walk(john)).simplify() (man(john) -> walk(john)) >>> print (man(john) < walk(john)).simplify() (man(john) <-> walk(john)) Python's built-in lambda operator can also be used with Expressions >>> john = VariableExpression(Variable('john')) >>> run_var = VariableExpression(Variable('run')) >>> run = lambda x: run_var(x) >>> run(john) ``betaConversionTestSuite.pl`` ------------------------------ Tests based on Blackburn & Bos' book, *Representation and Inference for Natural Language*. >>> x1 = lp.parse(r'\P.P(mia)(\x.walk(x))').simplify() >>> x2 = lp.parse(r'walk(mia)').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'exists x.(man(x) & ((\P.exists x.(woman(x) & P(x)))(\y.love(x,y))))').simplify() >>> x2 = lp.parse(r'exists x.(man(x) & exists y.(woman(y) & love(x,y)))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\a.sleep(a)(mia)').simplify() >>> x2 = lp.parse(r'sleep(mia)').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\a.\b.like(b,a)(mia)').simplify() >>> x2 = lp.parse(r'\b.like(b,mia)').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\a.(\b.like(b,a)(vincent))').simplify() >>> x2 = lp.parse(r'\a.like(vincent,a)').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\a.((\b.like(b,a)(vincent)) & sleep(a))').simplify() >>> x2 = lp.parse(r'\a.(like(vincent,a) & sleep(a))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'(\a.\b.like(b,a)(mia)(vincent))').simplify() >>> x2 = lp.parse(r'like(vincent,mia)').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'P((\a.sleep(a)(vincent)))').simplify() >>> x2 = lp.parse(r'P(sleep(vincent))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\A.A((\b.sleep(b)(vincent)))').simplify() >>> x2 = lp.parse(r'\A.A(sleep(vincent))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\A.A(sleep(vincent))').simplify() >>> x2 = lp.parse(r'\A.A(sleep(vincent))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'(\A.A(vincent)(\b.sleep(b)))').simplify() >>> x2 = lp.parse(r'sleep(vincent)').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\A.believe(mia,A(vincent))(\b.sleep(b))').simplify() >>> x2 = lp.parse(r'believe(mia,sleep(vincent))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'(\A.(A(vincent) & A(mia)))(\b.sleep(b))').simplify() >>> x2 = lp.parse(r'(sleep(vincent) & sleep(mia))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\A.\B.(\C.C(A(vincent))(\d.probably(d)) & (\C.C(B(mia))(\d.improbably(d))))(\f.walk(f))(\f.talk(f))').simplify() >>> x2 = lp.parse(r'(probably(walk(vincent)) & improbably(talk(mia)))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'(\a.\b.(\C.C(a,b)(\d.\f.love(d,f))))(jules)(mia)').simplify() >>> x2 = lp.parse(r'love(jules,mia)').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'(\A.\B.exists c.(A(c) & B(c)))(\d.boxer(d),\d.sleep(d))').simplify() >>> x2 = lp.parse(r'exists c.(boxer(c) & sleep(c))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\A.Z(A)(\c.\a.like(a,c))').simplify() >>> x2 = lp.parse(r'Z(\c.\a.like(a,c))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'\A.\b.A(b)(\c.\b.like(b,c))').simplify() >>> x2 = lp.parse(r'\b.(\c.\b.like(b,c)(b))').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'(\a.\b.(\C.C(a,b)(\b.\a.loves(b,a))))(jules)(mia)').simplify() >>> x2 = lp.parse(r'loves(jules,mia)').simplify() >>> x1 == x2 True >>> x1 = lp.parse(r'(\A.\b.(exists b.A(b) & A(b)))(\c.boxer(c))(vincent)').simplify() >>> x2 = lp.parse(r'((exists b.boxer(b)) & boxer(vincent))').simplify() >>> x1 == x2 True Test Parser =========== >>> print lp.parse(r'john') john >>> print lp.parse(r'x') x >>> print lp.parse(r'-man(x)') -man(x) >>> print lp.parse(r'--man(x)') --man(x) >>> print lp.parse(r'(man(x))') man(x) >>> print lp.parse(r'((man(x)))') man(x) >>> print lp.parse(r'man(x) <-> tall(x)') (man(x) <-> tall(x)) >>> print lp.parse(r'(man(x) <-> tall(x))') (man(x) <-> tall(x)) >>> print lp.parse(r'(man(x) & tall(x) & walks(x))') ((man(x) & tall(x)) & walks(x)) >>> print lp.parse(r'((man(x) & tall(x)) & walks(x))') ((man(x) & tall(x)) & walks(x)) >>> print lp.parse(r'man(x) & (tall(x) & walks(x))') (man(x) & (tall(x) & walks(x))) >>> print lp.parse(r'(man(x) & (tall(x) & walks(x)))') (man(x) & (tall(x) & walks(x))) >>> print lp.parse(r'P(x) -> Q(x) <-> R(x) | S(x) & T(x)') ((P(x) -> Q(x)) <-> (R(x) | (S(x) & T(x)))) >>> print lp.parse(r'exists x.man(x)') exists x.man(x) >>> print lp.parse(r'exists x.(man(x) & tall(x))') exists x.(man(x) & tall(x)) >>> print lp.parse(r'exists x.(man(x) & tall(x) & walks(x))') exists x.((man(x) & tall(x)) & walks(x)) >>> print lp.parse(r'-P(x) & Q(x)') (-P(x) & Q(x)) >>> lp.parse(r'-P(x) & Q(x)') == lp.parse(r'(-P(x)) & Q(x)') True >>> print lp.parse(r'\x.man(x)') \x.man(x) >>> print lp.parse(r'\x.man(x)(john)') \x.man(x)(john) >>> print lp.parse(r'\x.man(x)(john) & tall(x)') (\x.man(x)(john) & tall(x)) >>> print lp.parse(r'\x.\y.sees(x,y)') \x y.sees(x,y) >>> print lp.parse(r'\x y.sees(x,y)') \x y.sees(x,y) >>> print lp.parse(r'\x.\y.sees(x,y)(a)') (\x y.sees(x,y))(a) >>> print lp.parse(r'\x y.sees(x,y)(a)') (\x y.sees(x,y))(a) >>> print lp.parse(r'\x.\y.sees(x,y)(a)(b)') ((\x y.sees(x,y))(a))(b) >>> print lp.parse(r'\x y.sees(x,y)(a)(b)') ((\x y.sees(x,y))(a))(b) >>> print lp.parse(r'\x.\y.sees(x,y)(a,b)') ((\x y.sees(x,y))(a))(b) >>> print lp.parse(r'\x y.sees(x,y)(a,b)') ((\x y.sees(x,y))(a))(b) >>> print lp.parse(r'((\x.\y.sees(x,y))(a))(b)') ((\x y.sees(x,y))(a))(b) >>> print lp.parse(r'P(x)(y)(z)') P(x,y,z) >>> print lp.parse(r'P(Q)') P(Q) >>> print lp.parse(r'P(Q(x))') P(Q(x)) >>> print lp.parse(r'(\x.exists y.walks(x,y))(x)') (\x.exists y.walks(x,y))(x) >>> print lp.parse(r'exists x.(x = john)') exists x.(x = john) >>> print lp.parse(r'((\P.\Q.exists x.(P(x) & Q(x)))(\x.dog(x)))(\x.bark(x))') ((\P Q.exists x.(P(x) & Q(x)))(\x.dog(x)))(\x.bark(x)) >>> a = lp.parse(r'exists c.exists b.A(b,c) & A(b,c)') >>> b = lp.parse(r'(exists c.(exists b.A(b,c))) & A(b,c)') >>> print a == b True >>> a = lp.parse(r'exists c.(exists b.A(b,c) & A(b,c))') >>> b = lp.parse(r'exists c.((exists b.A(b,c)) & A(b,c))') >>> print a == b True >>> print lp.parse(r'exists x.x = y') exists x.(x = y) >>> print lp.parse(r'A != B') -(A = B) >>> print lp.parse('P(x) & x=y & P(y)') ((P(x) & (x = y)) & P(y)) >>> try: print lp.parse(r'\walk.walk(x)') ... except ParseException,e: print e 'walk' is an illegal variable name. Constants may not be abstracted. \walk.walk(x) ^ >>> try: print lp.parse(r'all walk.walk(john)') ... except ParseException,e: print e 'walk' is an illegal variable name. Constants may not be quantified. all walk.walk(john) ^ >>> try: print lp.parse(r'x(john)') ... except ParseException,e: print e 'x' is an illegal predicate name. Individual variables may not be used as predicates. x(john) ^ >>> lpq = LogicParser() >>> lpq.quote_chars = [("'", "'", "\\", False)] >>> print lpq.parse(r"(man(x) & 'tall\'s,' (x) & walks (x) )") ((man(x) & tall's,(x)) & walks(x)) >>> lpq.quote_chars = [("'", "'", "\\", True)] >>> print lpq.parse(r"'tall\'s,'") 'tall\'s,' >>> print lpq.parse(r"'spaced name(x)'") 'spaced name(x)' >>> print lpq.parse(r"-'tall\'s,'(x)") -'tall\'s,'(x) >>> print lpq.parse(r"(man(x) & 'tall\'s,' (x) & walks (x) )") ((man(x) & 'tall\'s,'(x)) & walks(x)) Simplify ======== >>> print lp.parse(r'\x.man(x)(john)').simplify() man(john) >>> print lp.parse(r'\x.((man(x)))(john)').simplify() man(john) >>> print lp.parse(r'\x.\y.sees(x,y)(john, mary)').simplify() sees(john,mary) >>> print lp.parse(r'\x y.sees(x,y)(john, mary)').simplify() sees(john,mary) >>> print lp.parse(r'\x.\y.sees(x,y)(john)(mary)').simplify() sees(john,mary) >>> print lp.parse(r'\x y.sees(x,y)(john)(mary)').simplify() sees(john,mary) >>> print lp.parse(r'\x.\y.sees(x,y)(john)').simplify() \y.sees(john,y) >>> print lp.parse(r'\x y.sees(x,y)(john)').simplify() \y.sees(john,y) >>> print lp.parse(r'(\x.\y.sees(x,y)(john))(mary)').simplify() sees(john,mary) >>> print lp.parse(r'(\x y.sees(x,y)(john))(mary)').simplify() sees(john,mary) >>> print lp.parse(r'exists x.(man(x) & (\x.exists y.walks(x,y))(x))').simplify() exists x.(man(x) & exists y.walks(x,y)) >>> e1 = lp.parse(r'exists x.(man(x) & (\x.exists y.walks(x,y))(y))').simplify() >>> e2 = lp.parse(r'exists x.(man(x) & exists z1.walks(y,z1))') >>> e1 == e2 True >>> print lp.parse(r'(\P Q.exists x.(P(x) & Q(x)))(\x.dog(x))').simplify() \Q.exists x.(dog(x) & Q(x)) >>> print lp.parse(r'((\P.\Q.exists x.(P(x) & Q(x)))(\x.dog(x)))(\x.bark(x))').simplify() exists x.(dog(x) & bark(x)) >>> print lp.parse(r'\P.(P(x)(y))(\a b.Q(a,b))').simplify() Q(x,y) Replace ======= >>> a = lp.parse(r'a') >>> x = lp.parse(r'x') >>> y = lp.parse(r'y') >>> z = lp.parse(r'z') >>> print lp.parse(r'man(x)').replace(x.variable, a, False) man(a) >>> print lp.parse(r'(man(x) & tall(x))').replace(x.variable, a, False) (man(a) & tall(a)) >>> print lp.parse(r'exists x.man(x)').replace(x.variable, a, False) exists x.man(x) >>> print lp.parse(r'exists x.man(x)').replace(x.variable, a, True) exists a.man(a) >>> print lp.parse(r'exists x.give(x,y,z)').replace(y.variable, a, False) exists x.give(x,a,z) >>> print lp.parse(r'exists x.give(x,y,z)').replace(y.variable, a, True) exists x.give(x,a,z) >>> e1 = lp.parse(r'exists x.give(x,y,z)').replace(y.variable, x, False) >>> e2 = lp.parse(r'exists z1.give(z1,x,z)') >>> e1 == e2 True >>> e1 = lp.parse(r'exists x.give(x,y,z)').replace(y.variable, x, True) >>> e2 = lp.parse(r'exists z1.give(z1,x,z)') >>> e1 == e2 True >>> print lp.parse(r'\x y z.give(x,y,z)').replace(y.variable, a, False) \x y z.give(x,y,z) >>> print lp.parse(r'\x y z.give(x,y,z)').replace(y.variable, a, True) \x a z.give(x,a,z) >>> print lp.parse(r'\x.\y.give(x,y,z)').replace(z.variable, a, False) \x y.give(x,y,a) >>> print lp.parse(r'\x.\y.give(x,y,z)').replace(z.variable, a, True) \x y.give(x,y,a) >>> e1 = lp.parse(r'\x.\y.give(x,y,z)').replace(z.variable, x, False) >>> e2 = lp.parse(r'\z1.\y.give(z1,y,x)') >>> e1 == e2 True >>> e1 = lp.parse(r'\x.\y.give(x,y,z)').replace(z.variable, x, True) >>> e2 = lp.parse(r'\z1.\y.give(z1,y,x)') >>> e1 == e2 True >>> print lp.parse(r'\x.give(x,y,z)').replace(z.variable, y, False) \x.give(x,y,y) >>> print lp.parse(r'\x.give(x,y,z)').replace(z.variable, y, True) \x.give(x,y,y) >>> from nltk.sem import logic >>> logic._counter._value = 0 >>> e1 = lp.parse('e1') >>> e2 = lp.parse('e2') >>> print lp.parse('exists e1 e2.(walk(e1) & talk(e2))').replace(e1.variable, e2, True) exists e2 e01.(walk(e2) & talk(e01)) Variables / Free ================ >>> print lp.parse(r'walk(john)').variables() set([Variable('john'), Variable('walk')]) >>> print lp.parse(r'walk(x)').variables() set([Variable('x'), Variable('walk')]) >>> print lp.parse(r'see(john,mary)').variables() set([Variable('see'), Variable('john'), Variable('mary')]) >>> print lp.parse(r'exists x.walk(x)').variables() set([Variable('walk')]) >>> print lp.parse(r'\x.see(john,x)').variables() set([Variable('see'), Variable('john')]) >>> print lp.parse(r'\x.see(john,x)(mary)').variables() set([Variable('see'), Variable('john'), Variable('mary')]) >>> print lp.parse(r'walk(john)').free() set([]) >>> print lp.parse(r'walk(x)').free() set([Variable('x')]) >>> print lp.parse(r'see(john,mary)').free() set([]) >>> print lp.parse(r'exists x.walk(x)').free() set([]) >>> print lp.parse(r'\x.see(john,x)').free() set([]) >>> print lp.parse(r'\x.see(john,x)(mary)').free() set([]) >>> print lp.parse(r'walk(john)').free(False) set([Variable('john')]) >>> print lp.parse(r'walk(x)').free(False) set([Variable('x')]) >>> print lp.parse(r'see(john,mary)').free(False) set([Variable('john'), Variable('mary')]) >>> print lp.parse(r'exists x.walk(x)').free(False) set([]) >>> print lp.parse(r'\x.see(john,x)').free(False) set([Variable('john')]) >>> print lp.parse(r'\x.see(john,x)(mary)').free(False) set([Variable('john'), Variable('mary')]) `normalize` >>> print lp.parse(r'\e083.(walk(e083, z472) & talk(e092, z938))').normalize() \e01.(walk(e01,z3) & talk(e02,z4)) Typed Logic +++++++++++ >>> from nltk.sem.logic import * >>> tlp = LogicParser(True) .type >>> print tlp.parse(r'man(x)').type ? >>> print tlp.parse(r'walk(angus)').type ? >>> print tlp.parse(r'-man(x)').type t >>> print tlp.parse(r'(man(x) <-> tall(x))').type t >>> print tlp.parse(r'exists x.(man(x) & tall(x))').type t >>> print tlp.parse(r'\x.man(x)').type >>> print tlp.parse(r'john').type e >>> print tlp.parse(r'\x y.sees(x,y)').type > >>> print tlp.parse(r'\x.man(x)(john)').type ? >>> print tlp.parse(r'\x.\y.sees(x,y)(john)').type >>> print tlp.parse(r'\x.\y.sees(x,y)(john)(mary)').type ? >>> print tlp.parse(r'\P.\Q.exists x.(P(x) & Q(x))').type <,<,t>> >>> print tlp.parse(r'\x.y').type >>> print tlp.parse(r'\P.P(x)').type <,?> >>> parsed = tlp.parse('see(john,mary)') >>> print parsed.type ? >>> print parsed.function see(john) >>> print parsed.function.type >>> print parsed.function.function see >>> print parsed.function.function.type > >>> parsed = tlp.parse('P(x,y)') >>> print parsed P(x,y) >>> print parsed.type ? >>> print parsed.function P(x) >>> print parsed.function.type >>> print parsed.function.function P >>> print parsed.function.function.type > >>> print tlp.parse(r'P').type ? >>> print tlp.parse(r'P', {'P': 't'}).type t >>> a = tlp.parse(r'P(x)') >>> print a.type ? >>> print a.function.type >>> print a.argument.type e >>> a = tlp.parse(r'-P(x)') >>> print a.type t >>> print a.term.type t >>> print a.term.function.type >>> print a.term.argument.type e >>> a = tlp.parse(r'P & Q') >>> print a.type t >>> print a.first.type t >>> print a.second.type t >>> a = tlp.parse(r'(P(x) & Q(x))') >>> print a.type t >>> print a.first.type t >>> print a.first.function.type >>> print a.first.argument.type e >>> print a.second.type t >>> print a.second.function.type >>> print a.second.argument.type e >>> a = tlp.parse(r'\x.P(x)') >>> print a.type >>> print a.term.function.type >>> print a.term.argument.type e >>> a = tlp.parse(r'\P.P(x)') >>> print a.type <,?> >>> print a.term.function.type >>> print a.term.argument.type e >>> a = tlp.parse(r'(\x.P(x)(john)) & Q(x)') >>> print a.type t >>> print a.first.type t >>> print a.first.function.type >>> print a.first.function.term.function.type >>> print a.first.function.term.argument.type e >>> print a.first.argument.type e >>> a = tlp.parse(r'\x y.P(x,y)(john)(mary) & Q(x)') >>> print a.type t >>> print a.first.type t >>> print a.first.function.type >>> print a.first.function.function.type > >>> a = tlp.parse(r'--P') >>> print a.type t >>> print a.term.type t >>> print a.term.term.type t >>> tlp.parse(r'\x y.P(x,y)').type > >>> tlp.parse(r'\x y.P(x,y)', {'P': '>'}).type > >>> a = tlp.parse(r'\P y.P(john,y)(\x y.see(x,y))') >>> a.type >>> a.function.type <>,> >>> a.function.term.term.function.function.type > >>> a.argument.type > >>> a = tlp.parse(r'exists c f.(father(c) = f)') >>> a.type t >>> a.term.term.type t >>> a.term.term.first.type e >>> a.term.term.first.function.type >>> a.term.term.second.type e typecheck() >>> a = tlp.parse('P(x)') >>> b = tlp.parse('Q(x)') >>> a.type ? >>> c = a & b >>> c.first.type ? >>> c.typecheck() # doctest: +ELLIPSIS {...} >>> c.first.type t >>> a = tlp.parse('P(x)') >>> b = tlp.parse('P(x) & Q(x)') >>> a.type ? >>> typecheck([a,b]) # doctest: +ELLIPSIS {...} >>> a.type t >>> e = tlp.parse(r'man(x)') >>> print e.typecheck() {'x': e, 'man': } >>> sig = {'man': ''} >>> e = tlp.parse(r'man(x)', sig) >>> print e.function.type >>> print e.typecheck() {'x': e, 'man': } >>> print e.function.type >>> print e.typecheck(sig) {'x': e, 'man': } findtype() >>> print tlp.parse(r'man(x)').findtype(Variable('man')) >>> print tlp.parse(r'see(x,y)').findtype(Variable('see')) > >>> print tlp.parse(r'P(Q(R(x)))').findtype(Variable('Q')) ? parse_type() >>> print parse_type('e') e >>> print parse_type('') >>> print parse_type('<,>') <,> >>> print parse_type('<,?>') <,?> alternative type format >>> print parse_type('e').str() IND >>> print parse_type('').str() (IND -> ANY) >>> print parse_type('<,t>').str() ((IND -> BOOL) -> BOOL) Type.__eq__() >>> from nltk.sem.logic import * >>> e = ENTITY_TYPE >>> t = TRUTH_TYPE >>> a = ANY_TYPE >>> et = ComplexType(e,t) >>> eet = ComplexType(e,ComplexType(e,t)) >>> at = ComplexType(a,t) >>> ea = ComplexType(e,a) >>> aa = ComplexType(a,a) >>> e == e True >>> t == t True >>> e == t False >>> a == t False >>> t == a False >>> a == a True >>> et == et True >>> a == et False >>> et == a False >>> a == ComplexType(a,aa) True >>> ComplexType(a,aa) == a True matches() >>> e.matches(t) False >>> a.matches(t) True >>> t.matches(a) True >>> a.matches(et) True >>> et.matches(a) True >>> ea.matches(eet) True >>> eet.matches(ea) True >>> aa.matches(et) True >>> aa.matches(t) True Type error during parsing ========================= >>> try: print tlp.parse(r'exists x y.(P(x) & P(x,y))') ... except InconsistentTypeHierarchyException, e: print e The variable 'P' was found in multiple places with different types. >>> try: tlp.parse(r'\x y.see(x,y)(\x.man(x))') ... except TypeException, e: print e The function '\x y.see(x,y)' is of type '>' and cannot be applied to '\x.man(x)' of type ''. Its argument must match type 'e'. >>> try: tlp.parse(r'\P x y.-P(x,y)(\x.-man(x))') ... except TypeException, e: print e The function '\P x y.-P(x,y)' is of type '<>,>>' and cannot be applied to '\x.-man(x)' of type ''. Its argument must match type '>'. >>> a = tlp.parse(r'-talk(x)') >>> signature = a.typecheck() >>> try: print tlp.parse(r'-talk(x,y)', signature) ... except InconsistentTypeHierarchyException, e: print e The variable 'talk' was found in multiple places with different types. >>> a = tlp.parse(r'-P(x)') >>> b = tlp.parse(r'-P(x,y)') >>> a.typecheck() # doctest: +ELLIPSIS {...} >>> b.typecheck() # doctest: +ELLIPSIS {...} >>> try: typecheck([a,b]) ... except InconsistentTypeHierarchyException, e: print e The variable 'P' was found in multiple places with different types. >>> a = tlp.parse(r'P(x)') >>> b = tlp.parse(r'P(x,y)') >>> signature = {'P': ''} >>> a.typecheck(signature) # doctest: +ELLIPSIS {...} >>> try: typecheck([a,b], signature) ... except InconsistentTypeHierarchyException, e: print e The variable 'P' was found in multiple places with different types. Parse errors ============ >>> try: lp.parse(r'') ... except ParseException, e: print e End of input found. Expression expected. ^ >>> try: lp.parse(r'(') ... except ParseException, e: print e End of input found. Expression expected. ( ^ >>> try: lp.parse(r')') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. ) ^ >>> try: lp.parse(r'()') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. () ^ >>> try: lp.parse(r'(P(x) & Q(x)') ... except ParseException, e: print e End of input found. Expected token ')'. (P(x) & Q(x) ^ >>> try: lp.parse(r'(P(x) &') ... except ParseException, e: print e End of input found. Expression expected. (P(x) & ^ >>> try: lp.parse(r'(P(x) | )') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. (P(x) | ) ^ >>> try: lp.parse(r'P(x) ->') ... except ParseException, e: print e End of input found. Expression expected. P(x) -> ^ >>> try: lp.parse(r'P(x') ... except ParseException, e: print e End of input found. Expected token ')'. P(x ^ >>> try: lp.parse(r'P(x,') ... except ParseException, e: print e End of input found. Expression expected. P(x, ^ >>> try: lp.parse(r'P(x,)') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. P(x,) ^ >>> try: lp.parse(r'exists') ... except ParseException, e: print e End of input found. Variable and Expression expected following quantifier 'exists'. exists ^ >>> try: lp.parse(r'exists x') ... except ParseException, e: print e End of input found. Expression expected. exists x ^ >>> try: lp.parse(r'exists x.') ... except ParseException, e: print e End of input found. Expression expected. exists x. ^ >>> try: lp.parse(r'\ ') ... except ParseException, e: print e End of input found. Variable and Expression expected following lambda operator. \ ^ >>> try: lp.parse(r'\ x') ... except ParseException, e: print e End of input found. Expression expected. \ x ^ >>> try: lp.parse(r'\ x y') ... except ParseException, e: print e End of input found. Expression expected. \ x y ^ >>> try: lp.parse(r'\ x.') ... except ParseException, e: print e End of input found. Expression expected. \ x. ^ >>> try: lp.parse(r'P(x)Q(x)') ... except ParseException, e: print e Unexpected token: 'Q'. P(x)Q(x) ^ >>> try: lp.parse(r'(P(x)Q(x)') ... except ParseException, e: print e Unexpected token: 'Q'. Expected token ')'. (P(x)Q(x) ^ >>> try: lp.parse(r'exists x y') ... except ParseException, e: print e End of input found. Expression expected. exists x y ^ >>> try: lp.parse(r'exists x y.') ... except ParseException, e: print e End of input found. Expression expected. exists x y. ^ >>> try: lp.parse(r'exists x -> y') ... except ParseException, e: print e Unexpected token: '->'. Expression expected. exists x -> y ^ >>> try: lp.parse(r'A -> ((P(x) & Q(x)) -> Z') ... except ParseException, e: print e End of input found. Expected token ')'. A -> ((P(x) & Q(x)) -> Z ^ >>> try: lp.parse(r'A -> ((P(x) &) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> ((P(x) &) -> Z ^ >>> try: lp.parse(r'A -> ((P(x) | )) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> ((P(x) | )) -> Z ^ >>> try: lp.parse(r'A -> (P(x) ->) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (P(x) ->) -> Z ^ >>> try: lp.parse(r'A -> (P(x) -> Z') ... except ParseException, e: print e End of input found. Expected token ')'. A -> (P(x) -> Z ^ >>> try: lp.parse(r'A -> (P(x,) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (P(x,) -> Z ^ >>> try: lp.parse(r'A -> (P(x,)) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (P(x,)) -> Z ^ >>> try: lp.parse(r'A -> (exists) -> Z') ... except ParseException, e: print e ')' is an illegal variable name. Constants may not be quantified. A -> (exists) -> Z ^ >>> try: lp.parse(r'A -> (exists x) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (exists x) -> Z ^ >>> try: lp.parse(r'A -> (exists x.) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (exists x.) -> Z ^ >>> try: lp.parse(r'A -> (\ ) -> Z') ... except ParseException, e: print e ')' is an illegal variable name. Constants may not be abstracted. A -> (\ ) -> Z ^ >>> try: lp.parse(r'A -> (\ x) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (\ x) -> Z ^ >>> try: lp.parse(r'A -> (\ x y) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (\ x y) -> Z ^ >>> try: lp.parse(r'A -> (\ x.) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (\ x.) -> Z ^ >>> try: lp.parse(r'A -> (P(x)Q(x)) -> Z') ... except ParseException, e: print e Unexpected token: 'Q'. Expected token ')'. A -> (P(x)Q(x)) -> Z ^ >>> try: lp.parse(r'A -> ((P(x)Q(x)) -> Z') ... except ParseException, e: print e Unexpected token: 'Q'. Expected token ')'. A -> ((P(x)Q(x)) -> Z ^ >>> try: lp.parse(r'A -> (all x y) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (all x y) -> Z ^ >>> try: lp.parse(r'A -> (exists x y.) -> Z') ... except ParseException, e: print e Unexpected token: ')'. Expression expected. A -> (exists x y.) -> Z ^ >>> try: lp.parse(r'A -> (exists x -> y) -> Z') ... except ParseException, e: print e Unexpected token: '->'. Expression expected. A -> (exists x -> y) -> Z ^