gluesemantics.doctest 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. .. Copyright (C) 2001-2019 NLTK Project
  2. .. For license information, see LICENSE.TXT
  3. ==============================================================================
  4. Glue Semantics
  5. ==============================================================================
  6. .. include:: ../../../nltk_book/definitions.rst
  7. ======================
  8. Linear logic
  9. ======================
  10. >>> from nltk.sem import logic
  11. >>> from nltk.sem.glue import *
  12. >>> from nltk.sem.linearlogic import *
  13. >>> from nltk.sem.linearlogic import Expression
  14. >>> read_expr = Expression.fromstring
  15. Parser
  16. >>> print(read_expr(r'f'))
  17. f
  18. >>> print(read_expr(r'(g -o f)'))
  19. (g -o f)
  20. >>> print(read_expr(r'(g -o (h -o f))'))
  21. (g -o (h -o f))
  22. >>> print(read_expr(r'((g -o G) -o G)'))
  23. ((g -o G) -o G)
  24. >>> print(read_expr(r'(g -o f)(g)'))
  25. (g -o f)(g)
  26. >>> print(read_expr(r'((g -o G) -o G)((g -o f))'))
  27. ((g -o G) -o G)((g -o f))
  28. Simplify
  29. >>> print(read_expr(r'f').simplify())
  30. f
  31. >>> print(read_expr(r'(g -o f)').simplify())
  32. (g -o f)
  33. >>> print(read_expr(r'((g -o G) -o G)').simplify())
  34. ((g -o G) -o G)
  35. >>> print(read_expr(r'(g -o f)(g)').simplify())
  36. f
  37. >>> try: read_expr(r'(g -o f)(f)').simplify()
  38. ... except LinearLogicApplicationException as e: print(e)
  39. ...
  40. Cannot apply (g -o f) to f. Cannot unify g with f given {}
  41. >>> print(read_expr(r'(G -o f)(g)').simplify())
  42. f
  43. >>> print(read_expr(r'((g -o G) -o G)((g -o f))').simplify())
  44. f
  45. Test BindingDict
  46. >>> h = ConstantExpression('h')
  47. >>> g = ConstantExpression('g')
  48. >>> f = ConstantExpression('f')
  49. >>> H = VariableExpression('H')
  50. >>> G = VariableExpression('G')
  51. >>> F = VariableExpression('F')
  52. >>> d1 = BindingDict({H: h})
  53. >>> d2 = BindingDict({F: f, G: F})
  54. >>> d12 = d1 + d2
  55. >>> all12 = ['%s: %s' % (v, d12[v]) for v in d12.d]
  56. >>> all12.sort()
  57. >>> print(all12)
  58. ['F: f', 'G: f', 'H: h']
  59. >>> BindingDict([(F,f),(G,g),(H,h)]) == BindingDict({F:f, G:g, H:h})
  60. True
  61. >>> d4 = BindingDict({F: f})
  62. >>> try: d4[F] = g
  63. ... except VariableBindingException as e: print(e)
  64. Variable F already bound to another value
  65. Test Unify
  66. >>> try: f.unify(g, BindingDict())
  67. ... except UnificationException as e: print(e)
  68. ...
  69. Cannot unify f with g given {}
  70. >>> f.unify(G, BindingDict()) == BindingDict({G: f})
  71. True
  72. >>> try: f.unify(G, BindingDict({G: h}))
  73. ... except UnificationException as e: print(e)
  74. ...
  75. Cannot unify f with G given {G: h}
  76. >>> f.unify(G, BindingDict({G: f})) == BindingDict({G: f})
  77. True
  78. >>> f.unify(G, BindingDict({H: f})) == BindingDict({G: f, H: f})
  79. True
  80. >>> G.unify(f, BindingDict()) == BindingDict({G: f})
  81. True
  82. >>> try: G.unify(f, BindingDict({G: h}))
  83. ... except UnificationException as e: print(e)
  84. ...
  85. Cannot unify G with f given {G: h}
  86. >>> G.unify(f, BindingDict({G: f})) == BindingDict({G: f})
  87. True
  88. >>> G.unify(f, BindingDict({H: f})) == BindingDict({G: f, H: f})
  89. True
  90. >>> G.unify(F, BindingDict()) == BindingDict({G: F})
  91. True
  92. >>> try: G.unify(F, BindingDict({G: H}))
  93. ... except UnificationException as e: print(e)
  94. ...
  95. Cannot unify G with F given {G: H}
  96. >>> G.unify(F, BindingDict({G: F})) == BindingDict({G: F})
  97. True
  98. >>> G.unify(F, BindingDict({H: F})) == BindingDict({G: F, H: F})
  99. True
  100. Test Compile
  101. >>> print(read_expr('g').compile_pos(Counter(), GlueFormula))
  102. (<ConstantExpression g>, [])
  103. >>> print(read_expr('(g -o f)').compile_pos(Counter(), GlueFormula))
  104. (<ImpExpression (g -o f)>, [])
  105. >>> print(read_expr('(g -o (h -o f))').compile_pos(Counter(), GlueFormula))
  106. (<ImpExpression (g -o (h -o f))>, [])
  107. ======================
  108. Glue
  109. ======================
  110. Demo of "John walks"
  111. --------------------
  112. >>> john = GlueFormula("John", "g")
  113. >>> print(john)
  114. John : g
  115. >>> walks = GlueFormula(r"\x.walks(x)", "(g -o f)")
  116. >>> print(walks)
  117. \x.walks(x) : (g -o f)
  118. >>> print(walks.applyto(john))
  119. \x.walks(x)(John) : (g -o f)(g)
  120. >>> print(walks.applyto(john).simplify())
  121. walks(John) : f
  122. Demo of "A dog walks"
  123. ---------------------
  124. >>> a = GlueFormula("\P Q.some x.(P(x) and Q(x))", "((gv -o gr) -o ((g -o G) -o G))")
  125. >>> print(a)
  126. \P Q.exists x.(P(x) & Q(x)) : ((gv -o gr) -o ((g -o G) -o G))
  127. >>> man = GlueFormula(r"\x.man(x)", "(gv -o gr)")
  128. >>> print(man)
  129. \x.man(x) : (gv -o gr)
  130. >>> walks = GlueFormula(r"\x.walks(x)", "(g -o f)")
  131. >>> print(walks)
  132. \x.walks(x) : (g -o f)
  133. >>> a_man = a.applyto(man)
  134. >>> print(a_man.simplify())
  135. \Q.exists x.(man(x) & Q(x)) : ((g -o G) -o G)
  136. >>> a_man_walks = a_man.applyto(walks)
  137. >>> print(a_man_walks.simplify())
  138. exists x.(man(x) & walks(x)) : f
  139. Demo of 'every girl chases a dog'
  140. ---------------------------------
  141. Individual words:
  142. >>> every = GlueFormula("\P Q.all x.(P(x) -> Q(x))", "((gv -o gr) -o ((g -o G) -o G))")
  143. >>> print(every)
  144. \P Q.all x.(P(x) -> Q(x)) : ((gv -o gr) -o ((g -o G) -o G))
  145. >>> girl = GlueFormula(r"\x.girl(x)", "(gv -o gr)")
  146. >>> print(girl)
  147. \x.girl(x) : (gv -o gr)
  148. >>> chases = GlueFormula(r"\x y.chases(x,y)", "(g -o (h -o f))")
  149. >>> print(chases)
  150. \x y.chases(x,y) : (g -o (h -o f))
  151. >>> a = GlueFormula("\P Q.some x.(P(x) and Q(x))", "((hv -o hr) -o ((h -o H) -o H))")
  152. >>> print(a)
  153. \P Q.exists x.(P(x) & Q(x)) : ((hv -o hr) -o ((h -o H) -o H))
  154. >>> dog = GlueFormula(r"\x.dog(x)", "(hv -o hr)")
  155. >>> print(dog)
  156. \x.dog(x) : (hv -o hr)
  157. Noun Quantification can only be done one way:
  158. >>> every_girl = every.applyto(girl)
  159. >>> print(every_girl.simplify())
  160. \Q.all x.(girl(x) -> Q(x)) : ((g -o G) -o G)
  161. >>> a_dog = a.applyto(dog)
  162. >>> print(a_dog.simplify())
  163. \Q.exists x.(dog(x) & Q(x)) : ((h -o H) -o H)
  164. The first reading is achieved by combining 'chases' with 'a dog' first.
  165. Since 'a girl' requires something of the form '(h -o H)' we must
  166. get rid of the 'g' in the glue of 'see'. We will do this with
  167. the '-o elimination' rule. So, x1 will be our subject placeholder.
  168. >>> xPrime = GlueFormula("x1", "g")
  169. >>> print(xPrime)
  170. x1 : g
  171. >>> xPrime_chases = chases.applyto(xPrime)
  172. >>> print(xPrime_chases.simplify())
  173. \y.chases(x1,y) : (h -o f)
  174. >>> xPrime_chases_a_dog = a_dog.applyto(xPrime_chases)
  175. >>> print(xPrime_chases_a_dog.simplify())
  176. exists x.(dog(x) & chases(x1,x)) : f
  177. Now we can retract our subject placeholder using lambda-abstraction and
  178. combine with the true subject.
  179. >>> chases_a_dog = xPrime_chases_a_dog.lambda_abstract(xPrime)
  180. >>> print(chases_a_dog.simplify())
  181. \x1.exists x.(dog(x) & chases(x1,x)) : (g -o f)
  182. >>> every_girl_chases_a_dog = every_girl.applyto(chases_a_dog)
  183. >>> r1 = every_girl_chases_a_dog.simplify()
  184. >>> r2 = GlueFormula(r'all x.(girl(x) -> exists z1.(dog(z1) & chases(x,z1)))', 'f')
  185. >>> r1 == r2
  186. True
  187. The second reading is achieved by combining 'every girl' with 'chases' first.
  188. >>> xPrime = GlueFormula("x1", "g")
  189. >>> print(xPrime)
  190. x1 : g
  191. >>> xPrime_chases = chases.applyto(xPrime)
  192. >>> print(xPrime_chases.simplify())
  193. \y.chases(x1,y) : (h -o f)
  194. >>> yPrime = GlueFormula("x2", "h")
  195. >>> print(yPrime)
  196. x2 : h
  197. >>> xPrime_chases_yPrime = xPrime_chases.applyto(yPrime)
  198. >>> print(xPrime_chases_yPrime.simplify())
  199. chases(x1,x2) : f
  200. >>> chases_yPrime = xPrime_chases_yPrime.lambda_abstract(xPrime)
  201. >>> print(chases_yPrime.simplify())
  202. \x1.chases(x1,x2) : (g -o f)
  203. >>> every_girl_chases_yPrime = every_girl.applyto(chases_yPrime)
  204. >>> print(every_girl_chases_yPrime.simplify())
  205. all x.(girl(x) -> chases(x,x2)) : f
  206. >>> every_girl_chases = every_girl_chases_yPrime.lambda_abstract(yPrime)
  207. >>> print(every_girl_chases.simplify())
  208. \x2.all x.(girl(x) -> chases(x,x2)) : (h -o f)
  209. >>> every_girl_chases_a_dog = a_dog.applyto(every_girl_chases)
  210. >>> r1 = every_girl_chases_a_dog.simplify()
  211. >>> r2 = GlueFormula(r'exists x.(dog(x) & all z2.(girl(z2) -> chases(z2,x)))', 'f')
  212. >>> r1 == r2
  213. True
  214. Compilation
  215. -----------
  216. >>> for cp in GlueFormula('m', '(b -o a)').compile(Counter()): print(cp)
  217. m : (b -o a) : {1}
  218. >>> for cp in GlueFormula('m', '((c -o b) -o a)').compile(Counter()): print(cp)
  219. v1 : c : {1}
  220. m : (b[1] -o a) : {2}
  221. >>> for cp in GlueFormula('m', '((d -o (c -o b)) -o a)').compile(Counter()): print(cp)
  222. v1 : c : {1}
  223. v2 : d : {2}
  224. m : (b[1, 2] -o a) : {3}
  225. >>> for cp in GlueFormula('m', '((d -o e) -o ((c -o b) -o a))').compile(Counter()): print(cp)
  226. v1 : d : {1}
  227. v2 : c : {2}
  228. m : (e[1] -o (b[2] -o a)) : {3}
  229. >>> for cp in GlueFormula('m', '(((d -o c) -o b) -o a)').compile(Counter()): print(cp)
  230. v1 : (d -o c) : {1}
  231. m : (b[1] -o a) : {2}
  232. >>> for cp in GlueFormula('m', '((((e -o d) -o c) -o b) -o a)').compile(Counter()): print(cp)
  233. v1 : e : {1}
  234. v2 : (d[1] -o c) : {2}
  235. m : (b[2] -o a) : {3}
  236. Demo of 'a man walks' using Compilation
  237. ---------------------------------------
  238. Premises
  239. >>> a = GlueFormula('\\P Q.some x.(P(x) and Q(x))', '((gv -o gr) -o ((g -o G) -o G))')
  240. >>> print(a)
  241. \P Q.exists x.(P(x) & Q(x)) : ((gv -o gr) -o ((g -o G) -o G))
  242. >>> man = GlueFormula('\\x.man(x)', '(gv -o gr)')
  243. >>> print(man)
  244. \x.man(x) : (gv -o gr)
  245. >>> walks = GlueFormula('\\x.walks(x)', '(g -o f)')
  246. >>> print(walks)
  247. \x.walks(x) : (g -o f)
  248. Compiled Premises:
  249. >>> counter = Counter()
  250. >>> ahc = a.compile(counter)
  251. >>> g1 = ahc[0]
  252. >>> print(g1)
  253. v1 : gv : {1}
  254. >>> g2 = ahc[1]
  255. >>> print(g2)
  256. v2 : g : {2}
  257. >>> g3 = ahc[2]
  258. >>> print(g3)
  259. \P Q.exists x.(P(x) & Q(x)) : (gr[1] -o (G[2] -o G)) : {3}
  260. >>> g4 = man.compile(counter)[0]
  261. >>> print(g4)
  262. \x.man(x) : (gv -o gr) : {4}
  263. >>> g5 = walks.compile(counter)[0]
  264. >>> print(g5)
  265. \x.walks(x) : (g -o f) : {5}
  266. Derivation:
  267. >>> g14 = g4.applyto(g1)
  268. >>> print(g14.simplify())
  269. man(v1) : gr : {1, 4}
  270. >>> g134 = g3.applyto(g14)
  271. >>> print(g134.simplify())
  272. \Q.exists x.(man(x) & Q(x)) : (G[2] -o G) : {1, 3, 4}
  273. >>> g25 = g5.applyto(g2)
  274. >>> print(g25.simplify())
  275. walks(v2) : f : {2, 5}
  276. >>> g12345 = g134.applyto(g25)
  277. >>> print(g12345.simplify())
  278. exists x.(man(x) & walks(x)) : f : {1, 2, 3, 4, 5}
  279. ---------------------------------
  280. Dependency Graph to Glue Formulas
  281. ---------------------------------
  282. >>> from nltk.corpus.reader.dependency import DependencyGraph
  283. >>> depgraph = DependencyGraph("""1 John _ NNP NNP _ 2 SUBJ _ _
  284. ... 2 sees _ VB VB _ 0 ROOT _ _
  285. ... 3 a _ ex_quant ex_quant _ 4 SPEC _ _
  286. ... 4 dog _ NN NN _ 2 OBJ _ _
  287. ... """)
  288. >>> gfl = GlueDict('nltk:grammars/sample_grammars/glue.semtype').to_glueformula_list(depgraph)
  289. >>> print(gfl) # doctest: +SKIP
  290. [\x y.sees(x,y) : (f -o (i -o g)),
  291. \x.dog(x) : (iv -o ir),
  292. \P Q.exists x.(P(x) & Q(x)) : ((iv -o ir) -o ((i -o I3) -o I3)),
  293. \P Q.exists x.(P(x) & Q(x)) : ((fv -o fr) -o ((f -o F4) -o F4)),
  294. \x.John(x) : (fv -o fr)]
  295. >>> glue = Glue()
  296. >>> for r in sorted([r.simplify().normalize() for r in glue.get_readings(glue.gfl_to_compiled(gfl))], key=str):
  297. ... print(r)
  298. exists z1.(John(z1) & exists z2.(dog(z2) & sees(z1,z2)))
  299. exists z1.(dog(z1) & exists z2.(John(z2) & sees(z2,z1)))
  300. -----------------------------------
  301. Dependency Graph to LFG f-structure
  302. -----------------------------------
  303. >>> from nltk.sem.lfg import FStructure
  304. >>> fstruct = FStructure.read_depgraph(depgraph)
  305. >>> print(fstruct) # doctest: +SKIP
  306. f:[pred 'sees'
  307. obj h:[pred 'dog'
  308. spec 'a']
  309. subj g:[pred 'John']]
  310. >>> fstruct.to_depgraph().tree().pprint()
  311. (sees (dog a) John)
  312. ---------------------------------
  313. LFG f-structure to Glue
  314. ---------------------------------
  315. >>> fstruct.to_glueformula_list(GlueDict('nltk:grammars/sample_grammars/glue.semtype')) # doctest: +SKIP
  316. [\x y.sees(x,y) : (i -o (g -o f)),
  317. \x.dog(x) : (gv -o gr),
  318. \P Q.exists x.(P(x) & Q(x)) : ((gv -o gr) -o ((g -o G3) -o G3)),
  319. \P Q.exists x.(P(x) & Q(x)) : ((iv -o ir) -o ((i -o I4) -o I4)),
  320. \x.John(x) : (iv -o ir)]
  321. .. see gluesemantics_malt.doctest for more