logic.doctest 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. .. Copyright (C) 2001-2019 NLTK Project
  2. .. For license information, see LICENSE.TXT
  3. =======================
  4. Logic & Lambda Calculus
  5. =======================
  6. The `nltk.logic` package allows expressions of First-Order Logic (FOL) to be
  7. parsed into ``Expression`` objects. In addition to FOL, the parser
  8. handles lambda-abstraction with variables of higher order.
  9. --------
  10. Overview
  11. --------
  12. >>> from nltk.sem.logic import *
  13. The default inventory of logical constants is the following:
  14. >>> boolean_ops() # doctest: +NORMALIZE_WHITESPACE
  15. negation -
  16. conjunction &
  17. disjunction |
  18. implication ->
  19. equivalence <->
  20. >>> equality_preds() # doctest: +NORMALIZE_WHITESPACE
  21. equality =
  22. inequality !=
  23. >>> binding_ops() # doctest: +NORMALIZE_WHITESPACE
  24. existential exists
  25. universal all
  26. lambda \
  27. ----------------
  28. Regression Tests
  29. ----------------
  30. Untyped Logic
  31. +++++++++++++
  32. Process logical expressions conveniently:
  33. >>> read_expr = Expression.fromstring
  34. Test for equality under alpha-conversion
  35. ========================================
  36. >>> e1 = read_expr('exists x.P(x)')
  37. >>> print(e1)
  38. exists x.P(x)
  39. >>> e2 = e1.alpha_convert(Variable('z'))
  40. >>> print(e2)
  41. exists z.P(z)
  42. >>> e1 == e2
  43. True
  44. >>> l = read_expr(r'\X.\X.X(X)(1)').simplify()
  45. >>> id = read_expr(r'\X.X(X)')
  46. >>> l == id
  47. True
  48. Test numerals
  49. =============
  50. >>> zero = read_expr(r'\F x.x')
  51. >>> one = read_expr(r'\F x.F(x)')
  52. >>> two = read_expr(r'\F x.F(F(x))')
  53. >>> three = read_expr(r'\F x.F(F(F(x)))')
  54. >>> four = read_expr(r'\F x.F(F(F(F(x))))')
  55. >>> succ = read_expr(r'\N F x.F(N(F,x))')
  56. >>> plus = read_expr(r'\M N F x.M(F,N(F,x))')
  57. >>> mult = read_expr(r'\M N F.M(N(F))')
  58. >>> pred = read_expr(r'\N F x.(N(\G H.H(G(F)))(\u.x)(\u.u))')
  59. >>> v1 = ApplicationExpression(succ, zero).simplify()
  60. >>> v1 == one
  61. True
  62. >>> v2 = ApplicationExpression(succ, v1).simplify()
  63. >>> v2 == two
  64. True
  65. >>> v3 = ApplicationExpression(ApplicationExpression(plus, v1), v2).simplify()
  66. >>> v3 == three
  67. True
  68. >>> v4 = ApplicationExpression(ApplicationExpression(mult, v2), v2).simplify()
  69. >>> v4 == four
  70. True
  71. >>> v5 = ApplicationExpression(pred, ApplicationExpression(pred, v4)).simplify()
  72. >>> v5 == two
  73. True
  74. Overloaded operators also exist, for convenience.
  75. >>> print(succ(zero).simplify() == one)
  76. True
  77. >>> print(plus(one,two).simplify() == three)
  78. True
  79. >>> print(mult(two,two).simplify() == four)
  80. True
  81. >>> print(pred(pred(four)).simplify() == two)
  82. True
  83. >>> john = read_expr(r'john')
  84. >>> man = read_expr(r'\x.man(x)')
  85. >>> walk = read_expr(r'\x.walk(x)')
  86. >>> man(john).simplify()
  87. <ApplicationExpression man(john)>
  88. >>> print(-walk(john).simplify())
  89. -walk(john)
  90. >>> print((man(john) & walk(john)).simplify())
  91. (man(john) & walk(john))
  92. >>> print((man(john) | walk(john)).simplify())
  93. (man(john) | walk(john))
  94. >>> print((man(john) > walk(john)).simplify())
  95. (man(john) -> walk(john))
  96. >>> print((man(john) < walk(john)).simplify())
  97. (man(john) <-> walk(john))
  98. Python's built-in lambda operator can also be used with Expressions
  99. >>> john = VariableExpression(Variable('john'))
  100. >>> run_var = VariableExpression(Variable('run'))
  101. >>> run = lambda x: run_var(x)
  102. >>> run(john)
  103. <ApplicationExpression run(john)>
  104. ``betaConversionTestSuite.pl``
  105. ------------------------------
  106. Tests based on Blackburn & Bos' book, *Representation and Inference
  107. for Natural Language*.
  108. >>> x1 = read_expr(r'\P.P(mia)(\x.walk(x))').simplify()
  109. >>> x2 = read_expr(r'walk(mia)').simplify()
  110. >>> x1 == x2
  111. True
  112. >>> x1 = read_expr(r'exists x.(man(x) & ((\P.exists x.(woman(x) & P(x)))(\y.love(x,y))))').simplify()
  113. >>> x2 = read_expr(r'exists x.(man(x) & exists y.(woman(y) & love(x,y)))').simplify()
  114. >>> x1 == x2
  115. True
  116. >>> x1 = read_expr(r'\a.sleep(a)(mia)').simplify()
  117. >>> x2 = read_expr(r'sleep(mia)').simplify()
  118. >>> x1 == x2
  119. True
  120. >>> x1 = read_expr(r'\a.\b.like(b,a)(mia)').simplify()
  121. >>> x2 = read_expr(r'\b.like(b,mia)').simplify()
  122. >>> x1 == x2
  123. True
  124. >>> x1 = read_expr(r'\a.(\b.like(b,a)(vincent))').simplify()
  125. >>> x2 = read_expr(r'\a.like(vincent,a)').simplify()
  126. >>> x1 == x2
  127. True
  128. >>> x1 = read_expr(r'\a.((\b.like(b,a)(vincent)) & sleep(a))').simplify()
  129. >>> x2 = read_expr(r'\a.(like(vincent,a) & sleep(a))').simplify()
  130. >>> x1 == x2
  131. True
  132. >>> x1 = read_expr(r'(\a.\b.like(b,a)(mia)(vincent))').simplify()
  133. >>> x2 = read_expr(r'like(vincent,mia)').simplify()
  134. >>> x1 == x2
  135. True
  136. >>> x1 = read_expr(r'P((\a.sleep(a)(vincent)))').simplify()
  137. >>> x2 = read_expr(r'P(sleep(vincent))').simplify()
  138. >>> x1 == x2
  139. True
  140. >>> x1 = read_expr(r'\A.A((\b.sleep(b)(vincent)))').simplify()
  141. >>> x2 = read_expr(r'\A.A(sleep(vincent))').simplify()
  142. >>> x1 == x2
  143. True
  144. >>> x1 = read_expr(r'\A.A(sleep(vincent))').simplify()
  145. >>> x2 = read_expr(r'\A.A(sleep(vincent))').simplify()
  146. >>> x1 == x2
  147. True
  148. >>> x1 = read_expr(r'(\A.A(vincent)(\b.sleep(b)))').simplify()
  149. >>> x2 = read_expr(r'sleep(vincent)').simplify()
  150. >>> x1 == x2
  151. True
  152. >>> x1 = read_expr(r'\A.believe(mia,A(vincent))(\b.sleep(b))').simplify()
  153. >>> x2 = read_expr(r'believe(mia,sleep(vincent))').simplify()
  154. >>> x1 == x2
  155. True
  156. >>> x1 = read_expr(r'(\A.(A(vincent) & A(mia)))(\b.sleep(b))').simplify()
  157. >>> x2 = read_expr(r'(sleep(vincent) & sleep(mia))').simplify()
  158. >>> x1 == x2
  159. True
  160. >>> x1 = read_expr(r'\A.\B.(\C.C(A(vincent))(\d.probably(d)) & (\C.C(B(mia))(\d.improbably(d))))(\f.walk(f))(\f.talk(f))').simplify()
  161. >>> x2 = read_expr(r'(probably(walk(vincent)) & improbably(talk(mia)))').simplify()
  162. >>> x1 == x2
  163. True
  164. >>> x1 = read_expr(r'(\a.\b.(\C.C(a,b)(\d.\f.love(d,f))))(jules)(mia)').simplify()
  165. >>> x2 = read_expr(r'love(jules,mia)').simplify()
  166. >>> x1 == x2
  167. True
  168. >>> x1 = read_expr(r'(\A.\B.exists c.(A(c) & B(c)))(\d.boxer(d),\d.sleep(d))').simplify()
  169. >>> x2 = read_expr(r'exists c.(boxer(c) & sleep(c))').simplify()
  170. >>> x1 == x2
  171. True
  172. >>> x1 = read_expr(r'\A.Z(A)(\c.\a.like(a,c))').simplify()
  173. >>> x2 = read_expr(r'Z(\c.\a.like(a,c))').simplify()
  174. >>> x1 == x2
  175. True
  176. >>> x1 = read_expr(r'\A.\b.A(b)(\c.\b.like(b,c))').simplify()
  177. >>> x2 = read_expr(r'\b.(\c.\b.like(b,c)(b))').simplify()
  178. >>> x1 == x2
  179. True
  180. >>> x1 = read_expr(r'(\a.\b.(\C.C(a,b)(\b.\a.loves(b,a))))(jules)(mia)').simplify()
  181. >>> x2 = read_expr(r'loves(jules,mia)').simplify()
  182. >>> x1 == x2
  183. True
  184. >>> x1 = read_expr(r'(\A.\b.(exists b.A(b) & A(b)))(\c.boxer(c))(vincent)').simplify()
  185. >>> x2 = read_expr(r'((exists b.boxer(b)) & boxer(vincent))').simplify()
  186. >>> x1 == x2
  187. True
  188. Test Parser
  189. ===========
  190. >>> print(read_expr(r'john'))
  191. john
  192. >>> print(read_expr(r'x'))
  193. x
  194. >>> print(read_expr(r'-man(x)'))
  195. -man(x)
  196. >>> print(read_expr(r'--man(x)'))
  197. --man(x)
  198. >>> print(read_expr(r'(man(x))'))
  199. man(x)
  200. >>> print(read_expr(r'((man(x)))'))
  201. man(x)
  202. >>> print(read_expr(r'man(x) <-> tall(x)'))
  203. (man(x) <-> tall(x))
  204. >>> print(read_expr(r'(man(x) <-> tall(x))'))
  205. (man(x) <-> tall(x))
  206. >>> print(read_expr(r'(man(x) & tall(x) & walks(x))'))
  207. (man(x) & tall(x) & walks(x))
  208. >>> print(read_expr(r'(man(x) & tall(x) & walks(x))').first)
  209. (man(x) & tall(x))
  210. >>> print(read_expr(r'man(x) | tall(x) & walks(x)'))
  211. (man(x) | (tall(x) & walks(x)))
  212. >>> print(read_expr(r'((man(x) & tall(x)) | walks(x))'))
  213. ((man(x) & tall(x)) | walks(x))
  214. >>> print(read_expr(r'man(x) & (tall(x) | walks(x))'))
  215. (man(x) & (tall(x) | walks(x)))
  216. >>> print(read_expr(r'(man(x) & (tall(x) | walks(x)))'))
  217. (man(x) & (tall(x) | walks(x)))
  218. >>> print(read_expr(r'P(x) -> Q(x) <-> R(x) | S(x) & T(x)'))
  219. ((P(x) -> Q(x)) <-> (R(x) | (S(x) & T(x))))
  220. >>> print(read_expr(r'exists x.man(x)'))
  221. exists x.man(x)
  222. >>> print(read_expr(r'exists x.(man(x) & tall(x))'))
  223. exists x.(man(x) & tall(x))
  224. >>> print(read_expr(r'exists x.(man(x) & tall(x) & walks(x))'))
  225. exists x.(man(x) & tall(x) & walks(x))
  226. >>> print(read_expr(r'-P(x) & Q(x)'))
  227. (-P(x) & Q(x))
  228. >>> read_expr(r'-P(x) & Q(x)') == read_expr(r'(-P(x)) & Q(x)')
  229. True
  230. >>> print(read_expr(r'\x.man(x)'))
  231. \x.man(x)
  232. >>> print(read_expr(r'\x.man(x)(john)'))
  233. \x.man(x)(john)
  234. >>> print(read_expr(r'\x.man(x)(john) & tall(x)'))
  235. (\x.man(x)(john) & tall(x))
  236. >>> print(read_expr(r'\x.\y.sees(x,y)'))
  237. \x y.sees(x,y)
  238. >>> print(read_expr(r'\x y.sees(x,y)'))
  239. \x y.sees(x,y)
  240. >>> print(read_expr(r'\x.\y.sees(x,y)(a)'))
  241. (\x y.sees(x,y))(a)
  242. >>> print(read_expr(r'\x y.sees(x,y)(a)'))
  243. (\x y.sees(x,y))(a)
  244. >>> print(read_expr(r'\x.\y.sees(x,y)(a)(b)'))
  245. ((\x y.sees(x,y))(a))(b)
  246. >>> print(read_expr(r'\x y.sees(x,y)(a)(b)'))
  247. ((\x y.sees(x,y))(a))(b)
  248. >>> print(read_expr(r'\x.\y.sees(x,y)(a,b)'))
  249. ((\x y.sees(x,y))(a))(b)
  250. >>> print(read_expr(r'\x y.sees(x,y)(a,b)'))
  251. ((\x y.sees(x,y))(a))(b)
  252. >>> print(read_expr(r'((\x.\y.sees(x,y))(a))(b)'))
  253. ((\x y.sees(x,y))(a))(b)
  254. >>> print(read_expr(r'P(x)(y)(z)'))
  255. P(x,y,z)
  256. >>> print(read_expr(r'P(Q)'))
  257. P(Q)
  258. >>> print(read_expr(r'P(Q(x))'))
  259. P(Q(x))
  260. >>> print(read_expr(r'(\x.exists y.walks(x,y))(x)'))
  261. (\x.exists y.walks(x,y))(x)
  262. >>> print(read_expr(r'exists x.(x = john)'))
  263. exists x.(x = john)
  264. >>> print(read_expr(r'((\P.\Q.exists x.(P(x) & Q(x)))(\x.dog(x)))(\x.bark(x))'))
  265. ((\P Q.exists x.(P(x) & Q(x)))(\x.dog(x)))(\x.bark(x))
  266. >>> a = read_expr(r'exists c.exists b.A(b,c) & A(b,c)')
  267. >>> b = read_expr(r'(exists c.(exists b.A(b,c))) & A(b,c)')
  268. >>> print(a == b)
  269. True
  270. >>> a = read_expr(r'exists c.(exists b.A(b,c) & A(b,c))')
  271. >>> b = read_expr(r'exists c.((exists b.A(b,c)) & A(b,c))')
  272. >>> print(a == b)
  273. True
  274. >>> print(read_expr(r'exists x.x = y'))
  275. exists x.(x = y)
  276. >>> print(read_expr('A(B)(C)'))
  277. A(B,C)
  278. >>> print(read_expr('(A(B))(C)'))
  279. A(B,C)
  280. >>> print(read_expr('A((B)(C))'))
  281. A(B(C))
  282. >>> print(read_expr('A(B(C))'))
  283. A(B(C))
  284. >>> print(read_expr('(A)(B(C))'))
  285. A(B(C))
  286. >>> print(read_expr('(((A)))(((B))(((C))))'))
  287. A(B(C))
  288. >>> print(read_expr(r'A != B'))
  289. -(A = B)
  290. >>> print(read_expr('P(x) & x=y & P(y)'))
  291. (P(x) & (x = y) & P(y))
  292. >>> try: print(read_expr(r'\walk.walk(x)'))
  293. ... except LogicalExpressionException as e: print(e)
  294. 'walk' is an illegal variable name. Constants may not be abstracted.
  295. \walk.walk(x)
  296. ^
  297. >>> try: print(read_expr(r'all walk.walk(john)'))
  298. ... except LogicalExpressionException as e: print(e)
  299. 'walk' is an illegal variable name. Constants may not be quantified.
  300. all walk.walk(john)
  301. ^
  302. >>> try: print(read_expr(r'x(john)'))
  303. ... except LogicalExpressionException as e: print(e)
  304. 'x' is an illegal predicate name. Individual variables may not be used as predicates.
  305. x(john)
  306. ^
  307. >>> from nltk.sem.logic import LogicParser # hack to give access to custom quote chars
  308. >>> lpq = LogicParser()
  309. >>> lpq.quote_chars = [("'", "'", "\\", False)]
  310. >>> print(lpq.parse(r"(man(x) & 'tall\'s,' (x) & walks (x) )"))
  311. (man(x) & tall's,(x) & walks(x))
  312. >>> lpq.quote_chars = [("'", "'", "\\", True)]
  313. >>> print(lpq.parse(r"'tall\'s,'"))
  314. 'tall\'s,'
  315. >>> print(lpq.parse(r"'spaced name(x)'"))
  316. 'spaced name(x)'
  317. >>> print(lpq.parse(r"-'tall\'s,'(x)"))
  318. -'tall\'s,'(x)
  319. >>> print(lpq.parse(r"(man(x) & 'tall\'s,' (x) & walks (x) )"))
  320. (man(x) & 'tall\'s,'(x) & walks(x))
  321. Simplify
  322. ========
  323. >>> print(read_expr(r'\x.man(x)(john)').simplify())
  324. man(john)
  325. >>> print(read_expr(r'\x.((man(x)))(john)').simplify())
  326. man(john)
  327. >>> print(read_expr(r'\x.\y.sees(x,y)(john, mary)').simplify())
  328. sees(john,mary)
  329. >>> print(read_expr(r'\x y.sees(x,y)(john, mary)').simplify())
  330. sees(john,mary)
  331. >>> print(read_expr(r'\x.\y.sees(x,y)(john)(mary)').simplify())
  332. sees(john,mary)
  333. >>> print(read_expr(r'\x y.sees(x,y)(john)(mary)').simplify())
  334. sees(john,mary)
  335. >>> print(read_expr(r'\x.\y.sees(x,y)(john)').simplify())
  336. \y.sees(john,y)
  337. >>> print(read_expr(r'\x y.sees(x,y)(john)').simplify())
  338. \y.sees(john,y)
  339. >>> print(read_expr(r'(\x.\y.sees(x,y)(john))(mary)').simplify())
  340. sees(john,mary)
  341. >>> print(read_expr(r'(\x y.sees(x,y)(john))(mary)').simplify())
  342. sees(john,mary)
  343. >>> print(read_expr(r'exists x.(man(x) & (\x.exists y.walks(x,y))(x))').simplify())
  344. exists x.(man(x) & exists y.walks(x,y))
  345. >>> e1 = read_expr(r'exists x.(man(x) & (\x.exists y.walks(x,y))(y))').simplify()
  346. >>> e2 = read_expr(r'exists x.(man(x) & exists z1.walks(y,z1))')
  347. >>> e1 == e2
  348. True
  349. >>> print(read_expr(r'(\P Q.exists x.(P(x) & Q(x)))(\x.dog(x))').simplify())
  350. \Q.exists x.(dog(x) & Q(x))
  351. >>> print(read_expr(r'((\P.\Q.exists x.(P(x) & Q(x)))(\x.dog(x)))(\x.bark(x))').simplify())
  352. exists x.(dog(x) & bark(x))
  353. >>> print(read_expr(r'\P.(P(x)(y))(\a b.Q(a,b))').simplify())
  354. Q(x,y)
  355. Replace
  356. =======
  357. >>> a = read_expr(r'a')
  358. >>> x = read_expr(r'x')
  359. >>> y = read_expr(r'y')
  360. >>> z = read_expr(r'z')
  361. >>> print(read_expr(r'man(x)').replace(x.variable, a, False))
  362. man(a)
  363. >>> print(read_expr(r'(man(x) & tall(x))').replace(x.variable, a, False))
  364. (man(a) & tall(a))
  365. >>> print(read_expr(r'exists x.man(x)').replace(x.variable, a, False))
  366. exists x.man(x)
  367. >>> print(read_expr(r'exists x.man(x)').replace(x.variable, a, True))
  368. exists a.man(a)
  369. >>> print(read_expr(r'exists x.give(x,y,z)').replace(y.variable, a, False))
  370. exists x.give(x,a,z)
  371. >>> print(read_expr(r'exists x.give(x,y,z)').replace(y.variable, a, True))
  372. exists x.give(x,a,z)
  373. >>> e1 = read_expr(r'exists x.give(x,y,z)').replace(y.variable, x, False)
  374. >>> e2 = read_expr(r'exists z1.give(z1,x,z)')
  375. >>> e1 == e2
  376. True
  377. >>> e1 = read_expr(r'exists x.give(x,y,z)').replace(y.variable, x, True)
  378. >>> e2 = read_expr(r'exists z1.give(z1,x,z)')
  379. >>> e1 == e2
  380. True
  381. >>> print(read_expr(r'\x y z.give(x,y,z)').replace(y.variable, a, False))
  382. \x y z.give(x,y,z)
  383. >>> print(read_expr(r'\x y z.give(x,y,z)').replace(y.variable, a, True))
  384. \x a z.give(x,a,z)
  385. >>> print(read_expr(r'\x.\y.give(x,y,z)').replace(z.variable, a, False))
  386. \x y.give(x,y,a)
  387. >>> print(read_expr(r'\x.\y.give(x,y,z)').replace(z.variable, a, True))
  388. \x y.give(x,y,a)
  389. >>> e1 = read_expr(r'\x.\y.give(x,y,z)').replace(z.variable, x, False)
  390. >>> e2 = read_expr(r'\z1.\y.give(z1,y,x)')
  391. >>> e1 == e2
  392. True
  393. >>> e1 = read_expr(r'\x.\y.give(x,y,z)').replace(z.variable, x, True)
  394. >>> e2 = read_expr(r'\z1.\y.give(z1,y,x)')
  395. >>> e1 == e2
  396. True
  397. >>> print(read_expr(r'\x.give(x,y,z)').replace(z.variable, y, False))
  398. \x.give(x,y,y)
  399. >>> print(read_expr(r'\x.give(x,y,z)').replace(z.variable, y, True))
  400. \x.give(x,y,y)
  401. >>> from nltk.sem import logic
  402. >>> logic._counter._value = 0
  403. >>> e1 = read_expr('e1')
  404. >>> e2 = read_expr('e2')
  405. >>> print(read_expr('exists e1 e2.(walk(e1) & talk(e2))').replace(e1.variable, e2, True))
  406. exists e2 e01.(walk(e2) & talk(e01))
  407. Variables / Free
  408. ================
  409. >>> examples = [r'walk(john)',
  410. ... r'walk(x)',
  411. ... r'?vp(?np)',
  412. ... r'see(john,mary)',
  413. ... r'exists x.walk(x)',
  414. ... r'\x.see(john,x)',
  415. ... r'\x.see(john,x)(mary)',
  416. ... r'P(x)',
  417. ... r'\P.P(x)',
  418. ... r'aa(x,bb(y),cc(z),P(w),u)',
  419. ... r'bo(?det(?n),@x)']
  420. >>> examples = [read_expr(e) for e in examples]
  421. >>> for e in examples:
  422. ... print('%-25s' % e, sorted(e.free()))
  423. walk(john) []
  424. walk(x) [Variable('x')]
  425. ?vp(?np) []
  426. see(john,mary) []
  427. exists x.walk(x) []
  428. \x.see(john,x) []
  429. (\x.see(john,x))(mary) []
  430. P(x) [Variable('P'), Variable('x')]
  431. \P.P(x) [Variable('x')]
  432. aa(x,bb(y),cc(z),P(w),u) [Variable('P'), Variable('u'), Variable('w'), Variable('x'), Variable('y'), Variable('z')]
  433. bo(?det(?n),@x) []
  434. >>> for e in examples:
  435. ... print('%-25s' % e, sorted(e.constants()))
  436. walk(john) [Variable('john')]
  437. walk(x) []
  438. ?vp(?np) [Variable('?np')]
  439. see(john,mary) [Variable('john'), Variable('mary')]
  440. exists x.walk(x) []
  441. \x.see(john,x) [Variable('john')]
  442. (\x.see(john,x))(mary) [Variable('john'), Variable('mary')]
  443. P(x) []
  444. \P.P(x) []
  445. aa(x,bb(y),cc(z),P(w),u) []
  446. bo(?det(?n),@x) [Variable('?n'), Variable('@x')]
  447. >>> for e in examples:
  448. ... print('%-25s' % e, sorted(e.predicates()))
  449. walk(john) [Variable('walk')]
  450. walk(x) [Variable('walk')]
  451. ?vp(?np) [Variable('?vp')]
  452. see(john,mary) [Variable('see')]
  453. exists x.walk(x) [Variable('walk')]
  454. \x.see(john,x) [Variable('see')]
  455. (\x.see(john,x))(mary) [Variable('see')]
  456. P(x) []
  457. \P.P(x) []
  458. aa(x,bb(y),cc(z),P(w),u) [Variable('aa'), Variable('bb'), Variable('cc')]
  459. bo(?det(?n),@x) [Variable('?det'), Variable('bo')]
  460. >>> for e in examples:
  461. ... print('%-25s' % e, sorted(e.variables()))
  462. walk(john) []
  463. walk(x) [Variable('x')]
  464. ?vp(?np) [Variable('?np'), Variable('?vp')]
  465. see(john,mary) []
  466. exists x.walk(x) []
  467. \x.see(john,x) []
  468. (\x.see(john,x))(mary) []
  469. P(x) [Variable('P'), Variable('x')]
  470. \P.P(x) [Variable('x')]
  471. aa(x,bb(y),cc(z),P(w),u) [Variable('P'), Variable('u'), Variable('w'), Variable('x'), Variable('y'), Variable('z')]
  472. bo(?det(?n),@x) [Variable('?det'), Variable('?n'), Variable('@x')]
  473. `normalize`
  474. >>> print(read_expr(r'\e083.(walk(e083, z472) & talk(e092, z938))').normalize())
  475. \e01.(walk(e01,z3) & talk(e02,z4))
  476. Typed Logic
  477. +++++++++++
  478. >>> from nltk.sem.logic import LogicParser
  479. >>> tlp = LogicParser(True)
  480. >>> print(tlp.parse(r'man(x)').type)
  481. ?
  482. >>> print(tlp.parse(r'walk(angus)').type)
  483. ?
  484. >>> print(tlp.parse(r'-man(x)').type)
  485. t
  486. >>> print(tlp.parse(r'(man(x) <-> tall(x))').type)
  487. t
  488. >>> print(tlp.parse(r'exists x.(man(x) & tall(x))').type)
  489. t
  490. >>> print(tlp.parse(r'\x.man(x)').type)
  491. <e,?>
  492. >>> print(tlp.parse(r'john').type)
  493. e
  494. >>> print(tlp.parse(r'\x y.sees(x,y)').type)
  495. <e,<e,?>>
  496. >>> print(tlp.parse(r'\x.man(x)(john)').type)
  497. ?
  498. >>> print(tlp.parse(r'\x.\y.sees(x,y)(john)').type)
  499. <e,?>
  500. >>> print(tlp.parse(r'\x.\y.sees(x,y)(john)(mary)').type)
  501. ?
  502. >>> print(tlp.parse(r'\P.\Q.exists x.(P(x) & Q(x))').type)
  503. <<e,t>,<<e,t>,t>>
  504. >>> print(tlp.parse(r'\x.y').type)
  505. <?,e>
  506. >>> print(tlp.parse(r'\P.P(x)').type)
  507. <<e,?>,?>
  508. >>> parsed = tlp.parse('see(john,mary)')
  509. >>> print(parsed.type)
  510. ?
  511. >>> print(parsed.function)
  512. see(john)
  513. >>> print(parsed.function.type)
  514. <e,?>
  515. >>> print(parsed.function.function)
  516. see
  517. >>> print(parsed.function.function.type)
  518. <e,<e,?>>
  519. >>> parsed = tlp.parse('P(x,y)')
  520. >>> print(parsed)
  521. P(x,y)
  522. >>> print(parsed.type)
  523. ?
  524. >>> print(parsed.function)
  525. P(x)
  526. >>> print(parsed.function.type)
  527. <e,?>
  528. >>> print(parsed.function.function)
  529. P
  530. >>> print(parsed.function.function.type)
  531. <e,<e,?>>
  532. >>> print(tlp.parse(r'P').type)
  533. ?
  534. >>> print(tlp.parse(r'P', {'P': 't'}).type)
  535. t
  536. >>> a = tlp.parse(r'P(x)')
  537. >>> print(a.type)
  538. ?
  539. >>> print(a.function.type)
  540. <e,?>
  541. >>> print(a.argument.type)
  542. e
  543. >>> a = tlp.parse(r'-P(x)')
  544. >>> print(a.type)
  545. t
  546. >>> print(a.term.type)
  547. t
  548. >>> print(a.term.function.type)
  549. <e,t>
  550. >>> print(a.term.argument.type)
  551. e
  552. >>> a = tlp.parse(r'P & Q')
  553. >>> print(a.type)
  554. t
  555. >>> print(a.first.type)
  556. t
  557. >>> print(a.second.type)
  558. t
  559. >>> a = tlp.parse(r'(P(x) & Q(x))')
  560. >>> print(a.type)
  561. t
  562. >>> print(a.first.type)
  563. t
  564. >>> print(a.first.function.type)
  565. <e,t>
  566. >>> print(a.first.argument.type)
  567. e
  568. >>> print(a.second.type)
  569. t
  570. >>> print(a.second.function.type)
  571. <e,t>
  572. >>> print(a.second.argument.type)
  573. e
  574. >>> a = tlp.parse(r'\x.P(x)')
  575. >>> print(a.type)
  576. <e,?>
  577. >>> print(a.term.function.type)
  578. <e,?>
  579. >>> print(a.term.argument.type)
  580. e
  581. >>> a = tlp.parse(r'\P.P(x)')
  582. >>> print(a.type)
  583. <<e,?>,?>
  584. >>> print(a.term.function.type)
  585. <e,?>
  586. >>> print(a.term.argument.type)
  587. e
  588. >>> a = tlp.parse(r'(\x.P(x)(john)) & Q(x)')
  589. >>> print(a.type)
  590. t
  591. >>> print(a.first.type)
  592. t
  593. >>> print(a.first.function.type)
  594. <e,t>
  595. >>> print(a.first.function.term.function.type)
  596. <e,t>
  597. >>> print(a.first.function.term.argument.type)
  598. e
  599. >>> print(a.first.argument.type)
  600. e
  601. >>> a = tlp.parse(r'\x y.P(x,y)(john)(mary) & Q(x)')
  602. >>> print(a.type)
  603. t
  604. >>> print(a.first.type)
  605. t
  606. >>> print(a.first.function.type)
  607. <e,t>
  608. >>> print(a.first.function.function.type)
  609. <e,<e,t>>
  610. >>> a = tlp.parse(r'--P')
  611. >>> print(a.type)
  612. t
  613. >>> print(a.term.type)
  614. t
  615. >>> print(a.term.term.type)
  616. t
  617. >>> tlp.parse(r'\x y.P(x,y)').type
  618. <e,<e,?>>
  619. >>> tlp.parse(r'\x y.P(x,y)', {'P': '<e,<e,t>>'}).type
  620. <e,<e,t>>
  621. >>> a = tlp.parse(r'\P y.P(john,y)(\x y.see(x,y))')
  622. >>> a.type
  623. <e,?>
  624. >>> a.function.type
  625. <<e,<e,?>>,<e,?>>
  626. >>> a.function.term.term.function.function.type
  627. <e,<e,?>>
  628. >>> a.argument.type
  629. <e,<e,?>>
  630. >>> a = tlp.parse(r'exists c f.(father(c) = f)')
  631. >>> a.type
  632. t
  633. >>> a.term.term.type
  634. t
  635. >>> a.term.term.first.type
  636. e
  637. >>> a.term.term.first.function.type
  638. <e,e>
  639. >>> a.term.term.second.type
  640. e
  641. typecheck()
  642. >>> a = tlp.parse('P(x)')
  643. >>> b = tlp.parse('Q(x)')
  644. >>> a.type
  645. ?
  646. >>> c = a & b
  647. >>> c.first.type
  648. ?
  649. >>> c.typecheck() # doctest: +ELLIPSIS
  650. {...}
  651. >>> c.first.type
  652. t
  653. >>> a = tlp.parse('P(x)')
  654. >>> b = tlp.parse('P(x) & Q(x)')
  655. >>> a.type
  656. ?
  657. >>> typecheck([a,b]) # doctest: +ELLIPSIS
  658. {...}
  659. >>> a.type
  660. t
  661. >>> e = tlp.parse(r'man(x)')
  662. >>> print(dict((k,str(v)) for k,v in e.typecheck().items()) == {'x': 'e', 'man': '<e,?>'})
  663. True
  664. >>> sig = {'man': '<e, t>'}
  665. >>> e = tlp.parse(r'man(x)', sig)
  666. >>> print(e.function.type)
  667. <e,t>
  668. >>> print(dict((k,str(v)) for k,v in e.typecheck().items()) == {'x': 'e', 'man': '<e,t>'})
  669. True
  670. >>> print(e.function.type)
  671. <e,t>
  672. >>> print(dict((k,str(v)) for k,v in e.typecheck(sig).items()) == {'x': 'e', 'man': '<e,t>'})
  673. True
  674. findtype()
  675. >>> print(tlp.parse(r'man(x)').findtype(Variable('man')))
  676. <e,?>
  677. >>> print(tlp.parse(r'see(x,y)').findtype(Variable('see')))
  678. <e,<e,?>>
  679. >>> print(tlp.parse(r'P(Q(R(x)))').findtype(Variable('Q')))
  680. ?
  681. reading types from strings
  682. >>> Type.fromstring('e')
  683. e
  684. >>> Type.fromstring('<e,t>')
  685. <e,t>
  686. >>> Type.fromstring('<<e,t>,<e,t>>')
  687. <<e,t>,<e,t>>
  688. >>> Type.fromstring('<<e,?>,?>')
  689. <<e,?>,?>
  690. alternative type format
  691. >>> Type.fromstring('e').str()
  692. 'IND'
  693. >>> Type.fromstring('<e,?>').str()
  694. '(IND -> ANY)'
  695. >>> Type.fromstring('<<e,t>,t>').str()
  696. '((IND -> BOOL) -> BOOL)'
  697. Type.__eq__()
  698. >>> from nltk.sem.logic import *
  699. >>> e = ENTITY_TYPE
  700. >>> t = TRUTH_TYPE
  701. >>> a = ANY_TYPE
  702. >>> et = ComplexType(e,t)
  703. >>> eet = ComplexType(e,ComplexType(e,t))
  704. >>> at = ComplexType(a,t)
  705. >>> ea = ComplexType(e,a)
  706. >>> aa = ComplexType(a,a)
  707. >>> e == e
  708. True
  709. >>> t == t
  710. True
  711. >>> e == t
  712. False
  713. >>> a == t
  714. False
  715. >>> t == a
  716. False
  717. >>> a == a
  718. True
  719. >>> et == et
  720. True
  721. >>> a == et
  722. False
  723. >>> et == a
  724. False
  725. >>> a == ComplexType(a,aa)
  726. True
  727. >>> ComplexType(a,aa) == a
  728. True
  729. matches()
  730. >>> e.matches(t)
  731. False
  732. >>> a.matches(t)
  733. True
  734. >>> t.matches(a)
  735. True
  736. >>> a.matches(et)
  737. True
  738. >>> et.matches(a)
  739. True
  740. >>> ea.matches(eet)
  741. True
  742. >>> eet.matches(ea)
  743. True
  744. >>> aa.matches(et)
  745. True
  746. >>> aa.matches(t)
  747. True
  748. Type error during parsing
  749. =========================
  750. >>> try: print(tlp.parse(r'exists x y.(P(x) & P(x,y))'))
  751. ... except InconsistentTypeHierarchyException as e: print(e)
  752. The variable 'P' was found in multiple places with different types.
  753. >>> try: tlp.parse(r'\x y.see(x,y)(\x.man(x))')
  754. ... except TypeException as e: print(e)
  755. The function '\x y.see(x,y)' is of type '<e,<e,?>>' and cannot be applied to '\x.man(x)' of type '<e,?>'. Its argument must match type 'e'.
  756. >>> try: tlp.parse(r'\P x y.-P(x,y)(\x.-man(x))')
  757. ... except TypeException as e: print(e)
  758. The function '\P x y.-P(x,y)' is of type '<<e,<e,t>>,<e,<e,t>>>' and cannot be applied to '\x.-man(x)' of type '<e,t>'. Its argument must match type '<e,<e,t>>'.
  759. >>> a = tlp.parse(r'-talk(x)')
  760. >>> signature = a.typecheck()
  761. >>> try: print(tlp.parse(r'-talk(x,y)', signature))
  762. ... except InconsistentTypeHierarchyException as e: print(e)
  763. The variable 'talk' was found in multiple places with different types.
  764. >>> a = tlp.parse(r'-P(x)')
  765. >>> b = tlp.parse(r'-P(x,y)')
  766. >>> a.typecheck() # doctest: +ELLIPSIS
  767. {...}
  768. >>> b.typecheck() # doctest: +ELLIPSIS
  769. {...}
  770. >>> try: typecheck([a,b])
  771. ... except InconsistentTypeHierarchyException as e: print(e)
  772. The variable 'P' was found in multiple places with different types.
  773. >>> a = tlp.parse(r'P(x)')
  774. >>> b = tlp.parse(r'P(x,y)')
  775. >>> signature = {'P': '<e,t>'}
  776. >>> a.typecheck(signature) # doctest: +ELLIPSIS
  777. {...}
  778. >>> try: typecheck([a,b], signature)
  779. ... except InconsistentTypeHierarchyException as e: print(e)
  780. The variable 'P' was found in multiple places with different types.
  781. Parse errors
  782. ============
  783. >>> try: read_expr(r'')
  784. ... except LogicalExpressionException as e: print(e)
  785. End of input found. Expression expected.
  786. <BLANKLINE>
  787. ^
  788. >>> try: read_expr(r'(')
  789. ... except LogicalExpressionException as e: print(e)
  790. End of input found. Expression expected.
  791. (
  792. ^
  793. >>> try: read_expr(r')')
  794. ... except LogicalExpressionException as e: print(e)
  795. Unexpected token: ')'. Expression expected.
  796. )
  797. ^
  798. >>> try: read_expr(r'()')
  799. ... except LogicalExpressionException as e: print(e)
  800. Unexpected token: ')'. Expression expected.
  801. ()
  802. ^
  803. >>> try: read_expr(r'(P(x) & Q(x)')
  804. ... except LogicalExpressionException as e: print(e)
  805. End of input found. Expected token ')'.
  806. (P(x) & Q(x)
  807. ^
  808. >>> try: read_expr(r'(P(x) &')
  809. ... except LogicalExpressionException as e: print(e)
  810. End of input found. Expression expected.
  811. (P(x) &
  812. ^
  813. >>> try: read_expr(r'(P(x) | )')
  814. ... except LogicalExpressionException as e: print(e)
  815. Unexpected token: ')'. Expression expected.
  816. (P(x) | )
  817. ^
  818. >>> try: read_expr(r'P(x) ->')
  819. ... except LogicalExpressionException as e: print(e)
  820. End of input found. Expression expected.
  821. P(x) ->
  822. ^
  823. >>> try: read_expr(r'P(x')
  824. ... except LogicalExpressionException as e: print(e)
  825. End of input found. Expected token ')'.
  826. P(x
  827. ^
  828. >>> try: read_expr(r'P(x,')
  829. ... except LogicalExpressionException as e: print(e)
  830. End of input found. Expression expected.
  831. P(x,
  832. ^
  833. >>> try: read_expr(r'P(x,)')
  834. ... except LogicalExpressionException as e: print(e)
  835. Unexpected token: ')'. Expression expected.
  836. P(x,)
  837. ^
  838. >>> try: read_expr(r'exists')
  839. ... except LogicalExpressionException as e: print(e)
  840. End of input found. Variable and Expression expected following quantifier 'exists'.
  841. exists
  842. ^
  843. >>> try: read_expr(r'exists x')
  844. ... except LogicalExpressionException as e: print(e)
  845. End of input found. Expression expected.
  846. exists x
  847. ^
  848. >>> try: read_expr(r'exists x.')
  849. ... except LogicalExpressionException as e: print(e)
  850. End of input found. Expression expected.
  851. exists x.
  852. ^
  853. >>> try: read_expr(r'\ ')
  854. ... except LogicalExpressionException as e: print(e)
  855. End of input found. Variable and Expression expected following lambda operator.
  856. \
  857. ^
  858. >>> try: read_expr(r'\ x')
  859. ... except LogicalExpressionException as e: print(e)
  860. End of input found. Expression expected.
  861. \ x
  862. ^
  863. >>> try: read_expr(r'\ x y')
  864. ... except LogicalExpressionException as e: print(e)
  865. End of input found. Expression expected.
  866. \ x y
  867. ^
  868. >>> try: read_expr(r'\ x.')
  869. ... except LogicalExpressionException as e: print(e)
  870. End of input found. Expression expected.
  871. \ x.
  872. ^
  873. >>> try: read_expr(r'P(x)Q(x)')
  874. ... except LogicalExpressionException as e: print(e)
  875. Unexpected token: 'Q'.
  876. P(x)Q(x)
  877. ^
  878. >>> try: read_expr(r'(P(x)Q(x)')
  879. ... except LogicalExpressionException as e: print(e)
  880. Unexpected token: 'Q'. Expected token ')'.
  881. (P(x)Q(x)
  882. ^
  883. >>> try: read_expr(r'exists x y')
  884. ... except LogicalExpressionException as e: print(e)
  885. End of input found. Expression expected.
  886. exists x y
  887. ^
  888. >>> try: read_expr(r'exists x y.')
  889. ... except LogicalExpressionException as e: print(e)
  890. End of input found. Expression expected.
  891. exists x y.
  892. ^
  893. >>> try: read_expr(r'exists x -> y')
  894. ... except LogicalExpressionException as e: print(e)
  895. Unexpected token: '->'. Expression expected.
  896. exists x -> y
  897. ^
  898. >>> try: read_expr(r'A -> ((P(x) & Q(x)) -> Z')
  899. ... except LogicalExpressionException as e: print(e)
  900. End of input found. Expected token ')'.
  901. A -> ((P(x) & Q(x)) -> Z
  902. ^
  903. >>> try: read_expr(r'A -> ((P(x) &) -> Z')
  904. ... except LogicalExpressionException as e: print(e)
  905. Unexpected token: ')'. Expression expected.
  906. A -> ((P(x) &) -> Z
  907. ^
  908. >>> try: read_expr(r'A -> ((P(x) | )) -> Z')
  909. ... except LogicalExpressionException as e: print(e)
  910. Unexpected token: ')'. Expression expected.
  911. A -> ((P(x) | )) -> Z
  912. ^
  913. >>> try: read_expr(r'A -> (P(x) ->) -> Z')
  914. ... except LogicalExpressionException as e: print(e)
  915. Unexpected token: ')'. Expression expected.
  916. A -> (P(x) ->) -> Z
  917. ^
  918. >>> try: read_expr(r'A -> (P(x) -> Z')
  919. ... except LogicalExpressionException as e: print(e)
  920. End of input found. Expected token ')'.
  921. A -> (P(x) -> Z
  922. ^
  923. >>> try: read_expr(r'A -> (P(x,) -> Z')
  924. ... except LogicalExpressionException as e: print(e)
  925. Unexpected token: ')'. Expression expected.
  926. A -> (P(x,) -> Z
  927. ^
  928. >>> try: read_expr(r'A -> (P(x,)) -> Z')
  929. ... except LogicalExpressionException as e: print(e)
  930. Unexpected token: ')'. Expression expected.
  931. A -> (P(x,)) -> Z
  932. ^
  933. >>> try: read_expr(r'A -> (exists) -> Z')
  934. ... except LogicalExpressionException as e: print(e)
  935. ')' is an illegal variable name. Constants may not be quantified.
  936. A -> (exists) -> Z
  937. ^
  938. >>> try: read_expr(r'A -> (exists x) -> Z')
  939. ... except LogicalExpressionException as e: print(e)
  940. Unexpected token: ')'. Expression expected.
  941. A -> (exists x) -> Z
  942. ^
  943. >>> try: read_expr(r'A -> (exists x.) -> Z')
  944. ... except LogicalExpressionException as e: print(e)
  945. Unexpected token: ')'. Expression expected.
  946. A -> (exists x.) -> Z
  947. ^
  948. >>> try: read_expr(r'A -> (\ ) -> Z')
  949. ... except LogicalExpressionException as e: print(e)
  950. ')' is an illegal variable name. Constants may not be abstracted.
  951. A -> (\ ) -> Z
  952. ^
  953. >>> try: read_expr(r'A -> (\ x) -> Z')
  954. ... except LogicalExpressionException as e: print(e)
  955. Unexpected token: ')'. Expression expected.
  956. A -> (\ x) -> Z
  957. ^
  958. >>> try: read_expr(r'A -> (\ x y) -> Z')
  959. ... except LogicalExpressionException as e: print(e)
  960. Unexpected token: ')'. Expression expected.
  961. A -> (\ x y) -> Z
  962. ^
  963. >>> try: read_expr(r'A -> (\ x.) -> Z')
  964. ... except LogicalExpressionException as e: print(e)
  965. Unexpected token: ')'. Expression expected.
  966. A -> (\ x.) -> Z
  967. ^
  968. >>> try: read_expr(r'A -> (P(x)Q(x)) -> Z')
  969. ... except LogicalExpressionException as e: print(e)
  970. Unexpected token: 'Q'. Expected token ')'.
  971. A -> (P(x)Q(x)) -> Z
  972. ^
  973. >>> try: read_expr(r'A -> ((P(x)Q(x)) -> Z')
  974. ... except LogicalExpressionException as e: print(e)
  975. Unexpected token: 'Q'. Expected token ')'.
  976. A -> ((P(x)Q(x)) -> Z
  977. ^
  978. >>> try: read_expr(r'A -> (all x y) -> Z')
  979. ... except LogicalExpressionException as e: print(e)
  980. Unexpected token: ')'. Expression expected.
  981. A -> (all x y) -> Z
  982. ^
  983. >>> try: read_expr(r'A -> (exists x y.) -> Z')
  984. ... except LogicalExpressionException as e: print(e)
  985. Unexpected token: ')'. Expression expected.
  986. A -> (exists x y.) -> Z
  987. ^
  988. >>> try: read_expr(r'A -> (exists x -> y) -> Z')
  989. ... except LogicalExpressionException as e: print(e)
  990. Unexpected token: '->'. Expression expected.
  991. A -> (exists x -> y) -> Z
  992. ^