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,784 +1,790 @@
1
- # Natural Language Toolkit: Models for first-order languages with lambda
2
- #
3
- # Copyright (C) 2001-2015 NLTK Project
4
- # Author: Ewan Klein <ewan@inf.ed.ac.uk>,
5
- # URL: <http://nltk.sourceforge.net>
6
- # For license information, see LICENSE.TXT
7
-
8
- #TODO:
9
- #- fix tracing
10
- #- fix iterator-based approach to existentials
11
-
12
- """
13
- This module provides data structures for representing first-order
14
- models.
15
- """
16
- from __future__ import print_function, unicode_literals
17
-
18
- from pprint import pformat
19
- import inspect
20
- import textwrap
21
- import re
22
-
23
- from nltk.decorators import decorator # this used in code that is commented out
24
- from nltk.compat import string_types, python_2_unicode_compatible
25
-
26
- from nltk.sem.logic import (AbstractVariableExpression, AllExpression, Expression,
27
- AndExpression, ApplicationExpression, EqualityExpression,
28
- ExistsExpression, IffExpression, ImpExpression,
29
- IndividualVariableExpression, LambdaExpression,
30
- NegatedExpression, OrExpression,
31
- Variable, is_indvar)
32
-
33
-
34
- class Error(Exception): pass
35
-
36
- class Undefined(Error): pass
37
-
38
- def trace(f, *args, **kw):
39
- argspec = inspect.getargspec(f)
40
- d = dict(zip(argspec[0], args))
41
- if d.pop('trace', None):
42
- print()
43
- for item in d.items():
44
- print("%s => %s" % item)
45
- return f(*args, **kw)
46
-
47
- def is_rel(s):
48
- """
49
- Check whether a set represents a relation (of any arity).
50
-
51
- :param s: a set containing tuples of str elements
52
- :type s: set
53
- :rtype: bool
54
- """
55
- # we have the empty relation, i.e. set()
56
- if len(s) == 0:
57
- return True
58
- # all the elements are tuples of the same length
59
- elif all(isinstance(el, tuple) for el in s) and len(max(s))==len(min(s)):
60
- return True
61
- else:
62
- raise ValueError("Set %r contains sequences of different lengths" % s)
63
-
64
- def set2rel(s):
65
- """
66
- Convert a set containing individuals (strings or numbers) into a set of
67
- unary tuples. Any tuples of strings already in the set are passed through
68
- unchanged.
69
-
70
- For example:
71
- - set(['a', 'b']) => set([('a',), ('b',)])
72
- - set([3, 27]) => set([('3',), ('27',)])
73
-
74
- :type s: set
75
- :rtype: set of tuple of str
76
- """
77
- new = set()
78
- for elem in s:
79
- if isinstance(elem, string_types):
80
- new.add((elem,))
81
- elif isinstance(elem, int):
82
- new.add((str(elem,)))
83
- else:
84
- new.add(elem)
85
- return new
86
-
87
- def arity(rel):
88
- """
89
- Check the arity of a relation.
90
- :type rel: set of tuples
91
- :rtype: int of tuple of str
92
- """
93
- if len(rel) == 0:
94
- return 0
95
- return len(list(rel)[0])
96
-
97
-
98
- @python_2_unicode_compatible
99
- class Valuation(dict):
100
- """
101
- A dictionary which represents a model-theoretic Valuation of non-logical constants.
102
- Keys are strings representing the constants to be interpreted, and values correspond
103
- to individuals (represented as strings) and n-ary relations (represented as sets of tuples
104
- of strings).
105
-
106
- An instance of ``Valuation`` will raise a KeyError exception (i.e.,
107
- just behave like a standard dictionary) if indexed with an expression that
108
- is not in its list of symbols.
109
- """
110
- def __init__(self, xs):
111
- """
112
- :param xs: a list of (symbol, value) pairs.
113
- """
114
- super(Valuation, self).__init__()
115
- for (sym, val) in xs:
116
- if isinstance(val, string_types) or isinstance(val, bool):
117
- self[sym] = val
118
- elif isinstance(val, set):
119
- self[sym] = set2rel(val)
120
- else:
121
- msg = textwrap.fill("Error in initializing Valuation. "
122
- "Unrecognized value for symbol '%s':\n%s" % (sym, val), width=66)
123
-
124
- raise ValueError(msg)
125
-
126
- def __getitem__(self, key):
127
- if key in self:
128
- return dict.__getitem__(self, key)
129
- else:
130
- raise Undefined("Unknown expression: '%s'" % key)
131
-
132
- def __str__(self):
133
- return pformat(self)
134
-
135
- @property
136
- def domain(self):
137
- """Set-theoretic domain of the value-space of a Valuation."""
138
- dom = []
139
- for val in self.values():
140
- if isinstance(val, string_types):
141
- dom.append(val)
142
- elif not isinstance(val, bool):
143
- dom.extend([elem for tuple_ in val for elem in tuple_ if elem is not None])
144
- return set(dom)
145
-
146
- @property
147
- def symbols(self):
148
- """The non-logical constants which the Valuation recognizes."""
149
- return sorted(self.keys())
150
-
151
- @classmethod
152
- def fromstring(cls, s):
153
- return read_valuation(s)
154
-
155
-
156
- ##########################################
157
- # REs used by the _read_valuation function
158
- ##########################################
159
- _VAL_SPLIT_RE = re.compile(r'\s*=+>\s*')
160
- _ELEMENT_SPLIT_RE = re.compile(r'\s*,\s*')
161
- _TUPLES_RE = re.compile(r"""\s*
162
- (\([^)]+\)) # tuple-expression
163
- \s*""", re.VERBOSE)
164
-
165
- def _read_valuation_line(s):
166
- """
167
- Read a line in a valuation file.
168
-
169
- Lines are expected to be of the form::
170
-
171
- noosa => n
172
- girl => {g1, g2}
173
- chase => {(b1, g1), (b2, g1), (g1, d1), (g2, d2)}
174
-
175
- :param s: input line
176
- :type s: str
177
- :return: a pair (symbol, value)
178
- :rtype: tuple
179
- """
180
- pieces = _VAL_SPLIT_RE.split(s)
181
- symbol = pieces[0]
182
- value = pieces[1]
183
- # check whether the value is meant to be a set
184
- if value.startswith('{'):
185
- value = value[1:-1]
186
- tuple_strings = _TUPLES_RE.findall(value)
187
- # are the set elements tuples?
188
- if tuple_strings:
189
- set_elements = []
190
- for ts in tuple_strings:
191
- ts = ts[1:-1]
192
- element = tuple(_ELEMENT_SPLIT_RE.split(ts))
193
- set_elements.append(element)
194
- else:
195
- set_elements = _ELEMENT_SPLIT_RE.split(value)
196
- value = set(set_elements)
197
- return symbol, value
198
-
199
- def read_valuation(s, encoding=None):
200
- """
201
- Convert a valuation string into a valuation.
202
-
203
- :param s: a valuation string
204
- :type s: str
205
- :param encoding: the encoding of the input string, if it is binary
206
- :type encoding: str
207
- :return: a ``nltk.sem`` valuation
208
- :rtype: Valuation
209
- """
210
- if encoding is not None:
211
- s = s.decode(encoding)
212
- statements = []
213
- for linenum, line in enumerate(s.splitlines()):
214
- line = line.strip()
215
- if line.startswith('#') or line=='': continue
216
- try:
217
- statements.append(_read_valuation_line(line))
218
- except ValueError:
219
- raise ValueError('Unable to parse line %s: %s' % (linenum, line))
220
- return Valuation(statements)
221
-
222
-
223
- @python_2_unicode_compatible
224
- class Assignment(dict):
225
- """
226
- A dictionary which represents an assignment of values to variables.
227
-
228
- An assigment can only assign values from its domain.
229
-
230
- If an unknown expression *a* is passed to a model *M*\ 's
231
- interpretation function *i*, *i* will first check whether *M*\ 's
232
- valuation assigns an interpretation to *a* as a constant, and if
233
- this fails, *i* will delegate the interpretation of *a* to
234
- *g*. *g* only assigns values to individual variables (i.e.,
235
- members of the class ``IndividualVariableExpression`` in the ``logic``
236
- module. If a variable is not assigned a value by *g*, it will raise
237
- an ``Undefined`` exception.
238
-
239
- A variable *Assignment* is a mapping from individual variables to
240
- entities in the domain. Individual variables are usually indicated
241
- with the letters ``'x'``, ``'y'``, ``'w'`` and ``'z'``, optionally
242
- followed by an integer (e.g., ``'x0'``, ``'y332'``). Assignments are
243
- created using the ``Assignment`` constructor, which also takes the
244
- domain as a parameter.
245
-
246
- >>> from nltk.sem.evaluate import Assignment
247
- >>> dom = set(['u1', 'u2', 'u3', 'u4'])
248
- >>> g3 = Assignment(dom, [('x', 'u1'), ('y', 'u2')])
249
- >>> g3 == {'x': 'u1', 'y': 'u2'}
250
- True
251
-
252
- There is also a ``print`` format for assignments which uses a notation
253
- closer to that in logic textbooks:
254
-
255
- >>> print(g3)
256
- g[u1/x][u2/y]
257
-
258
- It is also possible to update an assignment using the ``add`` method:
259
-
260
- >>> dom = set(['u1', 'u2', 'u3', 'u4'])
261
- >>> g4 = Assignment(dom)
262
- >>> g4.add('x', 'u1')
263
- {'x': 'u1'}
264
-
265
- With no arguments, ``purge()`` is equivalent to ``clear()`` on a dictionary:
266
-
267
- >>> g4.purge()
268
- >>> g4
269
- {}
270
-
271
- :param domain: the domain of discourse
272
- :type domain: set
273
- :param assign: a list of (varname, value) associations
274
- :type assign: list
275
- """
276
-
277
- def __init__(self, domain, assign=None):
278
- super(Assignment, self).__init__()
279
- self.domain = domain
280
- if assign:
281
- for (var, val) in assign:
282
- assert val in self.domain,\
283
- "'%s' is not in the domain: %s" % (val, self.domain)
284
- assert is_indvar(var),\
285
- "Wrong format for an Individual Variable: '%s'" % var
286
- self[var] = val
287
- self.variant = None
288
- self._addvariant()
289
-
290
- def __getitem__(self, key):
291
- if key in self:
292
- return dict.__getitem__(self, key)
293
- else:
294
- raise Undefined("Not recognized as a variable: '%s'" % key)
295
-
296
- def copy(self):
297
- new = Assignment(self.domain)
298
- new.update(self)
299
- return new
300
-
301
- def purge(self, var=None):
302
- """
303
- Remove one or all keys (i.e. logic variables) from an
304
- assignment, and update ``self.variant``.
305
-
306
- :param var: a Variable acting as a key for the assignment.
307
- """
308
- if var:
309
- del self[var]
310
- else:
311
- self.clear()
312
- self._addvariant()
313
- return None
314
-
315
- def __str__(self):
316
- """
317
- Pretty printing for assignments. {'x', 'u'} appears as 'g[u/x]'
318
- """
319
- gstring = "g"
320
- # Deterministic output for unit testing.
321
- variant = sorted(self.variant)
322
- for (val, var) in variant:
323
- gstring += "[%s/%s]" % (val, var)
324
- return gstring
325
-
326
- def _addvariant(self):
327
- """
328
- Create a more pretty-printable version of the assignment.
329
- """
330
- list_ = []
331
- for item in self.items():
332
- pair = (item[1], item[0])
333
- list_.append(pair)
334
- self.variant = list_
335
- return None
336
-
337
- def add(self, var, val):
338
- """
339
- Add a new variable-value pair to the assignment, and update
340
- ``self.variant``.
341
-
342
- """
343
- assert val in self.domain,\
344
- "%s is not in the domain %s" % (val, self.domain)
345
- assert is_indvar(var),\
346
- "Wrong format for an Individual Variable: '%s'" % var
347
- self[var] = val
348
- self._addvariant()
349
- return self
350
-
351
-
352
- @python_2_unicode_compatible
353
- class Model(object):
354
- """
355
- A first order model is a domain *D* of discourse and a valuation *V*.
356
-
357
- A domain *D* is a set, and a valuation *V* is a map that associates
358
- expressions with values in the model.
359
- The domain of *V* should be a subset of *D*.
360
-
361
- Construct a new ``Model``.
362
-
363
- :type domain: set
364
- :param domain: A set of entities representing the domain of discourse of the model.
365
- :type valuation: Valuation
366
- :param valuation: the valuation of the model.
367
- :param prop: If this is set, then we are building a propositional\
368
- model and don't require the domain of *V* to be subset of *D*.
369
- """
370
-
371
- def __init__(self, domain, valuation):
372
- assert isinstance(domain, set)
373
- self.domain = domain
374
- self.valuation = valuation
375
- if not domain.issuperset(valuation.domain):
376
- raise Error("The valuation domain, %s, must be a subset of the model's domain, %s"\
377
- % (valuation.domain, domain))
378
-
379
- def __repr__(self):
380
- return "(%r, %r)" % (self.domain, self.valuation)
381
-
382
- def __str__(self):
383
- return "Domain = %s,\nValuation = \n%s" % (self.domain, self.valuation)
384
-
385
- def evaluate(self, expr, g, trace=None):
386
- """
387
- Read input expressions, and provide a handler for ``satisfy``
388
- that blocks further propagation of the ``Undefined`` error.
389
- :param expr: An ``Expression`` of ``logic``.
390
- :type g: Assignment
391
- :param g: an assignment to individual variables.
392
- :rtype: bool or 'Undefined'
393
- """
394
- try:
395
- parsed = Expression.fromstring(expr)
396
- value = self.satisfy(parsed, g, trace=trace)
397
- if trace:
398
- print()
399
- print("'%s' evaluates to %s under M, %s" % (expr, value, g))
400
- return value
401
- except Undefined:
402
- if trace:
403
- print()
404
- print("'%s' is undefined under M, %s" % (expr, g))
405
- return 'Undefined'
406
-
407
-
408
- def satisfy(self, parsed, g, trace=None):
409
- """
410
- Recursive interpretation function for a formula of first-order logic.
411
-
412
- Raises an ``Undefined`` error when ``parsed`` is an atomic string
413
- but is not a symbol or an individual variable.
414
-
415
- :return: Returns a truth value or ``Undefined`` if ``parsed`` is\
416
- complex, and calls the interpretation function ``i`` if ``parsed``\
417
- is atomic.
418
-
419
- :param parsed: An expression of ``logic``.
420
- :type g: Assignment
421
- :param g: an assignment to individual variables.
422
- """
423
-
424
- if isinstance(parsed, ApplicationExpression):
425
- function, arguments = parsed.uncurry()
426
- if isinstance(function, AbstractVariableExpression):
427
- #It's a predicate expression ("P(x,y)"), so used uncurried arguments
428
- funval = self.satisfy(function, g)
429
- argvals = tuple(self.satisfy(arg, g) for arg in arguments)
430
- return argvals in funval
431
- else:
432
- #It must be a lambda expression, so use curried form
433
- funval = self.satisfy(parsed.function, g)
434
- argval = self.satisfy(parsed.argument, g)
435
- return funval[argval]
436
- elif isinstance(parsed, NegatedExpression):
437
- return not self.satisfy(parsed.term, g)
438
- elif isinstance(parsed, AndExpression):
439
- return self.satisfy(parsed.first, g) and \
440
- self.satisfy(parsed.second, g)
441
- elif isinstance(parsed, OrExpression):
442
- return self.satisfy(parsed.first, g) or \
443
- self.satisfy(parsed.second, g)
444
- elif isinstance(parsed, ImpExpression):
445
- return (not self.satisfy(parsed.first, g)) or \
446
- self.satisfy(parsed.second, g)
447
- elif isinstance(parsed, IffExpression):
448
- return self.satisfy(parsed.first, g) == \
449
- self.satisfy(parsed.second, g)
450
- elif isinstance(parsed, EqualityExpression):
451
- return self.satisfy(parsed.first, g) == \
452
- self.satisfy(parsed.second, g)
453
- elif isinstance(parsed, AllExpression):
454
- new_g = g.copy()
455
- for u in self.domain:
456
- new_g.add(parsed.variable.name, u)
457
- if not self.satisfy(parsed.term, new_g):
458
- return False
459
- return True
460
- elif isinstance(parsed, ExistsExpression):
461
- new_g = g.copy()
462
- for u in self.domain:
463
- new_g.add(parsed.variable.name, u)
464
- if self.satisfy(parsed.term, new_g):
465
- return True
466
- return False
467
- elif isinstance(parsed, LambdaExpression):
468
- cf = {}
469
- var = parsed.variable.name
470
- for u in self.domain:
471
- val = self.satisfy(parsed.term, g.add(var, u))
472
- # NB the dict would be a lot smaller if we do this:
473
- # if val: cf[u] = val
474
- # But then need to deal with cases where f(a) should yield
475
- # a function rather than just False.
476
- cf[u] = val
477
- return cf
478
- else:
479
- return self.i(parsed, g, trace)
480
-
481
- #@decorator(trace_eval)
482
- def i(self, parsed, g, trace=False):
483
- """
484
- An interpretation function.
485
-
486
- Assuming that ``parsed`` is atomic:
487
-
488
- - if ``parsed`` is a non-logical constant, calls the valuation *V*
489
- - else if ``parsed`` is an individual variable, calls assignment *g*
490
- - else returns ``Undefined``.
491
-
492
- :param parsed: an ``Expression`` of ``logic``.
493
- :type g: Assignment
494
- :param g: an assignment to individual variables.
495
- :return: a semantic value
496
- """
497
- # If parsed is a propositional letter 'p', 'q', etc, it could be in valuation.symbols
498
- # and also be an IndividualVariableExpression. We want to catch this first case.
499
- # So there is a procedural consequence to the ordering of clauses here:
500
- if parsed.variable.name in self.valuation.symbols:
501
- return self.valuation[parsed.variable.name]
502
- elif isinstance(parsed, IndividualVariableExpression):
503
- return g[parsed.variable.name]
504
-
505
- else:
506
- raise Undefined("Can't find a value for %s" % parsed)
507
-
508
- def satisfiers(self, parsed, varex, g, trace=None, nesting=0):
509
- """
510
- Generate the entities from the model's domain that satisfy an open formula.
511
-
512
- :param parsed: an open formula
513
- :type parsed: Expression
514
- :param varex: the relevant free individual variable in ``parsed``.
515
- :type varex: VariableExpression or str
516
- :param g: a variable assignment
517
- :type g: Assignment
518
- :return: a set of the entities that satisfy ``parsed``.
519
- """
520
-
521
- spacer = ' '
522
- indent = spacer + (spacer * nesting)
523
- candidates = []
524
-
525
- if isinstance(varex, string_types):
526
- var = Variable(varex)
527
- else:
528
- var = varex
529
-
530
- if var in parsed.free():
531
- if trace:
532
- print()
533
- print((spacer * nesting) + "Open formula is '%s' with assignment %s" % (parsed, g))
534
- for u in self.domain:
535
- new_g = g.copy()
536
- new_g.add(var.name, u)
537
- if trace and trace > 1:
538
- lowtrace = trace-1
539
- else:
540
- lowtrace = 0
541
- value = self.satisfy(parsed, new_g, lowtrace)
542
-
543
- if trace:
544
- print(indent + "(trying assignment %s)" % new_g)
545
-
546
- # parsed == False under g[u/var]?
547
- if value == False:
548
- if trace:
549
- print(indent + "value of '%s' under %s is False" % (parsed, new_g))
550
-
551
- # so g[u/var] is a satisfying assignment
552
- else:
553
- candidates.append(u)
554
- if trace:
555
- print(indent + "value of '%s' under %s is %s" % (parsed, new_g, value))
556
-
557
- result = set(c for c in candidates)
558
- # var isn't free in parsed
559
- else:
560
- raise Undefined("%s is not free in %s" % (var.name, parsed))
561
-
562
- return result
563
-
564
-
565
-
566
-
567
-
568
- #//////////////////////////////////////////////////////////////////////
569
- # Demo..
570
- #//////////////////////////////////////////////////////////////////////
571
- # number of spacer chars
572
- mult = 30
573
-
574
- # Demo 1: Propositional Logic
575
- #################
576
- def propdemo(trace=None):
577
- """Example of a propositional model."""
578
-
579
- global val1, dom1, m1, g1
580
- val1 = Valuation([('P', True), ('Q', True), ('R', False)])
581
- dom1 = set([])
582
- m1 = Model(dom1, val1)
583
- g1 = Assignment(dom1)
584
-
585
- print()
586
- print('*' * mult)
587
- print("Propositional Formulas Demo")
588
- print('*' * mult)
589
- print('(Propositional constants treated as nullary predicates)')
590
- print()
591
- print("Model m1:\n", m1)
592
- print('*' * mult)
593
- sentences = [
594
- '(P & Q)',
595
- '(P & R)',
596
- '- P',
597
- '- R',
598
- '- - P',
599
- '- (P & R)',
600
- '(P | R)',
601
- '(R | P)',
602
- '(R | R)',
603
- '(- P | R)',
604
- '(P | - P)',
605
- '(P -> Q)',
606
- '(P -> R)',
607
- '(R -> P)',
608
- '(P <-> P)',
609
- '(R <-> R)',
610
- '(P <-> R)',
611
- ]
612
-
613
- for sent in sentences:
614
- if trace:
615
- print()
616
- m1.evaluate(sent, g1, trace)
617
- else:
618
- print("The value of '%s' is: %s" % (sent, m1.evaluate(sent, g1)))
619
-
620
- # Demo 2: FOL Model
621
- #############
622
-
623
- def folmodel(quiet=False, trace=None):
624
- """Example of a first-order model."""
625
-
626
- global val2, v2, dom2, m2, g2
627
-
628
- v2 = [('adam', 'b1'), ('betty', 'g1'), ('fido', 'd1'),\
629
- ('girl', set(['g1', 'g2'])), ('boy', set(['b1', 'b2'])), ('dog', set(['d1'])),
630
- ('love', set([('b1', 'g1'), ('b2', 'g2'), ('g1', 'b1'), ('g2', 'b1')]))]
631
- val2 = Valuation(v2)
632
- dom2 = val2.domain
633
- m2 = Model(dom2, val2)
634
- g2 = Assignment(dom2, [('x', 'b1'), ('y', 'g2')])
635
-
636
- if not quiet:
637
- print()
638
- print('*' * mult)
639
- print("Models Demo")
640
- print("*" * mult)
641
- print("Model m2:\n", "-" * 14,"\n", m2)
642
- print("Variable assignment = ", g2)
643
-
644
- exprs = ['adam', 'boy', 'love', 'walks', 'x', 'y', 'z']
645
- parsed_exprs = [Expression.fromstring(e) for e in exprs]
646
-
647
- print()
648
- for parsed in parsed_exprs:
649
- try:
650
- print("The interpretation of '%s' in m2 is %s" % (parsed, m2.i(parsed, g2)))
651
- except Undefined:
652
- print("The interpretation of '%s' in m2 is Undefined" % parsed)
653
-
654
-
655
- applications = [('boy', ('adam')), ('walks', ('adam',)), ('love', ('adam', 'y')), ('love', ('y', 'adam'))]
656
-
657
- for (fun, args) in applications:
658
- try:
659
- funval = m2.i(Expression.fromstring(fun), g2)
660
- argsval = tuple(m2.i(Expression.fromstring(arg), g2) for arg in args)
661
- print("%s(%s) evaluates to %s" % (fun, args, argsval in funval))
662
- except Undefined:
663
- print("%s(%s) evaluates to Undefined" % (fun, args))
664
-
665
- # Demo 3: FOL
666
- #########
667
-
668
- def foldemo(trace=None):
669
- """
670
- Interpretation of closed expressions in a first-order model.
671
- """
672
- folmodel(quiet=True)
673
-
674
- print()
675
- print('*' * mult)
676
- print("FOL Formulas Demo")
677
- print('*' * mult)
678
-
679
- formulas = [
680
- 'love (adam, betty)',
681
- '(adam = mia)',
682
- '\\x. (boy(x) | girl(x))',
683
- '\\x. boy(x)(adam)',
684
- '\\x y. love(x, y)',
685
- '\\x y. love(x, y)(adam)(betty)',
686
- '\\x y. love(x, y)(adam, betty)',
687
- '\\x y. (boy(x) & love(x, y))',
688
- '\\x. exists y. (boy(x) & love(x, y))',
689
- 'exists z1. boy(z1)',
690
- 'exists x. (boy(x) & -(x = adam))',
691
- 'exists x. (boy(x) & all y. love(y, x))',
692
- 'all x. (boy(x) | girl(x))',
693
- 'all x. (girl(x) -> exists y. boy(y) & love(x, y))', #Every girl loves exists boy.
694
- 'exists x. (boy(x) & all y. (girl(y) -> love(y, x)))', #There is exists boy that every girl loves.
695
- 'exists x. (boy(x) & all y. (girl(y) -> love(x, y)))', #exists boy loves every girl.
696
- 'all x. (dog(x) -> - girl(x))',
697
- 'exists x. exists y. (love(x, y) & love(x, y))'
698
- ]
699
-
700
-
701
- for fmla in formulas:
702
- g2.purge()
703
- if trace:
704
- m2.evaluate(fmla, g2, trace)
705
- else:
706
- print("The value of '%s' is: %s" % (fmla, m2.evaluate(fmla, g2)))
707
-
708
-
709
- # Demo 3: Satisfaction
710
- #############
711
-
712
- def satdemo(trace=None):
713
- """Satisfiers of an open formula in a first order model."""
714
-
715
- print()
716
- print('*' * mult)
717
- print("Satisfiers Demo")
718
- print('*' * mult)
719
-
720
- folmodel(quiet=True)
721
-
722
- formulas = [
723
- 'boy(x)',
724
- '(x = x)',
725
- '(boy(x) | girl(x))',
726
- '(boy(x) & girl(x))',
727
- 'love(adam, x)',
728
- 'love(x, adam)',
729
- '-(x = adam)',
730
- 'exists z22. love(x, z22)',
731
- 'exists y. love(y, x)',
732
- 'all y. (girl(y) -> love(x, y))',
733
- 'all y. (girl(y) -> love(y, x))',
734
- 'all y. (girl(y) -> (boy(x) & love(y, x)))',
735
- '(boy(x) & all y. (girl(y) -> love(x, y)))',
736
- '(boy(x) & all y. (girl(y) -> love(y, x)))',
737
- '(boy(x) & exists y. (girl(y) & love(y, x)))',
738
- '(girl(x) -> dog(x))',
739
- 'all y. (dog(y) -> (x = y))',
740
- 'exists y. love(y, x)',
741
- 'exists y. (love(adam, y) & love(y, x))'
742
- ]
743
-
744
- if trace:
745
- print(m2)
746
-
747
- for fmla in formulas:
748
- print(fmla)
749
- Expression.fromstring(fmla)
750
-
751
- parsed = [Expression.fromstring(fmla) for fmla in formulas]
752
-
753
- for p in parsed:
754
- g2.purge()
755
- print("The satisfiers of '%s' are: %s" % (p, m2.satisfiers(p, 'x', g2, trace)))
756
-
757
-
758
- def demo(num=0, trace=None):
759
- """
760
- Run exists demos.
761
-
762
- - num = 1: propositional logic demo
763
- - num = 2: first order model demo (only if trace is set)
764
- - num = 3: first order sentences demo
765
- - num = 4: satisfaction of open formulas demo
766
- - any other value: run all the demos
767
-
768
- :param trace: trace = 1, or trace = 2 for more verbose tracing
769
- """
770
- demos = {
771
- 1: propdemo,
772
- 2: folmodel,
773
- 3: foldemo,
774
- 4: satdemo}
775
-
776
- try:
777
- demos[num](trace=trace)
778
- except KeyError:
779
- for num in demos:
780
- demos[num](trace=trace)
781
-
782
-
783
- if __name__ == "__main__":
784
- demo(2, trace=0)
1
+ # Natural Language Toolkit: Models for first-order languages with lambda
2
+ #
3
+ # Copyright (C) 2001-2018 NLTK Project
4
+ # Author: Ewan Klein <ewan@inf.ed.ac.uk>,
5
+ # URL: <http://nltk.sourceforge.net>
6
+ # For license information, see LICENSE.TXT
7
+
8
+ #TODO:
9
+ #- fix tracing
10
+ #- fix iterator-based approach to existentials
11
+
12
+ """
13
+ This module provides data structures for representing first-order
14
+ models.
15
+ """
16
+ from __future__ import print_function, unicode_literals
17
+
18
+ from pprint import pformat
19
+ import inspect
20
+ import textwrap
21
+ import re
22
+ import sys
23
+
24
+ from six import string_types
25
+
26
+ from nltk.decorators import decorator # this used in code that is commented out
27
+ from nltk.compat import python_2_unicode_compatible
28
+
29
+ from nltk.sem.logic import (AbstractVariableExpression, AllExpression, Expression,
30
+ AndExpression, ApplicationExpression, EqualityExpression,
31
+ ExistsExpression, IffExpression, ImpExpression,
32
+ IndividualVariableExpression, LambdaExpression,
33
+ NegatedExpression, OrExpression,
34
+ Variable, is_indvar)
35
+
36
+
37
+ class Error(Exception): pass
38
+
39
+ class Undefined(Error): pass
40
+
41
+ def trace(f, *args, **kw):
42
+ if sys.version_info[0] >= 3:
43
+ argspec = inspect.getfullargspec(f)
44
+ else:
45
+ argspec = inspect.getargspec(f)
46
+ d = dict(zip(argspec[0], args))
47
+ if d.pop('trace', None):
48
+ print()
49
+ for item in d.items():
50
+ print("%s => %s" % item)
51
+ return f(*args, **kw)
52
+
53
+ def is_rel(s):
54
+ """
55
+ Check whether a set represents a relation (of any arity).
56
+
57
+ :param s: a set containing tuples of str elements
58
+ :type s: set
59
+ :rtype: bool
60
+ """
61
+ # we have the empty relation, i.e. set()
62
+ if len(s) == 0:
63
+ return True
64
+ # all the elements are tuples of the same length
65
+ elif all(isinstance(el, tuple) for el in s) and len(max(s))==len(min(s)):
66
+ return True
67
+ else:
68
+ raise ValueError("Set %r contains sequences of different lengths" % s)
69
+
70
+ def set2rel(s):
71
+ """
72
+ Convert a set containing individuals (strings or numbers) into a set of
73
+ unary tuples. Any tuples of strings already in the set are passed through
74
+ unchanged.
75
+
76
+ For example:
77
+ - set(['a', 'b']) => set([('a',), ('b',)])
78
+ - set([3, 27]) => set([('3',), ('27',)])
79
+
80
+ :type s: set
81
+ :rtype: set of tuple of str
82
+ """
83
+ new = set()
84
+ for elem in s:
85
+ if isinstance(elem, string_types):
86
+ new.add((elem,))
87
+ elif isinstance(elem, int):
88
+ new.add((str(elem,)))
89
+ else:
90
+ new.add(elem)
91
+ return new
92
+
93
+ def arity(rel):
94
+ """
95
+ Check the arity of a relation.
96
+ :type rel: set of tuples
97
+ :rtype: int of tuple of str
98
+ """
99
+ if len(rel) == 0:
100
+ return 0
101
+ return len(list(rel)[0])
102
+
103
+
104
+ @python_2_unicode_compatible
105
+ class Valuation(dict):
106
+ """
107
+ A dictionary which represents a model-theoretic Valuation of non-logical constants.
108
+ Keys are strings representing the constants to be interpreted, and values correspond
109
+ to individuals (represented as strings) and n-ary relations (represented as sets of tuples
110
+ of strings).
111
+
112
+ An instance of ``Valuation`` will raise a KeyError exception (i.e.,
113
+ just behave like a standard dictionary) if indexed with an expression that
114
+ is not in its list of symbols.
115
+ """
116
+ def __init__(self, xs):
117
+ """
118
+ :param xs: a list of (symbol, value) pairs.
119
+ """
120
+ super(Valuation, self).__init__()
121
+ for (sym, val) in xs:
122
+ if isinstance(val, string_types) or isinstance(val, bool):
123
+ self[sym] = val
124
+ elif isinstance(val, set):
125
+ self[sym] = set2rel(val)
126
+ else:
127
+ msg = textwrap.fill("Error in initializing Valuation. "
128
+ "Unrecognized value for symbol '%s':\n%s" % (sym, val), width=66)
129
+
130
+ raise ValueError(msg)
131
+
132
+ def __getitem__(self, key):
133
+ if key in self:
134
+ return dict.__getitem__(self, key)
135
+ else:
136
+ raise Undefined("Unknown expression: '%s'" % key)
137
+
138
+ def __str__(self):
139
+ return pformat(self)
140
+
141
+ @property
142
+ def domain(self):
143
+ """Set-theoretic domain of the value-space of a Valuation."""
144
+ dom = []
145
+ for val in self.values():
146
+ if isinstance(val, string_types):
147
+ dom.append(val)
148
+ elif not isinstance(val, bool):
149
+ dom.extend([elem for tuple_ in val for elem in tuple_ if elem is not None])
150
+ return set(dom)
151
+
152
+ @property
153
+ def symbols(self):
154
+ """The non-logical constants which the Valuation recognizes."""
155
+ return sorted(self.keys())
156
+
157
+ @classmethod
158
+ def fromstring(cls, s):
159
+ return read_valuation(s)
160
+
161
+
162
+ ##########################################
163
+ # REs used by the _read_valuation function
164
+ ##########################################
165
+ _VAL_SPLIT_RE = re.compile(r'\s*=+>\s*')
166
+ _ELEMENT_SPLIT_RE = re.compile(r'\s*,\s*')
167
+ _TUPLES_RE = re.compile(r"""\s*
168
+ (\([^)]+\)) # tuple-expression
169
+ \s*""", re.VERBOSE)
170
+
171
+ def _read_valuation_line(s):
172
+ """
173
+ Read a line in a valuation file.
174
+
175
+ Lines are expected to be of the form::
176
+
177
+ noosa => n
178
+ girl => {g1, g2}
179
+ chase => {(b1, g1), (b2, g1), (g1, d1), (g2, d2)}
180
+
181
+ :param s: input line
182
+ :type s: str
183
+ :return: a pair (symbol, value)
184
+ :rtype: tuple
185
+ """
186
+ pieces = _VAL_SPLIT_RE.split(s)
187
+ symbol = pieces[0]
188
+ value = pieces[1]
189
+ # check whether the value is meant to be a set
190
+ if value.startswith('{'):
191
+ value = value[1:-1]
192
+ tuple_strings = _TUPLES_RE.findall(value)
193
+ # are the set elements tuples?
194
+ if tuple_strings:
195
+ set_elements = []
196
+ for ts in tuple_strings:
197
+ ts = ts[1:-1]
198
+ element = tuple(_ELEMENT_SPLIT_RE.split(ts))
199
+ set_elements.append(element)
200
+ else:
201
+ set_elements = _ELEMENT_SPLIT_RE.split(value)
202
+ value = set(set_elements)
203
+ return symbol, value
204
+
205
+ def read_valuation(s, encoding=None):
206
+ """
207
+ Convert a valuation string into a valuation.
208
+
209
+ :param s: a valuation string
210
+ :type s: str
211
+ :param encoding: the encoding of the input string, if it is binary
212
+ :type encoding: str
213
+ :return: a ``nltk.sem`` valuation
214
+ :rtype: Valuation
215
+ """
216
+ if encoding is not None:
217
+ s = s.decode(encoding)
218
+ statements = []
219
+ for linenum, line in enumerate(s.splitlines()):
220
+ line = line.strip()
221
+ if line.startswith('#') or line=='': continue
222
+ try:
223
+ statements.append(_read_valuation_line(line))
224
+ except ValueError:
225
+ raise ValueError('Unable to parse line %s: %s' % (linenum, line))
226
+ return Valuation(statements)
227
+
228
+
229
+ @python_2_unicode_compatible
230
+ class Assignment(dict):
231
+ """
232
+ A dictionary which represents an assignment of values to variables.
233
+
234
+ An assigment can only assign values from its domain.
235
+
236
+ If an unknown expression *a* is passed to a model *M*\ 's
237
+ interpretation function *i*, *i* will first check whether *M*\ 's
238
+ valuation assigns an interpretation to *a* as a constant, and if
239
+ this fails, *i* will delegate the interpretation of *a* to
240
+ *g*. *g* only assigns values to individual variables (i.e.,
241
+ members of the class ``IndividualVariableExpression`` in the ``logic``
242
+ module. If a variable is not assigned a value by *g*, it will raise
243
+ an ``Undefined`` exception.
244
+
245
+ A variable *Assignment* is a mapping from individual variables to
246
+ entities in the domain. Individual variables are usually indicated
247
+ with the letters ``'x'``, ``'y'``, ``'w'`` and ``'z'``, optionally
248
+ followed by an integer (e.g., ``'x0'``, ``'y332'``). Assignments are
249
+ created using the ``Assignment`` constructor, which also takes the
250
+ domain as a parameter.
251
+
252
+ >>> from nltk.sem.evaluate import Assignment
253
+ >>> dom = set(['u1', 'u2', 'u3', 'u4'])
254
+ >>> g3 = Assignment(dom, [('x', 'u1'), ('y', 'u2')])
255
+ >>> g3 == {'x': 'u1', 'y': 'u2'}
256
+ True
257
+
258
+ There is also a ``print`` format for assignments which uses a notation
259
+ closer to that in logic textbooks:
260
+
261
+ >>> print(g3)
262
+ g[u1/x][u2/y]
263
+
264
+ It is also possible to update an assignment using the ``add`` method:
265
+
266
+ >>> dom = set(['u1', 'u2', 'u3', 'u4'])
267
+ >>> g4 = Assignment(dom)
268
+ >>> g4.add('x', 'u1')
269
+ {'x': 'u1'}
270
+
271
+ With no arguments, ``purge()`` is equivalent to ``clear()`` on a dictionary:
272
+
273
+ >>> g4.purge()
274
+ >>> g4
275
+ {}
276
+
277
+ :param domain: the domain of discourse
278
+ :type domain: set
279
+ :param assign: a list of (varname, value) associations
280
+ :type assign: list
281
+ """
282
+
283
+ def __init__(self, domain, assign=None):
284
+ super(Assignment, self).__init__()
285
+ self.domain = domain
286
+ if assign:
287
+ for (var, val) in assign:
288
+ assert val in self.domain,\
289
+ "'%s' is not in the domain: %s" % (val, self.domain)
290
+ assert is_indvar(var),\
291
+ "Wrong format for an Individual Variable: '%s'" % var
292
+ self[var] = val
293
+ self.variant = None
294
+ self._addvariant()
295
+
296
+ def __getitem__(self, key):
297
+ if key in self:
298
+ return dict.__getitem__(self, key)
299
+ else:
300
+ raise Undefined("Not recognized as a variable: '%s'" % key)
301
+
302
+ def copy(self):
303
+ new = Assignment(self.domain)
304
+ new.update(self)
305
+ return new
306
+
307
+ def purge(self, var=None):
308
+ """
309
+ Remove one or all keys (i.e. logic variables) from an
310
+ assignment, and update ``self.variant``.
311
+
312
+ :param var: a Variable acting as a key for the assignment.
313
+ """
314
+ if var:
315
+ del self[var]
316
+ else:
317
+ self.clear()
318
+ self._addvariant()
319
+ return None
320
+
321
+ def __str__(self):
322
+ """
323
+ Pretty printing for assignments. {'x', 'u'} appears as 'g[u/x]'
324
+ """
325
+ gstring = "g"
326
+ # Deterministic output for unit testing.
327
+ variant = sorted(self.variant)
328
+ for (val, var) in variant:
329
+ gstring += "[%s/%s]" % (val, var)
330
+ return gstring
331
+
332
+ def _addvariant(self):
333
+ """
334
+ Create a more pretty-printable version of the assignment.
335
+ """
336
+ list_ = []
337
+ for item in self.items():
338
+ pair = (item[1], item[0])
339
+ list_.append(pair)
340
+ self.variant = list_
341
+ return None
342
+
343
+ def add(self, var, val):
344
+ """
345
+ Add a new variable-value pair to the assignment, and update
346
+ ``self.variant``.
347
+
348
+ """
349
+ assert val in self.domain,\
350
+ "%s is not in the domain %s" % (val, self.domain)
351
+ assert is_indvar(var),\
352
+ "Wrong format for an Individual Variable: '%s'" % var
353
+ self[var] = val
354
+ self._addvariant()
355
+ return self
356
+
357
+
358
+ @python_2_unicode_compatible
359
+ class Model(object):
360
+ """
361
+ A first order model is a domain *D* of discourse and a valuation *V*.
362
+
363
+ A domain *D* is a set, and a valuation *V* is a map that associates
364
+ expressions with values in the model.
365
+ The domain of *V* should be a subset of *D*.
366
+
367
+ Construct a new ``Model``.
368
+
369
+ :type domain: set
370
+ :param domain: A set of entities representing the domain of discourse of the model.
371
+ :type valuation: Valuation
372
+ :param valuation: the valuation of the model.
373
+ :param prop: If this is set, then we are building a propositional\
374
+ model and don't require the domain of *V* to be subset of *D*.
375
+ """
376
+
377
+ def __init__(self, domain, valuation):
378
+ assert isinstance(domain, set)
379
+ self.domain = domain
380
+ self.valuation = valuation
381
+ if not domain.issuperset(valuation.domain):
382
+ raise Error("The valuation domain, %s, must be a subset of the model's domain, %s"\
383
+ % (valuation.domain, domain))
384
+
385
+ def __repr__(self):
386
+ return "(%r, %r)" % (self.domain, self.valuation)
387
+
388
+ def __str__(self):
389
+ return "Domain = %s,\nValuation = \n%s" % (self.domain, self.valuation)
390
+
391
+ def evaluate(self, expr, g, trace=None):
392
+ """
393
+ Read input expressions, and provide a handler for ``satisfy``
394
+ that blocks further propagation of the ``Undefined`` error.
395
+ :param expr: An ``Expression`` of ``logic``.
396
+ :type g: Assignment
397
+ :param g: an assignment to individual variables.
398
+ :rtype: bool or 'Undefined'
399
+ """
400
+ try:
401
+ parsed = Expression.fromstring(expr)
402
+ value = self.satisfy(parsed, g, trace=trace)
403
+ if trace:
404
+ print()
405
+ print("'%s' evaluates to %s under M, %s" % (expr, value, g))
406
+ return value
407
+ except Undefined:
408
+ if trace:
409
+ print()
410
+ print("'%s' is undefined under M, %s" % (expr, g))
411
+ return 'Undefined'
412
+
413
+
414
+ def satisfy(self, parsed, g, trace=None):
415
+ """
416
+ Recursive interpretation function for a formula of first-order logic.
417
+
418
+ Raises an ``Undefined`` error when ``parsed`` is an atomic string
419
+ but is not a symbol or an individual variable.
420
+
421
+ :return: Returns a truth value or ``Undefined`` if ``parsed`` is\
422
+ complex, and calls the interpretation function ``i`` if ``parsed``\
423
+ is atomic.
424
+
425
+ :param parsed: An expression of ``logic``.
426
+ :type g: Assignment
427
+ :param g: an assignment to individual variables.
428
+ """
429
+
430
+ if isinstance(parsed, ApplicationExpression):
431
+ function, arguments = parsed.uncurry()
432
+ if isinstance(function, AbstractVariableExpression):
433
+ #It's a predicate expression ("P(x,y)"), so used uncurried arguments
434
+ funval = self.satisfy(function, g)
435
+ argvals = tuple(self.satisfy(arg, g) for arg in arguments)
436
+ return argvals in funval
437
+ else:
438
+ #It must be a lambda expression, so use curried form
439
+ funval = self.satisfy(parsed.function, g)
440
+ argval = self.satisfy(parsed.argument, g)
441
+ return funval[argval]
442
+ elif isinstance(parsed, NegatedExpression):
443
+ return not self.satisfy(parsed.term, g)
444
+ elif isinstance(parsed, AndExpression):
445
+ return self.satisfy(parsed.first, g) and \
446
+ self.satisfy(parsed.second, g)
447
+ elif isinstance(parsed, OrExpression):
448
+ return self.satisfy(parsed.first, g) or \
449
+ self.satisfy(parsed.second, g)
450
+ elif isinstance(parsed, ImpExpression):
451
+ return (not self.satisfy(parsed.first, g)) or \
452
+ self.satisfy(parsed.second, g)
453
+ elif isinstance(parsed, IffExpression):
454
+ return self.satisfy(parsed.first, g) == \
455
+ self.satisfy(parsed.second, g)
456
+ elif isinstance(parsed, EqualityExpression):
457
+ return self.satisfy(parsed.first, g) == \
458
+ self.satisfy(parsed.second, g)
459
+ elif isinstance(parsed, AllExpression):
460
+ new_g = g.copy()
461
+ for u in self.domain:
462
+ new_g.add(parsed.variable.name, u)
463
+ if not self.satisfy(parsed.term, new_g):
464
+ return False
465
+ return True
466
+ elif isinstance(parsed, ExistsExpression):
467
+ new_g = g.copy()
468
+ for u in self.domain:
469
+ new_g.add(parsed.variable.name, u)
470
+ if self.satisfy(parsed.term, new_g):
471
+ return True
472
+ return False
473
+ elif isinstance(parsed, LambdaExpression):
474
+ cf = {}
475
+ var = parsed.variable.name
476
+ for u in self.domain:
477
+ val = self.satisfy(parsed.term, g.add(var, u))
478
+ # NB the dict would be a lot smaller if we do this:
479
+ # if val: cf[u] = val
480
+ # But then need to deal with cases where f(a) should yield
481
+ # a function rather than just False.
482
+ cf[u] = val
483
+ return cf
484
+ else:
485
+ return self.i(parsed, g, trace)
486
+
487
+ #@decorator(trace_eval)
488
+ def i(self, parsed, g, trace=False):
489
+ """
490
+ An interpretation function.
491
+
492
+ Assuming that ``parsed`` is atomic:
493
+
494
+ - if ``parsed`` is a non-logical constant, calls the valuation *V*
495
+ - else if ``parsed`` is an individual variable, calls assignment *g*
496
+ - else returns ``Undefined``.
497
+
498
+ :param parsed: an ``Expression`` of ``logic``.
499
+ :type g: Assignment
500
+ :param g: an assignment to individual variables.
501
+ :return: a semantic value
502
+ """
503
+ # If parsed is a propositional letter 'p', 'q', etc, it could be in valuation.symbols
504
+ # and also be an IndividualVariableExpression. We want to catch this first case.
505
+ # So there is a procedural consequence to the ordering of clauses here:
506
+ if parsed.variable.name in self.valuation.symbols:
507
+ return self.valuation[parsed.variable.name]
508
+ elif isinstance(parsed, IndividualVariableExpression):
509
+ return g[parsed.variable.name]
510
+
511
+ else:
512
+ raise Undefined("Can't find a value for %s" % parsed)
513
+
514
+ def satisfiers(self, parsed, varex, g, trace=None, nesting=0):
515
+ """
516
+ Generate the entities from the model's domain that satisfy an open formula.
517
+
518
+ :param parsed: an open formula
519
+ :type parsed: Expression
520
+ :param varex: the relevant free individual variable in ``parsed``.
521
+ :type varex: VariableExpression or str
522
+ :param g: a variable assignment
523
+ :type g: Assignment
524
+ :return: a set of the entities that satisfy ``parsed``.
525
+ """
526
+
527
+ spacer = ' '
528
+ indent = spacer + (spacer * nesting)
529
+ candidates = []
530
+
531
+ if isinstance(varex, string_types):
532
+ var = Variable(varex)
533
+ else:
534
+ var = varex
535
+
536
+ if var in parsed.free():
537
+ if trace:
538
+ print()
539
+ print((spacer * nesting) + "Open formula is '%s' with assignment %s" % (parsed, g))
540
+ for u in self.domain:
541
+ new_g = g.copy()
542
+ new_g.add(var.name, u)
543
+ if trace and trace > 1:
544
+ lowtrace = trace-1
545
+ else:
546
+ lowtrace = 0
547
+ value = self.satisfy(parsed, new_g, lowtrace)
548
+
549
+ if trace:
550
+ print(indent + "(trying assignment %s)" % new_g)
551
+
552
+ # parsed == False under g[u/var]?
553
+ if value == False:
554
+ if trace:
555
+ print(indent + "value of '%s' under %s is False" % (parsed, new_g))
556
+
557
+ # so g[u/var] is a satisfying assignment
558
+ else:
559
+ candidates.append(u)
560
+ if trace:
561
+ print(indent + "value of '%s' under %s is %s" % (parsed, new_g, value))
562
+
563
+ result = set(c for c in candidates)
564
+ # var isn't free in parsed
565
+ else:
566
+ raise Undefined("%s is not free in %s" % (var.name, parsed))
567
+
568
+ return result
569
+
570
+
571
+
572
+
573
+
574
+ #//////////////////////////////////////////////////////////////////////
575
+ # Demo..
576
+ #//////////////////////////////////////////////////////////////////////
577
+ # number of spacer chars
578
+ mult = 30
579
+
580
+ # Demo 1: Propositional Logic
581
+ #################
582
+ def propdemo(trace=None):
583
+ """Example of a propositional model."""
584
+
585
+ global val1, dom1, m1, g1
586
+ val1 = Valuation([('P', True), ('Q', True), ('R', False)])
587
+ dom1 = set([])
588
+ m1 = Model(dom1, val1)
589
+ g1 = Assignment(dom1)
590
+
591
+ print()
592
+ print('*' * mult)
593
+ print("Propositional Formulas Demo")
594
+ print('*' * mult)
595
+ print('(Propositional constants treated as nullary predicates)')
596
+ print()
597
+ print("Model m1:\n", m1)
598
+ print('*' * mult)
599
+ sentences = [
600
+ '(P & Q)',
601
+ '(P & R)',
602
+ '- P',
603
+ '- R',
604
+ '- - P',
605
+ '- (P & R)',
606
+ '(P | R)',
607
+ '(R | P)',
608
+ '(R | R)',
609
+ '(- P | R)',
610
+ '(P | - P)',
611
+ '(P -> Q)',
612
+ '(P -> R)',
613
+ '(R -> P)',
614
+ '(P <-> P)',
615
+ '(R <-> R)',
616
+ '(P <-> R)',
617
+ ]
618
+
619
+ for sent in sentences:
620
+ if trace:
621
+ print()
622
+ m1.evaluate(sent, g1, trace)
623
+ else:
624
+ print("The value of '%s' is: %s" % (sent, m1.evaluate(sent, g1)))
625
+
626
+ # Demo 2: FOL Model
627
+ #############
628
+
629
+ def folmodel(quiet=False, trace=None):
630
+ """Example of a first-order model."""
631
+
632
+ global val2, v2, dom2, m2, g2
633
+
634
+ v2 = [('adam', 'b1'), ('betty', 'g1'), ('fido', 'd1'),\
635
+ ('girl', set(['g1', 'g2'])), ('boy', set(['b1', 'b2'])), ('dog', set(['d1'])),
636
+ ('love', set([('b1', 'g1'), ('b2', 'g2'), ('g1', 'b1'), ('g2', 'b1')]))]
637
+ val2 = Valuation(v2)
638
+ dom2 = val2.domain
639
+ m2 = Model(dom2, val2)
640
+ g2 = Assignment(dom2, [('x', 'b1'), ('y', 'g2')])
641
+
642
+ if not quiet:
643
+ print()
644
+ print('*' * mult)
645
+ print("Models Demo")
646
+ print("*" * mult)
647
+ print("Model m2:\n", "-" * 14,"\n", m2)
648
+ print("Variable assignment = ", g2)
649
+
650
+ exprs = ['adam', 'boy', 'love', 'walks', 'x', 'y', 'z']
651
+ parsed_exprs = [Expression.fromstring(e) for e in exprs]
652
+
653
+ print()
654
+ for parsed in parsed_exprs:
655
+ try:
656
+ print("The interpretation of '%s' in m2 is %s" % (parsed, m2.i(parsed, g2)))
657
+ except Undefined:
658
+ print("The interpretation of '%s' in m2 is Undefined" % parsed)
659
+
660
+
661
+ applications = [('boy', ('adam')), ('walks', ('adam',)), ('love', ('adam', 'y')), ('love', ('y', 'adam'))]
662
+
663
+ for (fun, args) in applications:
664
+ try:
665
+ funval = m2.i(Expression.fromstring(fun), g2)
666
+ argsval = tuple(m2.i(Expression.fromstring(arg), g2) for arg in args)
667
+ print("%s(%s) evaluates to %s" % (fun, args, argsval in funval))
668
+ except Undefined:
669
+ print("%s(%s) evaluates to Undefined" % (fun, args))
670
+
671
+ # Demo 3: FOL
672
+ #########
673
+
674
+ def foldemo(trace=None):
675
+ """
676
+ Interpretation of closed expressions in a first-order model.
677
+ """
678
+ folmodel(quiet=True)
679
+
680
+ print()
681
+ print('*' * mult)
682
+ print("FOL Formulas Demo")
683
+ print('*' * mult)
684
+
685
+ formulas = [
686
+ 'love (adam, betty)',
687
+ '(adam = mia)',
688
+ '\\x. (boy(x) | girl(x))',
689
+ '\\x. boy(x)(adam)',
690
+ '\\x y. love(x, y)',
691
+ '\\x y. love(x, y)(adam)(betty)',
692
+ '\\x y. love(x, y)(adam, betty)',
693
+ '\\x y. (boy(x) & love(x, y))',
694
+ '\\x. exists y. (boy(x) & love(x, y))',
695
+ 'exists z1. boy(z1)',
696
+ 'exists x. (boy(x) & -(x = adam))',
697
+ 'exists x. (boy(x) & all y. love(y, x))',
698
+ 'all x. (boy(x) | girl(x))',
699
+ 'all x. (girl(x) -> exists y. boy(y) & love(x, y))', #Every girl loves exists boy.
700
+ 'exists x. (boy(x) & all y. (girl(y) -> love(y, x)))', #There is exists boy that every girl loves.
701
+ 'exists x. (boy(x) & all y. (girl(y) -> love(x, y)))', #exists boy loves every girl.
702
+ 'all x. (dog(x) -> - girl(x))',
703
+ 'exists x. exists y. (love(x, y) & love(x, y))'
704
+ ]
705
+
706
+
707
+ for fmla in formulas:
708
+ g2.purge()
709
+ if trace:
710
+ m2.evaluate(fmla, g2, trace)
711
+ else:
712
+ print("The value of '%s' is: %s" % (fmla, m2.evaluate(fmla, g2)))
713
+
714
+
715
+ # Demo 3: Satisfaction
716
+ #############
717
+
718
+ def satdemo(trace=None):
719
+ """Satisfiers of an open formula in a first order model."""
720
+
721
+ print()
722
+ print('*' * mult)
723
+ print("Satisfiers Demo")
724
+ print('*' * mult)
725
+
726
+ folmodel(quiet=True)
727
+
728
+ formulas = [
729
+ 'boy(x)',
730
+ '(x = x)',
731
+ '(boy(x) | girl(x))',
732
+ '(boy(x) & girl(x))',
733
+ 'love(adam, x)',
734
+ 'love(x, adam)',
735
+ '-(x = adam)',
736
+ 'exists z22. love(x, z22)',
737
+ 'exists y. love(y, x)',
738
+ 'all y. (girl(y) -> love(x, y))',
739
+ 'all y. (girl(y) -> love(y, x))',
740
+ 'all y. (girl(y) -> (boy(x) & love(y, x)))',
741
+ '(boy(x) & all y. (girl(y) -> love(x, y)))',
742
+ '(boy(x) & all y. (girl(y) -> love(y, x)))',
743
+ '(boy(x) & exists y. (girl(y) & love(y, x)))',
744
+ '(girl(x) -> dog(x))',
745
+ 'all y. (dog(y) -> (x = y))',
746
+ 'exists y. love(y, x)',
747
+ 'exists y. (love(adam, y) & love(y, x))'
748
+ ]
749
+
750
+ if trace:
751
+ print(m2)
752
+
753
+ for fmla in formulas:
754
+ print(fmla)
755
+ Expression.fromstring(fmla)
756
+
757
+ parsed = [Expression.fromstring(fmla) for fmla in formulas]
758
+
759
+ for p in parsed:
760
+ g2.purge()
761
+ print("The satisfiers of '%s' are: %s" % (p, m2.satisfiers(p, 'x', g2, trace)))
762
+
763
+
764
+ def demo(num=0, trace=None):
765
+ """
766
+ Run exists demos.
767
+
768
+ - num = 1: propositional logic demo
769
+ - num = 2: first order model demo (only if trace is set)
770
+ - num = 3: first order sentences demo
771
+ - num = 4: satisfaction of open formulas demo
772
+ - any other value: run all the demos
773
+
774
+ :param trace: trace = 1, or trace = 2 for more verbose tracing
775
+ """
776
+ demos = {
777
+ 1: propdemo,
778
+ 2: folmodel,
779
+ 3: foldemo,
780
+ 4: satdemo}
781
+
782
+ try:
783
+ demos[num](trace=trace)
784
+ except KeyError:
785
+ for num in demos:
786
+ demos[num](trace=trace)
787
+
788
+
789
+ if __name__ == "__main__":
790
+ demo(2, trace=0)