nltk 3.2__zip → 3.3__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (406) hide show
  1. {nltk-3.2 → nltk-3.3}/INSTALL.txt +6 -6
  2. {nltk-3.2 → nltk-3.3}/LICENSE.txt +13 -13
  3. {nltk-3.2 → nltk-3.3}/MANIFEST.in +6 -6
  4. {nltk-3.2/nltk.egg-info → nltk-3.3}/PKG-INFO +13 -5
  5. nltk-3.2/README.txt → nltk-3.3/README.md +49 -48
  6. nltk-3.3/nltk/VERSION +1 -0
  7. {nltk-3.2 → nltk-3.3}/nltk/__init__.py +185 -185
  8. {nltk-3.2 → nltk-3.3}/nltk/app/__init__.py +52 -53
  9. {nltk-3.2 → nltk-3.3}/nltk/app/chartparser_app.py +2276 -2276
  10. {nltk-3.2 → nltk-3.3}/nltk/app/chunkparser_app.py +1262 -1264
  11. {nltk-3.2 → nltk-3.3}/nltk/app/collocations_app.py +347 -350
  12. {nltk-3.2 → nltk-3.3}/nltk/app/concordance_app.py +568 -570
  13. {nltk-3.2 → nltk-3.3}/nltk/app/nemo_app.py +156 -155
  14. {nltk-3.2 → nltk-3.3}/nltk/app/rdparser_app.py +892 -894
  15. {nltk-3.2 → nltk-3.3}/nltk/app/srparser_app.py +809 -809
  16. {nltk-3.2 → nltk-3.3}/nltk/app/wordfreq_app.py +32 -32
  17. {nltk-3.2 → nltk-3.3}/nltk/app/wordnet_app.py +968 -968
  18. {nltk-3.2 → nltk-3.3}/nltk/book.py +91 -90
  19. {nltk-3.2 → nltk-3.3}/nltk/ccg/__init__.py +22 -22
  20. {nltk-3.2 → nltk-3.3}/nltk/ccg/api.py +359 -335
  21. {nltk-3.2 → nltk-3.3}/nltk/ccg/chart.py +394 -361
  22. {nltk-3.2 → nltk-3.3}/nltk/ccg/combinator.py +343 -312
  23. {nltk-3.2 → nltk-3.3}/nltk/ccg/lexicon.py +328 -290
  24. nltk-3.3/nltk/ccg/logic.py +46 -0
  25. {nltk-3.2 → nltk-3.3}/nltk/chat/__init__.py +49 -49
  26. {nltk-3.2 → nltk-3.3}/nltk/chat/eliza.py +244 -244
  27. {nltk-3.2 → nltk-3.3}/nltk/chat/iesha.py +140 -140
  28. {nltk-3.2 → nltk-3.3}/nltk/chat/rude.py +92 -92
  29. {nltk-3.2 → nltk-3.3}/nltk/chat/suntsu.py +117 -117
  30. {nltk-3.2 → nltk-3.3}/nltk/chat/util.py +122 -120
  31. {nltk-3.2 → nltk-3.3}/nltk/chat/zen.py +282 -282
  32. {nltk-3.2 → nltk-3.3}/nltk/chunk/__init__.py +190 -190
  33. {nltk-3.2 → nltk-3.3}/nltk/chunk/api.py +51 -51
  34. {nltk-3.2 → nltk-3.3}/nltk/chunk/named_entity.py +331 -331
  35. {nltk-3.2 → nltk-3.3}/nltk/chunk/regexp.py +1390 -1384
  36. {nltk-3.2 → nltk-3.3}/nltk/chunk/util.py +600 -600
  37. {nltk-3.2 → nltk-3.3}/nltk/classify/__init__.py +98 -98
  38. {nltk-3.2 → nltk-3.3}/nltk/classify/api.py +193 -193
  39. {nltk-3.2 → nltk-3.3}/nltk/classify/decisiontree.py +295 -295
  40. {nltk-3.2 → nltk-3.3}/nltk/classify/maxent.py +1510 -1492
  41. {nltk-3.2 → nltk-3.3}/nltk/classify/megam.py +179 -178
  42. {nltk-3.2 → nltk-3.3}/nltk/classify/naivebayes.py +245 -242
  43. {nltk-3.2 → nltk-3.3}/nltk/classify/positivenaivebayes.py +170 -170
  44. {nltk-3.2 → nltk-3.3}/nltk/classify/rte_classify.py +160 -191
  45. {nltk-3.2 → nltk-3.3}/nltk/classify/scikitlearn.py +153 -151
  46. {nltk-3.2 → nltk-3.3}/nltk/classify/senna.py +183 -181
  47. {nltk-3.2 → nltk-3.3}/nltk/classify/svm.py +15 -15
  48. {nltk-3.2 → nltk-3.3}/nltk/classify/tadm.py +113 -112
  49. {nltk-3.2 → nltk-3.3}/nltk/classify/textcat.py +193 -193
  50. {nltk-3.2 → nltk-3.3}/nltk/classify/util.py +324 -312
  51. {nltk-3.2 → nltk-3.3}/nltk/classify/weka.py +346 -345
  52. {nltk-3.2 → nltk-3.3}/nltk/cluster/__init__.py +86 -86
  53. {nltk-3.2 → nltk-3.3}/nltk/cluster/api.py +74 -70
  54. {nltk-3.2 → nltk-3.3}/nltk/cluster/em.py +247 -247
  55. {nltk-3.2 → nltk-3.3}/nltk/cluster/gaac.py +168 -168
  56. {nltk-3.2 → nltk-3.3}/nltk/cluster/kmeans.py +221 -221
  57. {nltk-3.2 → nltk-3.3}/nltk/cluster/util.py +304 -289
  58. nltk-3.3/nltk/collections.py +640 -0
  59. {nltk-3.2 → nltk-3.3}/nltk/collocations.py +388 -388
  60. nltk-3.3/nltk/compat.py +365 -0
  61. {nltk-3.2 → nltk-3.3}/nltk/corpus/__init__.py +341 -320
  62. {nltk-3.2 → nltk-3.3}/nltk/corpus/europarl_raw.py +44 -44
  63. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/__init__.py +147 -145
  64. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/aligned.py +115 -114
  65. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/api.py +448 -446
  66. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bnc.py +252 -252
  67. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bracket_parse.py +227 -227
  68. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/categorized_sents.py +179 -178
  69. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chasen.py +140 -139
  70. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/childes.py +522 -494
  71. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chunked.py +212 -212
  72. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/cmudict.py +97 -95
  73. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/comparative_sents.py +280 -278
  74. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/conll.py +528 -521
  75. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/crubadan.py +116 -116
  76. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/dependency.py +101 -101
  77. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/framenet.py +3059 -2093
  78. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ieer.py +112 -111
  79. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/indian.py +85 -86
  80. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ipipan.py +332 -331
  81. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/knbc.py +187 -187
  82. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/lin.py +156 -156
  83. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/mte.py +311 -310
  84. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nkjp.py +429 -428
  85. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nombank.py +421 -421
  86. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nps_chat.py +73 -73
  87. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/opinion_lexicon.py +115 -115
  88. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/panlex_lite.py +165 -165
  89. nltk-3.3/nltk/corpus/reader/pl196x.py +292 -0
  90. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/plaintext.py +232 -233
  91. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ppattach.py +96 -95
  92. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/propbank.py +479 -481
  93. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/pros_cons.py +128 -126
  94. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/reviews.py +330 -328
  95. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/rte.py +144 -146
  96. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/semcor.py +256 -256
  97. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/senseval.py +203 -201
  98. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sentiwordnet.py +137 -137
  99. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sinica_treebank.py +75 -75
  100. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/string_category.py +60 -59
  101. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/switchboard.py +119 -119
  102. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/tagged.py +295 -294
  103. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/timit.py +452 -450
  104. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/toolbox.py +68 -68
  105. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/twitter.py +155 -157
  106. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/udhr.py +80 -80
  107. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/util.py +804 -800
  108. nltk-3.3/nltk/corpus/reader/verbnet.py +595 -0
  109. nltk-3.3/nltk/corpus/reader/wordlist.py +134 -0
  110. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/wordnet.py +2108 -2036
  111. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/xmldocs.py +392 -387
  112. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ycoe.py +243 -242
  113. {nltk-3.2 → nltk-3.3}/nltk/corpus/util.py +144 -127
  114. {nltk-3.2 → nltk-3.3}/nltk/data.py +1487 -1451
  115. {nltk-3.2 → nltk-3.3}/nltk/decorators.py +219 -215
  116. {nltk-3.2 → nltk-3.3}/nltk/downloader.py +2278 -2274
  117. {nltk-3.2 → nltk-3.3}/nltk/draw/__init__.py +27 -27
  118. {nltk-3.2 → nltk-3.3}/nltk/draw/cfg.py +774 -777
  119. {nltk-3.2 → nltk-3.3}/nltk/draw/dispersion.py +58 -58
  120. {nltk-3.2 → nltk-3.3}/nltk/draw/table.py +1098 -1098
  121. {nltk-3.2 → nltk-3.3}/nltk/draw/tree.py +963 -966
  122. {nltk-3.2 → nltk-3.3}/nltk/draw/util.py +2356 -2356
  123. {nltk-3.2 → nltk-3.3}/nltk/featstruct.py +2617 -2500
  124. {nltk-3.2 → nltk-3.3}/nltk/grammar.py +1559 -1516
  125. {nltk-3.2 → nltk-3.3}/nltk/help.py +56 -56
  126. {nltk-3.2 → nltk-3.3}/nltk/inference/__init__.py +20 -20
  127. {nltk-3.2 → nltk-3.3}/nltk/inference/api.py +597 -589
  128. {nltk-3.2 → nltk-3.3}/nltk/inference/discourse.py +612 -608
  129. {nltk-3.2 → nltk-3.3}/nltk/inference/mace.py +311 -311
  130. {nltk-3.2 → nltk-3.3}/nltk/inference/nonmonotonic.py +509 -509
  131. {nltk-3.2 → nltk-3.3}/nltk/inference/prover9.py +431 -431
  132. {nltk-3.2 → nltk-3.3}/nltk/inference/resolution.py +687 -687
  133. {nltk-3.2 → nltk-3.3}/nltk/inference/tableau.py +607 -607
  134. {nltk-3.2 → nltk-3.3}/nltk/internals.py +982 -982
  135. {nltk-3.2 → nltk-3.3}/nltk/jsontags.py +63 -63
  136. {nltk-3.2 → nltk-3.3}/nltk/lazyimport.py +142 -142
  137. {nltk-3.2 → nltk-3.3}/nltk/metrics/__init__.py +30 -29
  138. {nltk-3.2 → nltk-3.3}/nltk/metrics/agreement.py +421 -401
  139. nltk-3.3/nltk/metrics/aline.py +607 -0
  140. {nltk-3.2 → nltk-3.3}/nltk/metrics/association.py +414 -410
  141. {nltk-3.2 → nltk-3.3}/nltk/metrics/confusionmatrix.py +206 -206
  142. {nltk-3.2 → nltk-3.3}/nltk/metrics/distance.py +207 -202
  143. {nltk-3.2 → nltk-3.3}/nltk/metrics/paice.py +381 -381
  144. {nltk-3.2 → nltk-3.3}/nltk/metrics/scores.py +228 -228
  145. {nltk-3.2 → nltk-3.3}/nltk/metrics/segmentation.py +231 -232
  146. {nltk-3.2 → nltk-3.3}/nltk/metrics/spearman.py +69 -69
  147. {nltk-3.2 → nltk-3.3}/nltk/misc/__init__.py +11 -11
  148. {nltk-3.2 → nltk-3.3}/nltk/misc/babelfish.py +10 -10
  149. {nltk-3.2 → nltk-3.3}/nltk/misc/chomsky.py +135 -133
  150. {nltk-3.2 → nltk-3.3}/nltk/misc/minimalset.py +83 -83
  151. {nltk-3.2 → nltk-3.3}/nltk/misc/sort.py +157 -157
  152. {nltk-3.2 → nltk-3.3}/nltk/misc/wordfinder.py +129 -129
  153. {nltk-3.2 → nltk-3.3}/nltk/parse/__init__.py +81 -80
  154. {nltk-3.2 → nltk-3.3}/nltk/parse/api.py +66 -66
  155. {nltk-3.2 → nltk-3.3}/nltk/parse/bllip.py +282 -282
  156. {nltk-3.2 → nltk-3.3}/nltk/parse/chart.py +1682 -1681
  157. nltk-3.3/nltk/parse/corenlp.py +780 -0
  158. {nltk-3.2 → nltk-3.3}/nltk/parse/dependencygraph.py +760 -758
  159. {nltk-3.2 → nltk-3.3}/nltk/parse/earleychart.py +452 -451
  160. {nltk-3.2 → nltk-3.3}/nltk/parse/evaluate.py +129 -129
  161. {nltk-3.2 → nltk-3.3}/nltk/parse/featurechart.py +580 -578
  162. {nltk-3.2 → nltk-3.3}/nltk/parse/generate.py +87 -76
  163. {nltk-3.2 → nltk-3.3}/nltk/parse/malt.py +356 -356
  164. {nltk-3.2 → nltk-3.3}/nltk/parse/nonprojectivedependencyparser.py +783 -783
  165. {nltk-3.2 → nltk-3.3}/nltk/parse/pchart.py +522 -522
  166. {nltk-3.2 → nltk-3.3}/nltk/parse/projectivedependencyparser.py +579 -578
  167. {nltk-3.2 → nltk-3.3}/nltk/parse/recursivedescent.py +655 -656
  168. {nltk-3.2 → nltk-3.3}/nltk/parse/shiftreduce.py +458 -459
  169. {nltk-3.2 → nltk-3.3}/nltk/parse/stanford.py +431 -406
  170. {nltk-3.2 → nltk-3.3}/nltk/parse/transitionparser.py +774 -772
  171. {nltk-3.2 → nltk-3.3}/nltk/parse/util.py +231 -231
  172. {nltk-3.2 → nltk-3.3}/nltk/parse/viterbi.py +401 -401
  173. {nltk-3.2 → nltk-3.3}/nltk/probability.py +2410 -2355
  174. {nltk-3.2 → nltk-3.3}/nltk/sem/__init__.py +61 -61
  175. {nltk-3.2 → nltk-3.3}/nltk/sem/boxer.py +1261 -1261
  176. {nltk-3.2 → nltk-3.3}/nltk/sem/chat80.py +782 -782
  177. {nltk-3.2 → nltk-3.3}/nltk/sem/cooper_storage.py +118 -118
  178. {nltk-3.2 → nltk-3.3}/nltk/sem/drt.py +1258 -1257
  179. {nltk-3.2 → nltk-3.3}/nltk/sem/drt_glue_demo.py +485 -489
  180. {nltk-3.2 → nltk-3.3}/nltk/sem/evaluate.py +790 -784
  181. {nltk-3.2 → nltk-3.3}/nltk/sem/glue.py +696 -694
  182. {nltk-3.2 → nltk-3.3}/nltk/sem/hole.py +386 -384
  183. {nltk-3.2 → nltk-3.3}/nltk/sem/lfg.py +210 -208
  184. {nltk-3.2 → nltk-3.3}/nltk/sem/linearlogic.py +451 -449
  185. {nltk-3.2 → nltk-3.3}/nltk/sem/logic.py +1910 -1910
  186. {nltk-3.2 → nltk-3.3}/nltk/sem/relextract.py +476 -483
  187. {nltk-3.2 → nltk-3.3}/nltk/sem/skolemize.py +101 -101
  188. {nltk-3.2 → nltk-3.3}/nltk/sem/util.py +249 -249
  189. {nltk-3.2 → nltk-3.3}/nltk/sentiment/__init__.py +14 -14
  190. {nltk-3.2 → nltk-3.3}/nltk/sentiment/sentiment_analyzer.py +229 -229
  191. {nltk-3.2 → nltk-3.3}/nltk/sentiment/util.py +762 -752
  192. {nltk-3.2 → nltk-3.3}/nltk/sentiment/vader.py +443 -445
  193. {nltk-3.2 → nltk-3.3}/nltk/stem/__init__.py +31 -33
  194. {nltk-3.2 → nltk-3.3}/nltk/stem/api.py +28 -25
  195. nltk-3.3/nltk/stem/arlstem.py +369 -0
  196. {nltk-3.2 → nltk-3.3}/nltk/stem/isri.py +345 -345
  197. {nltk-3.2 → nltk-3.3}/nltk/stem/lancaster.py +337 -310
  198. nltk-3.3/nltk/stem/porter.py +710 -0
  199. {nltk-3.2 → nltk-3.3}/nltk/stem/regexp.py +61 -61
  200. {nltk-3.2 → nltk-3.3}/nltk/stem/rslp.py +142 -142
  201. {nltk-3.2 → nltk-3.3}/nltk/stem/snowball.py +4236 -3712
  202. {nltk-3.2 → nltk-3.3}/nltk/stem/util.py +22 -12
  203. {nltk-3.2 → nltk-3.3}/nltk/stem/wordnet.py +51 -51
  204. {nltk-3.2 → nltk-3.3}/nltk/tag/__init__.py +152 -127
  205. {nltk-3.2 → nltk-3.3}/nltk/tag/api.py +86 -81
  206. {nltk-3.2 → nltk-3.3}/nltk/tag/brill.py +424 -426
  207. {nltk-3.2 → nltk-3.3}/nltk/tag/brill_trainer.py +608 -608
  208. {nltk-3.2 → nltk-3.3}/nltk/tag/crf.py +204 -200
  209. {nltk-3.2 → nltk-3.3}/nltk/tag/hmm.py +1277 -1277
  210. {nltk-3.2 → nltk-3.3}/nltk/tag/hunpos.py +132 -132
  211. {nltk-3.2 → nltk-3.3}/nltk/tag/mapping.py +101 -101
  212. {nltk-3.2 → nltk-3.3}/nltk/tag/perceptron.py +329 -314
  213. {nltk-3.2 → nltk-3.3}/nltk/tag/senna.py +147 -145
  214. {nltk-3.2 → nltk-3.3}/nltk/tag/sequential.py +740 -736
  215. {nltk-3.2 → nltk-3.3}/nltk/tag/stanford.py +219 -196
  216. {nltk-3.2 → nltk-3.3}/nltk/tag/tnt.py +595 -604
  217. {nltk-3.2 → nltk-3.3}/nltk/tag/util.py +72 -72
  218. {nltk-3.2 → nltk-3.3}/nltk/tbl/__init__.py +28 -28
  219. {nltk-3.2 → nltk-3.3}/nltk/tbl/api.py +1 -1
  220. {nltk-3.2 → nltk-3.3}/nltk/tbl/demo.py +366 -366
  221. {nltk-3.2 → nltk-3.3}/nltk/tbl/erroranalysis.py +39 -39
  222. {nltk-3.2 → nltk-3.3}/nltk/tbl/feature.py +259 -261
  223. {nltk-3.2 → nltk-3.3}/nltk/tbl/rule.py +321 -321
  224. {nltk-3.2 → nltk-3.3}/nltk/tbl/template.py +303 -308
  225. {nltk-3.2 → nltk-3.3}/nltk/test/__init__.py +18 -18
  226. {nltk-3.2 → nltk-3.3}/nltk/test/all.py +24 -23
  227. {nltk-3.2 → nltk-3.3}/nltk/test/bleu.doctest +14 -14
  228. {nltk-3.2 → nltk-3.3}/nltk/test/bnc.doctest +60 -60
  229. {nltk-3.2 → nltk-3.3}/nltk/test/ccg.doctest +376 -395
  230. nltk-3.3/nltk/test/ccg_semantics.doctest +553 -0
  231. {nltk-3.2 → nltk-3.3}/nltk/test/chat80.doctest +234 -234
  232. {nltk-3.2 → nltk-3.3}/nltk/test/childes.doctest +184 -184
  233. {nltk-3.2 → nltk-3.3}/nltk/test/childes_fixt.py +14 -13
  234. {nltk-3.2 → nltk-3.3}/nltk/test/chunk.doctest +373 -373
  235. {nltk-3.2 → nltk-3.3}/nltk/test/classify.doctest +185 -185
  236. {nltk-3.2 → nltk-3.3}/nltk/test/classify_fixt.py +11 -10
  237. nltk-3.3/nltk/test/collections.doctest +20 -0
  238. {nltk-3.2 → nltk-3.3}/nltk/test/collocations.doctest +276 -276
  239. {nltk-3.2 → nltk-3.3}/nltk/test/compat.doctest +134 -138
  240. {nltk-3.2 → nltk-3.3}/nltk/test/compat_fixt.py +9 -8
  241. nltk-3.3/nltk/test/concordance.doctest +55 -0
  242. {nltk-3.2 → nltk-3.3}/nltk/test/corpus.doctest +2200 -2212
  243. {nltk-3.2 → nltk-3.3}/nltk/test/corpus_fixt.py +3 -3
  244. {nltk-3.2 → nltk-3.3}/nltk/test/crubadan.doctest +65 -65
  245. {nltk-3.2 → nltk-3.3}/nltk/test/data.doctest +379 -379
  246. {nltk-3.2 → nltk-3.3}/nltk/test/dependency.doctest +241 -241
  247. {nltk-3.2 → nltk-3.3}/nltk/test/discourse.doctest +546 -546
  248. {nltk-3.2 → nltk-3.3}/nltk/test/discourse_fixt.py +14 -13
  249. {nltk-3.2 → nltk-3.3}/nltk/test/doctest_nose_plugin.py +159 -156
  250. {nltk-3.2 → nltk-3.3}/nltk/test/drt.doctest +517 -517
  251. {nltk-3.2 → nltk-3.3}/nltk/test/featgram.doctest +607 -607
  252. {nltk-3.2 → nltk-3.3}/nltk/test/featstruct.doctest +1229 -1230
  253. {nltk-3.2 → nltk-3.3}/nltk/test/framenet.doctest +288 -239
  254. {nltk-3.2 → nltk-3.3}/nltk/test/generate.doctest +67 -67
  255. {nltk-3.2 → nltk-3.3}/nltk/test/gensim.doctest +140 -141
  256. {nltk-3.2 → nltk-3.3}/nltk/test/gensim_fixt.py +10 -9
  257. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics.doctest +384 -386
  258. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt.doctest +68 -68
  259. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt_fixt.py +12 -11
  260. {nltk-3.2 → nltk-3.3}/nltk/test/grammar.doctest +48 -48
  261. {nltk-3.2 → nltk-3.3}/nltk/test/grammartestsuites.doctest +109 -109
  262. {nltk-3.2 → nltk-3.3}/nltk/test/index.doctest +100 -100
  263. {nltk-3.2 → nltk-3.3}/nltk/test/inference.doctest +534 -534
  264. {nltk-3.2 → nltk-3.3}/nltk/test/inference_fixt.py +12 -11
  265. {nltk-3.2 → nltk-3.3}/nltk/test/internals.doctest +140 -140
  266. {nltk-3.2 → nltk-3.3}/nltk/test/japanese.doctest +48 -48
  267. {nltk-3.2 → nltk-3.3}/nltk/test/logic.doctest +1098 -1098
  268. {nltk-3.2 → nltk-3.3}/nltk/test/metrics.doctest +270 -270
  269. {nltk-3.2 → nltk-3.3}/nltk/test/misc.doctest +118 -118
  270. {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic.doctest +286 -286
  271. {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic_fixt.py +12 -11
  272. {nltk-3.2 → nltk-3.3}/nltk/test/paice.doctest +35 -35
  273. {nltk-3.2 → nltk-3.3}/nltk/test/parse.doctest +884 -884
  274. {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en.doctest +565 -565
  275. {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en_fixt.py +16 -16
  276. {nltk-3.2 → nltk-3.3}/nltk/test/probability.doctest +304 -304
  277. {nltk-3.2 → nltk-3.3}/nltk/test/probability_fixt.py +13 -12
  278. {nltk-3.2 → nltk-3.3}/nltk/test/propbank.doctest +176 -176
  279. {nltk-3.2 → nltk-3.3}/nltk/test/relextract.doctest +263 -263
  280. {nltk-3.2 → nltk-3.3}/nltk/test/resolution.doctest +221 -221
  281. {nltk-3.2 → nltk-3.3}/nltk/test/runtests.py +86 -64
  282. {nltk-3.2 → nltk-3.3}/nltk/test/segmentation_fixt.py +10 -10
  283. {nltk-3.2 → nltk-3.3}/nltk/test/semantics.doctest +665 -665
  284. {nltk-3.2 → nltk-3.3}/nltk/test/semantics_fixt.py +7 -7
  285. {nltk-3.2 → nltk-3.3}/nltk/test/sentiment.doctest +233 -233
  286. {nltk-3.2 → nltk-3.3}/nltk/test/sentiwordnet.doctest +41 -41
  287. {nltk-3.2 → nltk-3.3}/nltk/test/simple.doctest +85 -85
  288. {nltk-3.2 → nltk-3.3}/nltk/test/stem.doctest +78 -78
  289. {nltk-3.2 → nltk-3.3}/nltk/test/tag.doctest +33 -33
  290. {nltk-3.2 → nltk-3.3}/nltk/test/tokenize.doctest +273 -166
  291. {nltk-3.2 → nltk-3.3}/nltk/test/toolbox.doctest +307 -307
  292. {nltk-3.2 → nltk-3.3}/nltk/test/translate.doctest +242 -242
  293. {nltk-3.2 → nltk-3.3}/nltk/test/translate_fixt.py +3 -3
  294. {nltk-3.2 → nltk-3.3}/nltk/test/tree.doctest +1101 -1101
  295. {nltk-3.2 → nltk-3.3}/nltk/test/treeprettyprinter.doctest +127 -127
  296. {nltk-3.2 → nltk-3.3}/nltk/test/treetransforms.doctest +156 -156
  297. nltk-3.3/nltk/test/unit/test_2x_compat.py +63 -0
  298. nltk-3.3/nltk/test/unit/test_aline.py +52 -0
  299. nltk-3.3/nltk/test/unit/test_chunk.py +56 -0
  300. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_classify.py +55 -53
  301. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_collocations.py +88 -79
  302. nltk-3.3/nltk/test/unit/test_concordance.py +98 -0
  303. nltk-3.3/nltk/test/unit/test_corenlp.py +1000 -0
  304. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpora.py +200 -183
  305. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpus_views.py +45 -45
  306. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_hmm.py +88 -88
  307. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_json2csv_corpus.py +188 -187
  308. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_naivebayes.py +26 -26
  309. nltk-3.3/nltk/test/unit/test_rte_classify.py +86 -0
  310. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_seekable_unicode_stream_reader.py +124 -124
  311. nltk-3.3/nltk/test/unit/test_senna.py +74 -0
  312. nltk-3.3/nltk/test/unit/test_stem.py +121 -0
  313. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tag.py +20 -20
  314. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tgrep.py +628 -626
  315. nltk-3.3/nltk/test/unit/test_tokenize.py +168 -0
  316. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_twitter_auth.py +185 -185
  317. nltk-3.3/nltk/test/unit/test_wordnet.py +134 -0
  318. nltk-3.3/nltk/test/unit/translate/test_bleu.py +244 -0
  319. nltk-3.3/nltk/test/unit/translate/test_gdfa.py +57 -0
  320. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm1.py +75 -75
  321. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm2.py +87 -87
  322. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm3.py +105 -105
  323. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm4.py +126 -126
  324. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm5.py +166 -166
  325. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm_model.py +270 -270
  326. nltk-3.3/nltk/test/unit/translate/test_nist.py +37 -0
  327. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_stack_decoder.py +300 -300
  328. {nltk-3.2 → nltk-3.3}/nltk/test/unit/utils.py +41 -41
  329. {nltk-3.2 → nltk-3.3}/nltk/test/util.doctest +48 -48
  330. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet.doctest +595 -581
  331. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_fixt.py +7 -6
  332. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_lch.doctest +53 -53
  333. {nltk-3.2 → nltk-3.3}/nltk/test/wsd.doctest +68 -68
  334. {nltk-3.2 → nltk-3.3}/nltk/text.py +663 -610
  335. {nltk-3.2 → nltk-3.3}/nltk/tgrep.py +938 -937
  336. {nltk-3.2 → nltk-3.3}/nltk/tokenize/__init__.py +130 -107
  337. {nltk-3.2 → nltk-3.3}/nltk/tokenize/api.py +77 -78
  338. {nltk-3.2 → nltk-3.3}/nltk/tokenize/casual.py +343 -342
  339. {nltk-3.2 → nltk-3.3}/nltk/tokenize/mwe.py +120 -120
  340. nltk-3.3/nltk/tokenize/nist.py +173 -0
  341. {nltk-3.2 → nltk-3.3}/nltk/tokenize/punkt.py +1620 -1601
  342. {nltk-3.2 → nltk-3.3}/nltk/tokenize/regexp.py +208 -202
  343. nltk-3.3/nltk/tokenize/repp.py +151 -0
  344. {nltk-3.2 → nltk-3.3}/nltk/tokenize/sexpr.py +140 -142
  345. {nltk-3.2 → nltk-3.3}/nltk/tokenize/simple.py +138 -136
  346. {nltk-3.2 → nltk-3.3}/nltk/tokenize/stanford.py +117 -113
  347. nltk-3.3/nltk/tokenize/stanford_segmenter.py +246 -0
  348. {nltk-3.2 → nltk-3.3}/nltk/tokenize/texttiling.py +458 -460
  349. nltk-3.3/nltk/tokenize/toktok.py +155 -0
  350. nltk-3.3/nltk/tokenize/treebank.py +363 -0
  351. nltk-3.3/nltk/tokenize/util.py +261 -0
  352. {nltk-3.2 → nltk-3.3}/nltk/toolbox.py +499 -497
  353. {nltk-3.2 → nltk-3.3}/nltk/translate/__init__.py +24 -24
  354. {nltk-3.2 → nltk-3.3}/nltk/translate/api.py +331 -321
  355. {nltk-3.2 → nltk-3.3}/nltk/translate/bleu_score.py +615 -556
  356. nltk-3.3/nltk/translate/chrf_score.py +137 -0
  357. {nltk-3.2 → nltk-3.3}/nltk/translate/gale_church.py +248 -235
  358. {nltk-3.2 → nltk-3.3}/nltk/translate/gdfa.py +135 -131
  359. nltk-3.3/nltk/translate/gleu_score.py +193 -0
  360. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm1.py +250 -241
  361. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm2.py +308 -308
  362. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm3.py +337 -337
  363. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm4.py +467 -467
  364. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm5.py +639 -639
  365. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm_model.py +536 -533
  366. {nltk-3.2 → nltk-3.3}/nltk/translate/metrics.py +40 -40
  367. nltk-3.3/nltk/translate/nist_score.py +178 -0
  368. {nltk-3.2 → nltk-3.3}/nltk/translate/phrase_based.py +175 -175
  369. {nltk-3.2 → nltk-3.3}/nltk/translate/ribes_score.py +325 -325
  370. {nltk-3.2 → nltk-3.3}/nltk/translate/stack_decoder.py +499 -495
  371. {nltk-3.2 → nltk-3.3}/nltk/tree.py +1605 -1603
  372. {nltk-3.2 → nltk-3.3}/nltk/treeprettyprinter.py +564 -564
  373. {nltk-3.2 → nltk-3.3}/nltk/treetransforms.py +309 -309
  374. {nltk-3.2 → nltk-3.3}/nltk/twitter/__init__.py +28 -28
  375. {nltk-3.2 → nltk-3.3}/nltk/twitter/api.py +141 -136
  376. {nltk-3.2 → nltk-3.3}/nltk/twitter/common.py +264 -258
  377. {nltk-3.2 → nltk-3.3}/nltk/twitter/twitter_demo.py +288 -288
  378. {nltk-3.2 → nltk-3.3}/nltk/twitter/twitterclient.py +530 -530
  379. {nltk-3.2 → nltk-3.3}/nltk/twitter/util.py +147 -146
  380. nltk-3.3/nltk/util.py +751 -0
  381. {nltk-3.2 → nltk-3.3}/nltk/wsd.py +53 -53
  382. {nltk-3.2 → nltk-3.3/nltk.egg-info}/PKG-INFO +13 -5
  383. {nltk-3.2 → nltk-3.3}/nltk.egg-info/SOURCES.txt +26 -3
  384. nltk-3.3/nltk.egg-info/requires.txt +31 -0
  385. {nltk-3.2 → nltk-3.3}/setup.cfg +0 -1
  386. {nltk-3.2 → nltk-3.3}/setup.py +102 -75
  387. nltk-3.2/nltk/VERSION +0 -1
  388. nltk-3.2/nltk/compat.py +0 -680
  389. nltk-3.2/nltk/corpus/reader/pl196x.py +0 -278
  390. nltk-3.2/nltk/corpus/reader/verbnet.py +0 -408
  391. nltk-3.2/nltk/corpus/reader/wordlist.py +0 -37
  392. nltk-3.2/nltk/sentiment/vader_lexicon.txt +0 -7517
  393. nltk-3.2/nltk/six.py +0 -868
  394. nltk-3.2/nltk/stem/porter.py +0 -692
  395. nltk-3.2/nltk/test/unit/test_2x_compat.py +0 -26
  396. nltk-3.2/nltk/test/unit/test_stem.py +0 -36
  397. nltk-3.2/nltk/test/unit/test_tokenize.py +0 -23
  398. nltk-3.2/nltk/test/unit/translate/test_bleu.py +0 -84
  399. nltk-3.2/nltk/tokenize/treebank.py +0 -124
  400. nltk-3.2/nltk/tokenize/util.py +0 -90
  401. nltk-3.2/nltk/util.py +0 -1364
  402. {nltk-3.2 → nltk-3.3}/nltk/test/unit/__init__.py +0 -0
  403. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/__init__.py +0 -0
  404. {nltk-3.2 → nltk-3.3}/nltk.egg-info/dependency_links.txt +0 -0
  405. {nltk-3.2 → nltk-3.3}/nltk.egg-info/not-zip-safe +0 -0
  406. {nltk-3.2 → nltk-3.3}/nltk.egg-info/top_level.txt +0 -0
@@ -1,1257 +1,1258 @@
1
- # Natural Language Toolkit: Discourse Representation Theory (DRT)
2
- #
3
- # Author: Dan Garrette <dhgarrette@gmail.com>
4
- #
5
- # Copyright (C) 2001-2015 NLTK Project
6
- # URL: <http://nltk.org/>
7
- # For license information, see LICENSE.TXT
8
- from __future__ import print_function, unicode_literals
9
-
10
- import operator
11
- from functools import reduce
12
-
13
- from nltk.compat import string_types, python_2_unicode_compatible
14
- from nltk.sem.logic import (APP, AbstractVariableExpression, AllExpression,
15
- AndExpression, ApplicationExpression, BinaryExpression,
16
- BooleanExpression, ConstantExpression, EqualityExpression,
17
- EventVariableExpression, ExistsExpression, Expression,
18
- FunctionVariableExpression, ImpExpression,
19
- IndividualVariableExpression, LambdaExpression, Tokens,
20
- LogicParser, NegatedExpression, OrExpression, Variable,
21
- is_eventvar, is_funcvar, is_indvar, unique_variable)
22
-
23
- # Import Tkinter-based modules if they are available
24
- try:
25
- # imports are fixed for Python 2.x by nltk.compat
26
- from tkinter import Canvas
27
- from tkinter import Tk
28
- from tkinter.font import Font
29
- from nltk.util import in_idle
30
-
31
- except ImportError:
32
- # No need to print a warning here, nltk.draw has already printed one.
33
- pass
34
-
35
- class DrtTokens(Tokens):
36
- DRS = 'DRS'
37
- DRS_CONC = '+'
38
- PRONOUN = 'PRO'
39
- OPEN_BRACKET = '['
40
- CLOSE_BRACKET = ']'
41
- COLON = ':'
42
-
43
- PUNCT = [DRS_CONC, OPEN_BRACKET, CLOSE_BRACKET, COLON]
44
-
45
- SYMBOLS = Tokens.SYMBOLS + PUNCT
46
-
47
- TOKENS = Tokens.TOKENS + [DRS] + PUNCT
48
-
49
-
50
- class DrtParser(LogicParser):
51
- """A lambda calculus expression parser."""
52
- def __init__(self):
53
- LogicParser.__init__(self)
54
-
55
- self.operator_precedence = dict(
56
- [(x,1) for x in DrtTokens.LAMBDA_LIST] + \
57
- [(x,2) for x in DrtTokens.NOT_LIST] + \
58
- [(APP,3)] + \
59
- [(x,4) for x in DrtTokens.EQ_LIST+Tokens.NEQ_LIST] + \
60
- [(DrtTokens.COLON,5)] + \
61
- [(DrtTokens.DRS_CONC,6)] + \
62
- [(x,7) for x in DrtTokens.OR_LIST] + \
63
- [(x,8) for x in DrtTokens.IMP_LIST] + \
64
- [(None,9)])
65
-
66
- def get_all_symbols(self):
67
- """This method exists to be overridden"""
68
- return DrtTokens.SYMBOLS
69
-
70
- def isvariable(self, tok):
71
- return tok not in DrtTokens.TOKENS
72
-
73
- def handle(self, tok, context):
74
- """This method is intended to be overridden for logics that
75
- use different operators or expressions"""
76
- if tok in DrtTokens.NOT_LIST:
77
- return self.handle_negation(tok, context)
78
-
79
- elif tok in DrtTokens.LAMBDA_LIST:
80
- return self.handle_lambda(tok, context)
81
-
82
- elif tok == DrtTokens.OPEN:
83
- if self.inRange(0) and self.token(0) == DrtTokens.OPEN_BRACKET:
84
- return self.handle_DRS(tok, context)
85
- else:
86
- return self.handle_open(tok, context)
87
-
88
- elif tok.upper() == DrtTokens.DRS:
89
- self.assertNextToken(DrtTokens.OPEN)
90
- return self.handle_DRS(tok, context)
91
-
92
- elif self.isvariable(tok):
93
- if self.inRange(0) and self.token(0) == DrtTokens.COLON:
94
- return self.handle_prop(tok, context)
95
- else:
96
- return self.handle_variable(tok, context)
97
-
98
- def make_NegatedExpression(self, expression):
99
- return DrtNegatedExpression(expression)
100
-
101
- def handle_DRS(self, tok, context):
102
- # a DRS
103
- refs = self.handle_refs()
104
- if self.inRange(0) and self.token(0) == DrtTokens.COMMA: #if there is a comma (it's optional)
105
- self.token() # swallow the comma
106
- conds = self.handle_conds(context)
107
- self.assertNextToken(DrtTokens.CLOSE)
108
- return DRS(refs, conds, None)
109
-
110
- def handle_refs(self):
111
- self.assertNextToken(DrtTokens.OPEN_BRACKET)
112
- refs = []
113
- while self.inRange(0) and self.token(0) != DrtTokens.CLOSE_BRACKET:
114
- # Support expressions like: DRS([x y],C) == DRS([x,y],C)
115
- if refs and self.token(0) == DrtTokens.COMMA:
116
- self.token() # swallow the comma
117
- refs.append(self.get_next_token_variable('quantified'))
118
- self.assertNextToken(DrtTokens.CLOSE_BRACKET)
119
- return refs
120
-
121
- def handle_conds(self, context):
122
- self.assertNextToken(DrtTokens.OPEN_BRACKET)
123
- conds = []
124
- while self.inRange(0) and self.token(0) != DrtTokens.CLOSE_BRACKET:
125
- # Support expressions like: DRS([x y],C) == DRS([x, y],C)
126
- if conds and self.token(0) == DrtTokens.COMMA:
127
- self.token() # swallow the comma
128
- conds.append(self.process_next_expression(context))
129
- self.assertNextToken(DrtTokens.CLOSE_BRACKET)
130
- return conds
131
-
132
- def handle_prop(self, tok, context):
133
- variable = self.make_VariableExpression(tok)
134
- self.assertNextToken(':')
135
- drs = self.process_next_expression(DrtTokens.COLON)
136
- return DrtProposition(variable, drs)
137
-
138
- def make_EqualityExpression(self, first, second):
139
- """This method serves as a hook for other logic parsers that
140
- have different equality expression classes"""
141
- return DrtEqualityExpression(first, second)
142
-
143
- def get_BooleanExpression_factory(self, tok):
144
- """This method serves as a hook for other logic parsers that
145
- have different boolean operators"""
146
- if tok == DrtTokens.DRS_CONC:
147
- return lambda first, second: DrtConcatenation(first, second, None)
148
- elif tok in DrtTokens.OR_LIST:
149
- return DrtOrExpression
150
- elif tok in DrtTokens.IMP_LIST:
151
- def make_imp_expression(first, second):
152
- if isinstance(first, DRS):
153
- return DRS(first.refs, first.conds, second)
154
- if isinstance(first, DrtConcatenation):
155
- return DrtConcatenation(first.first, first.second, second)
156
- raise Exception('Antecedent of implication must be a DRS')
157
- return make_imp_expression
158
- else:
159
- return None
160
-
161
- def make_BooleanExpression(self, factory, first, second):
162
- return factory(first, second)
163
-
164
- def make_ApplicationExpression(self, function, argument):
165
- return DrtApplicationExpression(function, argument)
166
-
167
- def make_VariableExpression(self, name):
168
- return DrtVariableExpression(Variable(name))
169
-
170
- def make_LambdaExpression(self, variables, term):
171
- return DrtLambdaExpression(variables, term)
172
-
173
-
174
- class DrtExpression(object):
175
- """
176
- This is the base abstract DRT Expression from which every DRT
177
- Expression extends.
178
- """
179
-
180
- _drt_parser = DrtParser()
181
-
182
- @classmethod
183
- def fromstring(cls, s):
184
- return cls._drt_parser.parse(s)
185
-
186
- def applyto(self, other):
187
- return DrtApplicationExpression(self, other)
188
-
189
- def __neg__(self):
190
- return DrtNegatedExpression(self)
191
-
192
- def __and__(self, other):
193
- raise NotImplementedError()
194
-
195
- def __or__(self, other):
196
- assert isinstance(other, DrtExpression)
197
- return DrtOrExpression(self, other)
198
-
199
- def __gt__(self, other):
200
- assert isinstance(other, DrtExpression)
201
- if isinstance(self, DRS):
202
- return DRS(self.refs, self.conds, other)
203
- if isinstance(self, DrtConcatenation):
204
- return DrtConcatenation(self.first, self.second, other)
205
- raise Exception('Antecedent of implication must be a DRS')
206
-
207
- def equiv(self, other, prover=None):
208
- """
209
- Check for logical equivalence.
210
- Pass the expression (self <-> other) to the theorem prover.
211
- If the prover says it is valid, then the self and other are equal.
212
-
213
- :param other: an ``DrtExpression`` to check equality against
214
- :param prover: a ``nltk.inference.api.Prover``
215
- """
216
- assert isinstance(other, DrtExpression)
217
-
218
- f1 = self.simplify().fol();
219
- f2 = other.simplify().fol();
220
- return f1.equiv(f2, prover)
221
-
222
- @property
223
- def type(self):
224
- raise AttributeError("'%s' object has no attribute 'type'" %
225
- self.__class__.__name__)
226
-
227
- def typecheck(self, signature=None):
228
- raise NotImplementedError()
229
-
230
- def __add__(self, other):
231
- return DrtConcatenation(self, other, None)
232
-
233
- def get_refs(self, recursive=False):
234
- """
235
- Return the set of discourse referents in this DRS.
236
- :param recursive: bool Also find discourse referents in subterms?
237
- :return: list of ``Variable`` objects
238
- """
239
- raise NotImplementedError()
240
-
241
- def is_pronoun_function(self):
242
- """ Is self of the form "PRO(x)"? """
243
- return isinstance(self, DrtApplicationExpression) and \
244
- isinstance(self.function, DrtAbstractVariableExpression) and \
245
- self.function.variable.name == DrtTokens.PRONOUN and \
246
- isinstance(self.argument, DrtIndividualVariableExpression)
247
-
248
- def make_EqualityExpression(self, first, second):
249
- return DrtEqualityExpression(first, second)
250
-
251
- def make_VariableExpression(self, variable):
252
- return DrtVariableExpression(variable)
253
-
254
- def resolve_anaphora(self):
255
- return resolve_anaphora(self)
256
-
257
- def eliminate_equality(self):
258
- return self.visit_structured(lambda e: e.eliminate_equality(),
259
- self.__class__)
260
-
261
- def pretty_format(self):
262
- """
263
- Draw the DRS
264
- :return: the pretty print string
265
- """
266
- return '\n'.join(self._pretty())
267
-
268
- def pretty_print(self):
269
- print(self.pretty_format())
270
-
271
- def draw(self):
272
- DrsDrawer(self).draw()
273
-
274
-
275
- @python_2_unicode_compatible
276
- class DRS(DrtExpression, Expression):
277
- """A Discourse Representation Structure."""
278
- def __init__(self, refs, conds, consequent=None):
279
- """
280
- :param refs: list of ``DrtIndividualVariableExpression`` for the
281
- discourse referents
282
- :param conds: list of ``Expression`` for the conditions
283
- """
284
- self.refs = refs
285
- self.conds = conds
286
- self.consequent = consequent
287
-
288
- def replace(self, variable, expression, replace_bound=False, alpha_convert=True):
289
- """Replace all instances of variable v with expression E in self,
290
- where v is free in self."""
291
- if variable in self.refs:
292
- #if a bound variable is the thing being replaced
293
- if not replace_bound:
294
- return self
295
- else:
296
- i = self.refs.index(variable)
297
- if self.consequent:
298
- consequent = self.consequent.replace(variable, expression, True, alpha_convert)
299
- else:
300
- consequent = None
301
- return DRS(self.refs[:i]+[expression.variable]+self.refs[i+1:],
302
- [cond.replace(variable, expression, True, alpha_convert)
303
- for cond in self.conds],
304
- consequent)
305
- else:
306
- if alpha_convert:
307
- # any bound variable that appears in the expression must
308
- # be alpha converted to avoid a conflict
309
- for ref in (set(self.refs) & expression.free()):
310
- newvar = unique_variable(ref)
311
- newvarex = DrtVariableExpression(newvar)
312
- i = self.refs.index(ref)
313
- if self.consequent:
314
- consequent = self.consequent.replace(ref, newvarex, True, alpha_convert)
315
- else:
316
- consequent = None
317
- self = DRS(self.refs[:i]+[newvar]+self.refs[i+1:],
318
- [cond.replace(ref, newvarex, True, alpha_convert)
319
- for cond in self.conds],
320
- consequent)
321
-
322
- #replace in the conditions
323
- if self.consequent:
324
- consequent = self.consequent.replace(variable, expression, replace_bound, alpha_convert)
325
- else:
326
- consequent = None
327
- return DRS(self.refs,
328
- [cond.replace(variable, expression, replace_bound, alpha_convert)
329
- for cond in self.conds],
330
- consequent)
331
-
332
- def free(self):
333
- """:see: Expression.free()"""
334
- conds_free = reduce(operator.or_, [c.free() for c in self.conds], set())
335
- if self.consequent:
336
- conds_free.update(self.consequent.free())
337
- return conds_free - set(self.refs)
338
-
339
- def get_refs(self, recursive=False):
340
- """:see: AbstractExpression.get_refs()"""
341
- if recursive:
342
- conds_refs = self.refs + sum((c.get_refs(True) for c in self.conds), [])
343
- if self.consequent:
344
- conds_refs.extend(self.consequent.get_refs(True))
345
- return conds_refs
346
- else:
347
- return self.refs
348
-
349
- def visit(self, function, combinator):
350
- """:see: Expression.visit()"""
351
- parts = list(map(function, self.conds))
352
- if self.consequent:
353
- parts.append(function(self.consequent))
354
- return combinator(parts)
355
-
356
- def visit_structured(self, function, combinator):
357
- """:see: Expression.visit_structured()"""
358
- consequent = (function(self.consequent) if self.consequent else None)
359
- return combinator(self.refs, list(map(function, self.conds)), consequent)
360
-
361
- def eliminate_equality(self):
362
- drs = self
363
- i = 0
364
- while i < len(drs.conds):
365
- cond = drs.conds[i]
366
- if isinstance(cond, EqualityExpression) and \
367
- isinstance(cond.first, AbstractVariableExpression) and \
368
- isinstance(cond.second, AbstractVariableExpression):
369
- drs = DRS(list(set(drs.refs)-set([cond.second.variable])),
370
- drs.conds[:i]+drs.conds[i+1:],
371
- drs.consequent)
372
- if cond.second.variable != cond.first.variable:
373
- drs = drs.replace(cond.second.variable, cond.first, False, False)
374
- i = 0
375
- i -= 1
376
- i += 1
377
-
378
- conds = []
379
- for cond in drs.conds:
380
- new_cond = cond.eliminate_equality()
381
- new_cond_simp = new_cond.simplify()
382
- if not isinstance(new_cond_simp, DRS) or \
383
- new_cond_simp.refs or new_cond_simp.conds or \
384
- new_cond_simp.consequent:
385
- conds.append(new_cond)
386
-
387
- consequent = (drs.consequent.eliminate_equality() if drs.consequent else None)
388
- return DRS(drs.refs, conds, consequent)
389
-
390
- def fol(self):
391
- if self.consequent:
392
- accum = None
393
- if self.conds:
394
- accum = reduce(AndExpression, [c.fol() for c in self.conds])
395
-
396
- if accum:
397
- accum = ImpExpression(accum, self.consequent.fol())
398
- else:
399
- accum = self.consequent.fol()
400
-
401
- for ref in self.refs[::-1]:
402
- accum = AllExpression(ref, accum)
403
-
404
- return accum
405
-
406
- else:
407
- if not self.conds:
408
- raise Exception("Cannot convert DRS with no conditions to FOL.")
409
- accum = reduce(AndExpression, [c.fol() for c in self.conds])
410
- for ref in map(Variable, self._order_ref_strings(self.refs)[::-1]):
411
- accum = ExistsExpression(ref, accum)
412
- return accum
413
-
414
- def _pretty(self):
415
- refs_line = ' '.join(self._order_ref_strings(self.refs))
416
-
417
- cond_lines = [cond for cond_line in [filter(lambda s: s.strip(), cond._pretty())
418
- for cond in self.conds]
419
- for cond in cond_line]
420
- length = max([len(refs_line)] + list(map(len, cond_lines)))
421
- drs = ([' _' + '_' * length + '_ ',
422
- '| ' + refs_line.ljust(length) + ' |',
423
- '|-' + '-' * length + '-|'] +
424
- ['| ' + line.ljust(length) + ' |' for line in cond_lines] +
425
- ['|_' + '_' * length + '_|'])
426
- if self.consequent:
427
- return DrtBinaryExpression._assemble_pretty(drs, DrtTokens.IMP,
428
- self.consequent._pretty())
429
- return drs
430
-
431
- def _order_ref_strings(self, refs):
432
- strings = ["%s" % ref for ref in refs]
433
- ind_vars = []
434
- func_vars = []
435
- event_vars = []
436
- other_vars = []
437
- for s in strings:
438
- if is_indvar(s):
439
- ind_vars.append(s)
440
- elif is_funcvar(s):
441
- func_vars.append(s)
442
- elif is_eventvar(s):
443
- event_vars.append(s)
444
- else:
445
- other_vars.append(s)
446
- return sorted(other_vars) + \
447
- sorted(event_vars, key=lambda v: int([v[2:],-1][len(v[2:]) == 0])) + \
448
- sorted(func_vars, key=lambda v: (v[0], int([v[1:],-1][len(v[1:])==0]))) + \
449
- sorted(ind_vars, key=lambda v: (v[0], int([v[1:],-1][len(v[1:])==0])))
450
-
451
- def __eq__(self, other):
452
- r"""Defines equality modulo alphabetic variance.
453
- If we are comparing \x.M and \y.N, then check equality of M and N[x/y]."""
454
- if isinstance(other, DRS):
455
- if len(self.refs) == len(other.refs):
456
- converted_other = other
457
- for (r1, r2) in zip(self.refs, converted_other.refs):
458
- varex = self.make_VariableExpression(r1)
459
- converted_other = converted_other.replace(r2, varex, True)
460
- if self.consequent == converted_other.consequent and \
461
- len(self.conds) == len(converted_other.conds):
462
- for c1, c2 in zip(self.conds, converted_other.conds):
463
- if not (c1 == c2):
464
- return False
465
- return True
466
- return False
467
-
468
- def __ne__(self, other):
469
- return not self == other
470
-
471
- __hash__ = Expression.__hash__
472
-
473
- def __str__(self):
474
- drs = '([%s],[%s])' % (','.join(self._order_ref_strings(self.refs)),
475
- ', '.join("%s" % cond for cond in self.conds)) # map(str, self.conds)))
476
- if self.consequent:
477
- return DrtTokens.OPEN + drs + ' ' + DrtTokens.IMP + ' ' + \
478
- "%s" % self.consequent + DrtTokens.CLOSE
479
- return drs
480
-
481
-
482
- def DrtVariableExpression(variable):
483
- """
484
- This is a factory method that instantiates and returns a subtype of
485
- ``DrtAbstractVariableExpression`` appropriate for the given variable.
486
- """
487
- if is_indvar(variable.name):
488
- return DrtIndividualVariableExpression(variable)
489
- elif is_funcvar(variable.name):
490
- return DrtFunctionVariableExpression(variable)
491
- elif is_eventvar(variable.name):
492
- return DrtEventVariableExpression(variable)
493
- else:
494
- return DrtConstantExpression(variable)
495
-
496
-
497
- class DrtAbstractVariableExpression(DrtExpression, AbstractVariableExpression):
498
- def fol(self):
499
- return self
500
-
501
- def get_refs(self, recursive=False):
502
- """:see: AbstractExpression.get_refs()"""
503
- return []
504
-
505
- def _pretty(self):
506
- s = "%s" % self
507
- blank = ' '*len(s)
508
- return [blank, blank, s, blank]
509
-
510
- def eliminate_equality(self):
511
- return self
512
-
513
- class DrtIndividualVariableExpression(DrtAbstractVariableExpression, IndividualVariableExpression):
514
- pass
515
-
516
- class DrtFunctionVariableExpression(DrtAbstractVariableExpression, FunctionVariableExpression):
517
- pass
518
-
519
- class DrtEventVariableExpression(DrtIndividualVariableExpression, EventVariableExpression):
520
- pass
521
-
522
- class DrtConstantExpression(DrtAbstractVariableExpression, ConstantExpression):
523
- pass
524
-
525
-
526
- @python_2_unicode_compatible
527
- class DrtProposition(DrtExpression, Expression):
528
- def __init__(self, variable, drs):
529
- self.variable = variable
530
- self.drs = drs
531
-
532
- def replace(self, variable, expression, replace_bound=False, alpha_convert=True):
533
- if self.variable == variable:
534
- assert isinstance(expression, DrtAbstractVariableExpression), "Can only replace a proposition label with a variable"
535
- return DrtProposition(expression.variable, self.drs.replace(variable, expression, replace_bound, alpha_convert))
536
- else:
537
- return DrtProposition(self.variable, self.drs.replace(variable, expression, replace_bound, alpha_convert))
538
-
539
- def eliminate_equality(self):
540
- return DrtProposition(self.variable, self.drs.eliminate_equality())
541
-
542
- def get_refs(self, recursive=False):
543
- return (self.drs.get_refs(True) if recursive else [])
544
-
545
- def __eq__(self, other):
546
- return self.__class__ == other.__class__ and \
547
- self.variable == other.variable and \
548
- self.drs == other.drs
549
-
550
- def __ne__(self, other):
551
- return not self == other
552
-
553
- __hash__ = Expression.__hash__
554
-
555
- def fol(self):
556
- return self.drs.fol()
557
-
558
- def _pretty(self):
559
- drs_s = self.drs._pretty()
560
- blank = ' ' * len("%s" % self.variable)
561
- return ([blank + ' ' + line for line in drs_s[:1]] +
562
- ["%s" % self.variable + ':' + line for line in drs_s[1:2]] +
563
- [blank + ' ' + line for line in drs_s[2:]])
564
-
565
- def visit(self, function, combinator):
566
- """:see: Expression.visit()"""
567
- return combinator([function(self.drs)])
568
-
569
- def visit_structured(self, function, combinator):
570
- """:see: Expression.visit_structured()"""
571
- return combinator(self.variable, function(self.drs))
572
-
573
- def __str__(self):
574
- return 'prop(%s, %s)' % (self.variable, self.drs)
575
-
576
-
577
- class DrtNegatedExpression(DrtExpression, NegatedExpression):
578
- def fol(self):
579
- return NegatedExpression(self.term.fol())
580
-
581
- def get_refs(self, recursive=False):
582
- """:see: AbstractExpression.get_refs()"""
583
- return self.term.get_refs(recursive)
584
-
585
- def _pretty(self):
586
- term_lines = self.term._pretty()
587
- return ([' ' + line for line in term_lines[:2]] +
588
- ['__ ' + line for line in term_lines[2:3]] +
589
- [' | ' + line for line in term_lines[3:4]] +
590
- [' ' + line for line in term_lines[4:]])
591
-
592
- class DrtLambdaExpression(DrtExpression, LambdaExpression):
593
- def alpha_convert(self, newvar):
594
- """Rename all occurrences of the variable introduced by this variable
595
- binder in the expression to ``newvar``.
596
- :param newvar: ``Variable``, for the new variable
597
- """
598
- return self.__class__(newvar, self.term.replace(self.variable,
599
- DrtVariableExpression(newvar), True))
600
-
601
- def fol(self):
602
- return LambdaExpression(self.variable, self.term.fol())
603
-
604
- def _pretty(self):
605
- variables = [self.variable]
606
- term = self.term
607
- while term.__class__ == self.__class__:
608
- variables.append(term.variable)
609
- term = term.term
610
- var_string = ' '.join("%s" % v for v in variables) + DrtTokens.DOT
611
- term_lines = term._pretty()
612
- blank = ' ' * len(var_string)
613
- return ([' ' + blank + line for line in term_lines[:1]] +
614
- [' \ ' + blank + line for line in term_lines[1:2]] +
615
- [' /\ ' + var_string + line for line in term_lines[2:3]] +
616
- [' ' + blank + line for line in term_lines[3:]])
617
-
618
- class DrtBinaryExpression(DrtExpression, BinaryExpression):
619
- def get_refs(self, recursive=False):
620
- """:see: AbstractExpression.get_refs()"""
621
- return self.first.get_refs(True) + self.second.get_refs(True) if recursive else []
622
-
623
- def _pretty(self):
624
- return DrtBinaryExpression._assemble_pretty(self._pretty_subex(self.first), self.getOp(), self._pretty_subex(self.second))
625
-
626
- @staticmethod
627
- def _assemble_pretty(first_lines, op, second_lines):
628
- max_lines = max(len(first_lines), len(second_lines))
629
- first_lines = _pad_vertically(first_lines, max_lines)
630
- second_lines = _pad_vertically(second_lines, max_lines)
631
- blank = ' ' * len(op)
632
- first_second_lines = list(zip(first_lines, second_lines))
633
- return ([' ' + first_line + ' ' + blank + ' ' + second_line + ' ' for first_line, second_line in first_second_lines[:2]] +
634
- ['(' + first_line + ' ' + op + ' ' + second_line + ')' for first_line, second_line in first_second_lines[2:3]] +
635
- [' ' + first_line + ' ' + blank + ' ' + second_line + ' ' for first_line, second_line in first_second_lines[3:]])
636
-
637
- def _pretty_subex(self, subex):
638
- return subex._pretty()
639
-
640
- class DrtBooleanExpression(DrtBinaryExpression, BooleanExpression):
641
- pass
642
-
643
- class DrtOrExpression(DrtBooleanExpression, OrExpression):
644
- def fol(self):
645
- return OrExpression(self.first.fol(), self.second.fol())
646
-
647
- def _pretty_subex(self, subex):
648
- if isinstance(subex, DrtOrExpression):
649
- return [line[1:-1] for line in subex._pretty()]
650
- return DrtBooleanExpression._pretty_subex(self, subex)
651
-
652
- class DrtEqualityExpression(DrtBinaryExpression, EqualityExpression):
653
- def fol(self):
654
- return EqualityExpression(self.first.fol(), self.second.fol())
655
-
656
- @python_2_unicode_compatible
657
- class DrtConcatenation(DrtBooleanExpression):
658
- """DRS of the form '(DRS + DRS)'"""
659
- def __init__(self, first, second, consequent=None):
660
- DrtBooleanExpression.__init__(self, first, second)
661
- self.consequent = consequent
662
-
663
- def replace(self, variable, expression, replace_bound=False, alpha_convert=True):
664
- """Replace all instances of variable v with expression E in self,
665
- where v is free in self."""
666
- first = self.first
667
- second = self.second
668
- consequent = self.consequent
669
-
670
- # If variable is bound
671
- if variable in self.get_refs():
672
- if replace_bound:
673
- first = first.replace(variable, expression, replace_bound, alpha_convert)
674
- second = second.replace(variable, expression, replace_bound, alpha_convert)
675
- if consequent:
676
- consequent = consequent.replace(variable, expression, replace_bound, alpha_convert)
677
- else:
678
- if alpha_convert:
679
- # alpha convert every ref that is free in 'expression'
680
- for ref in (set(self.get_refs(True)) & expression.free()):
681
- v = DrtVariableExpression(unique_variable(ref))
682
- first = first.replace(ref, v, True, alpha_convert)
683
- second = second.replace(ref, v, True, alpha_convert)
684
- if consequent:
685
- consequent = consequent.replace(ref, v, True, alpha_convert)
686
-
687
- first = first.replace(variable, expression, replace_bound, alpha_convert)
688
- second = second.replace(variable, expression, replace_bound, alpha_convert)
689
- if consequent:
690
- consequent = consequent.replace(variable, expression, replace_bound, alpha_convert)
691
-
692
- return self.__class__(first, second, consequent)
693
-
694
- def eliminate_equality(self):
695
- #TODO: at some point. for now, simplify.
696
- drs = self.simplify()
697
- assert not isinstance(drs, DrtConcatenation)
698
- return drs.eliminate_equality()
699
-
700
- def simplify(self):
701
- first = self.first.simplify()
702
- second = self.second.simplify()
703
- consequent = (self.consequent.simplify() if self.consequent else None)
704
-
705
- if isinstance(first, DRS) and isinstance(second, DRS):
706
- # For any ref that is in both 'first' and 'second'
707
- for ref in (set(first.get_refs(True)) & set(second.get_refs(True))):
708
- # alpha convert the ref in 'second' to prevent collision
709
- newvar = DrtVariableExpression(unique_variable(ref))
710
- second = second.replace(ref, newvar, True)
711
-
712
- return DRS(first.refs + second.refs, first.conds + second.conds, consequent)
713
- else:
714
- return self.__class__(first, second, consequent)
715
-
716
- def get_refs(self, recursive=False):
717
- """:see: AbstractExpression.get_refs()"""
718
- refs = self.first.get_refs(recursive) + self.second.get_refs(recursive)
719
- if self.consequent and recursive:
720
- refs.extend(self.consequent.get_refs(True))
721
- return refs
722
-
723
- def getOp(self):
724
- return DrtTokens.DRS_CONC
725
-
726
- def __eq__(self, other):
727
- r"""Defines equality modulo alphabetic variance.
728
- If we are comparing \x.M and \y.N, then check equality of M and N[x/y]."""
729
- if isinstance(other, DrtConcatenation):
730
- self_refs = self.get_refs()
731
- other_refs = other.get_refs()
732
- if len(self_refs) == len(other_refs):
733
- converted_other = other
734
- for (r1,r2) in zip(self_refs, other_refs):
735
- varex = self.make_VariableExpression(r1)
736
- converted_other = converted_other.replace(r2, varex, True)
737
- return self.first == converted_other.first and \
738
- self.second == converted_other.second and \
739
- self.consequent == converted_other.consequent
740
- return False
741
-
742
- def __ne__(self, other):
743
- return not self == other
744
-
745
- __hash__ = DrtBooleanExpression.__hash__
746
-
747
- def fol(self):
748
- e = AndExpression(self.first.fol(), self.second.fol())
749
- if self.consequent:
750
- e = ImpExpression(e, self.consequent.fol())
751
- return e
752
-
753
- def _pretty(self):
754
- drs = DrtBinaryExpression._assemble_pretty(self._pretty_subex(self.first),
755
- self.getOp(),
756
- self._pretty_subex(self.second))
757
- if self.consequent:
758
- drs = DrtBinaryExpression._assemble_pretty(drs, DrtTokens.IMP,
759
- self._pretty(self.consequent))
760
- return drs
761
-
762
- def _pretty_subex(self, subex):
763
- if isinstance(subex, DrtConcatenation):
764
- return [line[1:-1] for line in subex._pretty()]
765
- return DrtBooleanExpression._pretty_subex(self, subex)
766
-
767
-
768
- def visit(self, function, combinator):
769
- """:see: Expression.visit()"""
770
- if self.consequent:
771
- return combinator([function(self.first), function(self.second), function(self.consequent)])
772
- else:
773
- return combinator([function(self.first), function(self.second)])
774
-
775
- def __str__(self):
776
- first = self._str_subex(self.first)
777
- second = self._str_subex(self.second)
778
- drs = Tokens.OPEN + first + ' ' + self.getOp() \
779
- + ' ' + second + Tokens.CLOSE
780
- if self.consequent:
781
- return DrtTokens.OPEN + drs + ' ' + DrtTokens.IMP + ' ' + \
782
- "%s" % self.consequent + DrtTokens.CLOSE
783
- return drs
784
-
785
- def _str_subex(self, subex):
786
- s = "%s" % subex
787
- if isinstance(subex, DrtConcatenation) and subex.consequent is None:
788
- return s[1:-1]
789
- return s
790
-
791
-
792
- class DrtApplicationExpression(DrtExpression, ApplicationExpression):
793
- def fol(self):
794
- return ApplicationExpression(self.function.fol(), self.argument.fol())
795
-
796
- def get_refs(self, recursive=False):
797
- """:see: AbstractExpression.get_refs()"""
798
- return (self.function.get_refs(True) + self.argument.get_refs(True)
799
- if recursive else [])
800
-
801
- def _pretty(self):
802
- function, args = self.uncurry()
803
- function_lines = function._pretty()
804
- args_lines = [arg._pretty() for arg in args]
805
- max_lines = max(map(len, [function_lines] + args_lines))
806
- function_lines = _pad_vertically(function_lines, max_lines)
807
- args_lines = [_pad_vertically(arg_lines, max_lines) for arg_lines in args_lines]
808
- func_args_lines = list(zip(function_lines, list(zip(*args_lines))))
809
- return ([func_line + ' ' + ' '.join(args_line) + ' ' for func_line, args_line in func_args_lines[:2]] +
810
- [func_line + '(' + ','.join(args_line) + ')' for func_line, args_line in func_args_lines[2:3]] +
811
- [func_line + ' ' + ' '.join(args_line) + ' ' for func_line, args_line in func_args_lines[3:]])
812
-
813
-
814
- def _pad_vertically(lines, max_lines):
815
- pad_line = [' ' * len(lines[0])]
816
- return lines + pad_line * (max_lines - len(lines))
817
-
818
-
819
- @python_2_unicode_compatible
820
- class PossibleAntecedents(list, DrtExpression, Expression):
821
- def free(self):
822
- """Set of free variables."""
823
- return set(self)
824
-
825
- def replace(self, variable, expression, replace_bound=False, alpha_convert=True):
826
- """Replace all instances of variable v with expression E in self,
827
- where v is free in self."""
828
- result = PossibleAntecedents()
829
- for item in self:
830
- if item == variable:
831
- self.append(expression)
832
- else:
833
- self.append(item)
834
- return result
835
-
836
- def _pretty(self):
837
- s = "%s" % self
838
- blank = ' ' * len(s)
839
- return [blank, blank, s]
840
-
841
- def __str__(self):
842
- return '[' + ','.join("%s" % it for it in self) + ']'
843
-
844
-
845
- class AnaphoraResolutionException(Exception):
846
- pass
847
-
848
-
849
- def resolve_anaphora(expression, trail=[]):
850
- if isinstance(expression, ApplicationExpression):
851
- if expression.is_pronoun_function():
852
- possible_antecedents = PossibleAntecedents()
853
- for ancestor in trail:
854
- for ref in ancestor.get_refs():
855
- refex = expression.make_VariableExpression(ref)
856
-
857
- #==========================================================
858
- # Don't allow resolution to itself or other types
859
- #==========================================================
860
- if refex.__class__ == expression.argument.__class__ and \
861
- not (refex == expression.argument):
862
- possible_antecedents.append(refex)
863
-
864
- if len(possible_antecedents) == 1:
865
- resolution = possible_antecedents[0]
866
- else:
867
- resolution = possible_antecedents
868
- return expression.make_EqualityExpression(expression.argument, resolution)
869
- else:
870
- r_function = resolve_anaphora(expression.function, trail + [expression])
871
- r_argument = resolve_anaphora(expression.argument, trail + [expression])
872
- return expression.__class__(r_function, r_argument)
873
-
874
- elif isinstance(expression, DRS):
875
- r_conds = []
876
- for cond in expression.conds:
877
- r_cond = resolve_anaphora(cond, trail + [expression])
878
-
879
- # if the condition is of the form '(x = [])' then raise exception
880
- if isinstance(r_cond, EqualityExpression):
881
- if isinstance(r_cond.first, PossibleAntecedents):
882
- #Reverse the order so that the variable is on the left
883
- temp = r_cond.first
884
- r_cond.first = r_cond.second
885
- r_cond.second = temp
886
- if isinstance(r_cond.second, PossibleAntecedents):
887
- if not r_cond.second:
888
- raise AnaphoraResolutionException("Variable '%s' does not "
889
- "resolve to anything." % r_cond.first)
890
-
891
- r_conds.append(r_cond)
892
- if expression.consequent:
893
- consequent = resolve_anaphora(expression.consequent, trail + [expression])
894
- else:
895
- consequent = None
896
- return expression.__class__(expression.refs, r_conds, consequent)
897
-
898
- elif isinstance(expression, AbstractVariableExpression):
899
- return expression
900
-
901
- elif isinstance(expression, NegatedExpression):
902
- return expression.__class__(resolve_anaphora(expression.term, trail + [expression]))
903
-
904
- elif isinstance(expression, DrtConcatenation):
905
- if expression.consequent:
906
- consequent = resolve_anaphora(expression.consequent, trail + [expression])
907
- else:
908
- consequent = None
909
- return expression.__class__(resolve_anaphora(expression.first, trail + [expression]),
910
- resolve_anaphora(expression.second, trail + [expression]),
911
- consequent)
912
-
913
- elif isinstance(expression, BinaryExpression):
914
- return expression.__class__(resolve_anaphora(expression.first, trail + [expression]),
915
- resolve_anaphora(expression.second, trail + [expression]))
916
-
917
- elif isinstance(expression, LambdaExpression):
918
- return expression.__class__(expression.variable, resolve_anaphora(expression.term, trail + [expression]))
919
-
920
-
921
- class DrsDrawer(object):
922
- BUFFER = 3 #Space between elements
923
- TOPSPACE = 10 #Space above whole DRS
924
- OUTERSPACE = 6 #Space to the left, right, and bottom of the whle DRS
925
-
926
- def __init__(self, drs, size_canvas=True, canvas=None):
927
- """
928
- :param drs: ``DrtExpression``, The DRS to be drawn
929
- :param size_canvas: bool, True if the canvas size should be the exact size of the DRS
930
- :param canvas: ``Canvas`` The canvas on which to draw the DRS. If none is given, create a new canvas.
931
- """
932
- master = None
933
- if not canvas:
934
- master = Tk()
935
- master.title("DRT")
936
-
937
- font = Font(family='helvetica', size=12)
938
-
939
- if size_canvas:
940
- canvas = Canvas(master, width=0, height=0)
941
- canvas.font = font
942
- self.canvas = canvas
943
- (right, bottom) = self._visit(drs, self.OUTERSPACE, self.TOPSPACE)
944
-
945
- width = max(right+self.OUTERSPACE, 100)
946
- height = bottom+self.OUTERSPACE
947
- canvas = Canvas(master, width=width, height=height)#, bg='white')
948
- else:
949
- canvas = Canvas(master, width=300, height=300)
950
-
951
- canvas.pack()
952
- canvas.font = font
953
-
954
- self.canvas = canvas
955
- self.drs = drs
956
- self.master = master
957
-
958
- def _get_text_height(self):
959
- """Get the height of a line of text"""
960
- return self.canvas.font.metrics("linespace")
961
-
962
- def draw(self, x=OUTERSPACE, y=TOPSPACE):
963
- """Draw the DRS"""
964
- self._handle(self.drs, self._draw_command, x, y)
965
-
966
- if self.master and not in_idle():
967
- self.master.mainloop()
968
- else:
969
- return self._visit(self.drs, x, y)
970
-
971
- def _visit(self, expression, x, y):
972
- """
973
- Return the bottom-rightmost point without actually drawing the item
974
-
975
- :param expression: the item to visit
976
- :param x: the top of the current drawing area
977
- :param y: the left side of the current drawing area
978
- :return: the bottom-rightmost point
979
- """
980
- return self._handle(expression, self._visit_command, x, y)
981
-
982
- def _draw_command(self, item, x, y):
983
- """
984
- Draw the given item at the given location
985
-
986
- :param item: the item to draw
987
- :param x: the top of the current drawing area
988
- :param y: the left side of the current drawing area
989
- :return: the bottom-rightmost point
990
- """
991
- if isinstance(item, string_types):
992
- self.canvas.create_text(x, y, anchor='nw', font=self.canvas.font, text=item)
993
- elif isinstance(item, tuple):
994
- # item is the lower-right of a box
995
- (right, bottom) = item
996
- self.canvas.create_rectangle(x, y, right, bottom)
997
- horiz_line_y = y + self._get_text_height() + (self.BUFFER * 2) #the line separating refs from conds
998
- self.canvas.create_line(x, horiz_line_y, right, horiz_line_y)
999
-
1000
- return self._visit_command(item, x, y)
1001
-
1002
- def _visit_command(self, item, x, y):
1003
- """
1004
- Return the bottom-rightmost point without actually drawing the item
1005
-
1006
- :param item: the item to visit
1007
- :param x: the top of the current drawing area
1008
- :param y: the left side of the current drawing area
1009
- :return: the bottom-rightmost point
1010
- """
1011
- if isinstance(item, string_types):
1012
- return (x + self.canvas.font.measure(item), y + self._get_text_height())
1013
- elif isinstance(item, tuple):
1014
- return item
1015
-
1016
- def _handle(self, expression, command, x=0, y=0):
1017
- """
1018
- :param expression: the expression to handle
1019
- :param command: the function to apply, either _draw_command or _visit_command
1020
- :param x: the top of the current drawing area
1021
- :param y: the left side of the current drawing area
1022
- :return: the bottom-rightmost point
1023
- """
1024
- if command == self._visit_command:
1025
- #if we don't need to draw the item, then we can use the cached values
1026
- try:
1027
- #attempt to retrieve cached values
1028
- right = expression._drawing_width + x
1029
- bottom = expression._drawing_height + y
1030
- return (right, bottom)
1031
- except AttributeError:
1032
- #the values have not been cached yet, so compute them
1033
- pass
1034
-
1035
- if isinstance(expression, DrtAbstractVariableExpression):
1036
- factory = self._handle_VariableExpression
1037
- elif isinstance(expression, DRS):
1038
- factory = self._handle_DRS
1039
- elif isinstance(expression, DrtNegatedExpression):
1040
- factory = self._handle_NegatedExpression
1041
- elif isinstance(expression, DrtLambdaExpression):
1042
- factory = self._handle_LambdaExpression
1043
- elif isinstance(expression, BinaryExpression):
1044
- factory = self._handle_BinaryExpression
1045
- elif isinstance(expression, DrtApplicationExpression):
1046
- factory = self._handle_ApplicationExpression
1047
- elif isinstance(expression, PossibleAntecedents):
1048
- factory = self._handle_VariableExpression
1049
- elif isinstance(expression, DrtProposition):
1050
- factory = self._handle_DrtProposition
1051
- else:
1052
- raise Exception(expression.__class__.__name__)
1053
-
1054
- (right, bottom) = factory(expression, command, x, y)
1055
-
1056
- #cache the values
1057
- expression._drawing_width = right - x
1058
- expression._drawing_height = bottom - y
1059
-
1060
- return (right, bottom)
1061
-
1062
- def _handle_VariableExpression(self, expression, command, x, y):
1063
- return command("%s" % expression, x, y)
1064
-
1065
- def _handle_NegatedExpression(self, expression, command, x, y):
1066
- # Find the width of the negation symbol
1067
- right = self._visit_command(DrtTokens.NOT, x, y)[0]
1068
-
1069
- # Handle term
1070
- (right, bottom) = self._handle(expression.term, command, right, y)
1071
-
1072
- # Handle variables now that we know the y-coordinate
1073
- command(DrtTokens.NOT, x, self._get_centered_top(y, bottom - y, self._get_text_height()))
1074
-
1075
- return (right, bottom)
1076
-
1077
- def _handle_DRS(self, expression, command, x, y):
1078
- left = x + self.BUFFER #indent the left side
1079
- bottom = y + self.BUFFER #indent the top
1080
-
1081
- # Handle Discourse Referents
1082
- if expression.refs:
1083
- refs = ' '.join("%s"%r for r in expression.refs)
1084
- else:
1085
- refs = ' '
1086
- (max_right, bottom) = command(refs, left, bottom)
1087
- bottom += (self.BUFFER * 2)
1088
-
1089
- # Handle Conditions
1090
- if expression.conds:
1091
- for cond in expression.conds:
1092
- (right, bottom) = self._handle(cond, command, left, bottom)
1093
- max_right = max(max_right, right)
1094
- bottom += self.BUFFER
1095
- else:
1096
- bottom += self._get_text_height() + self.BUFFER
1097
-
1098
- # Handle Box
1099
- max_right += self.BUFFER
1100
- return command((max_right, bottom), x, y)
1101
-
1102
- def _handle_ApplicationExpression(self, expression, command, x, y):
1103
- function, args = expression.uncurry()
1104
- if not isinstance(function, DrtAbstractVariableExpression):
1105
- #It's not a predicate expression ("P(x,y)"), so leave arguments curried
1106
- function = expression.function
1107
- args = [expression.argument]
1108
-
1109
- # Get the max bottom of any element on the line
1110
- function_bottom = self._visit(function, x, y)[1]
1111
- max_bottom = max([function_bottom] + [self._visit(arg, x, y)[1] for arg in args])
1112
-
1113
- line_height = max_bottom - y
1114
-
1115
- # Handle 'function'
1116
- function_drawing_top = self._get_centered_top(y, line_height, function._drawing_height)
1117
- right = self._handle(function, command, x, function_drawing_top)[0]
1118
-
1119
- # Handle open paren
1120
- centred_string_top = self._get_centered_top(y, line_height, self._get_text_height())
1121
- right = command(DrtTokens.OPEN, right, centred_string_top)[0]
1122
-
1123
- # Handle each arg
1124
- for (i,arg) in enumerate(args):
1125
- arg_drawing_top = self._get_centered_top(y, line_height, arg._drawing_height)
1126
- right = self._handle(arg, command, right, arg_drawing_top)[0]
1127
-
1128
- if i+1 < len(args):
1129
- #since it's not the last arg, add a comma
1130
- right = command(DrtTokens.COMMA + ' ', right, centred_string_top)[0]
1131
-
1132
- # Handle close paren
1133
- right = command(DrtTokens.CLOSE, right, centred_string_top)[0]
1134
-
1135
- return (right, max_bottom)
1136
-
1137
- def _handle_LambdaExpression(self, expression, command, x, y):
1138
- # Find the width of the lambda symbol and abstracted variables
1139
- variables = DrtTokens.LAMBDA + "%s" % expression.variable + DrtTokens.DOT
1140
- right = self._visit_command(variables, x, y)[0]
1141
-
1142
- # Handle term
1143
- (right, bottom) = self._handle(expression.term, command, right, y)
1144
-
1145
- # Handle variables now that we know the y-coordinate
1146
- command(variables, x, self._get_centered_top(y, bottom - y, self._get_text_height()))
1147
-
1148
- return (right, bottom)
1149
-
1150
- def _handle_BinaryExpression(self, expression, command, x, y):
1151
- # Get the full height of the line, based on the operands
1152
- first_height = self._visit(expression.first, 0, 0)[1]
1153
- second_height = self._visit(expression.second, 0, 0)[1]
1154
- line_height = max(first_height, second_height)
1155
-
1156
- # Handle open paren
1157
- centred_string_top = self._get_centered_top(y, line_height, self._get_text_height())
1158
- right = command(DrtTokens.OPEN, x, centred_string_top)[0]
1159
-
1160
- # Handle the first operand
1161
- first_height = expression.first._drawing_height
1162
- (right, first_bottom) = self._handle(expression.first, command, right, self._get_centered_top(y, line_height, first_height))
1163
-
1164
- # Handle the operator
1165
- right = command(' %s ' % expression.getOp(), right, centred_string_top)[0]
1166
-
1167
- # Handle the second operand
1168
- second_height = expression.second._drawing_height
1169
- (right, second_bottom) = self._handle(expression.second, command, right, self._get_centered_top(y, line_height, second_height))
1170
-
1171
- # Handle close paren
1172
- right = command(DrtTokens.CLOSE, right, centred_string_top)[0]
1173
-
1174
- return (right, max(first_bottom, second_bottom))
1175
-
1176
- def _handle_DrtProposition(self, expression, command, x, y):
1177
- # Find the width of the negation symbol
1178
- right = command(expression.variable, x, y)[0]
1179
-
1180
- # Handle term
1181
- (right, bottom) = self._handle(expression.term, command, right, y)
1182
-
1183
- return (right, bottom)
1184
-
1185
- def _get_centered_top(self, top, full_height, item_height):
1186
- """Get the y-coordinate of the point that a figure should start at if
1187
- its height is 'item_height' and it needs to be centered in an area that
1188
- starts at 'top' and is 'full_height' tall."""
1189
- return top + (full_height - item_height) / 2
1190
-
1191
-
1192
- def demo():
1193
- print('='*20 + 'TEST PARSE' + '='*20)
1194
- dexpr = DrtExpression.fromstring
1195
- print(dexpr(r'([x,y],[sees(x,y)])'))
1196
- print(dexpr(r'([x],[man(x), walks(x)])'))
1197
- print(dexpr(r'\x.\y.([],[sees(x,y)])'))
1198
- print(dexpr(r'\x.([],[walks(x)])(john)'))
1199
- print(dexpr(r'(([x],[walks(x)]) + ([y],[runs(y)]))'))
1200
- print(dexpr(r'(([],[walks(x)]) -> ([],[runs(x)]))'))
1201
- print(dexpr(r'([x],[PRO(x), sees(John,x)])'))
1202
- print(dexpr(r'([x],[man(x), -([],[walks(x)])])'))
1203
- print(dexpr(r'([],[(([x],[man(x)]) -> ([],[walks(x)]))])'))
1204
-
1205
- print('='*20 + 'Test fol()' + '='*20)
1206
- print(dexpr(r'([x,y],[sees(x,y)])').fol())
1207
-
1208
- print('='*20 + 'Test alpha conversion and lambda expression equality' + '='*20)
1209
- e1 = dexpr(r'\x.([],[P(x)])')
1210
- print(e1)
1211
- e2 = e1.alpha_convert(Variable('z'))
1212
- print(e2)
1213
- print(e1 == e2)
1214
-
1215
- print('='*20 + 'Test resolve_anaphora()' + '='*20)
1216
- print(resolve_anaphora(dexpr(r'([x,y,z],[dog(x), cat(y), walks(z), PRO(z)])')))
1217
- print(resolve_anaphora(dexpr(r'([],[(([x],[dog(x)]) -> ([y],[walks(y), PRO(y)]))])')))
1218
- print(resolve_anaphora(dexpr(r'(([x,y],[]) + ([],[PRO(x)]))')))
1219
-
1220
- print('='*20 + 'Test pretty_print()' + '='*20)
1221
- dexpr(r"([],[])").pretty_print()
1222
- dexpr(r"([],[([x],[big(x), dog(x)]) -> ([],[bark(x)]) -([x],[walk(x)])])").pretty_print()
1223
- dexpr(r"([x,y],[x=y]) + ([z],[dog(z), walk(z)])").pretty_print()
1224
- dexpr(r"([],[([x],[]) | ([y],[]) | ([z],[dog(z), walk(z)])])").pretty_print()
1225
- dexpr(r"\P.\Q.(([x],[]) + P(x) + Q(x))(\x.([],[dog(x)]))").pretty_print()
1226
-
1227
-
1228
- def test_draw():
1229
- try:
1230
- from tkinter import Tk
1231
- except ImportError:
1232
- from nose import SkipTest
1233
- raise SkipTest("tkinter is required, but it's not available.")
1234
-
1235
- expressions = [
1236
- r'x',
1237
- r'([],[])',
1238
- r'([x],[])',
1239
- r'([x],[man(x)])',
1240
-
1241
- r'([x,y],[sees(x,y)])',
1242
- r'([x],[man(x), walks(x)])',
1243
- r'\x.([],[man(x), walks(x)])',
1244
- r'\x y.([],[sees(x,y)])',
1245
- r'([],[(([],[walks(x)]) + ([],[runs(x)]))])',
1246
-
1247
- r'([x],[man(x), -([],[walks(x)])])',
1248
- r'([],[(([x],[man(x)]) -> ([],[walks(x)]))])'
1249
- ]
1250
-
1251
- for e in expressions:
1252
- d = DrtExpression.fromstring(e)
1253
- d.draw()
1254
-
1255
-
1256
- if __name__ == '__main__':
1257
- demo()
1
+ # Natural Language Toolkit: Discourse Representation Theory (DRT)
2
+ #
3
+ # Author: Dan Garrette <dhgarrette@gmail.com>
4
+ #
5
+ # Copyright (C) 2001-2018 NLTK Project
6
+ # URL: <http://nltk.org/>
7
+ # For license information, see LICENSE.TXT
8
+ from __future__ import print_function, unicode_literals
9
+
10
+ import operator
11
+ from functools import reduce
12
+ from itertools import chain
13
+
14
+ from six import string_types
15
+
16
+ from nltk.compat import python_2_unicode_compatible
17
+ from nltk.sem.logic import (APP, AbstractVariableExpression, AllExpression,
18
+ AndExpression, ApplicationExpression, BinaryExpression,
19
+ BooleanExpression, ConstantExpression, EqualityExpression,
20
+ EventVariableExpression, ExistsExpression, Expression,
21
+ FunctionVariableExpression, ImpExpression,
22
+ IndividualVariableExpression, LambdaExpression, Tokens,
23
+ LogicParser, NegatedExpression, OrExpression, Variable,
24
+ is_eventvar, is_funcvar, is_indvar, unique_variable)
25
+
26
+ # Import Tkinter-based modules if they are available
27
+ try:
28
+ from six.moves.tkinter import Canvas, Tk
29
+ from six.moves.tkinter_font import Font
30
+ from nltk.util import in_idle
31
+
32
+ except ImportError:
33
+ # No need to print a warning here, nltk.draw has already printed one.
34
+ pass
35
+
36
+ class DrtTokens(Tokens):
37
+ DRS = 'DRS'
38
+ DRS_CONC = '+'
39
+ PRONOUN = 'PRO'
40
+ OPEN_BRACKET = '['
41
+ CLOSE_BRACKET = ']'
42
+ COLON = ':'
43
+
44
+ PUNCT = [DRS_CONC, OPEN_BRACKET, CLOSE_BRACKET, COLON]
45
+
46
+ SYMBOLS = Tokens.SYMBOLS + PUNCT
47
+
48
+ TOKENS = Tokens.TOKENS + [DRS] + PUNCT
49
+
50
+
51
+ class DrtParser(LogicParser):
52
+ """A lambda calculus expression parser."""
53
+ def __init__(self):
54
+ LogicParser.__init__(self)
55
+
56
+ self.operator_precedence = dict(
57
+ [(x,1) for x in DrtTokens.LAMBDA_LIST] + \
58
+ [(x,2) for x in DrtTokens.NOT_LIST] + \
59
+ [(APP,3)] + \
60
+ [(x,4) for x in DrtTokens.EQ_LIST+Tokens.NEQ_LIST] + \
61
+ [(DrtTokens.COLON,5)] + \
62
+ [(DrtTokens.DRS_CONC,6)] + \
63
+ [(x,7) for x in DrtTokens.OR_LIST] + \
64
+ [(x,8) for x in DrtTokens.IMP_LIST] + \
65
+ [(None,9)])
66
+
67
+ def get_all_symbols(self):
68
+ """This method exists to be overridden"""
69
+ return DrtTokens.SYMBOLS
70
+
71
+ def isvariable(self, tok):
72
+ return tok not in DrtTokens.TOKENS
73
+
74
+ def handle(self, tok, context):
75
+ """This method is intended to be overridden for logics that
76
+ use different operators or expressions"""
77
+ if tok in DrtTokens.NOT_LIST:
78
+ return self.handle_negation(tok, context)
79
+
80
+ elif tok in DrtTokens.LAMBDA_LIST:
81
+ return self.handle_lambda(tok, context)
82
+
83
+ elif tok == DrtTokens.OPEN:
84
+ if self.inRange(0) and self.token(0) == DrtTokens.OPEN_BRACKET:
85
+ return self.handle_DRS(tok, context)
86
+ else:
87
+ return self.handle_open(tok, context)
88
+
89
+ elif tok.upper() == DrtTokens.DRS:
90
+ self.assertNextToken(DrtTokens.OPEN)
91
+ return self.handle_DRS(tok, context)
92
+
93
+ elif self.isvariable(tok):
94
+ if self.inRange(0) and self.token(0) == DrtTokens.COLON:
95
+ return self.handle_prop(tok, context)
96
+ else:
97
+ return self.handle_variable(tok, context)
98
+
99
+ def make_NegatedExpression(self, expression):
100
+ return DrtNegatedExpression(expression)
101
+
102
+ def handle_DRS(self, tok, context):
103
+ # a DRS
104
+ refs = self.handle_refs()
105
+ if self.inRange(0) and self.token(0) == DrtTokens.COMMA: #if there is a comma (it's optional)
106
+ self.token() # swallow the comma
107
+ conds = self.handle_conds(context)
108
+ self.assertNextToken(DrtTokens.CLOSE)
109
+ return DRS(refs, conds, None)
110
+
111
+ def handle_refs(self):
112
+ self.assertNextToken(DrtTokens.OPEN_BRACKET)
113
+ refs = []
114
+ while self.inRange(0) and self.token(0) != DrtTokens.CLOSE_BRACKET:
115
+ # Support expressions like: DRS([x y],C) == DRS([x,y],C)
116
+ if refs and self.token(0) == DrtTokens.COMMA:
117
+ self.token() # swallow the comma
118
+ refs.append(self.get_next_token_variable('quantified'))
119
+ self.assertNextToken(DrtTokens.CLOSE_BRACKET)
120
+ return refs
121
+
122
+ def handle_conds(self, context):
123
+ self.assertNextToken(DrtTokens.OPEN_BRACKET)
124
+ conds = []
125
+ while self.inRange(0) and self.token(0) != DrtTokens.CLOSE_BRACKET:
126
+ # Support expressions like: DRS([x y],C) == DRS([x, y],C)
127
+ if conds and self.token(0) == DrtTokens.COMMA:
128
+ self.token() # swallow the comma
129
+ conds.append(self.process_next_expression(context))
130
+ self.assertNextToken(DrtTokens.CLOSE_BRACKET)
131
+ return conds
132
+
133
+ def handle_prop(self, tok, context):
134
+ variable = self.make_VariableExpression(tok)
135
+ self.assertNextToken(':')
136
+ drs = self.process_next_expression(DrtTokens.COLON)
137
+ return DrtProposition(variable, drs)
138
+
139
+ def make_EqualityExpression(self, first, second):
140
+ """This method serves as a hook for other logic parsers that
141
+ have different equality expression classes"""
142
+ return DrtEqualityExpression(first, second)
143
+
144
+ def get_BooleanExpression_factory(self, tok):
145
+ """This method serves as a hook for other logic parsers that
146
+ have different boolean operators"""
147
+ if tok == DrtTokens.DRS_CONC:
148
+ return lambda first, second: DrtConcatenation(first, second, None)
149
+ elif tok in DrtTokens.OR_LIST:
150
+ return DrtOrExpression
151
+ elif tok in DrtTokens.IMP_LIST:
152
+ def make_imp_expression(first, second):
153
+ if isinstance(first, DRS):
154
+ return DRS(first.refs, first.conds, second)
155
+ if isinstance(first, DrtConcatenation):
156
+ return DrtConcatenation(first.first, first.second, second)
157
+ raise Exception('Antecedent of implication must be a DRS')
158
+ return make_imp_expression
159
+ else:
160
+ return None
161
+
162
+ def make_BooleanExpression(self, factory, first, second):
163
+ return factory(first, second)
164
+
165
+ def make_ApplicationExpression(self, function, argument):
166
+ return DrtApplicationExpression(function, argument)
167
+
168
+ def make_VariableExpression(self, name):
169
+ return DrtVariableExpression(Variable(name))
170
+
171
+ def make_LambdaExpression(self, variables, term):
172
+ return DrtLambdaExpression(variables, term)
173
+
174
+
175
+ class DrtExpression(object):
176
+ """
177
+ This is the base abstract DRT Expression from which every DRT
178
+ Expression extends.
179
+ """
180
+
181
+ _drt_parser = DrtParser()
182
+
183
+ @classmethod
184
+ def fromstring(cls, s):
185
+ return cls._drt_parser.parse(s)
186
+
187
+ def applyto(self, other):
188
+ return DrtApplicationExpression(self, other)
189
+
190
+ def __neg__(self):
191
+ return DrtNegatedExpression(self)
192
+
193
+ def __and__(self, other):
194
+ raise NotImplementedError()
195
+
196
+ def __or__(self, other):
197
+ assert isinstance(other, DrtExpression)
198
+ return DrtOrExpression(self, other)
199
+
200
+ def __gt__(self, other):
201
+ assert isinstance(other, DrtExpression)
202
+ if isinstance(self, DRS):
203
+ return DRS(self.refs, self.conds, other)
204
+ if isinstance(self, DrtConcatenation):
205
+ return DrtConcatenation(self.first, self.second, other)
206
+ raise Exception('Antecedent of implication must be a DRS')
207
+
208
+ def equiv(self, other, prover=None):
209
+ """
210
+ Check for logical equivalence.
211
+ Pass the expression (self <-> other) to the theorem prover.
212
+ If the prover says it is valid, then the self and other are equal.
213
+
214
+ :param other: an ``DrtExpression`` to check equality against
215
+ :param prover: a ``nltk.inference.api.Prover``
216
+ """
217
+ assert isinstance(other, DrtExpression)
218
+
219
+ f1 = self.simplify().fol();
220
+ f2 = other.simplify().fol();
221
+ return f1.equiv(f2, prover)
222
+
223
+ @property
224
+ def type(self):
225
+ raise AttributeError("'%s' object has no attribute 'type'" %
226
+ self.__class__.__name__)
227
+
228
+ def typecheck(self, signature=None):
229
+ raise NotImplementedError()
230
+
231
+ def __add__(self, other):
232
+ return DrtConcatenation(self, other, None)
233
+
234
+ def get_refs(self, recursive=False):
235
+ """
236
+ Return the set of discourse referents in this DRS.
237
+ :param recursive: bool Also find discourse referents in subterms?
238
+ :return: list of ``Variable`` objects
239
+ """
240
+ raise NotImplementedError()
241
+
242
+ def is_pronoun_function(self):
243
+ """ Is self of the form "PRO(x)"? """
244
+ return isinstance(self, DrtApplicationExpression) and \
245
+ isinstance(self.function, DrtAbstractVariableExpression) and \
246
+ self.function.variable.name == DrtTokens.PRONOUN and \
247
+ isinstance(self.argument, DrtIndividualVariableExpression)
248
+
249
+ def make_EqualityExpression(self, first, second):
250
+ return DrtEqualityExpression(first, second)
251
+
252
+ def make_VariableExpression(self, variable):
253
+ return DrtVariableExpression(variable)
254
+
255
+ def resolve_anaphora(self):
256
+ return resolve_anaphora(self)
257
+
258
+ def eliminate_equality(self):
259
+ return self.visit_structured(lambda e: e.eliminate_equality(),
260
+ self.__class__)
261
+
262
+ def pretty_format(self):
263
+ """
264
+ Draw the DRS
265
+ :return: the pretty print string
266
+ """
267
+ return '\n'.join(self._pretty())
268
+
269
+ def pretty_print(self):
270
+ print(self.pretty_format())
271
+
272
+ def draw(self):
273
+ DrsDrawer(self).draw()
274
+
275
+
276
+ @python_2_unicode_compatible
277
+ class DRS(DrtExpression, Expression):
278
+ """A Discourse Representation Structure."""
279
+ def __init__(self, refs, conds, consequent=None):
280
+ """
281
+ :param refs: list of ``DrtIndividualVariableExpression`` for the
282
+ discourse referents
283
+ :param conds: list of ``Expression`` for the conditions
284
+ """
285
+ self.refs = refs
286
+ self.conds = conds
287
+ self.consequent = consequent
288
+
289
+ def replace(self, variable, expression, replace_bound=False, alpha_convert=True):
290
+ """Replace all instances of variable v with expression E in self,
291
+ where v is free in self."""
292
+ if variable in self.refs:
293
+ #if a bound variable is the thing being replaced
294
+ if not replace_bound:
295
+ return self
296
+ else:
297
+ i = self.refs.index(variable)
298
+ if self.consequent:
299
+ consequent = self.consequent.replace(variable, expression, True, alpha_convert)
300
+ else:
301
+ consequent = None
302
+ return DRS(self.refs[:i]+[expression.variable]+self.refs[i+1:],
303
+ [cond.replace(variable, expression, True, alpha_convert)
304
+ for cond in self.conds],
305
+ consequent)
306
+ else:
307
+ if alpha_convert:
308
+ # any bound variable that appears in the expression must
309
+ # be alpha converted to avoid a conflict
310
+ for ref in (set(self.refs) & expression.free()):
311
+ newvar = unique_variable(ref)
312
+ newvarex = DrtVariableExpression(newvar)
313
+ i = self.refs.index(ref)
314
+ if self.consequent:
315
+ consequent = self.consequent.replace(ref, newvarex, True, alpha_convert)
316
+ else:
317
+ consequent = None
318
+ self = DRS(self.refs[:i]+[newvar]+self.refs[i+1:],
319
+ [cond.replace(ref, newvarex, True, alpha_convert)
320
+ for cond in self.conds],
321
+ consequent)
322
+
323
+ #replace in the conditions
324
+ if self.consequent:
325
+ consequent = self.consequent.replace(variable, expression, replace_bound, alpha_convert)
326
+ else:
327
+ consequent = None
328
+ return DRS(self.refs,
329
+ [cond.replace(variable, expression, replace_bound, alpha_convert)
330
+ for cond in self.conds],
331
+ consequent)
332
+
333
+ def free(self):
334
+ """:see: Expression.free()"""
335
+ conds_free = reduce(operator.or_, [c.free() for c in self.conds], set())
336
+ if self.consequent:
337
+ conds_free.update(self.consequent.free())
338
+ return conds_free - set(self.refs)
339
+
340
+ def get_refs(self, recursive=False):
341
+ """:see: AbstractExpression.get_refs()"""
342
+ if recursive:
343
+ conds_refs = self.refs + list(chain(*(c.get_refs(True) for c in self.conds)))
344
+ if self.consequent:
345
+ conds_refs.extend(self.consequent.get_refs(True))
346
+ return conds_refs
347
+ else:
348
+ return self.refs
349
+
350
+ def visit(self, function, combinator):
351
+ """:see: Expression.visit()"""
352
+ parts = list(map(function, self.conds))
353
+ if self.consequent:
354
+ parts.append(function(self.consequent))
355
+ return combinator(parts)
356
+
357
+ def visit_structured(self, function, combinator):
358
+ """:see: Expression.visit_structured()"""
359
+ consequent = (function(self.consequent) if self.consequent else None)
360
+ return combinator(self.refs, list(map(function, self.conds)), consequent)
361
+
362
+ def eliminate_equality(self):
363
+ drs = self
364
+ i = 0
365
+ while i < len(drs.conds):
366
+ cond = drs.conds[i]
367
+ if isinstance(cond, EqualityExpression) and \
368
+ isinstance(cond.first, AbstractVariableExpression) and \
369
+ isinstance(cond.second, AbstractVariableExpression):
370
+ drs = DRS(list(set(drs.refs)-set([cond.second.variable])),
371
+ drs.conds[:i]+drs.conds[i+1:],
372
+ drs.consequent)
373
+ if cond.second.variable != cond.first.variable:
374
+ drs = drs.replace(cond.second.variable, cond.first, False, False)
375
+ i = 0
376
+ i -= 1
377
+ i += 1
378
+
379
+ conds = []
380
+ for cond in drs.conds:
381
+ new_cond = cond.eliminate_equality()
382
+ new_cond_simp = new_cond.simplify()
383
+ if not isinstance(new_cond_simp, DRS) or \
384
+ new_cond_simp.refs or new_cond_simp.conds or \
385
+ new_cond_simp.consequent:
386
+ conds.append(new_cond)
387
+
388
+ consequent = (drs.consequent.eliminate_equality() if drs.consequent else None)
389
+ return DRS(drs.refs, conds, consequent)
390
+
391
+ def fol(self):
392
+ if self.consequent:
393
+ accum = None
394
+ if self.conds:
395
+ accum = reduce(AndExpression, [c.fol() for c in self.conds])
396
+
397
+ if accum:
398
+ accum = ImpExpression(accum, self.consequent.fol())
399
+ else:
400
+ accum = self.consequent.fol()
401
+
402
+ for ref in self.refs[::-1]:
403
+ accum = AllExpression(ref, accum)
404
+
405
+ return accum
406
+
407
+ else:
408
+ if not self.conds:
409
+ raise Exception("Cannot convert DRS with no conditions to FOL.")
410
+ accum = reduce(AndExpression, [c.fol() for c in self.conds])
411
+ for ref in map(Variable, self._order_ref_strings(self.refs)[::-1]):
412
+ accum = ExistsExpression(ref, accum)
413
+ return accum
414
+
415
+ def _pretty(self):
416
+ refs_line = ' '.join(self._order_ref_strings(self.refs))
417
+
418
+ cond_lines = [cond for cond_line in [filter(lambda s: s.strip(), cond._pretty())
419
+ for cond in self.conds]
420
+ for cond in cond_line]
421
+ length = max([len(refs_line)] + list(map(len, cond_lines)))
422
+ drs = ([' _' + '_' * length + '_ ',
423
+ '| ' + refs_line.ljust(length) + ' |',
424
+ '|-' + '-' * length + '-|'] +
425
+ ['| ' + line.ljust(length) + ' |' for line in cond_lines] +
426
+ ['|_' + '_' * length + '_|'])
427
+ if self.consequent:
428
+ return DrtBinaryExpression._assemble_pretty(drs, DrtTokens.IMP,
429
+ self.consequent._pretty())
430
+ return drs
431
+
432
+ def _order_ref_strings(self, refs):
433
+ strings = ["%s" % ref for ref in refs]
434
+ ind_vars = []
435
+ func_vars = []
436
+ event_vars = []
437
+ other_vars = []
438
+ for s in strings:
439
+ if is_indvar(s):
440
+ ind_vars.append(s)
441
+ elif is_funcvar(s):
442
+ func_vars.append(s)
443
+ elif is_eventvar(s):
444
+ event_vars.append(s)
445
+ else:
446
+ other_vars.append(s)
447
+ return sorted(other_vars) + \
448
+ sorted(event_vars, key=lambda v: int([v[2:],-1][len(v[2:]) == 0])) + \
449
+ sorted(func_vars, key=lambda v: (v[0], int([v[1:],-1][len(v[1:])==0]))) + \
450
+ sorted(ind_vars, key=lambda v: (v[0], int([v[1:],-1][len(v[1:])==0])))
451
+
452
+ def __eq__(self, other):
453
+ r"""Defines equality modulo alphabetic variance.
454
+ If we are comparing \x.M and \y.N, then check equality of M and N[x/y]."""
455
+ if isinstance(other, DRS):
456
+ if len(self.refs) == len(other.refs):
457
+ converted_other = other
458
+ for (r1, r2) in zip(self.refs, converted_other.refs):
459
+ varex = self.make_VariableExpression(r1)
460
+ converted_other = converted_other.replace(r2, varex, True)
461
+ if self.consequent == converted_other.consequent and \
462
+ len(self.conds) == len(converted_other.conds):
463
+ for c1, c2 in zip(self.conds, converted_other.conds):
464
+ if not (c1 == c2):
465
+ return False
466
+ return True
467
+ return False
468
+
469
+ def __ne__(self, other):
470
+ return not self == other
471
+
472
+ __hash__ = Expression.__hash__
473
+
474
+ def __str__(self):
475
+ drs = '([%s],[%s])' % (','.join(self._order_ref_strings(self.refs)),
476
+ ', '.join("%s" % cond for cond in self.conds)) # map(str, self.conds)))
477
+ if self.consequent:
478
+ return DrtTokens.OPEN + drs + ' ' + DrtTokens.IMP + ' ' + \
479
+ "%s" % self.consequent + DrtTokens.CLOSE
480
+ return drs
481
+
482
+
483
+ def DrtVariableExpression(variable):
484
+ """
485
+ This is a factory method that instantiates and returns a subtype of
486
+ ``DrtAbstractVariableExpression`` appropriate for the given variable.
487
+ """
488
+ if is_indvar(variable.name):
489
+ return DrtIndividualVariableExpression(variable)
490
+ elif is_funcvar(variable.name):
491
+ return DrtFunctionVariableExpression(variable)
492
+ elif is_eventvar(variable.name):
493
+ return DrtEventVariableExpression(variable)
494
+ else:
495
+ return DrtConstantExpression(variable)
496
+
497
+
498
+ class DrtAbstractVariableExpression(DrtExpression, AbstractVariableExpression):
499
+ def fol(self):
500
+ return self
501
+
502
+ def get_refs(self, recursive=False):
503
+ """:see: AbstractExpression.get_refs()"""
504
+ return []
505
+
506
+ def _pretty(self):
507
+ s = "%s" % self
508
+ blank = ' '*len(s)
509
+ return [blank, blank, s, blank]
510
+
511
+ def eliminate_equality(self):
512
+ return self
513
+
514
+ class DrtIndividualVariableExpression(DrtAbstractVariableExpression, IndividualVariableExpression):
515
+ pass
516
+
517
+ class DrtFunctionVariableExpression(DrtAbstractVariableExpression, FunctionVariableExpression):
518
+ pass
519
+
520
+ class DrtEventVariableExpression(DrtIndividualVariableExpression, EventVariableExpression):
521
+ pass
522
+
523
+ class DrtConstantExpression(DrtAbstractVariableExpression, ConstantExpression):
524
+ pass
525
+
526
+
527
+ @python_2_unicode_compatible
528
+ class DrtProposition(DrtExpression, Expression):
529
+ def __init__(self, variable, drs):
530
+ self.variable = variable
531
+ self.drs = drs
532
+
533
+ def replace(self, variable, expression, replace_bound=False, alpha_convert=True):
534
+ if self.variable == variable:
535
+ assert isinstance(expression, DrtAbstractVariableExpression), "Can only replace a proposition label with a variable"
536
+ return DrtProposition(expression.variable, self.drs.replace(variable, expression, replace_bound, alpha_convert))
537
+ else:
538
+ return DrtProposition(self.variable, self.drs.replace(variable, expression, replace_bound, alpha_convert))
539
+
540
+ def eliminate_equality(self):
541
+ return DrtProposition(self.variable, self.drs.eliminate_equality())
542
+
543
+ def get_refs(self, recursive=False):
544
+ return (self.drs.get_refs(True) if recursive else [])
545
+
546
+ def __eq__(self, other):
547
+ return self.__class__ == other.__class__ and \
548
+ self.variable == other.variable and \
549
+ self.drs == other.drs
550
+
551
+ def __ne__(self, other):
552
+ return not self == other
553
+
554
+ __hash__ = Expression.__hash__
555
+
556
+ def fol(self):
557
+ return self.drs.fol()
558
+
559
+ def _pretty(self):
560
+ drs_s = self.drs._pretty()
561
+ blank = ' ' * len("%s" % self.variable)
562
+ return ([blank + ' ' + line for line in drs_s[:1]] +
563
+ ["%s" % self.variable + ':' + line for line in drs_s[1:2]] +
564
+ [blank + ' ' + line for line in drs_s[2:]])
565
+
566
+ def visit(self, function, combinator):
567
+ """:see: Expression.visit()"""
568
+ return combinator([function(self.drs)])
569
+
570
+ def visit_structured(self, function, combinator):
571
+ """:see: Expression.visit_structured()"""
572
+ return combinator(self.variable, function(self.drs))
573
+
574
+ def __str__(self):
575
+ return 'prop(%s, %s)' % (self.variable, self.drs)
576
+
577
+
578
+ class DrtNegatedExpression(DrtExpression, NegatedExpression):
579
+ def fol(self):
580
+ return NegatedExpression(self.term.fol())
581
+
582
+ def get_refs(self, recursive=False):
583
+ """:see: AbstractExpression.get_refs()"""
584
+ return self.term.get_refs(recursive)
585
+
586
+ def _pretty(self):
587
+ term_lines = self.term._pretty()
588
+ return ([' ' + line for line in term_lines[:2]] +
589
+ ['__ ' + line for line in term_lines[2:3]] +
590
+ [' | ' + line for line in term_lines[3:4]] +
591
+ [' ' + line for line in term_lines[4:]])
592
+
593
+ class DrtLambdaExpression(DrtExpression, LambdaExpression):
594
+ def alpha_convert(self, newvar):
595
+ """Rename all occurrences of the variable introduced by this variable
596
+ binder in the expression to ``newvar``.
597
+ :param newvar: ``Variable``, for the new variable
598
+ """
599
+ return self.__class__(newvar, self.term.replace(self.variable,
600
+ DrtVariableExpression(newvar), True))
601
+
602
+ def fol(self):
603
+ return LambdaExpression(self.variable, self.term.fol())
604
+
605
+ def _pretty(self):
606
+ variables = [self.variable]
607
+ term = self.term
608
+ while term.__class__ == self.__class__:
609
+ variables.append(term.variable)
610
+ term = term.term
611
+ var_string = ' '.join("%s" % v for v in variables) + DrtTokens.DOT
612
+ term_lines = term._pretty()
613
+ blank = ' ' * len(var_string)
614
+ return ([' ' + blank + line for line in term_lines[:1]] +
615
+ [' \ ' + blank + line for line in term_lines[1:2]] +
616
+ [' /\ ' + var_string + line for line in term_lines[2:3]] +
617
+ [' ' + blank + line for line in term_lines[3:]])
618
+
619
+ class DrtBinaryExpression(DrtExpression, BinaryExpression):
620
+ def get_refs(self, recursive=False):
621
+ """:see: AbstractExpression.get_refs()"""
622
+ return self.first.get_refs(True) + self.second.get_refs(True) if recursive else []
623
+
624
+ def _pretty(self):
625
+ return DrtBinaryExpression._assemble_pretty(self._pretty_subex(self.first), self.getOp(), self._pretty_subex(self.second))
626
+
627
+ @staticmethod
628
+ def _assemble_pretty(first_lines, op, second_lines):
629
+ max_lines = max(len(first_lines), len(second_lines))
630
+ first_lines = _pad_vertically(first_lines, max_lines)
631
+ second_lines = _pad_vertically(second_lines, max_lines)
632
+ blank = ' ' * len(op)
633
+ first_second_lines = list(zip(first_lines, second_lines))
634
+ return ([' ' + first_line + ' ' + blank + ' ' + second_line + ' ' for first_line, second_line in first_second_lines[:2]] +
635
+ ['(' + first_line + ' ' + op + ' ' + second_line + ')' for first_line, second_line in first_second_lines[2:3]] +
636
+ [' ' + first_line + ' ' + blank + ' ' + second_line + ' ' for first_line, second_line in first_second_lines[3:]])
637
+
638
+ def _pretty_subex(self, subex):
639
+ return subex._pretty()
640
+
641
+ class DrtBooleanExpression(DrtBinaryExpression, BooleanExpression):
642
+ pass
643
+
644
+ class DrtOrExpression(DrtBooleanExpression, OrExpression):
645
+ def fol(self):
646
+ return OrExpression(self.first.fol(), self.second.fol())
647
+
648
+ def _pretty_subex(self, subex):
649
+ if isinstance(subex, DrtOrExpression):
650
+ return [line[1:-1] for line in subex._pretty()]
651
+ return DrtBooleanExpression._pretty_subex(self, subex)
652
+
653
+ class DrtEqualityExpression(DrtBinaryExpression, EqualityExpression):
654
+ def fol(self):
655
+ return EqualityExpression(self.first.fol(), self.second.fol())
656
+
657
+ @python_2_unicode_compatible
658
+ class DrtConcatenation(DrtBooleanExpression):
659
+ """DRS of the form '(DRS + DRS)'"""
660
+ def __init__(self, first, second, consequent=None):
661
+ DrtBooleanExpression.__init__(self, first, second)
662
+ self.consequent = consequent
663
+
664
+ def replace(self, variable, expression, replace_bound=False, alpha_convert=True):
665
+ """Replace all instances of variable v with expression E in self,
666
+ where v is free in self."""
667
+ first = self.first
668
+ second = self.second
669
+ consequent = self.consequent
670
+
671
+ # If variable is bound
672
+ if variable in self.get_refs():
673
+ if replace_bound:
674
+ first = first.replace(variable, expression, replace_bound, alpha_convert)
675
+ second = second.replace(variable, expression, replace_bound, alpha_convert)
676
+ if consequent:
677
+ consequent = consequent.replace(variable, expression, replace_bound, alpha_convert)
678
+ else:
679
+ if alpha_convert:
680
+ # alpha convert every ref that is free in 'expression'
681
+ for ref in (set(self.get_refs(True)) & expression.free()):
682
+ v = DrtVariableExpression(unique_variable(ref))
683
+ first = first.replace(ref, v, True, alpha_convert)
684
+ second = second.replace(ref, v, True, alpha_convert)
685
+ if consequent:
686
+ consequent = consequent.replace(ref, v, True, alpha_convert)
687
+
688
+ first = first.replace(variable, expression, replace_bound, alpha_convert)
689
+ second = second.replace(variable, expression, replace_bound, alpha_convert)
690
+ if consequent:
691
+ consequent = consequent.replace(variable, expression, replace_bound, alpha_convert)
692
+
693
+ return self.__class__(first, second, consequent)
694
+
695
+ def eliminate_equality(self):
696
+ #TODO: at some point. for now, simplify.
697
+ drs = self.simplify()
698
+ assert not isinstance(drs, DrtConcatenation)
699
+ return drs.eliminate_equality()
700
+
701
+ def simplify(self):
702
+ first = self.first.simplify()
703
+ second = self.second.simplify()
704
+ consequent = (self.consequent.simplify() if self.consequent else None)
705
+
706
+ if isinstance(first, DRS) and isinstance(second, DRS):
707
+ # For any ref that is in both 'first' and 'second'
708
+ for ref in (set(first.get_refs(True)) & set(second.get_refs(True))):
709
+ # alpha convert the ref in 'second' to prevent collision
710
+ newvar = DrtVariableExpression(unique_variable(ref))
711
+ second = second.replace(ref, newvar, True)
712
+
713
+ return DRS(first.refs + second.refs, first.conds + second.conds, consequent)
714
+ else:
715
+ return self.__class__(first, second, consequent)
716
+
717
+ def get_refs(self, recursive=False):
718
+ """:see: AbstractExpression.get_refs()"""
719
+ refs = self.first.get_refs(recursive) + self.second.get_refs(recursive)
720
+ if self.consequent and recursive:
721
+ refs.extend(self.consequent.get_refs(True))
722
+ return refs
723
+
724
+ def getOp(self):
725
+ return DrtTokens.DRS_CONC
726
+
727
+ def __eq__(self, other):
728
+ r"""Defines equality modulo alphabetic variance.
729
+ If we are comparing \x.M and \y.N, then check equality of M and N[x/y]."""
730
+ if isinstance(other, DrtConcatenation):
731
+ self_refs = self.get_refs()
732
+ other_refs = other.get_refs()
733
+ if len(self_refs) == len(other_refs):
734
+ converted_other = other
735
+ for (r1,r2) in zip(self_refs, other_refs):
736
+ varex = self.make_VariableExpression(r1)
737
+ converted_other = converted_other.replace(r2, varex, True)
738
+ return self.first == converted_other.first and \
739
+ self.second == converted_other.second and \
740
+ self.consequent == converted_other.consequent
741
+ return False
742
+
743
+ def __ne__(self, other):
744
+ return not self == other
745
+
746
+ __hash__ = DrtBooleanExpression.__hash__
747
+
748
+ def fol(self):
749
+ e = AndExpression(self.first.fol(), self.second.fol())
750
+ if self.consequent:
751
+ e = ImpExpression(e, self.consequent.fol())
752
+ return e
753
+
754
+ def _pretty(self):
755
+ drs = DrtBinaryExpression._assemble_pretty(self._pretty_subex(self.first),
756
+ self.getOp(),
757
+ self._pretty_subex(self.second))
758
+ if self.consequent:
759
+ drs = DrtBinaryExpression._assemble_pretty(drs, DrtTokens.IMP,
760
+ self._pretty(self.consequent))
761
+ return drs
762
+
763
+ def _pretty_subex(self, subex):
764
+ if isinstance(subex, DrtConcatenation):
765
+ return [line[1:-1] for line in subex._pretty()]
766
+ return DrtBooleanExpression._pretty_subex(self, subex)
767
+
768
+
769
+ def visit(self, function, combinator):
770
+ """:see: Expression.visit()"""
771
+ if self.consequent:
772
+ return combinator([function(self.first), function(self.second), function(self.consequent)])
773
+ else:
774
+ return combinator([function(self.first), function(self.second)])
775
+
776
+ def __str__(self):
777
+ first = self._str_subex(self.first)
778
+ second = self._str_subex(self.second)
779
+ drs = Tokens.OPEN + first + ' ' + self.getOp() \
780
+ + ' ' + second + Tokens.CLOSE
781
+ if self.consequent:
782
+ return DrtTokens.OPEN + drs + ' ' + DrtTokens.IMP + ' ' + \
783
+ "%s" % self.consequent + DrtTokens.CLOSE
784
+ return drs
785
+
786
+ def _str_subex(self, subex):
787
+ s = "%s" % subex
788
+ if isinstance(subex, DrtConcatenation) and subex.consequent is None:
789
+ return s[1:-1]
790
+ return s
791
+
792
+
793
+ class DrtApplicationExpression(DrtExpression, ApplicationExpression):
794
+ def fol(self):
795
+ return ApplicationExpression(self.function.fol(), self.argument.fol())
796
+
797
+ def get_refs(self, recursive=False):
798
+ """:see: AbstractExpression.get_refs()"""
799
+ return (self.function.get_refs(True) + self.argument.get_refs(True)
800
+ if recursive else [])
801
+
802
+ def _pretty(self):
803
+ function, args = self.uncurry()
804
+ function_lines = function._pretty()
805
+ args_lines = [arg._pretty() for arg in args]
806
+ max_lines = max(map(len, [function_lines] + args_lines))
807
+ function_lines = _pad_vertically(function_lines, max_lines)
808
+ args_lines = [_pad_vertically(arg_lines, max_lines) for arg_lines in args_lines]
809
+ func_args_lines = list(zip(function_lines, list(zip(*args_lines))))
810
+ return ([func_line + ' ' + ' '.join(args_line) + ' ' for func_line, args_line in func_args_lines[:2]] +
811
+ [func_line + '(' + ','.join(args_line) + ')' for func_line, args_line in func_args_lines[2:3]] +
812
+ [func_line + ' ' + ' '.join(args_line) + ' ' for func_line, args_line in func_args_lines[3:]])
813
+
814
+
815
+ def _pad_vertically(lines, max_lines):
816
+ pad_line = [' ' * len(lines[0])]
817
+ return lines + pad_line * (max_lines - len(lines))
818
+
819
+
820
+ @python_2_unicode_compatible
821
+ class PossibleAntecedents(list, DrtExpression, Expression):
822
+ def free(self):
823
+ """Set of free variables."""
824
+ return set(self)
825
+
826
+ def replace(self, variable, expression, replace_bound=False, alpha_convert=True):
827
+ """Replace all instances of variable v with expression E in self,
828
+ where v is free in self."""
829
+ result = PossibleAntecedents()
830
+ for item in self:
831
+ if item == variable:
832
+ self.append(expression)
833
+ else:
834
+ self.append(item)
835
+ return result
836
+
837
+ def _pretty(self):
838
+ s = "%s" % self
839
+ blank = ' ' * len(s)
840
+ return [blank, blank, s]
841
+
842
+ def __str__(self):
843
+ return '[' + ','.join("%s" % it for it in self) + ']'
844
+
845
+
846
+ class AnaphoraResolutionException(Exception):
847
+ pass
848
+
849
+
850
+ def resolve_anaphora(expression, trail=[]):
851
+ if isinstance(expression, ApplicationExpression):
852
+ if expression.is_pronoun_function():
853
+ possible_antecedents = PossibleAntecedents()
854
+ for ancestor in trail:
855
+ for ref in ancestor.get_refs():
856
+ refex = expression.make_VariableExpression(ref)
857
+
858
+ #==========================================================
859
+ # Don't allow resolution to itself or other types
860
+ #==========================================================
861
+ if refex.__class__ == expression.argument.__class__ and \
862
+ not (refex == expression.argument):
863
+ possible_antecedents.append(refex)
864
+
865
+ if len(possible_antecedents) == 1:
866
+ resolution = possible_antecedents[0]
867
+ else:
868
+ resolution = possible_antecedents
869
+ return expression.make_EqualityExpression(expression.argument, resolution)
870
+ else:
871
+ r_function = resolve_anaphora(expression.function, trail + [expression])
872
+ r_argument = resolve_anaphora(expression.argument, trail + [expression])
873
+ return expression.__class__(r_function, r_argument)
874
+
875
+ elif isinstance(expression, DRS):
876
+ r_conds = []
877
+ for cond in expression.conds:
878
+ r_cond = resolve_anaphora(cond, trail + [expression])
879
+
880
+ # if the condition is of the form '(x = [])' then raise exception
881
+ if isinstance(r_cond, EqualityExpression):
882
+ if isinstance(r_cond.first, PossibleAntecedents):
883
+ #Reverse the order so that the variable is on the left
884
+ temp = r_cond.first
885
+ r_cond.first = r_cond.second
886
+ r_cond.second = temp
887
+ if isinstance(r_cond.second, PossibleAntecedents):
888
+ if not r_cond.second:
889
+ raise AnaphoraResolutionException("Variable '%s' does not "
890
+ "resolve to anything." % r_cond.first)
891
+
892
+ r_conds.append(r_cond)
893
+ if expression.consequent:
894
+ consequent = resolve_anaphora(expression.consequent, trail + [expression])
895
+ else:
896
+ consequent = None
897
+ return expression.__class__(expression.refs, r_conds, consequent)
898
+
899
+ elif isinstance(expression, AbstractVariableExpression):
900
+ return expression
901
+
902
+ elif isinstance(expression, NegatedExpression):
903
+ return expression.__class__(resolve_anaphora(expression.term, trail + [expression]))
904
+
905
+ elif isinstance(expression, DrtConcatenation):
906
+ if expression.consequent:
907
+ consequent = resolve_anaphora(expression.consequent, trail + [expression])
908
+ else:
909
+ consequent = None
910
+ return expression.__class__(resolve_anaphora(expression.first, trail + [expression]),
911
+ resolve_anaphora(expression.second, trail + [expression]),
912
+ consequent)
913
+
914
+ elif isinstance(expression, BinaryExpression):
915
+ return expression.__class__(resolve_anaphora(expression.first, trail + [expression]),
916
+ resolve_anaphora(expression.second, trail + [expression]))
917
+
918
+ elif isinstance(expression, LambdaExpression):
919
+ return expression.__class__(expression.variable, resolve_anaphora(expression.term, trail + [expression]))
920
+
921
+
922
+ class DrsDrawer(object):
923
+ BUFFER = 3 #Space between elements
924
+ TOPSPACE = 10 #Space above whole DRS
925
+ OUTERSPACE = 6 #Space to the left, right, and bottom of the whle DRS
926
+
927
+ def __init__(self, drs, size_canvas=True, canvas=None):
928
+ """
929
+ :param drs: ``DrtExpression``, The DRS to be drawn
930
+ :param size_canvas: bool, True if the canvas size should be the exact size of the DRS
931
+ :param canvas: ``Canvas`` The canvas on which to draw the DRS. If none is given, create a new canvas.
932
+ """
933
+ master = None
934
+ if not canvas:
935
+ master = Tk()
936
+ master.title("DRT")
937
+
938
+ font = Font(family='helvetica', size=12)
939
+
940
+ if size_canvas:
941
+ canvas = Canvas(master, width=0, height=0)
942
+ canvas.font = font
943
+ self.canvas = canvas
944
+ (right, bottom) = self._visit(drs, self.OUTERSPACE, self.TOPSPACE)
945
+
946
+ width = max(right+self.OUTERSPACE, 100)
947
+ height = bottom+self.OUTERSPACE
948
+ canvas = Canvas(master, width=width, height=height)#, bg='white')
949
+ else:
950
+ canvas = Canvas(master, width=300, height=300)
951
+
952
+ canvas.pack()
953
+ canvas.font = font
954
+
955
+ self.canvas = canvas
956
+ self.drs = drs
957
+ self.master = master
958
+
959
+ def _get_text_height(self):
960
+ """Get the height of a line of text"""
961
+ return self.canvas.font.metrics("linespace")
962
+
963
+ def draw(self, x=OUTERSPACE, y=TOPSPACE):
964
+ """Draw the DRS"""
965
+ self._handle(self.drs, self._draw_command, x, y)
966
+
967
+ if self.master and not in_idle():
968
+ self.master.mainloop()
969
+ else:
970
+ return self._visit(self.drs, x, y)
971
+
972
+ def _visit(self, expression, x, y):
973
+ """
974
+ Return the bottom-rightmost point without actually drawing the item
975
+
976
+ :param expression: the item to visit
977
+ :param x: the top of the current drawing area
978
+ :param y: the left side of the current drawing area
979
+ :return: the bottom-rightmost point
980
+ """
981
+ return self._handle(expression, self._visit_command, x, y)
982
+
983
+ def _draw_command(self, item, x, y):
984
+ """
985
+ Draw the given item at the given location
986
+
987
+ :param item: the item to draw
988
+ :param x: the top of the current drawing area
989
+ :param y: the left side of the current drawing area
990
+ :return: the bottom-rightmost point
991
+ """
992
+ if isinstance(item, string_types):
993
+ self.canvas.create_text(x, y, anchor='nw', font=self.canvas.font, text=item)
994
+ elif isinstance(item, tuple):
995
+ # item is the lower-right of a box
996
+ (right, bottom) = item
997
+ self.canvas.create_rectangle(x, y, right, bottom)
998
+ horiz_line_y = y + self._get_text_height() + (self.BUFFER * 2) #the line separating refs from conds
999
+ self.canvas.create_line(x, horiz_line_y, right, horiz_line_y)
1000
+
1001
+ return self._visit_command(item, x, y)
1002
+
1003
+ def _visit_command(self, item, x, y):
1004
+ """
1005
+ Return the bottom-rightmost point without actually drawing the item
1006
+
1007
+ :param item: the item to visit
1008
+ :param x: the top of the current drawing area
1009
+ :param y: the left side of the current drawing area
1010
+ :return: the bottom-rightmost point
1011
+ """
1012
+ if isinstance(item, string_types):
1013
+ return (x + self.canvas.font.measure(item), y + self._get_text_height())
1014
+ elif isinstance(item, tuple):
1015
+ return item
1016
+
1017
+ def _handle(self, expression, command, x=0, y=0):
1018
+ """
1019
+ :param expression: the expression to handle
1020
+ :param command: the function to apply, either _draw_command or _visit_command
1021
+ :param x: the top of the current drawing area
1022
+ :param y: the left side of the current drawing area
1023
+ :return: the bottom-rightmost point
1024
+ """
1025
+ if command == self._visit_command:
1026
+ #if we don't need to draw the item, then we can use the cached values
1027
+ try:
1028
+ #attempt to retrieve cached values
1029
+ right = expression._drawing_width + x
1030
+ bottom = expression._drawing_height + y
1031
+ return (right, bottom)
1032
+ except AttributeError:
1033
+ #the values have not been cached yet, so compute them
1034
+ pass
1035
+
1036
+ if isinstance(expression, DrtAbstractVariableExpression):
1037
+ factory = self._handle_VariableExpression
1038
+ elif isinstance(expression, DRS):
1039
+ factory = self._handle_DRS
1040
+ elif isinstance(expression, DrtNegatedExpression):
1041
+ factory = self._handle_NegatedExpression
1042
+ elif isinstance(expression, DrtLambdaExpression):
1043
+ factory = self._handle_LambdaExpression
1044
+ elif isinstance(expression, BinaryExpression):
1045
+ factory = self._handle_BinaryExpression
1046
+ elif isinstance(expression, DrtApplicationExpression):
1047
+ factory = self._handle_ApplicationExpression
1048
+ elif isinstance(expression, PossibleAntecedents):
1049
+ factory = self._handle_VariableExpression
1050
+ elif isinstance(expression, DrtProposition):
1051
+ factory = self._handle_DrtProposition
1052
+ else:
1053
+ raise Exception(expression.__class__.__name__)
1054
+
1055
+ (right, bottom) = factory(expression, command, x, y)
1056
+
1057
+ #cache the values
1058
+ expression._drawing_width = right - x
1059
+ expression._drawing_height = bottom - y
1060
+
1061
+ return (right, bottom)
1062
+
1063
+ def _handle_VariableExpression(self, expression, command, x, y):
1064
+ return command("%s" % expression, x, y)
1065
+
1066
+ def _handle_NegatedExpression(self, expression, command, x, y):
1067
+ # Find the width of the negation symbol
1068
+ right = self._visit_command(DrtTokens.NOT, x, y)[0]
1069
+
1070
+ # Handle term
1071
+ (right, bottom) = self._handle(expression.term, command, right, y)
1072
+
1073
+ # Handle variables now that we know the y-coordinate
1074
+ command(DrtTokens.NOT, x, self._get_centered_top(y, bottom - y, self._get_text_height()))
1075
+
1076
+ return (right, bottom)
1077
+
1078
+ def _handle_DRS(self, expression, command, x, y):
1079
+ left = x + self.BUFFER #indent the left side
1080
+ bottom = y + self.BUFFER #indent the top
1081
+
1082
+ # Handle Discourse Referents
1083
+ if expression.refs:
1084
+ refs = ' '.join("%s"%r for r in expression.refs)
1085
+ else:
1086
+ refs = ' '
1087
+ (max_right, bottom) = command(refs, left, bottom)
1088
+ bottom += (self.BUFFER * 2)
1089
+
1090
+ # Handle Conditions
1091
+ if expression.conds:
1092
+ for cond in expression.conds:
1093
+ (right, bottom) = self._handle(cond, command, left, bottom)
1094
+ max_right = max(max_right, right)
1095
+ bottom += self.BUFFER
1096
+ else:
1097
+ bottom += self._get_text_height() + self.BUFFER
1098
+
1099
+ # Handle Box
1100
+ max_right += self.BUFFER
1101
+ return command((max_right, bottom), x, y)
1102
+
1103
+ def _handle_ApplicationExpression(self, expression, command, x, y):
1104
+ function, args = expression.uncurry()
1105
+ if not isinstance(function, DrtAbstractVariableExpression):
1106
+ #It's not a predicate expression ("P(x,y)"), so leave arguments curried
1107
+ function = expression.function
1108
+ args = [expression.argument]
1109
+
1110
+ # Get the max bottom of any element on the line
1111
+ function_bottom = self._visit(function, x, y)[1]
1112
+ max_bottom = max([function_bottom] + [self._visit(arg, x, y)[1] for arg in args])
1113
+
1114
+ line_height = max_bottom - y
1115
+
1116
+ # Handle 'function'
1117
+ function_drawing_top = self._get_centered_top(y, line_height, function._drawing_height)
1118
+ right = self._handle(function, command, x, function_drawing_top)[0]
1119
+
1120
+ # Handle open paren
1121
+ centred_string_top = self._get_centered_top(y, line_height, self._get_text_height())
1122
+ right = command(DrtTokens.OPEN, right, centred_string_top)[0]
1123
+
1124
+ # Handle each arg
1125
+ for (i,arg) in enumerate(args):
1126
+ arg_drawing_top = self._get_centered_top(y, line_height, arg._drawing_height)
1127
+ right = self._handle(arg, command, right, arg_drawing_top)[0]
1128
+
1129
+ if i+1 < len(args):
1130
+ #since it's not the last arg, add a comma
1131
+ right = command(DrtTokens.COMMA + ' ', right, centred_string_top)[0]
1132
+
1133
+ # Handle close paren
1134
+ right = command(DrtTokens.CLOSE, right, centred_string_top)[0]
1135
+
1136
+ return (right, max_bottom)
1137
+
1138
+ def _handle_LambdaExpression(self, expression, command, x, y):
1139
+ # Find the width of the lambda symbol and abstracted variables
1140
+ variables = DrtTokens.LAMBDA + "%s" % expression.variable + DrtTokens.DOT
1141
+ right = self._visit_command(variables, x, y)[0]
1142
+
1143
+ # Handle term
1144
+ (right, bottom) = self._handle(expression.term, command, right, y)
1145
+
1146
+ # Handle variables now that we know the y-coordinate
1147
+ command(variables, x, self._get_centered_top(y, bottom - y, self._get_text_height()))
1148
+
1149
+ return (right, bottom)
1150
+
1151
+ def _handle_BinaryExpression(self, expression, command, x, y):
1152
+ # Get the full height of the line, based on the operands
1153
+ first_height = self._visit(expression.first, 0, 0)[1]
1154
+ second_height = self._visit(expression.second, 0, 0)[1]
1155
+ line_height = max(first_height, second_height)
1156
+
1157
+ # Handle open paren
1158
+ centred_string_top = self._get_centered_top(y, line_height, self._get_text_height())
1159
+ right = command(DrtTokens.OPEN, x, centred_string_top)[0]
1160
+
1161
+ # Handle the first operand
1162
+ first_height = expression.first._drawing_height
1163
+ (right, first_bottom) = self._handle(expression.first, command, right, self._get_centered_top(y, line_height, first_height))
1164
+
1165
+ # Handle the operator
1166
+ right = command(' %s ' % expression.getOp(), right, centred_string_top)[0]
1167
+
1168
+ # Handle the second operand
1169
+ second_height = expression.second._drawing_height
1170
+ (right, second_bottom) = self._handle(expression.second, command, right, self._get_centered_top(y, line_height, second_height))
1171
+
1172
+ # Handle close paren
1173
+ right = command(DrtTokens.CLOSE, right, centred_string_top)[0]
1174
+
1175
+ return (right, max(first_bottom, second_bottom))
1176
+
1177
+ def _handle_DrtProposition(self, expression, command, x, y):
1178
+ # Find the width of the negation symbol
1179
+ right = command(expression.variable, x, y)[0]
1180
+
1181
+ # Handle term
1182
+ (right, bottom) = self._handle(expression.term, command, right, y)
1183
+
1184
+ return (right, bottom)
1185
+
1186
+ def _get_centered_top(self, top, full_height, item_height):
1187
+ """Get the y-coordinate of the point that a figure should start at if
1188
+ its height is 'item_height' and it needs to be centered in an area that
1189
+ starts at 'top' and is 'full_height' tall."""
1190
+ return top + (full_height - item_height) / 2
1191
+
1192
+
1193
+ def demo():
1194
+ print('='*20 + 'TEST PARSE' + '='*20)
1195
+ dexpr = DrtExpression.fromstring
1196
+ print(dexpr(r'([x,y],[sees(x,y)])'))
1197
+ print(dexpr(r'([x],[man(x), walks(x)])'))
1198
+ print(dexpr(r'\x.\y.([],[sees(x,y)])'))
1199
+ print(dexpr(r'\x.([],[walks(x)])(john)'))
1200
+ print(dexpr(r'(([x],[walks(x)]) + ([y],[runs(y)]))'))
1201
+ print(dexpr(r'(([],[walks(x)]) -> ([],[runs(x)]))'))
1202
+ print(dexpr(r'([x],[PRO(x), sees(John,x)])'))
1203
+ print(dexpr(r'([x],[man(x), -([],[walks(x)])])'))
1204
+ print(dexpr(r'([],[(([x],[man(x)]) -> ([],[walks(x)]))])'))
1205
+
1206
+ print('='*20 + 'Test fol()' + '='*20)
1207
+ print(dexpr(r'([x,y],[sees(x,y)])').fol())
1208
+
1209
+ print('='*20 + 'Test alpha conversion and lambda expression equality' + '='*20)
1210
+ e1 = dexpr(r'\x.([],[P(x)])')
1211
+ print(e1)
1212
+ e2 = e1.alpha_convert(Variable('z'))
1213
+ print(e2)
1214
+ print(e1 == e2)
1215
+
1216
+ print('='*20 + 'Test resolve_anaphora()' + '='*20)
1217
+ print(resolve_anaphora(dexpr(r'([x,y,z],[dog(x), cat(y), walks(z), PRO(z)])')))
1218
+ print(resolve_anaphora(dexpr(r'([],[(([x],[dog(x)]) -> ([y],[walks(y), PRO(y)]))])')))
1219
+ print(resolve_anaphora(dexpr(r'(([x,y],[]) + ([],[PRO(x)]))')))
1220
+
1221
+ print('='*20 + 'Test pretty_print()' + '='*20)
1222
+ dexpr(r"([],[])").pretty_print()
1223
+ dexpr(r"([],[([x],[big(x), dog(x)]) -> ([],[bark(x)]) -([x],[walk(x)])])").pretty_print()
1224
+ dexpr(r"([x,y],[x=y]) + ([z],[dog(z), walk(z)])").pretty_print()
1225
+ dexpr(r"([],[([x],[]) | ([y],[]) | ([z],[dog(z), walk(z)])])").pretty_print()
1226
+ dexpr(r"\P.\Q.(([x],[]) + P(x) + Q(x))(\x.([],[dog(x)]))").pretty_print()
1227
+
1228
+
1229
+ def test_draw():
1230
+ try:
1231
+ from six.moves.tkinter import Tk
1232
+ except ImportError:
1233
+ from nose import SkipTest
1234
+ raise SkipTest("tkinter is required, but it's not available.")
1235
+
1236
+ expressions = [
1237
+ r'x',
1238
+ r'([],[])',
1239
+ r'([x],[])',
1240
+ r'([x],[man(x)])',
1241
+
1242
+ r'([x,y],[sees(x,y)])',
1243
+ r'([x],[man(x), walks(x)])',
1244
+ r'\x.([],[man(x), walks(x)])',
1245
+ r'\x y.([],[sees(x,y)])',
1246
+ r'([],[(([],[walks(x)]) + ([],[runs(x)]))])',
1247
+
1248
+ r'([x],[man(x), -([],[walks(x)])])',
1249
+ r'([],[(([x],[man(x)]) -> ([],[walks(x)]))])'
1250
+ ]
1251
+
1252
+ for e in expressions:
1253
+ d = DrtExpression.fromstring(e)
1254
+ d.draw()
1255
+
1256
+
1257
+ if __name__ == '__main__':
1258
+ demo()