Compare commits

..

394 Commits
v2.0 ... master

Author SHA1 Message Date
Panupong (Ice) Pasupat 876338fdbc
Update README.md 2022-03-03 10:25:21 -08:00
Panupong (Ice) Pasupat c6e2e89a65
Update README.md
Updated as suggested in #117
2022-03-02 20:56:00 -08:00
Panupong (Ice) Pasupat b27c06906d
Update DOCUMENTATION.md 2020-08-20 20:13:29 -07:00
Panupong (Ice) Pasupat 5b114fd4a7
Merge pull request #214 from percyliang/update-run-files
Updated run files to support the latest change in fig
2020-08-05 22:13:14 -07:00
Panupong Pasupat 2788dbf13f Updated run files to support the latest change in fig 2020-08-05 22:02:48 -07:00
Panupong (Ice) Pasupat c95d17fb6c
Update README.md 2020-07-08 11:50:41 -07:00
Panupong (Ice) Pasupat 299f37b300
Merge pull request #207 from percyliang/dependabot/pip/interactive/community-server/httplib2-0.18.0
Bump httplib2 from 0.10.3 to 0.18.0 in /interactive/community-server
2020-05-20 10:06:42 -07:00
dependabot[bot] e0173545fa
Bump httplib2 from 0.10.3 to 0.18.0 in /interactive/community-server
Bumps [httplib2](https://github.com/httplib2/httplib2) from 0.10.3 to 0.18.0.
- [Release notes](https://github.com/httplib2/httplib2/releases)
- [Changelog](https://github.com/httplib2/httplib2/blob/master/CHANGELOG)
- [Commits](https://github.com/httplib2/httplib2/compare/v0.10.3...v0.18.0)

Signed-off-by: dependabot[bot] <support@github.com>
2020-05-20 16:13:36 +00:00
Panupong Pasupat 8ba98924d4 Fixed the broken dependency 2020-02-18 18:25:46 -08:00
Panupong (Ice) Pasupat 1cec9ea0ab
Added how to generate .tagged files 2018-08-29 12:50:53 -07:00
Panupong (Ice) Pasupat 7b9f4625c6
Merge pull request #181 from percyliang/fix-recursion
Fixed the recursion bug
2018-04-24 03:37:55 -07:00
Panupong Pasupat 0ad3c6a3cd Fixed the recursion bug 2018-04-24 03:36:21 -07:00
Panupong (Ice) Pasupat 7d4994be3f
Merge pull request #177 from ppasupat/fix-cprune-deps
Fix cprune dependencies
2018-03-15 00:54:02 -07:00
Panupong Pasupat b9a2a8fff8 Edited tables readme 2018-03-15 00:52:28 -07:00
Panupong Pasupat bcbfdd4b57 Correct cprune dependency in build.xml and nn_0 file resource download 2018-03-15 00:49:38 -07:00
Panupong Pasupat 8842fdcd77 Removed the missing options from run file. 2018-03-01 09:20:55 -08:00
Panupong Pasupat 8dfcb95b6f [tables] Changed the default option for value normalization 2018-02-07 22:18:21 -08:00
Panupong (Ice) Pasupat 490ba9e29b
Merge pull request #166 from ppasupat/run-file-hotfix
Run file hotfix
2018-01-11 16:08:22 -08:00
Panupong Pasupat b6b0290819 Turn on tagged file by default 2018-01-11 16:07:17 -08:00
Panupong Pasupat e7f378ba92 Fixed incorrect options 2018-01-11 15:52:34 -08:00
Panupong Pasupat fac585007e Merge branch 'master' into develop 2017-11-01 14:40:43 -07:00
Panupong (Ice) Pasupat e0d7de61f1
Merge pull request #157 from ppasupat/port-yuchen
Port the macro grammar codes
2017-11-01 14:39:35 -07:00
Panupong Pasupat 73b4a2d224 Updated README 2017-11-01 14:23:28 -07:00
Panupong (Ice) Pasupat 1463bf9848 Merge pull request #158 from hsimpson22/addMoreStringConcat
Add more string args to JavaExecutor plus function
2017-10-12 18:22:22 -07:00
hsimpson 9eb7ecc50a added up to 15 string args 2017-10-10 19:53:45 -07:00
hsimpson 8fbea78518 adding longer string concatenation (from 7 string args to 11 string args) 2017-10-10 19:38:49 -07:00
Panupong Pasupat 86ed9ab957 Merge branch 'master' into port-yuchen
Conflicts:
	run
	src/edu/stanford/nlp/sempre/FloatingParser.java
2017-09-04 16:28:18 -07:00
Panupong (Ice) Pasupat aa0c7123c6 Merge pull request #156 from ppasupat/fix-overnight-gen
Fixed the floating parser to allow canonical utterance generation
2017-09-04 16:26:20 -07:00
Panupong Pasupat 6f704027f9 Handle floating rules with non-cat RHS 2017-09-04 16:18:23 -07:00
Panupong Pasupat f9807e8fec Added the run command to README 2017-09-04 15:39:42 -07:00
Panupong Pasupat 1fc5b82030 Fixed the normalization stuff 2017-09-04 15:09:23 -07:00
Panupong Pasupat 1dd4a4ef35 Fixed the floating parser to allow canonical utterance generation 2017-09-01 18:29:34 -07:00
Panupong Pasupat 3ef45877f3 Make cprune less verbose 2017-09-01 17:25:41 -07:00
Panupong Pasupat 4c1bcffebd Also log the number of correct and incorrect derivations 2017-08-31 16:13:34 -07:00
Panupong Pasupat 3e7c052621 Fixed bug in feature 2017-08-31 03:41:19 -07:00
Panupong Pasupat 212e28fc77 Added a few more docstrings 2017-08-31 00:06:31 -07:00
Panupong Pasupat bc878e69e5 Try to fix the superlative error + refactored a bunch 2017-08-30 20:49:51 -07:00
Panupong Pasupat 8a987add98 Added more features 2017-08-30 18:21:22 -07:00
Panupong Pasupat c475bddba2 Added table executor 2017-08-30 15:40:38 -07:00
Panupong Pasupat e355572acd Added TOPALT 2017-08-29 13:38:45 -07:00
Panupong Pasupat 922946cf0b Hack superlative for now 2017-08-29 06:05:44 -07:00
Panupong Pasupat c7726bae0b One more 2017-08-29 04:30:27 -07:00
Panupong Pasupat f78d1c77c1 Be more lenient with parentheses 2017-08-29 04:27:56 -07:00
Panupong Pasupat f57d5c16b1 Oops 2017-08-29 04:24:15 -07:00
Panupong Pasupat 174f57b5d4 Changed how texts are normalized 2017-08-29 04:19:11 -07:00
Panupong Pasupat 7b710ab942 Convert to lower case before evaluation 2017-08-29 04:04:50 -07:00
Panupong Pasupat 9f97024e9d Refactored the stuff in FloatingParser 2017-08-29 03:28:48 -07:00
Panupong Pasupat 7de8d83244 Refactoring cprune out of Derivation 2017-08-29 02:20:33 -07:00
Panupong Pasupat 3ad5477081 Add git-hash information when using CodaLab 2017-08-28 23:17:19 -07:00
Panupong Pasupat 4dacb85050 Changed how strings are normalized 2017-08-28 17:40:59 -07:00
Panupong Pasupat 58f8798cbe Added table id 2017-08-28 17:40:59 -07:00
Panupong Pasupat a5d99a4ac9 Edited TableColumnAnalyzer 2017-08-28 17:40:59 -07:00
Panupong Pasupat f041f1db03 Added TableColumnAnalyzer 2017-08-28 17:40:57 -07:00
Panupong Pasupat f203345ffd Updated the Wikipedia scraping scripts 2017-08-28 17:37:07 -07:00
Panupong Pasupat af0957b445 Changed how values are evaluated 2017-08-28 17:34:22 -07:00
Panupong Pasupat f291f52ef4 Changed how table target values are canonicalized 2017-08-28 17:34:22 -07:00
Panupong Pasupat b2f0ff1aa8 Write predicted output to a TSV file. 2017-08-28 17:34:22 -07:00
Panupong (Ice) Pasupat 766f6b2ada Merge pull request #152 from JisuPark/feature/enhance-install
feat(install): Add unlisted dependency and change shebang of ruby script
2017-08-07 15:02:57 -07:00
JisuPark d7cda19953 feat(install): Add unlisted dependency and change shebang of ruby script 2017-08-06 19:26:08 +09:00
Panupong (Ice) Pasupat 7eabe5794a Merge pull request #150 from putama/master
Minor fix for tables pretty-print view script
2017-07-11 16:16:29 -07:00
Prasetya Utama 4307ce4949 fix table path in pretty-print view script 2017-07-11 18:55:44 -04:00
Panupong Pasupat 98cb9a7b13 Merge branch 'develop' 2017-05-18 11:12:15 -07:00
Panupong Pasupat 5120660036 Edited README 2017-05-18 11:10:36 -07:00
Panupong Pasupat 047afababb Edited the Value conversion in LambdaDCSExecutor 2017-05-17 20:49:34 -07:00
Panupong Pasupat 5b43659fe0 Minor edit in CustomExample 2017-05-17 19:10:05 -07:00
Panupong Pasupat 79ca2d3758 Fixed the floating parser test 2017-05-17 18:46:38 -07:00
Panupong Pasupat 35aa466d82 Removed bad FloatingParser tests 2017-05-17 18:18:57 -07:00
Panupong Pasupat bdf2e3465f Fixed LambdaDCSExecutorTest 2017-05-17 17:52:49 -07:00
Panupong (Ice) Pasupat 82b0f6f050 Merge pull request #141 from ppasupat/fix-tables
Fix the tables module to match ACL2015
2017-05-02 18:17:52 -07:00
Panupong (Ice) Pasupat e4c603750f Merge pull request #139 from ppasupat/develop
Merge master into develop
2017-05-02 16:51:07 -07:00
Panupong (Ice) Pasupat 2df32f0872 Merge pull request #140 from ppasupat/master
Updated README by adding a dependency to make
2017-05-02 16:50:01 -07:00
Panupong Pasupat 71fc59309d Updated README by adding a dependency to make 2017-04-30 19:34:10 -07:00
Panupong Pasupat 68b4742490 Edited README for the tables module 2017-04-30 19:31:43 -07:00
Panupong Pasupat 4ec7d378a4 Fixed the run file 2017-04-30 19:06:11 -07:00
Panupong Pasupat 24ad29a14f Converted back to the original TableKnowledgeGraph from ACL15 2017-04-30 15:21:01 -07:00
Panupong Pasupat e170317341 Removed tables.alignment and added cosmetic changes 2017-04-30 15:19:30 -07:00
Panupong Pasupat cb8c9dc639 Also dump matched numbers, dates, and date ranges. 2017-04-26 16:49:43 -07:00
Panupong Pasupat 2c98635831 TaggedFuzzyGenerator -- dump all fuzzy matched entities and relations 2017-04-26 16:49:43 -07:00
Panupong Pasupat da52c3e6f0 Updated fictitious-dump-lf.py 2017-04-26 16:49:43 -07:00
Panupong Pasupat 0561b450e5 Added another schema for DPD LF dumping 2017-04-26 16:49:43 -07:00
Panupong Pasupat d73ebf2aac Added convert-to-prefix 2017-04-26 16:49:43 -07:00
Panupong Pasupat 2c3d12f302 Read dataset v0.5 2017-04-26 16:49:43 -07:00
Panupong Pasupat 5501946659 Dump all correct LFs 2017-04-26 16:49:42 -07:00
Panupong Pasupat 6d30178590 Changed fig group number 2017-04-26 16:49:42 -07:00
Panupong Pasupat 629b74d2c2 Changed some default options 2017-04-26 16:49:42 -07:00
Panupong Pasupat f6773e9506 Edited features back 2017-04-26 16:49:42 -07:00
Panupong Pasupat 5fc7ef83f2 Headword improved 2017-04-26 16:49:42 -07:00
Panupong Pasupat fe67fb348d Dependency changed 2017-04-26 16:49:42 -07:00
Panupong Pasupat 2baee8e8a4 Fixed stupid bug 2017-04-26 16:49:42 -07:00
Panupong Pasupat f2ba77bd75 Better convert to postfix 2017-04-26 16:49:42 -07:00
Panupong Pasupat d200bc5eb1 Added a script to dump logical forms 2017-04-26 16:49:42 -07:00
Panupong Pasupat fe29ab52c9 Start row index from 1 2017-04-26 16:49:42 -07:00
Percy Liang e15cb2c1dc fix title 2017-04-11 00:35:35 -07:00
Percy Liang 59acdcfa05 fix versions in README 2017-04-11 00:29:37 -07:00
Percy Liang e09c05e0a1 Merge pull request #134 from sidaw/master
interactive learning
2017-04-08 22:23:04 -07:00
Sida Wang 144f15c5da minor typo 2017-04-08 22:00:38 -07:00
Sida Wang 50d1f13f43 more readme updates 2017-04-08 21:40:51 -07:00
Sida Wang 8961edb003 fix test 2017-04-07 22:44:04 -07:00
Sida Wang 41abd8b8e9 data process, faster parsing, reproduce results 2017-04-07 22:41:34 -07:00
Sida Wang ff76ec27b6 commit for clean repo 2017-04-07 17:56:49 -07:00
Sida Wang 8d5d7c486f more data analysis 2017-04-07 07:00:47 -07:00
Sida Wang 8d3d170bd9 readme updates, efficiency improvements, etc 2017-04-06 23:22:40 -07:00
Sida Wang 65fd5122ca fix tests 2017-04-06 11:44:48 -07:00
Sida Wang c231f85dea revert Trie and simply grammar 2017-04-06 08:40:26 -07:00
Sida Wang fe4e034b90 resume changes and perf improvements 2017-04-06 07:48:15 -07:00
Sida Wang a9ab6c8f7a bug fix for more numbers and colors 2017-04-04 18:13:22 -07:00
Sida Wang d4621b8d53 readme, and more parameters in run 2017-03-28 23:36:40 -07:00
Sida Wang 1a8d45b4c1 update README 2017-03-28 12:43:04 -07:00
Sida Wang 20570463b3 Rename DAL.grammar to dal.grammar 2017-03-28 12:00:17 -07:00
Sida Wang 2a5365ef69 rename, README, refactor master 2017-03-28 10:13:05 -07:00
Sida Wang 165160461b automatic cleanup for style, with some inspection 2017-03-27 20:10:44 -07:00
Sida Wang 12cac10e93 more readable Grammar.parseSemanticFn, move InteractiveMaster and BeamFloatingParser to interactive 2017-03-27 19:56:14 -07:00
Sida Wang daea6171c2 Merge pull request #28 from samginn/sidaw-interactive
Update requirements.txt
2017-03-27 19:16:09 -07:00
Sam Ginn 8b43211038 Hide secrets 2017-03-27 15:07:18 -05:00
Sam Ginn b2dfa6f0e9 Merge remote-tracking branch 'upstream/master' into sidaw-interactive
* upstream/master: (42 commits)
  percy comments round 2
  simpler settings for PR
  more PR issues addressed, css colors and more numbers
  renaming to DCA
  clean up, debug and test passing
  refactor compiles
  deal with simple issues
  let master only depend on ILUtils, instead of interactive. not particularly useful
  move community server
  exclude my tests in main
  outerloop stuff
  gziped data
  all merged except for master
  compiles and tests passing
  compiles and tests passing
  merge core 1, test complile
  add action formula to core
  compiles and tests passing
  merge build
  stats for context
  ...
2017-03-27 15:04:23 -05:00
Sam Ginn 11ddbd2954 Update requirements.txt with just what's needed 2017-03-27 15:02:49 -05:00
Sida Wang da796adfec percy comments round 2 2017-03-27 00:20:49 -07:00
Sida Wang ae1904437f simpler settings for PR 2017-03-26 17:18:36 -07:00
Sida Wang ba0be9d659 more PR issues addressed, css colors and more numbers 2017-03-26 16:39:57 -07:00
Sida Wang 44005b2b9e renaming to DCA 2017-03-26 10:09:27 -07:00
Sida Wang fd9dc4be70 clean up, debug and test passing 2017-03-26 01:49:22 -07:00
Sida Wang dc5f6f4d51 refactor compiles 2017-03-21 15:39:44 -07:00
Sida Wang 21b3f9904a deal with simple issues 2017-03-18 18:43:10 -07:00
Sida Wang 52958774ad let master only depend on ILUtils, instead of interactive. not particularly useful 2017-03-17 23:18:10 -07:00
Sida Wang 001c2a1aa2 move community server 2017-03-17 22:45:54 -07:00
Sida Wang e248913129 Merge pull request #27 from samginn/sidaw-interactive
User accounts for community server
2017-03-17 22:45:24 -07:00
Sida Wang 068bdbfcac exclude my tests in main 2017-03-17 22:40:39 -07:00
Sida Wang 4c765362d0 outerloop stuff 2017-03-17 22:08:24 -07:00
Sida Wang c7199c00af gziped data 2017-03-17 22:02:06 -07:00
Sida Wang dc1cb50cb3 all merged except for master 2017-03-17 20:52:49 -07:00
Sida Wang ccd4b839d2 compiles and tests passing 2017-03-17 20:17:54 -07:00
Sida Wang 7febda907e compiles and tests passing 2017-03-17 19:52:12 -07:00
Sida Wang a14533d718 merge core 1, test complile 2017-03-17 19:26:17 -07:00
Sida Wang 341d27a363 add action formula to core 2017-03-17 16:02:55 -07:00
Sam Ginn f835bcf2c2 Use user token for delete 2017-03-17 00:45:39 -07:00
Sida Wang 9f08f21633 compiles and tests passing 2017-03-17 00:24:24 -07:00
Sam Ginn 8335aa2e1e OAuth authentication and authorization 2017-03-08 15:59:34 -08:00
Sida Wang e7281e2d14 merge build 2017-03-08 14:43:58 -08:00
Sida Wang d8bc66f9e0 Merge branch 'master' of https://github.com/percyliang/sempre 2017-03-08 14:38:47 -08:00
Sam Ginn dde8bf98f1 Add Slack OAuth 2017-03-07 23:47:43 -08:00
Sam Ginn 06ddb7dcbf Store thumbnail of structure 2017-03-07 22:14:17 -08:00
Panupong (Ice) Pasupat ff129650e2 Merge pull request #133 from percyliang/develop
SEMPRE develop -> SEMPRE master
2017-03-07 21:22:53 -08:00
Sida Wang 5616182eeb Merge branch 'percyliang-master' 2017-03-02 14:55:40 -08:00
Sida Wang 15807e32b0 merge with updates 2017-03-02 14:55:19 -08:00
Sida Wang 157cea445f Merge pull request #23 from sidaw/sidaw-interactive
Sidaw interactive
2017-03-02 14:40:19 -08:00
Sida Wang 5c391195dc stats for context 2017-02-17 15:10:18 -08:00
Sida Wang 0ec0dd4d2e add more data 2017-02-17 14:57:28 -08:00
Panupong (Ice) Pasupat 4f778daa22 Merge pull request #128 from percyliang/master
Merge master into develop
2017-02-13 15:52:12 -08:00
Sida Wang 953ec08dcd :Merge branch 'sidaw-interactive' of https://github.com/sidaw/sempre-interactive into sidaw-interactive 2017-02-07 15:38:28 -08:00
Sida Wang e793cfcf13 new cube limit and stuf 2017-02-07 15:38:17 -08:00
Sida Wang d2214efda8 Merge pull request #22 from samginn/sidaw-interactive
Send down all the structs at once
2017-02-03 18:21:37 -08:00
Sam Ginn 6c85cc6c3d Send down all the structs at once 2017-02-03 18:00:46 -08:00
Sida Wang 07ad58abc7 Merge pull request #21 from samginn/sidaw-interactive
Fix citation sort and show 10 top builders
2017-02-03 13:05:16 -08:00
Sam Ginn f036ecc678 Fix citation sort and show 10 top builders 2017-02-03 12:48:26 -08:00
Sida Wang ffd8cb298b Merge branch 'sidaw-interactive' of https://github.com/sidaw/sempre-interactive into sidaw-interactive 2017-02-03 02:32:00 -08:00
Sida Wang 32b4470e40 final stress test, improvements to grammar induction, general bug fixes 2017-02-03 02:31:52 -08:00
Sida Wang bb38eb442c Merge pull request #20 from samginn/sidaw-interactive
fix safepath check to test absolute paths
2017-02-02 22:55:13 -08:00
Sida Wang f16fdf8b54 simple packing, tested 2017-02-02 11:03:13 -08:00
Sida Wang 75e2ceb64e grammar test passing 2017-02-02 08:23:33 -08:00
Sida Wang b03ab90688 grammar induction iteration, fix parenthesis bug 2017-02-02 07:09:44 -08:00
Sam Ginn 6da565982e fix safepath check to test absolute paths 2017-02-01 22:51:37 -08:00
Sida Wang 83c43998c4 qualifer 3 data, fix up of qualifer 1 2017-02-01 21:52:34 -08:00
Sida Wang 23b1764ff0 improvements to features, bug fix on automatic scoping 2017-02-01 20:40:10 -08:00
Sida Wang 5a860ab1bd Merge pull request #19 from samginn/sidaw-interactive
ensure path names from user data are safe paths
2017-01-31 23:07:38 -08:00
Sida Wang 02a25f5af0 language analyzer exception length stats 2017-01-31 15:32:07 -08:00
Sam Ginn e52f5b5822 ensure path names from user data are safe paths 2017-01-31 12:23:14 -08:00
Sida Wang d81370eaf5 Merge pull request #18 from samginn/sidaw-interactive
SID parameters from URL server
2017-01-30 22:08:42 -08:00
Sam Ginn 6920b8fc2d Get shared struct id from passed sid via URL param 2017-01-30 21:10:12 -08:00
Sam Ginn 73170c7d23 Revert "Add save structure to slot"
This reverts commit 509be8cf95.
2017-01-30 21:09:09 -08:00
Sida Wang ae46098d43 Merge branch 'sidaw-interactive' of https://github.com/sidaw/sempre-interactive into sidaw-interactive 2017-01-30 02:05:24 -08:00
Sida Wang 13b7eba13e analysis script 2017-01-30 02:05:19 -08:00
Sida Wang bc0b9e656b Merge pull request #17 from samginn/sidaw-interactive
Bug Fixes: put logs in their own files by uid bug fix and sort top builders properly
2017-01-30 02:04:03 -08:00
Sam Ginn 509be8cf95 Add save structure to slot 2017-01-30 00:14:09 -08:00
Sida Wang 10075d88ab rename command inputs 2017-01-29 23:52:41 -08:00
Sida Wang 822d902e5d analytics and new data 2017-01-29 23:52:22 -08:00
Sam Ginn 310bd5797f sort top builders properly 2017-01-29 16:52:14 -08:00
Sam Ginn 04550e8c12 put logs in their own files by uid bug fix 2017-01-29 15:59:41 -08:00
Sida Wang 06420127f2 analysis utilities 2017-01-29 13:36:56 -08:00
Sida Wang ce23b45066 bug fixes for deriving empty formula 2017-01-29 00:40:49 -08:00
Sida Wang 0b52931789 bug fixes 2017-01-28 23:47:54 -08:00
Sida Wang dcde9d3b73 Merge branch 'sidaw-interactive' of https://github.com/sidaw/sempre-interactive into sidaw-interactive 2017-01-28 21:43:32 -08:00
Sida Wang 84c93f1377 no scoping on def 2017-01-28 21:43:23 -08:00
Sida Wang 34eded2c21 Merge pull request #16 from samginn/sidaw-interactive
Show 7 top builders with top 7 citations and only 3 newest builders
2017-01-28 21:37:45 -08:00
Sam Ginn 15ffcfa874 Show 7 top builders with top 7 citations and only 3 newest builders 2017-01-28 19:14:18 -08:00
Sida Wang 7a74929661 messing with block, changed isolate to be blocklike, default to no scoping on definitions 2017-01-28 18:51:23 -08:00
Sida Wang 842a626913 more error checking, rule source, etc. 2017-01-27 21:07:30 -08:00
Sida Wang fdba93c017 source information for rules 2017-01-26 15:29:11 -08:00
Sida Wang 4bba263616 Merge pull request #14 from samginn/sidaw-interactive
send sessionID per request
2017-01-25 18:45:00 -08:00
Sam Ginn 5435b5a20b send sessionID per request 2017-01-25 18:29:12 -08:00
Sida Wang f3a3a05347 trying to catch the threading issue 2017-01-25 15:37:28 -08:00
Sida Wang 5c83e6c612 simplications 2017-01-25 14:39:10 -08:00
Sida Wang 5ba580c58d Merge pull request #13 from samginn/sidaw-interactive
prefer sending definitions with cites
2017-01-25 13:29:40 -08:00
Sam Ginn dc26e6b390 prefer sending definitions with cites 2017-01-25 13:10:57 -08:00
Sida Wang 37f4f02610 test server for Sam 2017-01-25 11:38:20 -08:00
Sida Wang e085e31a09 Merge pull request #12 from samginn/sidaw-interactive
update h-index formula and score formula and delete structs support
2017-01-24 23:43:01 -08:00
Sam Ginn 2bb1e8340c Added delete structs 2017-01-24 23:33:26 -08:00
Sida Wang a093ef5b60 simulator, sandboxing, bug fixes 2017-01-24 23:33:26 -08:00
Sida Wang 3f4d37bf4d sandbox bug fix 2017-01-24 23:33:05 -08:00
Sida Wang 397f103bee simulator, sandboxing, bug fixes 2017-01-24 23:12:29 -08:00
Sam Ginn ac43e36e5f update h-index formula and score formula 2017-01-23 16:53:23 -08:00
Sida Wang 63e6a01e8f sandbox bug fix 2017-01-23 11:42:56 -08:00
Sida Wang 341526626a Merge pull request #11 from samginn/sidaw-interactive
Fix log writing bug and H-index citation score for builders
2017-01-23 09:19:38 -08:00
Sam Ginn 04a49d0aac Merge branch 'sidaw-interactive' of github.com:samginn/sempre-interactive into sidaw-interactive
* 'sidaw-interactive' of github.com:samginn/sempre-interactive:
  don't scrub uid when sending to client
  fix file write bug with file not getting flushed
2017-01-23 02:17:52 -08:00
Sam Ginn a037f9d89c add scoring function 2017-01-23 02:16:53 -08:00
Sam Ginn 794e827526 don't scrub uid when sending to client 2017-01-23 01:23:05 -08:00
Sam Ginn 8cec892fa5 fix file write bug with file not getting flushed 2017-01-23 01:23:05 -08:00
Sam Ginn 26d873c64b don't scrub uid when sending to client 2017-01-23 01:18:47 -08:00
Sam Ginn ac1fd7dfeb fix file write bug with file not getting flushed 2017-01-23 01:03:04 -08:00
Sida Wang 306ec6f65b sanbox updates 2017-01-22 15:22:53 -08:00
Sida Wang 5b706edc4e fix run for older ruby 2017-01-22 00:54:32 -08:00
Sida Wang 6ac387f5f2 stress test, improvement to citation tracker and logging 2017-01-22 00:28:20 -08:00
Sida Wang 38ba8c4142 Merge pull request #10 from samginn/sidaw-interactive
Move community-server to sempre repo
2017-01-21 15:22:23 -08:00
Sam Ginn e81771edc9 Move community-server to sempre repo 2017-01-21 14:43:38 -08:00
Sida Wang fc8f05fd3a small update 2017-01-21 02:18:13 -08:00
Sida Wang ff89b3b8d3 small updates 2017-01-21 02:13:05 -08:00
Sida Wang dc3e469f84 citation tracker 2017-01-21 02:00:37 -08:00
Sida Wang 8cf34edb09 stress test of the jsonserver 2017-01-20 17:58:48 -08:00
Sida Wang 9f1ce55f9f json server, perf, and etc 2017-01-20 02:41:33 -08:00
Sida Wang 66511dcb34 final update 2017-01-18 01:54:18 -08:00
Sida Wang 131a08d191 block limit, overlaping moves and the like 2017-01-17 19:19:19 -08:00
Sida Wang def171510f ignore stuff 2017-01-16 20:39:16 -08:00
Sida Wang 7fef288eef reorg, clean up, and read in logs 2017-01-16 20:37:40 -08:00
Sida Wang 6ec499ac19 bug fix with select, and for 2017-01-16 00:21:56 -08:00
Sida Wang bc1b72a6fa minor changes 2017-01-16 00:15:45 -08:00
Sida Wang 6b580355e2 change input dir 2017-01-16 00:13:07 -08:00
Sida Wang 887b2ab8c0 passing tests again, fixed selection behavior 2017-01-16 00:10:32 -08:00
Sida Wang 36eca0e73c logging and auto read utilities, some bug fixes 2017-01-15 23:42:55 -08:00
Sida Wang 1e7c1c3fbb fixes of iso 2017-01-15 17:54:53 -08:00
Sida Wang e2a92619dc scoping improvements 2017-01-15 17:37:54 -08:00
Sida Wang d5a9d036c0 executor test still passing, playing with scoping rules 2017-01-15 14:13:05 -08:00
Sida Wang 9d8a191ef0 json logging 2017-01-11 19:56:36 -08:00
Sida Wang e2a725daca for demo in meeting, parsing again after def 2017-01-11 16:59:14 -08:00
Sida Wang db5703e703 new grammar induction 2017-01-11 16:49:27 -08:00
Sida Wang 0bbdfeb77c passing not action test properly! 2017-01-09 20:38:58 -08:00
Sida Wang 2da0c97f7b passing no action test 2017-01-09 18:03:33 -08:00
Sida Wang 2f5e3f754b window features for grammar induction 2017-01-09 11:32:28 -08:00
Sida Wang 307610e473 new server commands 2017-01-07 21:03:08 -08:00
Sida Wang 1e955838a0 testset 2017-01-07 18:02:02 -08:00
Sida Wang 3d68330bbe grammar induction test 2017-01-07 17:46:07 -08:00
Sida Wang 7a10a749dc grammar induction tests working! 2017-01-07 13:06:03 -08:00
Sida Wang ef60c1c0dc highest scoring packing DP 2017-01-06 23:39:48 -08:00
Sida Wang 9f4867b3c0 messing more with grammar induction 2017-01-06 17:15:20 -08:00
Sida Wang a21ed35864 grammarInducer bug fix 2017-01-05 14:54:36 -08:00
Sida Wang a34804f1e2 prune after floating, noop, bugs 2017-01-04 01:52:54 -08:00
Sida Wang b9a17e3b6f move bug fix 2017-01-03 20:42:06 -08:00
Sida Wang f3a8f2be0e server updates 2017-01-03 16:10:26 -08:00
Sida Wang 9ba813dd75 ActionExecutorTest passing agian 2017-01-02 16:08:29 -08:00
Sida Wang be125a1f81 minor 2017-01-01 12:27:53 -08:00
Sida Wang 98a732532d more scoping stuff, default block, bug fixes 2016-12-31 22:31:01 -08:00
Sida Wang f5c4b3bea2 previous, scoping 2016-12-31 12:04:51 -08:00
Sida Wang 0a9ce28f97 cube is working 2016-12-30 18:02:06 -08:00
Sida Wang 77005c35a8 logical language improvements. default local scope etc. 2016-12-30 16:10:25 -08:00
Sida Wang 1c5af981db variables, making selection less special 2016-12-29 22:33:20 -08:00
Sida Wang 4b1ba2dce7 test, interactive commands 2016-12-15 15:31:06 -08:00
Percy Liang 3ed286f542 Merge pull request #124 from percyliang/geo880
adding a geo880 module as a playground
2016-12-06 18:18:23 -08:00
Jonathan Berant a7a4c6bc06 adding a geo880 module as a playground 2016-12-06 09:12:28 +02:00
Sida Wang 09a8bc84bb tests, and supporting spaces 2016-11-17 18:34:56 -08:00
Sida Wang 0d7cf3587f adding fake block, passed ActionExecutorTest 2016-11-17 16:33:53 -08:00
Sida Wang a1d2afe7a8 fix the nothing rule bug 2016-11-16 21:11:30 -08:00
Sida Wang 9d5b885fd9 not formula bug 2016-11-16 16:58:59 -08:00
Sida Wang 1ca0ce630b for demo purpose 2016-11-16 16:39:27 -08:00
Sida Wang 3e9e51e431 hack for the null rule 2016-11-15 23:29:19 -08:00
Sida Wang 4a55534101 bug fix 2016-11-15 23:27:56 -08:00
Sida Wang 243ad36f9b grammar induction tests 2016-11-15 22:37:53 -08:00
Percy Liang 53dacb5d4e Merge pull request #123 from ppasupat/fix-sparql-doc
Updated contents on SPARQL in README / TUTORIAL
2016-11-15 14:53:08 -08:00
Panupong Pasupat f0248a0c2b Updated contents on SPARQL in README / TUTORIAL 2016-11-15 14:02:14 -08:00
Sida Wang b22b647c04 no object 2016-11-15 02:10:54 -08:00
Sida Wang 509b0535ca object grammar 2016-11-15 02:08:42 -08:00
Sida Wang df753cb2e7 new grammar induction, working without exceptions 2016-11-15 02:04:48 -08:00
Panupong (Ice) Pasupat 3b31ba7aef Update README.md
Added more information regarding ant freebase
2016-10-26 21:38:13 -07:00
Panupong Pasupat 9b449f99be Merge branch 'master' into develop 2016-09-26 10:04:51 -07:00
Panupong Pasupat 725b69877d Merge branch 'thammegowda-master' 2016-09-26 10:02:57 -07:00
Panupong Pasupat 07e1a93002 Removed rlwrap 2016-09-26 10:02:28 -07:00
Thamme Gowda c8c9a7d92e Added JLine prompt
JLine provides convenient CLI functionality like
history (UP arrow), edit the input characters (Left arrow)
that can be seen in modern shells like bash
2016-09-25 02:47:21 -07:00
Sida Wang d67a630232 better features 2016-08-23 16:20:56 -07:00
Sida Wang 8406f97000 Merge pull request #8 from samginn/sidaw-interactive
Actions to Action rule
2016-08-23 16:04:54 -07:00
Sam Ginn ae8c627d68 CopyDerivs optimization to HashSet 2016-08-23 14:51:16 -07:00
Sam Ginn 4b46e061c8 Actions -> FROOT instead of Actions -> Action 2016-08-22 18:01:14 -07:00
Sida Wang e45b125858 Merge pull request #7 from samginn/sidaw-interactive
BeamFloatingParser fix for Core Status
2016-08-22 17:22:42 -07:00
Sam Ginn 69ddc36cbd Queries always go to floating parser, while definitions are normal 2016-08-22 16:53:09 -07:00
Sam Ginn b28c87ea3d BeamFloatingParser fix for Core Status 2016-08-22 15:50:32 -07:00
Sida Wang 61b48589ef floating response 2016-08-22 15:05:25 -07:00
Sida Wang 4d65a9ae89 -Server.maxCandidates 2016-08-22 10:43:57 -07:00
Sida Wang 43614f7ba4 new build 2016-08-21 17:19:38 -07:00
Sida Wang f97e92e3c0 build object top 2016-08-21 17:15:01 -07:00
Sida Wang 627793b0cc adding induced rules, and induced status 2016-08-21 16:09:36 -07:00
Sida Wang 2852a8e0ff submit, and grammar induction workaround 2016-08-20 15:46:17 -07:00
Sida Wang 8ea35c6446 reference definitions 2016-08-20 13:22:50 -07:00
Sida Wang c1b2b414dd BeamFloatingFeature computer 2016-08-19 15:35:34 -07:00
Percy Liang ef886be822 Merge pull request #111 from ppasupat/ice-tables-dump-tagged
[tables] In CoreNLP-tagged table dumpers, renamed "annotated" to "tagged" to avoid confusion
2016-08-19 13:50:02 +02:00
Percy Liang f6d696ce41 Merge pull request #110 from ppasupat/ice-tables-fix-dates
[tables] Fixed date comparison in LambdaDCSExecutor
2016-08-19 13:48:34 +02:00
Sida Wang 16f556ae87 action change, isolation formula, more tests 2016-08-18 17:44:48 -07:00
Sida Wang 0207e00a7d Merge pull request #6 from samginn/sidaw-interactive
Support nothing rules
2016-08-18 16:48:57 -07:00
Panupong Pasupat 7991a1801a Renamed "annotated" to "tagged" to avoid confusion 2016-08-17 19:58:47 -07:00
Panupong Pasupat 254640fc84 Filter the dumped logical forms based on the fixed ValueEvaluator 2016-08-17 19:51:13 -07:00
Panupong Pasupat ba59a2a083 Fixed date evaluation and NameValue string. Also added more tests.
Conflicts:
	src/edu/stanford/nlp/sempre/tables/lambdadcs/LambdaDCSExecutorTest.java
2016-08-17 19:51:11 -07:00
Sam Ginn d5560c5e8a ready to turk 2016-08-12 22:42:47 -05:00
Sam Ginn 0a233aa79b Merge branch 'sidaw-interactive' of https://github.com/sidaw/sempre-interactive into sidaw-interactive
* 'sidaw-interactive' of https://github.com/sidaw/sempre-interactive:
  action executor passes, but still confusing
2016-08-09 16:21:33 -05:00
Jonathan Berant d3a1395481 fix to pull-dependencies 2016-08-06 15:02:55 -07:00
Jonathan Berant 032e66ee26 (a) add mode esslli_2016 in pull-dependencies and run file (b) add option to load naiveknowledgegraph from interactive mode 2016-08-06 14:19:45 -07:00
Sida Wang 6221efc1ac action executor passes, but still confusing 2016-08-06 03:07:24 -07:00
Sam Ginn bc3cb4a773 Support nothing rules 2016-08-05 16:21:59 -07:00
Sida Wang f94f45f73f error value, more information etc. 2016-08-05 15:09:40 -07:00
Sida Wang 19b0040e66 Merge branch 'samginn-sidaw-interactive' into sidaw-interactive 2016-08-04 14:56:31 -07:00
Sida Wang 338be133b5 merge 2016-08-04 14:56:22 -07:00
Sam Ginn ae341ca557 Integrate the floating parser 2016-08-04 14:47:58 -07:00
Sam Ginn d143d9a3b9 Merge branch 'sidaw-interactive' of github.com:sidaw/sempre-interactive into sidaw-interactive
* 'sidaw-interactive' of github.com:sidaw/sempre-interactive:
  fixing selection behavior, for demo
  bug fi
2016-08-03 16:43:43 -07:00
Sida Wang fd60ab86ef fixing selection behavior, for demo 2016-08-03 16:43:15 -07:00
Sida Wang 10671b96f3 bug fi 2016-08-03 16:30:19 -07:00
Sam Ginn 22ea78f03e Merge branch 'sidaw-interactive' of github.com:sidaw/sempre-interactive into sidaw-interactive
* 'sidaw-interactive' of github.com:sidaw/sempre-interactive:
  easy bug
2016-08-03 16:03:11 -07:00
Sam Ginn 2fc9867f9d Weak Projective Floating Parser 2016-08-03 16:03:08 -07:00
Sida Wang 87f2f4ef79 easy bug 2016-08-03 16:02:02 -07:00
Sida Wang 2b318707d8 test improvements 2016-08-03 15:43:00 -07:00
Sida Wang fe8fe833a0 more tests 2016-08-03 15:38:06 -07:00
Sida Wang 0eaaff3827 tests 2016-08-01 18:30:34 -07:00
Sida Wang ee40aa6c98 parser test, some bug fixes 2016-08-01 16:30:08 -07:00
Sida Wang fc1c2521fb handle anchor, grammar induction bug fic 2016-07-29 15:45:34 -07:00
Sida Wang 60a4f2b42d more floating rules and etc. 2016-07-28 17:45:01 -07:00
Sida Wang 185c6a2552 updating grammar 2016-07-27 14:48:12 -07:00
Sida Wang 1bf011c709 more features and all tests are passing now 2016-07-25 23:51:33 -07:00
Sida Wang 95011a77d2 perform action, floating rules, and the like 2016-07-25 15:49:59 -07:00
Sida Wang eb1d1c9dc6 actione executor test 2016-07-24 18:47:17 -07:00
Sida Wang 101caeddb0 new action executor, in restricted lambda dcs! mostly workgin 2016-07-24 01:11:59 -07:00
Sida Wang edce6c998e slight updates 2016-07-18 16:26:42 -07:00
Jonathan Berant 114ee52462 adding link to installing virtuoso on OS/X 2016-07-16 15:20:25 -07:00
Jonathan Berant 0a034feaa9 fix to tutorial 2016-07-16 14:06:02 -07:00
Sida Wang 0ae8fc59fd really stupid thing with the optionparser, which now has trouble with $ 2016-07-14 17:40:55 -07:00
Sida Wang 6e97e77511 debugged new language 2016-07-13 14:51:13 -07:00
Sida Wang 98d871eccd lambda dcs like grammar 2016-07-10 00:06:25 -07:00
Sida Wang 7b121482dd easier add semantics 2016-07-08 02:09:06 -07:00
Sida Wang 25396a1d34 basic language working 2016-07-06 19:01:44 -07:00
Sida Wang 999006bbee more grammar debugging 2016-07-05 01:04:57 -07:00
Sida Wang 5fa98eb7ce bug fix on the grammar 2016-07-05 00:24:06 -07:00
Sida Wang eb8bc13712 update run script, and MagnetWorld 2016-07-05 00:13:37 -07:00
Sida Wang eb67a5ccda merge with latest dev 2016-07-04 02:11:35 -07:00
Sida Wang 7df35e5dd8 Merge pull request #2 from sidaw/develop
update interactive with develop
2016-07-04 01:35:42 -07:00
Sida Wang ec511e203f Merge pull request #1 from percyliang/master
updating dev branch...
2016-07-04 01:33:48 -07:00
Sida Wang 72a5d6c383 add shrdlurn and get it to run 2016-07-03 16:41:52 -07:00
Sida Wang 4ea4dda841 added interactive, fix, and compiles 2016-07-03 15:15:57 -07:00
Sida Wang 2ce1ae88f4 interactive package 2016-07-03 15:06:09 -07:00
Sida Wang 1d7c149f26 copying over 2016-07-03 15:03:21 -07:00
Panupong Pasupat 995ef44844 Only allow min, max, argmin, argmax if all dates are comparable 2016-06-30 16:34:31 -07:00
Panupong (Ice) Pasupat 423adfebdb Merge pull request #100 from ppasupat/ice-tables-bugfix
Ice tables bugfix
2016-06-24 14:33:04 -07:00
Panupong Pasupat 8f43637467 Edited analysis scripts for tables 2016-06-22 03:51:15 -07:00
Panupong Pasupat 55f4a2f8b8 Edited the fictitious worlds experiments 2016-06-21 18:49:22 -07:00
Panupong (Ice) Pasupat 9283ff2140 Merge pull request #99 from ppasupat/ice-tables
Ice tables files for ACL 2016
2016-06-06 14:02:03 -07:00
Panupong Pasupat 05b941f223 Removed header-frequencies.txt 2016-06-04 16:33:36 -07:00
Panupong Pasupat 53d02315ab Added more files related to tables experiments 2016-06-04 16:15:28 -07:00
Panupong Pasupat 2071579b8c Added changes in the tables package 2016-06-04 14:31:36 -07:00
Percy Liang 21fe64ffcc Merge pull request #97 from sloanesturz/documentation
Minor documentation fixes
2016-05-21 17:01:02 -07:00
Sloane Sturzenegger 48d74b50b0 Documentation fixes 2016-05-21 15:07:43 -07:00
Percy Liang 2a35fd89da Merge pull request #94 from crazydonkey200/bugfix-expandPrefix
Fix a bug in expanding prefix of a triple's second argument.
2016-04-28 22:56:50 -07:00
Percy Liang 2101cec812 Merge pull request #64 from joymufeng/master
Remove the dependency of edu.stanford.nlp.io.IOUtils
2016-04-28 22:54:01 -07:00
Panupong (Ice) Pasupat fc5cd62fc4 Merge pull request #95 from ppasupat/import-from-ice-tables-core-major
More changes to core classes
2016-04-23 14:02:38 -07:00
crazydonkey200 9c1b2b4ad7 Handle both cases (when there is and is not a space before ".") and escape "." in the regular expression with backslash. 2016-04-23 15:51:50 -05:00
Panupong Pasupat 7eff08dd0f Minor edits 2016-04-22 17:02:11 -07:00
Panupong Pasupat 6fdfe96db0 Formatting issues 2016-04-20 15:21:03 -07:00
Panupong Pasupat 94a4a87e3a Removed MutatingParser; already added to Parser 2016-04-20 15:19:30 -07:00
Panupong Pasupat f9537ec5de Fixed some errors 2016-04-20 15:17:07 -07:00
Panupong Pasupat 1a89ab2495 Made more edits to the core package 2016-04-20 15:08:46 -07:00
Panupong (Ice) Pasupat ab7b7e6bd2 Merge pull request #92 from ppasupat/import-from-ice-tables-core-minor
Edited several functions in core classes
2016-04-20 13:34:54 -07:00
Panupong Pasupat a121d16e02 Minor edits 2016-04-20 13:34:23 -07:00
Panupong Pasupat a7a64bb254 Let's deal with evaluator later 2016-04-18 13:50:13 -07:00
crazydonkey200 0d9cd664c8 Fixed a bug in expanding prefix of a triple's second argument.
More details in https://github.com/percyliang/sempre/issues/93
2016-04-15 19:16:45 -05:00
Panupong Pasupat 1f7264555d Edited pull-dependencies and YearRangeFn 2016-04-14 14:51:15 -07:00
Panupong Pasupat bfdcf2cd59 Removed classes used only in tables package 2016-04-13 17:33:00 -07:00
Panupong Pasupat 9e9cb927a1 Resolved some comments 2016-04-13 17:13:03 -07:00
Panupong Pasupat 2f80d51b0a Removed ExecutorCache 2016-04-11 16:44:48 -07:00
Panupong Pasupat 83cb3946d6 Edited several functions in core classes 2016-04-10 21:09:51 -07:00
Panupong (Ice) Pasupat 47c6c0ff79 Merge pull request #91 from ppasupat/import-from-local-master-tables-stuff
Table-releated code and resources from local repository's master branch
2016-04-10 17:54:01 -07:00
Panupong Pasupat 5ced249846 Renamed mutate 2016-04-10 17:53:31 -07:00
Panupong Pasupat 31189e902e Merge branch 'develop' into import-from-local-master-tables-stuff 2016-04-10 17:52:41 -07:00
Panupong (Ice) Pasupat 71ab4f2638 Merge pull request #90 from ppasupat/import-from-local-core
Patched from master branch of local repository (core code and scripts)
2016-04-10 17:43:38 -07:00
Panupong Pasupat 80a5114fe1 Renamed method mutate 2016-04-10 17:42:40 -07:00
Panupong Pasupat c1e1793b5d Removed MutatingParser 2016-04-10 01:53:56 -07:00
Panupong Pasupat 7b6d95301e Deleted unused freebase files and removed MutatingParser interface 2016-04-10 01:44:40 -07:00
Panupong Pasupat 537bf66429 Missing image 2016-04-09 23:23:28 -07:00
Panupong Pasupat 506314c5e6 Table stuff from master branch 2016-04-09 23:13:14 -07:00
Panupong Pasupat 791cdd13dc Added changes to core code (mostly code edits) 2016-04-09 23:08:25 -07:00
Panupong Pasupat 0a436b811f Added auxiliary data 2016-04-09 23:07:35 -07:00
Panupong Pasupat 9f45a3a360 Added information about develop branch 2016-04-08 12:48:59 -07:00
Panupong (Ice) Pasupat 3f4328b287 Update tutorial.ttl
A quick fix to make the TTL file correct.
2016-01-26 11:14:14 -08:00
Percy Liang 4491704aec change license 2016-01-08 21:02:02 -08:00
Percy Liang b4d4e83725 change license 2016-01-08 21:01:13 -08:00
Panupong Pasupat 81394a171b Edited the run file to make @mode=freebase work. 2015-08-06 21:21:38 -07:00
Panupong Pasupat 9158ed41b4 Make core not dependent on corenlp 2015-08-06 20:51:11 -07:00
yonatansito 6ac9350168 Merge pull request #69 from h1395010/master
Update README.md
2015-08-02 23:49:39 -07:00
S. Matthew English 9ff7738d6e Update README.md 2015-07-27 21:11:55 +08:00
joymufeng d619c0c9d8 Remove the dependency of edu.stanford.nlp.io.IOUtils 2015-07-04 16:09:13 +08:00
Jonathan Berant a432073cb2 adding missing file freebase tutorial lexicon file 2015-07-01 07:57:28 -07:00
Panupong (Ice) Pasupat 29a5d33aee Update build.xml 2015-06-16 21:07:40 -07:00
Panupong (Ice) Pasupat 7cadf2c469 Update README.md 2015-06-16 20:59:01 -07:00
Panupong Pasupat 64a021f2ed Updated overnight and tables 2015-06-16 20:55:53 -07:00
Panupong Pasupat 9178eb7322 Added tables and overnight modules 2015-06-04 18:01:24 -07:00
394 changed files with 40104 additions and 1447 deletions

46
.gitignore vendored Normal file
View File

@ -0,0 +1,46 @@
lib
fig
sfig
refdb
virtuoso-opensource
classes
libsempre
sempre.jar
module-classes.txt
state
out
test-output
.project
.classpath
.settings
.idea
semparse.iml
*~
*.swp
*.bak
*.pyc
*.cache
*.DS_Store
java.hprof.txt
# Don't put papers here
/papers
# Symlinks
/c
/e
/t
/x
scr
rdf
# interactive outputs
int-output*
int-backup
interactive/.ipynb_checkpoints
# Community server logs
community-server/data
community-server/data-backup

View File

@ -146,7 +146,7 @@ The possible `Value`s, along with an example are as follows:
In general:
(table (<header-string-1> ... <header-string-n>) (<row-1-value-1> ... <value-1-value-n>) ...)
(table (<header-string-1> ... <header-string-n>) (<row-1-value-1> ... <row-1-value-n>) ...)
There are some more arcane `Value`s (see `Values.java` for a list), but they
are not that important from the point of view of specifying a logical form.
@ -945,7 +945,7 @@ which are used in our first sematic parsing applications, but they probably
should be avoided unless you're specifically doing Freebase QA. Even in that
case, the main thing you should think about is:
(rule $Entity ($PHRASE) (LexiconFn fbsearch)
(rule $Entity ($PHRASE) (LexiconFn fbsearch))
which uses the Freebase Search API to look up entities. Be aware here that the
API will generously return many candidate entities for any string you give it,

View File

@ -1,340 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (c) 2013, Stanford University.
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at
Preamble
http://www.apache.org/licenses/LICENSE-2.0
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

View File

@ -1,38 +0,0 @@
BUILD_DEPS = libsempre/sempre-core.jar \
libsempre/sempre-cache.jar \
libsempre/sempre-freebase.jar \
libsempre/sempre-fbalignment.jar \
libsempre/sempre-paraphrase.jar \
libsempre/sempre-corenlp.jar \
libsempre/sempre-jungle.jar
default: module-classes $(BUILD_DEPS)
module-classes:
scripts/extract-module-classes.rb
core: libsempre/sempre-core.jar
libsempre/sempre-core.jar: \
$(shell ls src/edu/stanford/nlp/sempre/*.java) \
$(shell ls src/edu/stanford/nlp/sempre/test/*.java)
cd src/edu/stanford/nlp/sempre && ant compile
cache: libsempre/sempre-cache.jar
libsempre/sempre-cache.jar: \
$(shell find src/edu/stanford/nlp/sempre/cache -name "*.java")
cd src/edu/stanford/nlp/sempre/cache && ant compile
corenlp: libsempre/sempre-corenlp.jar
libsempre/sempre-corenlp.jar: libsempre/sempre-core.jar libsempre/sempre-cache.jar \
$(shell find src/edu/stanford/nlp/sempre/corenlp -name "*.java")
cd src/edu/stanford/nlp/sempre/corenlp && ant compile
freebase: libsempre/sempre-freebase.jar
libsempre/sempre-freebase.jar: libsempre/sempre-core.jar libsempre/sempre-cache.jar \
$(shell find src/edu/stanford/nlp/sempre/freebase -name "*.java")
cd src/edu/stanford/nlp/sempre/freebase && ant compile
clean:
rm -rf classes libsempre

View File

@ -1,4 +1,4 @@
# SEMPRE 2.0: Semantic Parsing with Execution
# SEMPRE 2.4: Semantic Parsing with Execution
## What is semantic parsing?
@ -24,7 +24,7 @@ A virtual travel agent task:
- Denotation: `(list ...)`
By parsing utterances into logical forms, we obtain a rich representation that
enables mucher deeper, context-aware understanding beyond the words. With the
enables much deeper, context-aware understanding beyond the words. With the
rise of natural language interfaces, semantic parsers are becoming increasingly
more powerful and useful.
@ -62,6 +62,8 @@ SEMPRE has been used in the following papers:
offshoot, and does not use many of the core learning and parsing utiltiies in
SEMPRE. To reproduce those results, check out SEMPRE 1.0.
Please refer to the [project page](https://nlp.stanford.edu/software/sempre/) for a more complete list.
## Where do I go next?
- If you're new to semantic parsing, you can learn more from the [background
@ -82,6 +84,8 @@ You must have the following already installed on your system.
- Ant 1.8.2
- Ruby 1.8.7 or 1.9
- wget
- make (for compiling fig and Virtuoso)
- zip (for unzip downloaded dependencies)
Other dependencies will be downloaded as you need them. SEMPRE has been tested
on Ubuntu Linux 12.04 and MacOS X. Your mileage will vary depending on how
@ -95,18 +99,21 @@ similar your system is.
2. Download the minimal core dependencies (all dependencies will be placed in `lib`):
./pull-dependencies core
ruby ./pull-dependencies core
3. Compile the source code (this produces `libsempre/sempre-core.jar`):
make core
ant core
If there is any issue during compilation, try deleting the directories `lib` and `fig`
and rerunning `./pull-dependencies core`
4. Run an interactive shell:
./run @mode=simple
ruby ./run @mode=simple
You should be able to type the following into the shell and get the answer `(number 7)`:
(execute (call + (number 3) (number 4)))
To go further, check out the [tutorial](TUTORIAL.md) and then the [full
@ -118,24 +125,40 @@ If you will be using natural language to query databases (e.g., Freebase), then
you will also need to setup your own Virtuoso database (unless someone already
has done this for you):
# For Ubuntu, make sure these dependencies are installed
For Ubuntu, follow this:
sudo apt-get install -y automake gawk gperf libtool bison flex libssl-dev
# Clone the repository
git clone https://github.com/openlink/virtuoso-opensource
./pull-dependencies virtuoso
# Make and install
cd virtuoso-opensource
git checkout tags/v7.0.0
# Configure
./autogen.sh
mv INSTALL INSTALL.txt # Avoid conflict on case-insensitive file systems
./configure --prefix=$PWD/install
# Make (this takes a while)
make
make install
cd ..
on OS/X you can install virtuoso using homebrew by following the instructions
[here](http://carsten.io/virtuoso-os-on-mac-os/)
To have SEMPRE interact with Virtuoso, the required modules need to be compiled as follow:
./pull-dependencies core corenlp freebase
ant freebase
# Contribute
To contribute code or resource to SEMPRE:
- Create a fork of the repository. If you already have a fork,
it is a good idea to sync with the upstream repository first.
- Push your changes to a new branch in your fork.
- Start a pull request: go to your branch on the GitHub website,
then click "New pull request". Please specify the `develop` branch
of the upstream repository.
# ChangeLog
Changes from SEMPRE 1.0 to SEMPRE 2.0:
@ -146,10 +169,23 @@ Changes from SEMPRE 1.0 to SEMPRE 2.0:
- Removed fbalignment (EMNLP 2013) and paraphrase (ACL 2014) components to
avoid confusion. If you want to reproduce those systems, use SEMPRE 1.0.
# License
Changes from SEMPRE 2.0 to SEMPRE 2.1:
SEMPRE is licensed under the [GNU General Public
License](http://www.gnu.org/licenses/gpl-2.0.html) (v2 or later).
Note that this is the /full/ GPL, which allows many free uses, but not
its use in distributed [proprietary
software](http://www.gnu.org/licenses/gpl-faq.html#GPLInProprietarySystem).
- Added the `tables` package for the paper *Compositional semantic parsing on semi-structured tables* (ACL 2015).
- Add and `overnight` package for the paper *Building a semantic parser overnight* (ACL 2015).
Changes from SEMPRE 2.1 to SEMPRE 2.2:
- Added code for the paper *Inferring Logical Forms From Denotations* (ACL 2016).
Changes from SEMPRE 2.2 to SEMPRE 2.3:
- Added the `interactive` package for the paper *Naturalizing a programming language through interaction* (ACL 2017).
Changes from SEMPRE 2.3 to SEMPRE 2.3.1:
- Modified the `tables` module to resemble SEMPRE 2.1, effectively making it work again.
Changes from SEMPRE 2.3.1 to SEMPRE 2.4:
- Added the `cprune` package for the paper *Macro Grammars and Holistic Triggering for Efficient Semantic Parsing* (EMNLP 2017).

View File

@ -17,7 +17,8 @@ Recall that in semantic parsing, *natural language utterances* are mapped into
*logical forms* (think programs), which are executed to produce some
*denotation* (think return value).
We have assumed you have already downloaded SEMPRE and can open up a shell:
We have assumed you have already [installed](README.md#installation)
SEMPRE and can open up a shell:
./run @mode=simple
@ -32,7 +33,7 @@ shell command and executes it. To see which command is run, do:
This should print out:
rlwrap java -cp libsempre/*:lib/* -ea edu.stanford.nlp.sempre.Main -interactive
java -cp libsempre/*:lib/* -ea edu.stanford.nlp.sempre.Main -Main.interactive
You can pass in additional options:
@ -175,7 +176,7 @@ derivation representing a number.
Now, you can parse the following:
four
2.718
20
Note: if you now type in `three`, you should get two derivations that yield the
same answer, one coming from each rule. Note that `twenty-five million` will
@ -334,7 +335,7 @@ The complete derivation for *three plus four* is illustrated here:
three plus four
**Exercise 2.1**: write rules can parse the following utterances into
**Exercise 2.1**: write rules that can parse the following utterances into
into the category `$Expr`:
length of hello world # 11
@ -375,7 +376,7 @@ You can put a set of grammar rules in a file (e.g.,
./run @mode=simple -Grammar.inPaths data/tutorial-arithmetic.grammar
If you make edit the grammar, you can reload the grammar without exiting the
If you edit the grammar, you can reload the grammar without exiting the
prompt by typing:
(reload)
@ -396,7 +397,7 @@ etc.):
Compile it:
make corenlp
ant corenlp
Now we can load the SEMPRE interactive shell with `CoreNLPAnalyzer`:
@ -552,7 +553,7 @@ where $s$ and $o$ are entities and $p$ is a property. For example:
is one triple. If we think of the entities as nodes in a directed graph, the
each triple is a directed edge between two nodes labeled with the property.
See `data/tutorial.ttl` for an example of a tiny subset of the Freebase graph
See `freebase/data/tutorial.ttl` for an example of a tiny subset of the Freebase graph
pertaining to geography about California.
First, pull the dependencies needed for Freebase:
@ -586,7 +587,7 @@ To stop the server:
### Setting up a copy of Freebase
The best case is someone already installed Freebase for you and handed you a
host:port. Otherwise, to run your own copy of the Freebase graph (a
host:port. Otherwise, to run your own copy of the entire Freebase graph (a
2013 snapshot), read on.
Download it (this is really big and takes a LONG time):
@ -611,12 +612,9 @@ We assume you have started the Virtuoso database:
Then start up a prompt:
./run @mode=simple-freebase @sparqlserver=localhost:3001
The simplest logical formula in lambda DCS is a single entity:
fb:en.california
./run @mode=simple-freebase-nocache @sparqlserver=localhost:3001
The simplest logical formula in lambda DCS is a single entity such as `fb:en.california`.
To execute this query, simply type the following into the interactive prompt:
(execute fb:en.california)
@ -753,7 +751,7 @@ is the basis for the overloading.
Now start the interactive prompt:
./run @mode=simple-freebase @sparqlserver=localhost:3001 -Grammar.inPaths freebase/data/tutorial-freebase.grammar -SimpleLexicon.inPaths freebase/data/tutorial-freebase.lexicon
./run @mode=simple-freebase-nocache @sparqlserver=localhost:3001 -Grammar.inPaths freebase/data/tutorial-freebase.grammar -SimpleLexicon.inPaths freebase/data/tutorial-freebase.lexicon
We should be able to parse the following utterances:

130
build.xml Normal file
View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<project default="compile" name="semparse">
<!-- Set useful variables -->
<property name="target" value="1.8"/>
<property name="source" value="1.8"/>
<property name="root" value="."/>
<property name="src" location="${root}/src/"/>
<property name="classes" location="${root}/classes"/>
<property name="lib" location="${root}/lib"/>
<property name="libsempre" location="${root}/libsempre"/>
<path id="lib.path">
<fileset dir="${libsempre}" includes="*.jar"/>
<fileset dir="${lib}" includes="*.jar"/>
</path>
<!-- Create directories -->
<target name="init">
<exec executable="${root}/scripts/extract-module-classes.rb"/>
<mkdir dir="${classes}"/>
<mkdir dir="${libsempre}"/>
</target>
<!-- Compile -->
<target name="compile" depends="init">
<antcall target="compile.released"/>
</target>
<target name="compile.released" depends="init,core,cache,corenlp,freebase,tables,cprune,overnight"/>
<!-- Compile core -->
<target name="core" depends="init">
<echo message="Compiling ${ant.project.name}: core"/>
<mkdir dir="${classes}"/>
<javac srcdir="${src}" destdir="${classes}" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/*.java"/>
<include name="edu/stanford/nlp/sempre/test/"/>
</javac>
<jar destfile="${libsempre}/sempre-core.jar" basedir="${classes}" includes="edu/**"/>
</target>
<!-- Compile cache -->
<target name="cache" depends="init">
<echo message="Compiling ${ant.project.name}: cache"/>
<mkdir dir="${classes}/cache"/>
<javac srcdir="${src}" destdir="${classes}/cache" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/cache/"/>
</javac>
<jar destfile="${libsempre}/sempre-cache.jar" basedir="${classes}/cache"/>
</target>
<!-- Compile corenlp -->
<target name="corenlp" depends="init,core,cache">
<echo message="Compiling ${ant.project.name}: corenlp"/>
<mkdir dir="${classes}/corenlp"/>
<javac srcdir="${src}" destdir="${classes}/corenlp" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/corenlp/"/>
</javac>
<jar destfile="${libsempre}/sempre-corenlp.jar" basedir="${classes}/corenlp"/>
</target>
<!-- Compile freebase -->
<target name="freebase" depends="init,core,cache">
<echo message="Compiling ${ant.project.name}: freebase"/>
<mkdir dir="${classes}/freebase"/>
<javac srcdir="${src}" destdir="${classes}/freebase" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/freebase/"/>
</javac>
<jar destfile="${libsempre}/sempre-freebase.jar" basedir="${classes}/freebase"/>
</target>
<!-- Compile tables -->
<target name="tables" depends="init,core,corenlp,cprune">
<echo message="Compiling ${ant.project.name}: tables"/>
<mkdir dir="${classes}/tables"/>
<javac srcdir="${src}" destdir="${classes}/tables" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/tables/"/>
</javac>
<jar destfile="${libsempre}/sempre-tables.jar" basedir="${classes}/tables"/>
</target>
<!-- Compile cprune -->
<target name="cprune" depends="init,core">
<echo message="Compiling ${ant.project.name}: cprune"/>
<mkdir dir="${classes}/cprune"/>
<javac srcdir="${src}" destdir="${classes}/cprune" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/cprune/"/>
</javac>
<jar destfile="${libsempre}/sempre-cprune.jar" basedir="${classes}/cprune"/>
</target>
<!-- Compile overnight -->
<target name="overnight" depends="init,core">
<echo message="Compiling ${ant.project.name}: overnight"/>
<mkdir dir="${classes}/overnight"/>
<javac srcdir="${src}" destdir="${classes}/overnight" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/overnight/"/>
</javac>
<jar destfile="${libsempre}/sempre-overnight.jar" basedir="${classes}/overnight"/>
</target>
<!-- Compile interactive -->
<target name="interactive" depends="init,core">
<echo message="Compiling ${ant.project.name}: interactive"/>
<mkdir dir="${classes}/interactive"/>
<javac srcdir="${src}" destdir="${classes}/interactive" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/interactive/"/>
</javac>
<jar destfile="${libsempre}/sempre-interactive.jar" basedir="${classes}/interactive"/>
</target>
<!-- Compile geo880 -->
<target name="geo880" depends="init,core,corenlp,tables">
<echo message="Compiling ${ant.project.name}: geo880"/>
<mkdir dir="${classes}/geo880"/>
<javac srcdir="${src}" destdir="${classes}/geo880" classpathref="lib.path" debug="true" includeantruntime="false" source="${source}" target="${target}">
<include name="edu/stanford/nlp/sempre/geo880/"/>
</javac>
<jar destfile="${libsempre}/sempre-geo880.jar" basedir="${classes}/geo880"/>
</target>
<!-- Clean up -->
<target name="clean">
<delete includeemptydirs="true" quiet="true">
<fileset dir="${classes}" followsymlinks="false"/>
<fileset dir="${libsempre}" followsymlinks="false"/>
<fileset file="module-classes.txt" followsymlinks="false"/>
</delete>
</target>
</project>

View File

@ -0,0 +1,6 @@
{"lexeme": "california", "formula": "fb:en.california"}
{"lexeme": "the golden state", "formula": "fb:en.california"}
{"lexeme": "cities", "formula": "(fb:type.object.type fb:location.citytown)"}
{"lexeme": "towns", "formula": "(fb:type.object.type fb:location.citytown)"}
{"lexeme": "in", "formula": "fb:location.location.containedby"}
{"lexeme": "located in", "formula": "fb:location.location.containedby"}

View File

@ -1,21 +1,21 @@
@prefix fb: <http://rdf.freebase.com/ns/>.
@prefix fb: <http://rdf.freebase.com/ns/> .
fb:en.los_angeles fb:location.location.containedby fb:en.california.
fb:en.san_francisco fb:location.location.containedby fb:en.california.
fb:en.mount_whitney fb:location.location.containedby fb:en.california.
fb:en.los_angeles fb:location.location.containedby fb:en.california .
fb:en.san_francisco fb:location.location.containedby fb:en.california .
fb:en.mount_whitney fb:location.location.containedby fb:en.california .
fb:en.seattle fb:type.object.type fb:location.citytown.
fb:en.san_francisco fb:type.object.type fb:location.citytown.
fb:en.los_angeles fb:type.object.type fb:location.citytown.
fb:en.mount_whitney fb:type.object.type fb:geography.mountain.
fb:en.california fb:type.object.type fb:location.us_state.
fb:en.seattle fb:type.object.type fb:location.citytown .
fb:en.san_francisco fb:type.object.type fb:location.citytown .
fb:en.los_angeles fb:type.object.type fb:location.citytown .
fb:en.mount_whitney fb:type.object.type fb:geography.mountain .
fb:en.california fb:type.object.type fb:location.us_state .
fb:en.seattle fb:type.object.name "Seattle"@en.
fb:en.san_francisco fb:type.object.name "San Francisco"@en.
fb:en.los_angeles fb:type.object.name "Los Angeles"@en.
fb:en.mount_whitney fb:type.object.name "Mount Whitney"@en.
fb:en.california fb:type.object.name "California"@en.
fb:en.seattle fb:type.object.name "Seattle"@en .
fb:en.san_francisco fb:type.object.name "San Francisco"@en .
fb:en.los_angeles fb:type.object.name "Los Angeles"@en .
fb:en.mount_whitney fb:type.object.name "Mount Whitney"@en .
fb:en.california fb:type.object.name "California"@en .
fb:en.seattle fb:location.location.area "369.2"^^xsd:double.
fb:en.san_francisco fb:location.location.area "600.6"@en.
fb:en.los_angeles fb:location.location.area "1301.97"^^xsd:double.
fb:en.seattle fb:location.location.area "369.2"^^xsd:double .
fb:en.san_francisco fb:location.location.area "600.6"@en .
fb:en.los_angeles fb:location.location.area "1301.97"^^xsd:double .

View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
require 'open-uri'

View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
require 'open-uri'
require 'json'

View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
# This script provides a convenient wrapper for the Virtuoso SPARQL server.
@ -151,7 +151,7 @@ def add
# Virtuoso can't handle prefixes in the second argument, so need to expand.
tmp = "virtuoso-#{port}-#{i}.ttl"
log "==== Step A: Converting #{ttl} to #{tmp}..."
run "time #{chunkCmd} -indices #{i} | sed -r -e 's/\\tfb:([^\\t]*).$/\\t\\<http:\\/\\/rdf.freebase.com\\/ns\\/\\1\\>./' > #{tmp}"
run "time #{chunkCmd} -indices #{i} | sed -r -e 's/\\tfb:([^\\t ]*)[\\t ]*\\.$/\\t\\<http:\\/\\/rdf.freebase.com\\/ns\\/\\1\\>./' > #{tmp}"
# Index the ttl file
log "==== Step B: Indexing #{tmp}..."

115
interactive/README.md Normal file
View File

@ -0,0 +1,115 @@
# README
This `interactive` package is the code for our paper
*Naturalizing a programming language through interaction* (ACL 2017).
A live demo is at [www.voxelurn.com](http://www.voxelurn.com).
voxelurn is a language interface to a voxel world.
This server handles commands used to learn from definitions, and other interactive queries.
In this setting, the system begin with the dependency-based action language (`dal.grammar`), and gradually expand the language through interacting with it users.
## Overview of the components
### sempre.interactive
The `edu.stanford.nlp.sempre.interactive` package live in this repo contains code for
* running interactive commands (such as query, accept, reject, definition)
* executor for the dependency-based action (DAL) language
* voxelurn specific code in `edu.stanford.nlp.sempre.interactive.voxelurn` for actually generating the voxel and manipulating them
Utilties and resources such as the grammar and run script are in this directory, and the code in in the regular `sempre/src` directory.
### voxelurn client
It queries the server, and renders the voxels to a browser. A live version is at [www.voxelurn.com](http://www.voxelurn.com), which queries our server. You can also find a client for localhost at [http://local.voxelurn.com](http://local.voxelurn.com), which is the same client, but with queries going to `http://localhost:8410` instead.
Code for the client at `https://github.com/sidaw/shrdlurn`. See its [README.md](https://github.com/sidaw/shrdlurn/blob/master/README.md) if you want to work with and build the client yourself.
### voxelurn community server
Located at `interactive/community-server`, the community server
handles other functionalities such as logging client actions, leaderboard, submiting structures, authentication etc. and generally functions not related to parsing. This server is needed for running interactive experiments, but is not required just for trying out voxelurn.
## Running the SEMPRE server for Voxelurn
0. Setup SEMPRE dependencies and compile
./pull-dependencies core
ant interactive
1. Start the server
./interactive/run @mode=voxelurn -server -interactive
things in the core language such as `add red left`, `repeat 3 [select left]` should work.
2. Feed the server existing definitions, which should take less than 2 minutes.
./interactive/run @mode=simulator @server=local @sandbox=none @task=freebuilddef -maxQueries 2496
try `add dancer` now.
### Interacting with the server
After you run the above, there are 3 ways to interact and try your own commands.
* The visual way is to use the client: [http://local.voxelurn.com](http://local.voxelurn.com).
Code for the client is at `https://github.com/sidaw/shrdlurn` (see its [README.md](https://github.com/sidaw/shrdlurn/blob/master/README.md)).
Try `[add dancer; front 5] 3 times`.
* Hit `Ctrl-D` on the terminal running the server, and type `add red top`, or `add green monster`
* On a browser, type `http://localhost:8410/sempre?q=(:q add green monster)`
## Experiments in ACL2017
1. Start the server
./interactive/run @mode=voxelurn -server -interactive
2. Feed the server all the query logs
./interactive/run @mode=simulator @server=local @sandbox=none @task=freebuild -maxQueries 103874
This currently takes just under 30 minutes. Decrease maxQuery for a quicker experiment. This generate `plotInfo.json` in `./state/execs/${lastExec}.exec/` where `lastExec` is `cat ./state/lastExec`.
3. Taking `../state/execs/${lastExec}.exec/plotInfo.json` as input, we can analyze the data and produce some plots using the following ipython notebook
ipython notebook interactive/analyze_data.ipynb
which prints out basic statistics and generates the plots used in our paper. The plots are saved at `../state/execs/${lastExec}.exec/`
## Misc.
There are some unit tests
./interactive/run @mode=test
To specify a specific test class and verbosity
./interactive/run @mode=test @class=DALExecutorTest -verbose 5
Clean up or backup data
./interactive/run @mode=backup # save previous data logs
./interactive/run @mode=trash # deletes previous data logs
Data, in .gz can be found in queries.
* `./interactive/queries/freebuild.def.json.gz`
has 2495 definitions combining just over 10k utterances.
* `./interactive/queries/freebuild.json.gz` has 103873 queries made during the main experiment.
## Voxelurn community server (optional and in development)
This server helps with client side logging, leaderboard, authentication etc. basically anything that is not directly related to parsing.
This component is only required if you want to run the interactive experiment yourself. It is fairly coupled with the [voxelurn client](http://github.com/sidaw/shrdlurn), which sends the request to this server.
cd interactive/community-server
python install-deps.py
python server.py --port 8403
# required keys for authentication
export SEMPRE_JWT_SECRET=ANY_RANDOM_SEQEUNCE
export SLACK_OAUTH_SECRET=OAUTH_KEY_FROM_SLACK

View File

@ -0,0 +1,424 @@
{
"cells": [
{
"cell_type": "raw",
"metadata": {},
"source": [
"A line looks like this\n",
" \"time\": \"2017-01-21T05:31:57.474\",\n",
" \"id\": \"AMT_A1HKYY6XI2OHO1\",\n",
" \"log\": \"(:q \\\"repeat 10 [ Ebony Wall; select front]\\\")\",\n",
" \"stats.type\": \"q\",\n",
" \"stats.size\": 1,\n",
" \"stats.status\": \"Induced\",\n",
" \"queryCount\": 2707"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import csv\n",
"import numpy as np\n",
"import pandas as pd \n",
"import matplotlib\n",
"import matplotlib.pyplot as plt\n",
"import json\n",
"import os\n",
"import subprocess\n",
"from collections import OrderedDict\n",
"%matplotlib inline \n",
"\n",
"with open('../state/lastExec', 'rb') as lastExec:\n",
" lastExecInd = lastExec.readline().strip()\n",
"print lastExecInd\n",
" \n",
"rows = []; \n",
"execInd = lastExecInd;\n",
"execPath = '../state/execs/%s.exec/' % execInd\n",
"#print 'analyzing: ' + execPath\n",
"def printOptions():\n",
" with open(os.path.join(execPath,'options.map')) as optionsfile:\n",
" opts = filter(lambda l: 'file' in l or 'logFiles' in l or 'reqParams' in l, optionsfile.readlines());\n",
" for opt in opts: print opt.strip()\n",
" # egrep 'file|Simulator'\n",
"printOptions()\n",
"\n",
"with open('../state/execs/%s.exec/plotInfo.json' % execInd, 'rb') as jsonfile:\n",
" json_lines = jsonfile.readlines()\n",
"\n",
"rawrows = [json.loads(l) for l in json_lines]\n",
"rows = [r for r in rawrows if r.has_key('stats.type')]\n",
"\n",
"print '%d queries in plotInfo' % len(json_lines)\n",
"\n",
"def print_defstats():\n",
" filtered_rows = [r for r in rows if r['stats.type'] == 'def' and r['stats.num_rules'] >= 1]\n",
" total_failed = np.sum([r['stats.num_failed'] for r in filtered_rows])\n",
" total_body = np.sum([r['stats.num_body'] for r in filtered_rows])\n",
"\n",
" stats = {\\\n",
" 'total_def_queries': len(filtered_rows), \\\n",
" 'total_rules': np.sum([r['stats.num_rules'] for r in filtered_rows]), \\\n",
" 'total_failed': total_failed, \\\n",
" 'total_body': total_body\n",
" }\n",
" print ''\n",
" print stats\n",
" print 'failpercent: %.4f' % (float(total_failed)/float(total_body))\n",
"print_defstats()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": false
},
"outputs": [],
"source": [
"\n",
"\n",
"def print_stats():\n",
" filtered_rows = [r for r in rows if r['stats.type'] == 'accept']\n",
" induced_rows = [r for r in rows if r['stats.type'] == 'accept' and r['stats.status']=='Induced']\n",
" core_rows = [r for r in rows if r['stats.type'] == 'accept' and r['stats.status']=='Core']\n",
" none_rows = [r for r in rows if r['stats.type'] == 'accept' and r['stats.status']=='Nothing']\n",
"\n",
" stats = {\\\n",
" 'accepted': len(filtered_rows), \\\n",
" 'induced': len(induced_rows), \\\n",
" 'inducedp':len(induced_rows)/float(len(filtered_rows)),\\\n",
" 'core': len(core_rows), \\\n",
" 'corep':len(core_rows)/float(len(filtered_rows)),\\\n",
" 'none': len(none_rows), \\\n",
" 'nonep':len(none_rows)/float(len(filtered_rows))\\\n",
" }\n",
" print '\\nCount of accepted query / percentage'\n",
" print ' total:{accepted}\\n induced:{induced}({inducedp:.4f})\\n core:{core}({corep:.4f})\\n none:{none}({nonep:.4f}),'.format(**stats)\n",
" #print 'check %f' % (stats['inducedp']+stats['corep']+stats['nonep'])\n",
" \n",
" statscorrect = {\n",
" 'accepted0': np.mean([1 if r['stats.rank']==0 and r['stats.status']!='Nothing' else 0 for r in filtered_rows]),\\\n",
" 'accepted1': np.mean([1 if r['stats.rank']>=0 and r['stats.status']!='Nothing' else 0 for r in filtered_rows]),\\\n",
" 'induced0': np.mean([1 if r['stats.rank']==0 and r['stats.status']=='Induced' else 0 for r in filtered_rows]),\\\n",
" 'induced1': np.mean([1 if r['stats.rank']>=0 and r['stats.status']=='Induced' else 0 for r in filtered_rows]),\\\n",
" 'core0': np.mean([1 if r['stats.rank']==0 and r['stats.status']=='Core' else 0 for r in filtered_rows]),\\\n",
" 'core1': np.mean([1 if r['stats.rank']>=0 and r['stats.status']=='Core' else 0 for r in filtered_rows])\\\n",
" }\n",
" print '\\nranked 1 accepted / found accepted'\n",
" print ' total:{accepted0:.4f}/{accepted1:.4f}\\n induced:{induced0:.4f}/{induced1:.4f}\\n core:{core0:.4f}/{core1:.4f}'.format(**statscorrect)\n",
"\n",
" token_types = set();\n",
" rows_types = [r for r in rows if r['stats.type'] == 'q'];\n",
" for r in rows_types:\n",
" token_types |= set(r['q'].split(' '))\n",
" \n",
" print '\\nThere are %d token types of %d query types' % (len(token_types), len(rows_types))\n",
"print_stats()\n",
"\n",
"def percent_core():\n",
" allq = [r for r in rows if r['stats.type'] == 'accept'];\n",
" is_status = [100 if r['stats.status'] == 'Induced' else 0 for r in allq]\n",
" print 'percent_induced %f' % np.mean(is_status)\n",
" print 'percent_induced_last10k %f' % np.mean(is_status[len(is_status)-10000:])\n",
"percent_core()\n",
"\n",
"# print filtered_rows[0]\n",
"\n",
"\n",
"\n",
"def percent_error():\n",
" allerror = [r for r in rawrows if r.has_key('stats.error')];\n",
" alluerror = [r for r in rawrows if r.has_key('stats.uncaught_error')];\n",
" print 'errors %d (%d uncaught)' % (len(allerror), len(alluerror))\n",
"percent_error()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"\n",
"def plot_reset():\n",
" global p\n",
" p = {'color': 'r', 'linewidth': 2, 'alpha':0.5}\n",
" #, 'marker':'*', 'markersize':0.3}\n",
"plot_reset()\n",
"def savefig(filename = 'fig.pdf'):\n",
" plt.savefig(os.path.join(execPath,filename) , bbox_inches=\"tight\")\n",
"\n",
"def plot_cumavg(x, y, xlabel='query#', ylabel='recall', title=None):\n",
" y_cum = np.cumsum(y).tolist()\n",
" #print accepts_np[:,1]\n",
" y_cumavg = [cum / float(count+1) for count,cum in enumerate(y_cum)]\n",
" #N = 500;\n",
" #y_cumavg = np.convolve(np.array(y), np.ones((N,))/N, mode='same').tolist()\n",
" #print accept_rate \n",
" #plt.scatter(means_baseline[0:], means[0:], s=colors, alpha=0.8, c='r')\n",
" plt.plot(x, y_cumavg, **p)\n",
" \n",
" plt.xlabel(xlabel, fontsize=12)\n",
" plt.ylabel(ylabel, fontsize=12)\n",
" # plt.xlim(0, 0.65)\n",
" plt.ylim(0, max(y_cumavg)*1.02)\n",
" plt.xlim(0, len(rows)*1.02)\n",
" xp = np.linspace(0, 0.65, 300)\n",
" \n",
" #plt.gca().set_aspect('equal', adjustable='box')\n",
" plottitle = title if title is not None else '%s_vs_%s.pdf' % (xlabel, ylabel)\n",
" # plt.savefig(os.path.join(execPath,plottitle) , bbox_inches=\"tight\")\n",
" \n",
"def print_avg(x, name = 'unnamed'):\n",
" print 'avg(%s): %f' % (name, reduce(lambda a,b: a+b, x) / float(len(x)));\n",
"def average_stat(stat = 'stats.size', type = 'accept'):\n",
" filtered_rows = [r for r in rows if r['stats.type'] == type]\n",
" query_counts = [r['queryCount'] for r in filtered_rows]\n",
" stats = [r[stat] for r in filtered_rows]\n",
" plot_cumavg(query_counts, stats, xlabel='query#', ylabel=stat.replace('stats.','').replace('size','# parses'));\n",
" print_avg(stats, stat)\n",
"plt.figure()\n",
"p['color'] = 'b'\n",
"average_stat(stat = 'stats.size')\n",
"#savefig('ambiguity.pdf')\n",
"\n",
"\n",
"def precent_status(filtered_rows, status = 'Core'):\n",
" query_counts = [r['queryCount'] for r in filtered_rows]\n",
" is_status = [100 if r['stats.status'] == status else 0 for r in filtered_rows]\n",
" print_avg(is_status, 'percent of status ' + status)\n",
" plot_cumavg(query_counts, is_status, xlabel='query #', ylabel='percent');\n",
"\n",
"\n",
"def plotCoreInducedNone(filtered_rows):\n",
" p['color'] = 'g'; p['label'] = 'induced';\n",
" precent_status(filtered_rows,status = 'Induced');\n",
" p['color'] = 'b'; p['label'] = 'core';\n",
" precent_status(filtered_rows, status = 'Core');\n",
" plt.legend(frameon=False)\n",
" \n",
"plt.figure()\n",
"plotCoreInducedNone([r for r in rows if r['stats.type'] == 'accept'])\n",
"# savefig('parse_status_accepted.pdf')\n",
"\n",
"def plotCoreInducedNone(filtered_rows):\n",
" p['color'] = 'r'; p['label'] = 'none';\n",
" precent_status(filtered_rows, status = 'Nothing');\n",
" p['color'] = 'g'; p['label'] = 'induced';\n",
" precent_status(filtered_rows,status = 'Induced');\n",
" p['color'] = 'b'; p['label'] = 'core';\n",
" precent_status(filtered_rows, status = 'Core');\n",
" plt.legend(frameon=False)\n",
"plt.figure()\n",
"plotCoreInducedNone([r for r in rows if r['stats.type'] == 'q' and r.has_key('stats.status')])\n",
"plt.ylim(0, 70)\n",
"savefig('parse_status_q.pdf')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def top_users(counts, line):\n",
" id = 'sessionId'\n",
" if line[id] in counts:\n",
" counts[line[id]] = counts[line[id]] + 1\n",
" else:\n",
" counts[line[id]] = 1\n",
" return counts\n",
"\n",
"accept_all = [r for r in rows if r['stats.type']=='accept']\n",
"accept_nothing = [r for r in rows if r['stats.type']=='accept' and r['stats.status']=='Nothing']\n",
"\n",
"for r in accept_nothing[:5]:\n",
" print '{q}'.format(**r)\n",
" \n",
"sorted(reduce(top_users, rows, {}).items(), key=lambda x: -x[1]);"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def precent_status_user(filtered_rows):\n",
" query_counts = [r['queryCount'] for r in filtered_rows]\n",
" is_status = [100 if r['stats.status'] == 'Induced' else 0 for r in filtered_rows]\n",
" plot_cumavg(query_counts, is_status, xlabel='query #', ylabel='precent induced');\n",
"\n",
"rows_to_count = [r for r in rows if r['stats.type'] == 'accept']\n",
"ranked_users = sorted(reduce(top_users, rows_to_count[5000:], {}).items(), key=lambda x: -x[1])\n",
"\n",
"plt.figure()\n",
"topnum = 5;\n",
"plot_reset()\n",
"p['alpha'] = 1;\n",
"p['linewidth'] = 5;\n",
"p['label'] = 'all'; \n",
"p['color'] = 'k';\n",
"precent_status_user([r for r in rows if r['stats.type'] == 'accept']); \n",
"\n",
"colors = ['c', 'r', 'm', 'y', 'b', 'g']\n",
"plot_reset()\n",
"p['alpha'] = 1;\n",
"p['linewidth'] = 5;\n",
"p['alpha'] = 0.5;\n",
"p['marker'] = 'o';\n",
"p['markersize'] = 1;\n",
"\n",
"for g in enumerate(ranked_users[0:5]):\n",
" # (0, (u'AMT_A1HKYY6XI2OHO1', 2830))\n",
" p['label'] = '#%d' % (g[0]+1);\n",
" #plotsetting['alpha'] = 1-float(g[0])/topnum;\n",
" p['color'] = colors[g[0]];\n",
" # print plotsetting['color']\n",
" precent_status_user([r for r in rows if r['stats.type'] == 'accept' and r['sessionId'] == g[1][0]])\n",
" print g\n",
"\n",
"plt.ylim(-0.1, 100)\n",
"plt.legend(frameon=False, loc='lower right')\n",
"savefig('parse_status_topuser.pdf');"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"source": [
"def expressivity(status = 'Core'):\n",
" filtered_rows = [r for r in rows if r['stats.type'] == 'accept' and r['stats.status'] == status]\n",
" query_counts = [r['queryCount'] for r in filtered_rows]\n",
" len_formula = [r['stats.len_formula'] for r in filtered_rows]\n",
" len_utterance = [r['stats.len_utterance'] for r in filtered_rows]\n",
" form_per_q = [float(ls[0])/ls[1] for ls in zip(len_formula, len_utterance)]\n",
" plot_cumavg(query_counts, form_per_q, xlabel='query#', ylabel='\"expressiveness\"');\n",
"\n",
" #plot_cumavg(query_counts, len_utterance, xlabel='query#', ylabel='length');\n",
" print_avg(form_per_q, 'formula length')\n",
"plt.figure()\n",
"plot_reset()\n",
"p['color'] = 'b'; p['label'] = 'core'; expressivity('Core')\n",
"p['color'] = 'g'; p['label'] = 'induced'; expressivity('Induced')\n",
"plt.legend(frameon=False, loc='upper left')\n",
"# savefig('expressiveness.pdf')\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def expressivity_by_users(filtered_rows):\n",
" query_counts = [r['queryCount'] for r in filtered_rows]\n",
" len_formula = [r['stats.len_formula'] for r in filtered_rows]\n",
" len_utterance = [r['stats.len_utterance'] for r in filtered_rows]\n",
" form_per_q = [float(ls[0])/ls[1] for ls in zip(len_formula, len_utterance)]\n",
" plot_cumavg(query_counts, form_per_q, xlabel='query#', ylabel='len(z) / len(x)');\n",
"\n",
"plot_reset()\n",
"plt.figure()\n",
"p['alpha'] = 1;\n",
"p['linewidth'] = 5;\n",
"p['label'] = 'all'; \n",
"p['color'] = 'k';\n",
"expressivity_by_users([r for r in rows if r['stats.type'] == 'accept' ])\n",
" \n",
"colors = ['c', 'r', 'm', 'y', 'b']\n",
"plot_reset()\n",
"p['alpha'] = 1;\n",
"p['linewidth'] = 5;\n",
"p['alpha'] = 0.5;\n",
"p['marker'] = 'o';\n",
"p['markersize'] = 1;\n",
"rows_to_count = [r for r in rows if r['stats.type'] == 'accept']\n",
"ranked_users = sorted(reduce(top_users, rows_to_count, {}).items(), key=lambda x: -x[1])\n",
"for g in enumerate(ranked_users[0:5]):\n",
" print g\n",
" p['label'] = '#%d' % (g[0]+1);\n",
" p['color'] = colors[g[0]];\n",
" expressivity_by_users([r for r in rows if r['stats.type'] == 'accept' \\\n",
" and r['sessionId'] == g[1][0]])\n",
"\n",
"plt.ylim([0,30])\n",
"plt.legend(frameon=False, loc='lower right')\n",
"savefig('expressiveness_by_user.pdf')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def query_reformulation_by_user():\n",
" q_all = [r for r in rows if r['stats.type']=='q']\n",
" q_nothing = [r for r in rows if r['stats.type']=='q' and r.has_key('stats.status') and r['stats.status']=='Nothing']\n",
" print 'q_nothing: %d / %d totallines: %d' % (len(q_nothing), len(q_all), len(json_lines))\n",
" ranked_users = sorted(reduce(top_users, q_all, {}).items(), key=lambda x: -x[1])\n",
"\n",
" num_user = 3;\n",
" num_query = 100;\n",
" for g in (ranked_users[0:num_user]):\n",
" print g\n",
" print '********************'\n",
" rows_userg = [r for r in rows if r['stats.type']=='q' and r['sessionId']==g[0] and r.has_key('stats.status') ]\n",
" print_count = 0\n",
" prev_nothing = False\n",
" for r in rows_userg[-num_query:]:\n",
" if prev_nothing or r['stats.status']=='Nothing':\n",
" print_count = print_count + 1\n",
" if print_count>100: break\n",
" print r['stats.status'] + ':\\t' + r['q'].replace('(:q \"','').replace('\")','')\n",
" prev_nothing = True if r['stats.status']=='Nothing' else False\n",
"\n",
"query_reformulation_by_user()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.9"
}
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -0,0 +1,13 @@
#!/usr/bin/env python
"""
Installs the needed dependencies for the community-server.
Ideally, you would use virtualenv.
"""
import pip
print("Installing community-server dependencies...")
pip.main(['install', '-r', 'requirements.txt'])

View File

@ -0,0 +1,15 @@
eventlet==0.20.1
Flask==0.12
Flask-Cors==3.0.2
Flask-SocketIO==2.8.2
greenlet==0.4.11
httplib2==0.18.0
itsdangerous==0.24
Jinja2==2.9.4
jsonschema==2.5.1
pep8==1.7.0
pexpect==4.2.0
PyJWT==1.4.2
python-socketio==1.6.2
requests==2.10.0
Werkzeug==0.11.15

View File

@ -0,0 +1,573 @@
#!/usr/bin/env python
"""
SHRDLURN - Community & Logging Server
# Instructions
You can run the server by running ```./server.py --port <PORT_NUMBER>```
"""
import json
import sys
import time
import os
import random
import eventlet
import glob
from optparse import OptionParser
from flask import Flask, request, session
from flask_cors import CORS
from flask_socketio import SocketIO, emit, join_room, leave_room
import jwt
import requests
# Setup flask
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
# We need to enable CORS support to handle CORS flights from the frontend
CORS(app)
# The community server runs through websockets to enable real-time updates
socketio = SocketIO(app)
# Hardcoded folders for the data (mirrored in data_rotate.py)
DATA_FOLDER = "community-server/data/"
LOG_FOLDER = os.path.join(DATA_FOLDER, "log/")
STRUCTS_FOLDER = os.path.join(DATA_FOLDER, "structs/")
CITATION_FOLDER = "../int-output/citation"
# Scoring function parameters
GRAVITY = 1.1 # higher the gravity, the faster old structs lose score
TIME_INTERVAL = 7200.0 # break off by every 30 minutes
# Default port for the server
DEFAULT_PORT = 8406
JWT_SECRET = os.environ['SEMPRE_JWT_SECRET']
SLACK_SECRET = os.environ['SLACK_OAUTH_SECRET']
@app.route("/")
def index():
return "Hello World! ~ SHRDLURN Community Server"
def is_safe_path(basedir, path, follow_symlinks=True):
"""https://security.openstack.org/guidelines/dg_using-file-paths.html"""
# resolves symbolic links
if follow_symlinks:
return os.path.realpath(path).startswith(os.path.realpath(basedir))
return os.path.abspath(path).startswith(os.path.abspath(basedir))
def score_struct(timestamp, upvotesN):
"""We use the HN formula to score structures for ranking.
Formula is: (P + 1) / ((T + 2)^GRAVITY)
where: - P: the number of unique upvotes for the structure
- T: the amount of TIME_INTERVALs that have elapsed since the
structure was submitted
- GRAVITY: a constant to determine the weight of T v. P
"""
time_ago = (current_unix_time() / TIME_INTERVAL) - \
(int(timestamp) / TIME_INTERVAL)
return (upvotesN + 1) / ((time_ago + 2) ** GRAVITY)
def current_unix_time():
"""Returns the number of seconds since the epoch."""
return int(time.time())
def emit_structs():
"""Walk through the STRUCTS_FOLDER directory and read each struct and emit
it to the user one by one."""
structs = []
for uid in [name for name in os.listdir(STRUCTS_FOLDER) if os.path.isdir(os.path.join(STRUCTS_FOLDER, name))]:
uid_folder = os.path.join(STRUCTS_FOLDER, uid)
count = 0
for name in os.listdir(uid_folder):
if count > 100:
break
path = os.path.join(uid_folder, name)
if not os.path.isfile(path):
continue
fname = name[:-5]
try:
with open(path, 'r') as f:
lines = f.readlines()
upvotes = json.loads(lines[0].strip())
timestamp = json.loads(lines[1].strip())
struct = json.loads(lines[2].strip())
image = lines[3].strip()
score = score_struct(timestamp, len(upvotes))
message = {"uid": uid, "id": fname, "score": score, "upvotes": [
up for up in upvotes], "struct": struct, "image": image}
structs.append(message)
count += 1
except:
pass
emit("structs", structs)
def emit_user_structs_count(uid):
""""Emits a count of the total number of user structs in the folder."""
path = os.path.join(STRUCTS_FOLDER, uid)
if not is_safe_path(STRUCTS_FOLDER, path):
return
structs = [name[:-5] for name in os.listdir(path) if os.path.isfile(
os.path.join(path, name)) and os.path.join(path, name).endswith(".json")]
if os.path.isdir(path):
structs = [name[:-5] for name in os.listdir(path) if os.path.isfile(
os.path.join(path, name)) and os.path.join(path, name).endswith(".json")]
emit("user_structs", {"structs": structs})
def emit_utterances():
"""Emit a list of the last 11 utterances for the 5 most recent turkers."""
latest_5 = []
for dirname, subdirs, files in os.walk(LOG_FOLDER):
for fname in files:
path = os.path.join(dirname, fname)
mtime = os.stat(path).st_mtime
file_info = (mtime, fname[:-5], path)
if len(latest_5) < 3:
latest_5.append(file_info)
else:
earliest_time = latest_5[0][0]
earliest_idx = 0
for idx, l in enumerate(latest_5):
if l[0] < earliest_time:
earliest_time = l[0]
earliest_idx = idx
if mtime > earliest_time:
latest_5[earliest_idx] = file_info
for (time, uid, path) in sorted(latest_5, key=lambda s: int(s[0]), reverse=True):
uid = uid
utts = []
count = 0
for line in reverse_readline(path):
data = json.loads(line)
if (data["type"] == "accept" or data["type"] == "define"):
utts.append(line)
count += 1
if count > 10:
break
message = {"uid": uid, "utterances": utts}
emit("utterances", message)
def h_index(citations):
"""https://github.com/kamyu104/LeetCode/blob/master/Python/h-index.py"""
n = len(citations)
count = [0] * (n + 1)
for x in citations:
# Put all x >= n in the same bucket.
if x >= n:
count[n] += 1
else:
count[x] += 1
h = 0
for i in reversed(xrange(0, n + 1)):
h += count[i]
if h >= i:
return i
return h
def compute_citations(dir):
citations = []
for fname in os.listdir(dir):
if not fname.endswith(".json"):
continue
path = os.path.join(dir, fname)
with open(path, 'r') as f:
data = json.load(f)
citations.append(data)
citation_numbers = [citation["cite"] + citation["self"]
for citation in citations]
citation_score = h_index(citation_numbers)
return (citations, citation_score)
def emit_top_builders():
top_5_builders = []
for uid in os.listdir(CITATION_FOLDER):
subdir = os.path.join(CITATION_FOLDER, uid)
if not os.path.isdir(subdir):
continue
top_5_builders = sorted(
top_5_builders, key=lambda b: b[1], reverse=True)
(citations, citation_score) = compute_citations(subdir)
top_5_builders = sorted(
top_5_builders, key=lambda b: b[1], reverse=True)
if len(top_5_builders) < 10 or citation_score > top_5_builders[9][1]:
# If there are more than 5 citations with cites, only return those
citations = sorted(
citations, key=lambda c: c["cite"] + c["self"], reverse=True)[:10]
# if len(citations_with_cites) >= 6:
# citations = citations_with_cites
# Sort them by score and return the top 7.
citations = sorted(
citations, key=lambda c: c["cite"] + c["self"], reverse=True)[:10]
struct = (uid, citation_score, citations)
if len(top_5_builders) < 10:
top_5_builders.append(struct)
else:
top_5_builders[9] = struct
emit("top_builders", {"top_builders": top_5_builders},
broadcast=True, room="community")
def log(message):
"""Logs the given message by writing it in the uid's JSON log file."""
uid = message["uid"] if 'uid' in message else "NULL_session"
user = current_user(message['token'])
if user:
uid = user['id']
path = os.path.join(LOG_FOLDER, uid + ".json")
if not is_safe_path(LOG_FOLDER, path):
print("NOT SAFE!", path)
return
# Add a timestamp to the log
message["timestamp"] = current_unix_time()
# Append the log to the end of the file
with open(path, 'a') as f:
json.dump(message, f)
f.write('\n')
@socketio.on('getscore')
def get_score(data):
user = current_user(data['token'])
if not user:
return
uid = user['id']
subdir = os.path.join(CITATION_FOLDER, uid)
if (os.path.isdir(subdir) and is_safe_path(CITATION_FOLDER, subdir)):
(citations, score) = compute_citations(subdir)
emit("score", {"score": score})
@socketio.on('delete_struct')
def delete_struct(data):
user = current_user(data['token'])
if not user:
return
uid = user['id']
struct_id = data["id"]
struct_path = struct_id + ".json"
subdir = os.path.join(STRUCTS_FOLDER, uid)
if not (is_safe_path(STRUCTS_FOLDER, subdir)):
return
path = os.path.join(subdir, struct_path)
if (is_safe_path(subdir, path) and os.path.isfile(path)):
delete_dir = os.path.join(STRUCTS_FOLDER, uid, "deleted")
make_dir_if_necessary(delete_dir)
os.rename(path, os.path.join(delete_dir, struct_path))
@socketio.on('join')
def on_join(data):
"""When a user joins the "community" room, emit to them the list of
the top 5 most recent users' most recent 11 utterances and all of the
submitted structs."""
room = data['room']
join_room(room)
if (room == "community"):
# And then we emit the most recent 5 users' utterances per file
emit_utterances()
# and also emit the top builders when first joining
emit_top_builders()
# We iterate through all the shared structs and emit them one by one
emit_structs()
@socketio.on('leave')
def on_leave(data):
"""A user can leave a room"""
# username = data['sessionId']
room = data['room']
leave_room(room)
@socketio.on('share')
def handle_share(data):
"""Users can share structs. We save this struct in STRUCTS_FOLDER/UID/SCORE_ID.json
where UID is the uid of the user who submitted the struct, SCORE is the
current score of the struct and ID is the unique index (auto-incremented) of
this particular struct.."""
user = current_user(data['token'])
if not user:
return
uid = user['id']
user_structs_folder = os.path.join(STRUCTS_FOLDER, uid)
if not is_safe_path(STRUCTS_FOLDER, user_structs_folder):
return
make_dir_if_necessary(user_structs_folder)
new_struct_path = os.path.join(user_structs_folder, data["id"] + ".json")
if not is_safe_path(user_structs_folder, new_struct_path):
return
submission_time = current_unix_time()
score = score_struct(submission_time, 0)
with open(new_struct_path, 'w') as f:
f.write("[]\n") # it starts with no upvoters
f.write(str(submission_time) + "\n") # timestamp of submission
f.write(json.dumps(data["struct"]) + "\n") # the actual struct
f.write(data["image"]) # the png of the struct
# Broadcast addition to the "community" room
message = {"uid": uid, "id": data["id"], "score": score, "upvotes": [
], "struct": data["struct"], "image": data["image"]}
emit("struct", message, broadcast=True, room="community")
@socketio.on('upvote')
def upvote(data):
"""Users can upvote other users' structures."""
user = current_user(data['token'])
# if no authenticated user, do nothing
if not user:
return
subdir = os.path.join(STRUCTS_FOLDER, data["struct_uid"])
if not is_safe_path(STRUCTS_FOLDER, subdir):
return
struct_path = os.path.join(subdir, str(data["id"]) + ".json")
# if the struct does not exist, do nothing
if not (is_safe_path(subdir, struct_path) or os.path.isfile(struct_path)):
print("not", struct_path)
return
# Read the first line of the file to get the number of upvotes
upvotes = []
score = 0
with open(struct_path, 'r+') as f:
upvotes = json.loads(f.readline().strip())
# If the user has not already upvoted this, add them
if user['id'] not in upvotes:
upvotes.append(user['id'])
timestamp = f.readline()
struct = f.readline()
image = f.readline()
# reset file to top
f.seek(0)
# write file back with updated upvotes
f.write(json.dumps(upvotes) + "\n")
f.write(timestamp) # rewrite the timestamp
f.write(struct) # rewrite the actual struct
f.write(image) # rewrite the image
message = {"uid": data["struct_uid"],
"id": data["id"], "up": user['id'], "score": score}
f.truncate() # truncate to ensure flush appropriate
# calculate score
score = score_struct(timestamp, len(upvotes))
# and then broadcast the new upvote to the room:
message = {"uid": data["struct_uid"],
"id": data["id"], "up": user['id'], "score": score}
emit("upvote", message, broadcast=True, room="community")
@socketio.on('log')
def handle_log(data):
"""Receive a log message in the form of {"type": LOG_TYPE, "msg": LOG_OBJECT}
If the log type is an accept of utterance, then broadcast that to all
community-connected clients."""
if "type" not in data:
# If the log object is improper, don't do anything.
return
log(data)
# If the message is an accept or define type, broadcast it to all
# community-connected clients so they can update their display.
if data["type"] == "accept":
emit("new_accept", {"uid": data['uid'], "query": data["msg"]["query"], "timestamp": current_unix_time()},
broadcast=True, room="community")
elif data["type"] == "define":
emit("new_define", {"uid": data['uid'], "defined": data["msg"]["defineAs"], "timestamp": current_unix_time()},
broadcast=True, room="community")
@socketio.on('session')
def get_session(data):
"""On every new connection, the client should transmit the sessionId to tell
the server that a new session has started. This sessionId is then used for
all future authentication by storing it as uid in the session global
context variable."""
session.uid = data['uid']
log({"type": "connect", "token": ""})
@socketio.on('getstructcount')
def getstructcount(data):
emit_user_structs_count(data['uid'])
@socketio.on('connect')
def connect():
"""Return an ok if connection worked"""
emit('ok', {'data': 'Connected'})
@socketio.on('disconnect')
def disconnect():
"""Log the fact that a user disconnected."""
if 'uid' in session:
log({"uid": session.uid, "type": "disconnect"})
@socketio.on('sign_in')
def sign_in(data):
r = requests.get("https://slack.com/api/oauth.access", params={
'code': data['code'], 'client_id': '130265636855.151294060356', 'client_secret': SLACK_SECRET})
data = r.json()
session['access_token'] = data['access_token']
user = data['user']
session['user'] = user
encoded = jwt.encode(
{'name': user['name'], 'email': user['email'], 'id': user['id']}, JWT_SECRET, algorithm='HS256').decode('utf-8')
emit('sign_in', {
"name": user['name'], "email": user['email'], 'id': user['id'], 'token': encoded})
@socketio.on('get_user')
def get_user(data):
user = current_user(data['token'])
if user:
emit('sign_in', {
"name": user['name'], "email": user['email'], 'id': user['id'], 'token': data['token']
})
else:
emit('sign_in_failed')
def current_user(token):
try:
return jwt.decode(token, JWT_SECRET, algorithms=['HS256'])
except:
return False
# http://stackoverflow.com/questions/2301789/read-a-file-in-reverse-order-using-python
def reverse_readline(filename, buf_size=8192):
"""a generator that returns the lines of a file in reverse order"""
with open(filename) as fh:
segment = None
offset = 0
fh.seek(0, os.SEEK_END)
file_size = remaining_size = fh.tell()
while remaining_size > 0:
offset = min(file_size, offset + buf_size)
fh.seek(file_size - offset)
buffer = fh.read(min(remaining_size, buf_size))
remaining_size -= buf_size
lines = buffer.split('\n')
# the first line of the buffer is probably not a complete line so
# we'll save it and append it to the last line of the next buffer
# we read
if segment is not None:
# if the previous chunk starts right from the beginning of line
# do not concact the segment to the last line of new chunk
# instead, yield the segment first
if buffer[-1] is not '\n':
lines[-1] += segment
else:
yield segment
segment = lines[0]
for index in range(len(lines) - 1, 0, -1):
if len(lines[index]):
yield lines[index]
# Don't yield None if the file was empty
if segment is not None:
yield segment
def make_dir_if_necessary(dir_name):
"""Creates the directory if not already created"""
if not os.path.exists(dir_name):
os.makedirs(dir_name)
if __name__ == "__main__":
# Create any missing directories
make_dir_if_necessary(DATA_FOLDER)
make_dir_if_necessary(LOG_FOLDER)
make_dir_if_necessary(STRUCTS_FOLDER)
# Parse arguments
parser = OptionParser()
parser.add_option("-p", "--port", dest="port",
help="port number to run the server", default=DEFAULT_PORT)
(options, args) = parser.parse_args()
# Run the server
# NB: socketio.run uses eventlet to run a production webserver
# so, make sure that "eventlet" is installed, or else it will default to
# the werkzeug development server which is unsafe and slow.
socketio.run(app, host='0.0.0.0', port=int(options.port))

View File

@ -0,0 +1,148 @@
{"lexeme": "AliceBlue", "formula": "aliceblue", "type": "color"}
{"lexeme": "AntiqueWhite", "formula": "antiquewhite", "type": "color"}
{"lexeme": "Aqua", "formula": "aqua", "type": "color"}
{"lexeme": "Aquamarine", "formula": "aquamarine", "type": "color"}
{"lexeme": "Azure", "formula": "azure", "type": "color"}
{"lexeme": "Beige", "formula": "beige", "type": "color"}
{"lexeme": "Bisque", "formula": "bisque", "type": "color"}
{"lexeme": "Black", "formula": "black", "type": "color"}
{"lexeme": "BlanchedAlmond", "formula": "blanchedalmond", "type": "color"}
{"lexeme": "Blue", "formula": "blue", "type": "color"}
{"lexeme": "BlueViolet", "formula": "blueviolet", "type": "color"}
{"lexeme": "Brown", "formula": "brown", "type": "color"}
{"lexeme": "BurlyWood", "formula": "burlywood", "type": "color"}
{"lexeme": "CadetBlue", "formula": "cadetblue", "type": "color"}
{"lexeme": "Chartreuse", "formula": "chartreuse", "type": "color"}
{"lexeme": "Chocolate", "formula": "chocolate", "type": "color"}
{"lexeme": "Coral", "formula": "coral", "type": "color"}
{"lexeme": "CornflowerBlue", "formula": "cornflowerblue", "type": "color"}
{"lexeme": "Cornsilk", "formula": "cornsilk", "type": "color"}
{"lexeme": "Crimson", "formula": "crimson", "type": "color"}
{"lexeme": "Cyan", "formula": "cyan", "type": "color"}
{"lexeme": "DarkBlue", "formula": "darkblue", "type": "color"}
{"lexeme": "DarkCyan", "formula": "darkcyan", "type": "color"}
{"lexeme": "DarkGoldenRod", "formula": "darkgoldenrod", "type": "color"}
{"lexeme": "DarkGray", "formula": "darkgray", "type": "color"}
{"lexeme": "DarkGrey", "formula": "darkgrey", "type": "color"}
{"lexeme": "DarkGreen", "formula": "darkgreen", "type": "color"}
{"lexeme": "DarkKhaki", "formula": "darkkhaki", "type": "color"}
{"lexeme": "DarkMagenta", "formula": "darkmagenta", "type": "color"}
{"lexeme": "DarkOliveGreen", "formula": "darkolivegreen", "type": "color"}
{"lexeme": "DarkOrange", "formula": "darkorange", "type": "color"}
{"lexeme": "DarkOrchid", "formula": "darkorchid", "type": "color"}
{"lexeme": "DarkRed", "formula": "darkred", "type": "color"}
{"lexeme": "DarkSalmon", "formula": "darksalmon", "type": "color"}
{"lexeme": "DarkSeaGreen", "formula": "darkseagreen", "type": "color"}
{"lexeme": "DarkSlateBlue", "formula": "darkslateblue", "type": "color"}
{"lexeme": "DarkSlateGray", "formula": "darkslategray", "type": "color"}
{"lexeme": "DarkSlateGrey", "formula": "darkslategrey", "type": "color"}
{"lexeme": "DarkTurquoise", "formula": "darkturquoise", "type": "color"}
{"lexeme": "DarkViolet", "formula": "darkviolet", "type": "color"}
{"lexeme": "DeepPink", "formula": "deeppink", "type": "color"}
{"lexeme": "DeepSkyBlue", "formula": "deepskyblue", "type": "color"}
{"lexeme": "DimGray", "formula": "dimgray", "type": "color"}
{"lexeme": "DimGrey", "formula": "dimgrey", "type": "color"}
{"lexeme": "DodgerBlue", "formula": "dodgerblue", "type": "color"}
{"lexeme": "FireBrick", "formula": "firebrick", "type": "color"}
{"lexeme": "FloralWhite", "formula": "floralwhite", "type": "color"}
{"lexeme": "ForestGreen", "formula": "forestgreen", "type": "color"}
{"lexeme": "Fuchsia", "formula": "fuchsia", "type": "color"}
{"lexeme": "Gainsboro", "formula": "gainsboro", "type": "color"}
{"lexeme": "GhostWhite", "formula": "ghostwhite", "type": "color"}
{"lexeme": "Gold", "formula": "gold", "type": "color"}
{"lexeme": "GoldenRod", "formula": "goldenrod", "type": "color"}
{"lexeme": "Gray", "formula": "gray", "type": "color"}
{"lexeme": "Grey", "formula": "grey", "type": "color"}
{"lexeme": "Green", "formula": "green", "type": "color"}
{"lexeme": "GreenYellow", "formula": "greenyellow", "type": "color"}
{"lexeme": "HoneyDew", "formula": "honeydew", "type": "color"}
{"lexeme": "HotPink", "formula": "hotpink", "type": "color"}
{"lexeme": "IndianRed", "formula": "indianred", "type": "color"}
{"lexeme": "Indigo", "formula": "indigo", "type": "color"}
{"lexeme": "Ivory", "formula": "ivory", "type": "color"}
{"lexeme": "Khaki", "formula": "khaki", "type": "color"}
{"lexeme": "Lavender", "formula": "lavender", "type": "color"}
{"lexeme": "LavenderBlush", "formula": "lavenderblush", "type": "color"}
{"lexeme": "LawnGreen", "formula": "lawngreen", "type": "color"}
{"lexeme": "LemonChiffon", "formula": "lemonchiffon", "type": "color"}
{"lexeme": "LightBlue", "formula": "lightblue", "type": "color"}
{"lexeme": "LightCoral", "formula": "lightcoral", "type": "color"}
{"lexeme": "LightCyan", "formula": "lightcyan", "type": "color"}
{"lexeme": "LightGoldenRodYellow", "formula": "lightgoldenrodyellow", "type": "color"}
{"lexeme": "LightGray", "formula": "lightgray", "type": "color"}
{"lexeme": "LightGrey", "formula": "lightgrey", "type": "color"}
{"lexeme": "LightGreen", "formula": "lightgreen", "type": "color"}
{"lexeme": "LightPink", "formula": "lightpink", "type": "color"}
{"lexeme": "LightSalmon", "formula": "lightsalmon", "type": "color"}
{"lexeme": "LightSeaGreen", "formula": "lightseagreen", "type": "color"}
{"lexeme": "LightSkyBlue", "formula": "lightskyblue", "type": "color"}
{"lexeme": "LightSlateGray", "formula": "lightslategray", "type": "color"}
{"lexeme": "LightSlateGrey", "formula": "lightslategrey", "type": "color"}
{"lexeme": "LightSteelBlue", "formula": "lightsteelblue", "type": "color"}
{"lexeme": "LightYellow", "formula": "lightyellow", "type": "color"}
{"lexeme": "Lime", "formula": "lime", "type": "color"}
{"lexeme": "LimeGreen", "formula": "limegreen", "type": "color"}
{"lexeme": "Linen", "formula": "linen", "type": "color"}
{"lexeme": "Magenta", "formula": "magenta", "type": "color"}
{"lexeme": "Maroon", "formula": "maroon", "type": "color"}
{"lexeme": "MediumAquaMarine", "formula": "mediumaquamarine", "type": "color"}
{"lexeme": "MediumBlue", "formula": "mediumblue", "type": "color"}
{"lexeme": "MediumOrchid", "formula": "mediumorchid", "type": "color"}
{"lexeme": "MediumPurple", "formula": "mediumpurple", "type": "color"}
{"lexeme": "MediumSeaGreen", "formula": "mediumseagreen", "type": "color"}
{"lexeme": "MediumSlateBlue", "formula": "mediumslateblue", "type": "color"}
{"lexeme": "MediumSpringGreen", "formula": "mediumspringgreen", "type": "color"}
{"lexeme": "MediumTurquoise", "formula": "mediumturquoise", "type": "color"}
{"lexeme": "MediumVioletRed", "formula": "mediumvioletred", "type": "color"}
{"lexeme": "MidnightBlue", "formula": "midnightblue", "type": "color"}
{"lexeme": "MintCream", "formula": "mintcream", "type": "color"}
{"lexeme": "MistyRose", "formula": "mistyrose", "type": "color"}
{"lexeme": "Moccasin", "formula": "moccasin", "type": "color"}
{"lexeme": "NavajoWhite", "formula": "navajowhite", "type": "color"}
{"lexeme": "Navy", "formula": "navy", "type": "color"}
{"lexeme": "OldLace", "formula": "oldlace", "type": "color"}
{"lexeme": "Olive", "formula": "olive", "type": "color"}
{"lexeme": "OliveDrab", "formula": "olivedrab", "type": "color"}
{"lexeme": "Orange", "formula": "orange", "type": "color"}
{"lexeme": "OrangeRed", "formula": "orangered", "type": "color"}
{"lexeme": "Orchid", "formula": "orchid", "type": "color"}
{"lexeme": "PaleGoldenRod", "formula": "palegoldenrod", "type": "color"}
{"lexeme": "PaleGreen", "formula": "palegreen", "type": "color"}
{"lexeme": "PaleTurquoise", "formula": "paleturquoise", "type": "color"}
{"lexeme": "PaleVioletRed", "formula": "palevioletred", "type": "color"}
{"lexeme": "PapayaWhip", "formula": "papayawhip", "type": "color"}
{"lexeme": "PeachPuff", "formula": "peachpuff", "type": "color"}
{"lexeme": "Peru", "formula": "peru", "type": "color"}
{"lexeme": "Pink", "formula": "pink", "type": "color"}
{"lexeme": "Plum", "formula": "plum", "type": "color"}
{"lexeme": "PowderBlue", "formula": "powderblue", "type": "color"}
{"lexeme": "Purple", "formula": "purple", "type": "color"}
{"lexeme": "RebeccaPurple", "formula": "rebeccapurple", "type": "color"}
{"lexeme": "Red", "formula": "red", "type": "color"}
{"lexeme": "RosyBrown", "formula": "rosybrown", "type": "color"}
{"lexeme": "RoyalBlue", "formula": "royalblue", "type": "color"}
{"lexeme": "SaddleBrown", "formula": "saddlebrown", "type": "color"}
{"lexeme": "Salmon", "formula": "salmon", "type": "color"}
{"lexeme": "SandyBrown", "formula": "sandybrown", "type": "color"}
{"lexeme": "SeaGreen", "formula": "seagreen", "type": "color"}
{"lexeme": "SeaShell", "formula": "seashell", "type": "color"}
{"lexeme": "Sienna", "formula": "sienna", "type": "color"}
{"lexeme": "Silver", "formula": "silver", "type": "color"}
{"lexeme": "SkyBlue", "formula": "skyblue", "type": "color"}
{"lexeme": "SlateBlue", "formula": "slateblue", "type": "color"}
{"lexeme": "SlateGray", "formula": "slategray", "type": "color"}
{"lexeme": "SlateGrey", "formula": "slategrey", "type": "color"}
{"lexeme": "Snow", "formula": "snow", "type": "color"}
{"lexeme": "SpringGreen", "formula": "springgreen", "type": "color"}
{"lexeme": "SteelBlue", "formula": "steelblue", "type": "color"}
{"lexeme": "Tan", "formula": "tan", "type": "color"}
{"lexeme": "Teal", "formula": "teal", "type": "color"}
{"lexeme": "Thistle", "formula": "thistle", "type": "color"}
{"lexeme": "Tomato", "formula": "tomato", "type": "color"}
{"lexeme": "Turquoise", "formula": "turquoise", "type": "color"}
{"lexeme": "Violet", "formula": "violet", "type": "color"}
{"lexeme": "Wheat", "formula": "wheat", "type": "color"}
{"lexeme": "White", "formula": "white", "type": "color"}
{"lexeme": "WhiteSmoke", "formula": "whitesmoke", "type": "color"}
{"lexeme": "Yellow", "formula": "yellow", "type": "color"}
{"lexeme": "YellowGreen", "formula": "yellowgreen", "type": "color"}

104
interactive/dal.grammar Normal file
View File

@ -0,0 +1,104 @@
# Grammar for Dependency-based Action Language (DAL)
# which is based on lambda DCS, and designed to interpolate
# well with NL
(def @select select)
(def @update update)
(def @remove remove)
(def @R reverse)
(rule $ROOT ($Actions) (IdentityFn) (anchored 1))
(rule $ROOT ($Actions) (interactive.BlockFn isolate) (anchored 1))
(rule $ROOT ($Actions) (interactive.BlockFn block) (anchored 1))
(rule $Actions ($Actions ; $Action) (lambda a1 (lambda a2 (:s (var a1) (var a2)))) (anchored 1))
(rule $Actions ($Action) (IdentityFn) (anchored 1))
(rule $Action ({ $Actions }) (lambda a (:blk (var a))) (anchored 1))
(rule $Action (return { $Actions }) (lambda a (:blkr (var a))) (anchored 1))
(rule $Action ([ $Actions ]) (IdentityFn) (anchored 1))
(rule $Action (repeat $Numbers $Action) (lambda n (lambda a (:loop (var n) (var a)))) (anchored 1))
(rule $Action (if $ValueSets $Action) (lambda b (lambda a (:if (var b) (var a)))) (anchored 1))
(rule $Action (if $Sets $Action) (lambda b (lambda a (:if (var b) (var a)))) (anchored 1))
# basic actions, local scope "for has color red [add red left; add red top]"
# (rule $Action (for $Sets $Action ) (lambda s (lambda a (:for (var s) (var a)))) (anchored 1))
(rule $Action (foreach $Sets $Action ) (lambda s (lambda a (:foreach (var s) (var a)))) (anchored 1))
(rule $Action (foreach $Action ) (lambda a (:foreach this (var a))) (anchored 1))
(rule $Action (isolate $Action ) (lambda a (:isolate (var a))) (anchored 1))
(rule $Action (while $Sets $Action ) (lambda s (lambda a (:while (var s) (var a)))) (anchored 1))
# global actions
(rule $Action (select $Sets) (lambda s (: @select (var s))) (anchored 1))
(rule $Action (select) (ConstantFn (: @select)) (anchored 1))
(rule $Action (update $Rel $ValueSets) (lambda r (lambda v (: @update (var r) (var v)))) (anchored 1))
(rule $Action (remove) (ConstantFn (: @remove)) (anchored 1))
(rule $Action (remove $Sets) (lambda s (: @remove (var s))) (anchored 1))
############### unary sets
(rule $Set (selected) this (anchored 1))
(rule $Set (previous) prev (anchored 1))
(rule $Set (this) this (anchored 1))
(rule $Set (all) * (anchored 1))
(rule $Set (nothing) nothing (anchored 1))
(rule $Set (none) nothing (anchored 1))
############### basic set operations
# just use or and filter, which does and
(for @op (or and)
(rule $Sets ($Sets @op $Set) (lambda s1 (lambda s2
(@op (var s1) (var s2)))) (anchored 1))
(rule $ValueSets ($ValueSets @op $ValueSet) (lambda s1 (lambda s2
(@op (var s1) (var s2)))) (anchored 1))
)
# this would require universe of each type
# (rule $ValueSet (not $ValueSet) (lambda s (not (var s))) (anchored 1))
(rule $Set (not $Sets) (lambda s (not (var s))) (anchored 1))
(rule $ValueSets ($ValueSet) (IdentityFn) (anchored 1))
(rule $ValueSet ([ $ValueSets ]) (IdentityFn) (anchored 1))
(rule $Sets ($Set) (IdentityFn) (anchored 1))
(rule $Set ([ $Sets ]) (IdentityFn) (anchored 1))
############### Joins
(rule $ValueSet ($Rel of $Set) (lambda r (lambda s
((@R (var r)) (var s)))) (anchored 1))
(rule $Set (has $Rel $ValueSet) (lambda r (lambda s
((var r) (var s)))) (anchored 1))
############### Arithmetic
(for @op (+ -)
(rule $Numbers ($Numbers @op $Number) (lambda n1 (lambda n2
(@op (var n1) (var n2)))) (anchored 1))
)
(rule $Number ([ $Numbers ]) (IdentityFn) (anchored 1))
(rule $Numbers ( $Number ) (IdentityFn) (anchored 1))
#############################
# Floating rules
#############################
# (rule $Action ($Numbers $Actions) (lambda n (lambda a (:loop (var n) (var a)))) (floating 1)) # do add red top 3 times
# (rule $Action ($Sets $Actions) (lambda s (lambda a (:foreach (var s) (var a)))) (floating 1))
# (rule $Action ($Actions $Actions) (lambda a1 (lambda a2 (:s (var a1) (var a2)))) (floating 1)) # add red top then remove them
# let floating rules continue to propagate, and generate a lot of candidates
# (rule $Actions ($Action) (IdentityFn) (floating 1))
# (rule $ValueSets ($Rel $Sets) (lambda r (lambda s
# ((reverse (var r)) (var s)))) (floating 1))
# (rule $Action ($Sets) (lambda s (: @select (var s))) (floating 1))
# (rule $Set ($Rel $ValueSets) (lambda r (lambda s
# ((var r) (var s)))) (floating 1))
# (rule $Action ($Rel $ValueSets) (lambda r (lambda v (: @update (var r) (var v)))) (floating 1))
# (rule $Action (nothing) (ConstantFn (: @remove)) (floating 1))
# (rule $FROOT ($Action) (IdentityFn) (floating 1))
# (rule $FROOT ($Actions) (IdentityFn) (floating 1))

View File

@ -0,0 +1,23 @@
# README
## Processed
* freebuild.def.json.gz contains just the 2495 definition queries in freebuild.json.gz
gzcat freebuild.json.gz | grep '(:def'
* freebuild.json.gz is the main data file. Obtained by:
awk '{print "{\"qid\":" NR "," substr($0,2)}' freebuildbig-0206 > freebuild.id.json
jq -c '{"qid":.qid, "q":.q, "sessionId": .sessionId[:10], "time":.time}' freebuild.id.json > freebuild.json
## Raw queries
* freebuildbig-0206.def is the raw query log, without context
* qualifier3-0201: 30 turkers, 1 rejection
* qualifiers: turkers had to build a fixed target
* freebuild[12]: qualified turkers can build whatever they want

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,185 @@
{"time":"2017-01-22T00:14:52.709","sessionId":"sidaw","q":"(:q \"add red top 3 times\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.739","sessionId":"sidaw","q":"(:q \"add red top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.786","sessionId":"sidaw","q":"(:accept \"add red top\" \"(: add red top)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.797","sessionId":"sidaw","q":"(:q \"add red top 3 times\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.805","sessionId":"sidaw","q":"(:q \"repeat 3 [add red top]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.812","sessionId":"sidaw","q":"(:accept \"repeat 3 [add red top]\" \"(:loop (number 3) (: add red top))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.820","sessionId":"sidaw","q":"(:def_ret \"add red top 3 times\" \"[[\\\"repeat 3 [add red top]\\\",\\\"(:loop (number 3) (: add red top))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.852","sessionId":"sidaw","q":"(:q \"add cardinal\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.858","sessionId":"sidaw","q":"(:q \"add red\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.863","sessionId":"sidaw","q":"(:accept \"add red\" \"(: add red here)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.868","sessionId":"sidaw","q":"(:def_ret \"add cardinal\" \"[[\\\"add red\\\",\\\"(: add red here)\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.884","sessionId":"sidaw","q":"(:q \"yellow stick size 5\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.889","sessionId":"sidaw","q":"(:q \"repeat 5 [ add yellow; select top]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.898","sessionId":"sidaw","q":"(:accept \"repeat 5 [ add yellow; select top]\" \"(:loop (number 5) (:s (: add yellow here) (: select (call adj top))))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.905","sessionId":"sidaw","q":"(:def_ret \"yellow stick size 5\" \"[[\\\"repeat 5 [ add yellow; select top]\\\",\\\"(:loop (number 5) (:s (: add yellow here) (: select (call adj top))))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.922","sessionId":"sidaw","q":"(:q \"yellow beam left 5\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.929","sessionId":"sidaw","q":"(:q \"{repeat 5 [ add yellow; select left]}\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.939","sessionId":"sidaw","q":"(:accept \"{repeat 5 [ add yellow; select left]}\" \"(:blk (:loop (number 5) (:s (: add yellow here) (: select (call adj left)))))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.947","sessionId":"sidaw","q":"(:def_ret \"yellow beam left 5\" \"[[\\\"{repeat 5 [ add yellow; select left]}\\\",\\\"(:blk (:loop (number 5) (:s (: add yellow here) (: select (call adj left)))))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.962","sessionId":"sidaw","q":"(:q \"move down\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.968","sessionId":"sidaw","q":"(:q \"move bot\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.978","sessionId":"sidaw","q":"(:q \"select bot\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.984","sessionId":"sidaw","q":"(:accept \"select bot\" \"(: select (call adj bot))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.990","sessionId":"sidaw","q":"(:def_ret \"move down\" \"[[\\\"select bot\\\",\\\"(: select (call adj bot))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:52.999","sessionId":"sidaw","q":"(:q \"move down\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.006","sessionId":"sidaw","q":"(:q \"move bot\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.012","sessionId":"sidaw","q":"(:q \"move right\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.015","sessionId":"sidaw","q":"(:accept \"move right\" \"(: move right)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.021","sessionId":"sidaw","q":"(:q \"move up\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.028","sessionId":"sidaw","q":"(:q \"move top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.032","sessionId":"sidaw","q":"(:accept \"move top\" \"(: move top)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.036","sessionId":"sidaw","q":"(:def_ret \"move up\" \"[[\\\"move top\\\",\\\"(: move top)\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.046","sessionId":"sidaw","q":"(:q \"move up\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.051","sessionId":"sidaw","q":"(:accept \"move up\" \"(: move top)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.057","sessionId":"sidaw","q":"(:accept \"move up\" \"(not *)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.063","sessionId":"sidaw","q":"(:q \"select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.066","sessionId":"sidaw","q":"(:accept \"select top\" \"(: select (call adj top))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.070","sessionId":"sidaw","q":"(:def_ret \"move up\" \"[[\\\"select top\\\",\\\"(: select (call adj top))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.081","sessionId":"sidaw","q":"(:q \"move up\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.090","sessionId":"sidaw","q":"(:q \"select yellow\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.096","sessionId":"sidaw","q":"(:q \"select has color yellow\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.102","sessionId":"sidaw","q":"(:accept \"select has color yellow\" \"(: select (color yellow))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.106","sessionId":"sidaw","q":"(:def_ret \"select yellow\" \"[[\\\"select has color yellow\\\",\\\"(: select (color yellow))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.115","sessionId":"sidaw","q":"(:q \"update color red\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.119","sessionId":"sidaw","q":"(:accept \"update color red\" \"(: update color red)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.124","sessionId":"sidaw","q":"(:q \"select origin\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.128","sessionId":"sidaw","q":"(:accept \"select origin\" \"(: select (call origin))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.135","sessionId":"sidaw","q":"(:q \"select red\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.139","sessionId":"sidaw","q":"(:accept \"select red\" \"(: select (color red))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.148","sessionId":"sidaw","q":"(:q \"foreach red [move right]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.155","sessionId":"sidaw","q":"(:q \"foreach has color red [move right]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.162","sessionId":"sidaw","q":"(:accept \"foreach has color red [move right]\" \"(:foreach (color red) (: move right))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.169","sessionId":"sidaw","q":"(:def_ret \"foreach red [move right]\" \"[[\\\"foreach has color red [move right]\\\",\\\"(:foreach (color red) (: move right))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.182","sessionId":"sidaw","q":"(:q \"remove red\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.187","sessionId":"sidaw","q":"(:q \"remove has color red\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.191","sessionId":"sidaw","q":"(:accept \"remove has color red\" \"(: remove (color red))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.195","sessionId":"sidaw","q":"(:def_ret \"remove red\" \"[[\\\"remove has color red\\\",\\\"(: remove (color red))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.204","sessionId":"sidaw","q":"(:q \"select none\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.207","sessionId":"sidaw","q":"(:accept \"select none\" \"(: select nothing)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.213","sessionId":"sidaw","q":"(:q \"select origin\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.216","sessionId":"sidaw","q":"(:accept \"select origin\" \"(: select (call origin))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.220","sessionId":"sidaw","q":"(:q \"yellow sq size 3\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.225","sessionId":"sidaw","q":"(:q \"yellow beam back 3\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.230","sessionId":"sidaw","q":"(:q \"repeat 3 [yellow beam back 3; select left]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.238","sessionId":"sidaw","q":"(:accept \"repeat 3 [yellow beam back 3; select left]\" \"(:loop (number 3) (:s (:blk (:loop (number 3) (:s (: add yellow here) (: select (call adj back))))) (: select (call adj left))))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.250","sessionId":"sidaw","q":"(:q \"select front\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.255","sessionId":"sidaw","q":"(:accept \"select front\" \"(: select (call adj front))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.259","sessionId":"sidaw","q":"(:def \"yellow sq size 3\" \"[[\\\"repeat 3 [yellow beam back 3; select left]\\\",\\\"(:loop (number 3) (:s (:blk (:loop (number 3) (:s (: add yellow here) (: select (call adj back))))) (: select (call adj left))))\\\"],[\\\"select front\\\",\\\"(: select (call adj front))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.276","sessionId":"sidaw","q":"(:q \"yellow sq size 3\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.281","sessionId":"sidaw","q":"(:accept \"yellow sq size 3\" \"(:blk (:loop (number 3) (:s (:blk (:loop (number 3) (:s (: add yellow here) (: select (call adj back))))) (: select (call adj left)))) (: select (call adj front)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.291","sessionId":"sidaw","q":"(:q \"select origin\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.295","sessionId":"sidaw","q":"(:accept \"select origin\" \"(: select (call origin))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.303","sessionId":"sidaw","q":"(:q \"red sq size 4\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.311","sessionId":"sidaw","q":"(:accept \"red sq size 4\" \"(:blk (:loop (number 4) (:s (:blk (:loop (number 4) (:s (: add red here) (: select (call adj back))))) (: select (call adj left)))) (: select (call adj front)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.327","sessionId":"sidaw","q":"(:q \"red cube size 4\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.331","sessionId":"sidaw","q":"(:q \"red sq size 4\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.337","sessionId":"sidaw","q":"(:accept \"red sq size 4\" \"(:blk (:loop (number 4) (:s (:blk (:loop (number 4) (:s (: add red here) (: select (call adj back))))) (: select (call adj left)))) (: select (call adj front)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.345","sessionId":"sidaw","q":"(:q \"repeat 4-1 [select top; red sq size 4]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.358","sessionId":"sidaw","q":"(:accept \"repeat 4-1 [select top; red sq size 4]\" \"(:loop (- (number 4) (number 1)) (:s (: select (call adj top)) (:blk (:loop (number 4) (:s (:blk (:loop (number 4) (:s (: add red here) (: select (call adj back))))) (: select (call adj left)))) (: select (call adj front)))))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.377","sessionId":"sidaw","q":"(:def \"red cube size 4\" \"[[\\\"red sq size 4\\\",\\\"(:blk (:loop (number 4) (:s (:blk (:loop (number 4) (:s (: add red here) (: select (call adj back))))) (: select (call adj left)))) (: select (call adj front)))\\\"],[\\\"repeat 4-1 [select top; red sq size 4]\\\",\\\"(:loop (- (number 4) (number 1)) (:s (: select (call adj top)) (:blk (:loop (number 4) (:s (:blk (:loop (number 4) (:s (: add red here) (: select (call adj back))))) (: select (call adj left)))) (: select (call adj front)))))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.412","sessionId":"sidaw","q":"(:q \"brown cube size 4\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.436","sessionId":"sidaw","q":"(:q \"brown cube size 5\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.462","sessionId":"sidaw","q":"(:q \"move back\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.471","sessionId":"sidaw","q":"(:accept \"move back\" \"(: move back)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.490","sessionId":"sidaw","q":"(:q \"select very back of very top of red\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.498","sessionId":"sidaw","q":"(:q \"select very back of very top of has color red\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.508","sessionId":"sidaw","q":"(:accept \"select very back of very top of has color red\" \"(: select (call veryx back (call veryx top (color red))))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.522","sessionId":"sidaw","q":"(:q \"add blue top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.528","sessionId":"sidaw","q":"(:accept \"add blue top\" \"(: add blue top)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.542","sessionId":"sidaw","q":"(:q \"select blue\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.549","sessionId":"sidaw","q":"(:accept \"select blue\" \"(: select (color blue))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.561","sessionId":"sidaw","q":"(:q \"select this and not very left and not very right\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.573","sessionId":"sidaw","q":"(:accept \"select this and not very left and not very right\" \"(: select (and (and this (not (call veryx left))) (not (call veryx right))))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.593","sessionId":"sidaw","q":"(:q \"add yellow top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.599","sessionId":"sidaw","q":"(:accept \"add yellow top\" \"(: add yellow top)\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.605","sessionId":"sidaw","q":"(:q \"brown beam top 5\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.609","sessionId":"sidaw","q":"(:q \"brown beam top 10\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.613","sessionId":"sidaw","q":"(:q \"brown beam top 12\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.616","sessionId":"sidaw","q":"(:q \"brown beam top 9\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.621","sessionId":"sidaw","q":"(:q \"brown beam top 10\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.624","sessionId":"sidaw","q":"(:accept \"brown beam top 10\" \"(:blk (:loop (number 10) (:s (: add brown here) (: select (call adj top)))))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.630","sessionId":"sidaw","q":"(:q \"green branch 3\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.637","sessionId":"sidaw","q":"(:q \"repeat 3 [add green left; add green right; add green front; add green back]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.644","sessionId":"sidaw","q":"(:accept \"repeat 3 [add green left; add green right; add green front; add green back]\" \"(:loop (number 3) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.651","sessionId":"sidaw","q":"(:def_ret \"green branch 3\" \"[[\\\"repeat 3 [add green left; add green right; add green front; add green back]\\\",\\\"(:loop (number 3) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back)))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.664","sessionId":"sidaw","q":"(:q \"select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.666","sessionId":"sidaw","q":"(:accept \"select top\" \"(: select (call adj top))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.672","sessionId":"sidaw","q":"(:q \"green branch 3\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.678","sessionId":"sidaw","q":"(:q \"green branch 4\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.682","sessionId":"sidaw","q":"(:accept \"green branch 4\" \"(:loop (number 4) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.695","sessionId":"sidaw","q":"(:q \"select top of top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.699","sessionId":"sidaw","q":"(:accept \"select top of top\" \"(: select (call adj top (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.704","sessionId":"sidaw","q":"(:q \"yellow branch 5\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.712","sessionId":"sidaw","q":"(:q \"green branch 5\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.717","sessionId":"sidaw","q":"(:accept \"green branch 5\" \"(:loop (number 5) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.728","sessionId":"sidaw","q":"(:q \"select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.734","sessionId":"sidaw","q":"(:accept \"select top\" \"(: select (call adj top))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.745","sessionId":"sidaw","q":"(:q \"green branch 3\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.751","sessionId":"sidaw","q":"(:accept \"green branch 3\" \"(:loop (number 3) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.763","sessionId":"sidaw","q":"(:q \"select top of top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.769","sessionId":"sidaw","q":"(:accept \"select top of top\" \"(: select (call adj top (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.780","sessionId":"sidaw","q":"(:q \"green branch 2\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.785","sessionId":"sidaw","q":"(:accept \"green branch 2\" \"(:loop (number 2) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.801","sessionId":"sidaw","q":"(:q \"select top of top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.808","sessionId":"sidaw","q":"(:accept \"select top of top\" \"(: select (call adj top (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.818","sessionId":"sidaw","q":"(:q \"green branch\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.826","sessionId":"sidaw","q":"(:q \"green branch 1\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.831","sessionId":"sidaw","q":"(:accept \"green branch 1\" \"(:loop (number 1) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.839","sessionId":"sidaw","q":"(:q \"brown beam top 10\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.844","sessionId":"sidaw","q":"(:accept \"brown beam top 10\" \"(:blk (:loop (number 10) (:s (: add brown here) (: select (call adj top)))))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.850","sessionId":"sidaw","q":"(:q \"green branch 1; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.854","sessionId":"sidaw","q":"(:accept \"green branch 1; select top\" \"(:s (:loop (number 1) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.862","sessionId":"sidaw","q":"(:q \"green branch 2; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.866","sessionId":"sidaw","q":"(:accept \"green branch 2; select top\" \"(:s (:loop (number 2) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.872","sessionId":"sidaw","q":"(:q \"green branch 5; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.876","sessionId":"sidaw","q":"(:accept \"green branch 5; select top\" \"(:s (:loop (number 5) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.885","sessionId":"sidaw","q":"(:q \"green branch 4; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.891","sessionId":"sidaw","q":"(:accept \"green branch 4; select top\" \"(:s (:loop (number 4) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.903","sessionId":"sidaw","q":"(:q \"green branch 3; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.909","sessionId":"sidaw","q":"(:accept \"green branch 3; select top\" \"(:s (:loop (number 3) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.922","sessionId":"sidaw","q":"(:q \"green branch 2; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.927","sessionId":"sidaw","q":"(:accept \"green branch 2; select top\" \"(:s (:loop (number 2) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.941","sessionId":"sidaw","q":"(:q \"green branch 1; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.946","sessionId":"sidaw","q":"(:accept \"green branch 1; select top\" \"(:s (:loop (number 1) (:s (:s (:s (: add green left) (: add green right)) (: add green front)) (: add green back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.960","sessionId":"sidaw","q":"(:q \"red branch 1; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.966","sessionId":"sidaw","q":"(:accept \"red branch 1; select top\" \"(:s (:loop (number 1) (:s (:s (:s (: add red left) (: add red right)) (: add red front)) (: add red back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.980","sessionId":"sidaw","q":"(:q \"red branch 2; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:53.988","sessionId":"sidaw","q":"(:accept \"red branch 2; select top\" \"(:s (:loop (number 2) (:s (:s (:s (: add red left) (: add red right)) (: add red front)) (: add red back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:54.004","sessionId":"sidaw","q":"(:q \"red branch 3; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:54.012","sessionId":"sidaw","q":"(:accept \"red branch 3; select top\" \"(:s (:loop (number 3) (:s (:s (:s (: add red left) (: add red right)) (: add red front)) (: add red back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:54.030","sessionId":"sidaw","q":"(:q \"red branch 4; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:54.041","sessionId":"sidaw","q":"(:accept \"red branch 4; select top\" \"(:s (:loop (number 4) (:s (:s (:s (: add red left) (: add red right)) (: add red front)) (: add red back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:14:54.060","sessionId":"sidaw","q":"(:q \"red branch 5; select top\")","remote":"localhost"}
{"time":"2017-01-22T00:14:54.073","sessionId":"sidaw","q":"(:accept \"red branch 5; select top\" \"(:s (:loop (number 5) (:s (:s (:s (: add red left) (: add red right)) (: add red front)) (: add red back))) (: select (call adj top)))\")","remote":"localhost"}
{"time":"2017-01-22T00:16:42.444","sessionId":"w3nFZG1uYN","q":"(:q \"while [has color red] [select up; add yellow]\")","remote":"localhost"}
{"time":"2017-01-22T00:16:45.576","sessionId":"w3nFZG1uYN","q":"(:accept \"while [has color red] [select up; add yellow]\" \"(:while (color red) (:s (: select (call adj top)) (: add yellow here)))\")","remote":"localhost"}
{"time":"2017-01-22T00:17:16.687","sessionId":"w3nFZG1uYN","q":"(:q \"while [this and has color red] [select up; add yellow]\")","remote":"localhost"}
{"time":"2017-01-22T00:17:25.866","sessionId":"w3nFZG1uYN","q":"(:q \"red cube size 5\")","remote":"localhost"}
{"time":"2017-01-22T00:17:26.172","sessionId":"w3nFZG1uYN","q":"(:accept \"red cube size 5\" \"(:blk (:blk (:loop (number 5) (:s (:blk (:loop (number 5) (:s (: add red here) (: select (call adj back))))) (: select (call adj left)))) (: select (call adj front))) (:loop (- (number 5) (number 1)) (:s (: select (call adj top)) (:blk (:loop (number 5) (:s (:blk (:loop (number 5) (:s (: add red here) (: select (call adj back))))) (: select (call adj left)))) (: select (call adj front))))))\")","remote":"localhost"}
{"time":"2017-01-22T00:17:27.580","sessionId":"w3nFZG1uYN","q":"(:q \"while [this and has color red] [select up; add yellow]\")","remote":"localhost"}
{"time":"2017-01-22T00:17:42.205","sessionId":"w3nFZG1uYN","q":"(:q \"while [this and has color red] [add yellow; select up]\")","remote":"localhost"}
{"time":"2017-01-22T00:17:43.220","sessionId":"w3nFZG1uYN","q":"(:accept \"while [this and has color red] [add yellow; select up]\" \"(:while (and this (color red)) (:s (: add yellow here) (: select (call adj top))))\")","remote":"localhost"}
{"time":"2017-01-22T00:19:24.781","sessionId":"w3nFZG1uYN","q":"(:q \"replace the red with yellow\")","remote":"localhost"}
{"time":"2017-01-22T00:19:33.117","sessionId":"w3nFZG1uYN","q":"(:def_ret \"replace the red with yellow\" \"[[\\\"while [this and has color red] [add yellow; select up]\\\",\\\"(:while (and this (color red)) (:s (: add yellow here) (: select (call adj top))))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:19:37.579","sessionId":"w3nFZG1uYN","q":"(:q \"select origin\")","remote":"localhost"}
{"time":"2017-01-22T00:19:38.099","sessionId":"w3nFZG1uYN","q":"(:accept \"select origin\" \"(: select (call origin))\")","remote":"localhost"}
{"time":"2017-01-22T00:19:41.179","sessionId":"w3nFZG1uYN","q":"(:q \"select right of right\")","remote":"localhost"}
{"time":"2017-01-22T00:19:45.019","sessionId":"w3nFZG1uYN","q":"(:q \"select left of left\")","remote":"localhost"}
{"time":"2017-01-22T00:19:45.439","sessionId":"w3nFZG1uYN","q":"(:accept \"select left of left\" \"(: select (call adj left (call adj left)))\")","remote":"localhost"}
{"time":"2017-01-22T00:19:52.202","sessionId":"w3nFZG1uYN","q":"(:q \"replace the red with orange\")","remote":"localhost"}
{"time":"2017-01-22T00:19:52.897","sessionId":"w3nFZG1uYN","q":"(:accept \"replace the red with orange\" \"(:while (and this (color red)) (:s (: add orange here) (: select (call adj top))))\")","remote":"localhost"}
{"time":"2017-01-22T00:20:50.449","sessionId":"w3nFZG1uYN","q":"(:q \"add red\")","remote":"localhost"}
{"time":"2017-01-22T00:20:50.777","sessionId":"w3nFZG1uYN","q":"(:accept \"add red\" \"(: add red here)\")","remote":"localhost"}
{"time":"2017-01-22T00:20:55.194","sessionId":"w3nFZG1uYN","q":"(:q \"select left 6 times\")","remote":"localhost"}
{"time":"2017-01-22T00:20:55.638","sessionId":"w3nFZG1uYN","q":"(:accept \"select left 6 times\" \"(:loop (number 6) (: select (call adj left)))\")","remote":"localhost"}
{"time":"2017-01-22T00:21:07.717","sessionId":"w3nFZG1uYN","q":"(:q \"move right to the red block\")","remote":"localhost"}
{"time":"2017-01-22T00:21:38.542","sessionId":"w3nFZG1uYN","q":"(:q \"while [has color red and not this] [move right]\")","remote":"localhost"}
{"time":"2017-01-22T00:21:45.078","sessionId":"w3nFZG1uYN","q":"(:q \"while [has color red and not this] [select right]\")","remote":"localhost"}
{"time":"2017-01-22T00:21:46.845","sessionId":"w3nFZG1uYN","q":"(:accept \"while [has color red and not this] [select right]\" \"(:while (and (color red) (not this)) (: select (call adj right)))\")","remote":"localhost"}
{"time":"2017-01-22T00:21:53.183","sessionId":"w3nFZG1uYN","q":"(:def_ret \"move right to the red block\" \"[[\\\"while [has color red and not this] [select right]\\\",\\\"(:while (and (color red) (not this)) (: select (call adj right)))\\\"]]\")","remote":"localhost"}
{"time":"2017-01-22T00:21:58.891","sessionId":"w3nFZG1uYN","q":"(:q \"move left 3 times\")","remote":"localhost"}
{"time":"2017-01-22T00:22:03.707","sessionId":"w3nFZG1uYN","q":"(:q \"select left 3 times\")","remote":"localhost"}
{"time":"2017-01-22T00:22:04.077","sessionId":"w3nFZG1uYN","q":"(:accept \"select left 3 times\" \"(:loop (number 3) (: select (call adj left)))\")","remote":"localhost"}
{"time":"2017-01-22T00:22:07.389","sessionId":"w3nFZG1uYN","q":"(:q \"move right to the red block\")","remote":"localhost"}
{"time":"2017-01-22T00:22:07.797","sessionId":"w3nFZG1uYN","q":"(:accept \"move right to the red block\" \"(:while (and (color red) (not this)) (: select (call adj right)))\")","remote":"localhost"}

233
interactive/run Executable file
View File

@ -0,0 +1,233 @@
#!/usr/bin/env ruby
# This is the main entry point for running SHRDLURN. See
# fig/lib/execrunner.rb for more documentation for how commands are generated.
# There are a bunch of modes that this script can be invoked with, which
# loosely correspond to the modules.
$: << 'fig/lib'
require 'execrunner'
$optPrefix = '-'
$path = 'interactive'
$output = 'interactive/output'
$modes = []
def addMode(name, description, func)
$modes << [name, description, func]
end
def codalab(dependencies=nil)
# Set @cl=1 to run job on CodaLab
dependencies ||= l(':fig', ':lib', ':module-classes.txt', ':libsempre')
l(
letDefault(:cl, 0),
sel(:cl,
l(),
l('cl', 'run', dependencies, '---', 'LC_ALL=C.UTF-8'),
nil),
nil)
end
def header(modules='core', codalabDependencies=nil)
l(
codalab(codalabDependencies),
# Queuing system
letDefault(:q, 0), sel(:q, l(), l('fig/bin/q', '-shareWorkingPath', o('mem', '5g'), o('memGrace', 10), '-add', '---')),
# Create execution directory
letDefault(:pooldir, 1),
sel(:pooldir, l(), 'fig/bin/qcreate'),
# Run the Java command...
'java',
'-ea',
'-Dmodules='+modules,
# Memory size
letDefault(:memsize, 'default'),
sel(:memsize, {
'tiny' => l('-Xms2G', '-Xmx4G'),
'low' => l('-Xms5G', '-Xmx7G'),
'default' => l('-Xms8G', '-Xmx10G'),
'medium' => l('-Xms12G', '-Xmx14G'),
'high' => l('-Xms20G', '-Xmx24G'),
'higher' => l('-Xms40G', '-Xmx50G'),
'impressive' => l('-Xms75G', '-Xmx90G'),
}),
# Classpath
'-cp', 'libsempre/*:lib/*',
# Profiling
letDefault(:prof, 0), sel(:prof, l(), '-Xrunhprof:cpu=samples,depth=100,file=_OUTPATH_/java.hprof.txt'),
# Debugging
letDefault(:debug, 0), sel(:debug, l(), l('-Xdebug', '-Xrunjdwp:server=y,transport=dt_socket,suspend=y,address=8898')),
nil)
end
def figOpts; l(selo(:pooldir, 'execDir', 'exec', '_OUTPATH_'), o('overwriteExecDir'), o('addToView', 0)) end
############################################################
# Unit tests
addMode('backup', 'small commands like run community server, backup, or simulator', lambda { |e| l(
lambda { |e| system 'echo "backing up with mv"'},
lambda { |e| system 'mkdir -p ./int-backup/'},
letDefault(:msg, 'backing up, no message'),
lambda { |e| l('echo ', :msg, '> ./int-backup/message')},
lambda { |e| l('echo ', '`date +%Y-%m-%d.%H:%M:%S`', '>> ./int-backup/message')},
lambda { |e| system 'mv int-output int-backup/`date +%Y-%m-%d.%H:%M:%S`'},
lambda { |e| system 'mkdir -p ./int-output'},
nil)})
addMode('backup-data', 'put community-server into trash with time stamp', lambda { |e| l(
lambda { |e| system 'echo "backing up data with mv"'},
lambda { |e| system 'mkdir -p ./community-server/data-backup'},
lambda { |e| system 'mv ./community-server/data ./community-server/data-backup/`date +%Y-%m-%d.%H:%M:%S`'},
nil)})
addMode('trash', 'put int-output into trash with time stamp', lambda { |e| l(
lambda { |e| system 'echo "trashing int-output with time stamp"'},
lambda { |e| system 'mv int-output int-output-trash-`date +%Y-%m-%d.%H:%M:%S`'},
lambda { |e| system 'rm -rf int-output-trash-*'},
lambda { |e| system 'mkdir -p ./int-output'},
nil)})
addMode('test', 'Run unit tests for interactive stuff', lambda { |e|
l(
'java', '-ea', '-Xmx12g', '-cp', 'libsempre/*:lib/*',
letDefault(:debug, 0), sel(:debug, l(), l('-Xdebug', '-Xrunjdwp:server=y,transport=dt_socket,suspend=y,address=8898')),
'org.testng.TestNG',
lambda { |e|
if e[:class]
l('-testclass', 'edu.stanford.nlp.sempre.interactive.test.' + e[:class])
else
"./#{$path}/testng.xml"
end
},
nil)
})
addMode('simulator', 'run the simulator', lambda { |e| l(
# rlwrap,
header('core,interactive'),
'edu.stanford.nlp.sempre.interactive.Simulator',
figOpts,
letDefault(:server, 'local'),
sel(:server, {
'local' => o('serverURL', 'http://localhost:8410'),
'remote' => o('serverURL', 'http://jonsson.stanford.edu:8410')
}),
# set to 0 to enable logging
o('numThreads', 1),
letDefault(:sandbox, 'full'),
sel(:sandbox, {
'all' => o('reqParams', 'grammar=0\&cite=0\&learn=0\&logging=0'),
'nolog' => o('reqParams', 'grammar=0\&cite=0\&learn=1\&logging=0'),
'nolearn' => o('reqParams', 'grammar=1\&cite=1\&learn=0\&logging=0'),
'none' => o('reqParams', 'grammar=1\&cite=1\&learn=1\&logging=0'),
'nocite' => o('reqParams', 'grammar=1\&cite=0\&learn=1\&logging=0'),
}),
letDefault(:task, 'sidaw'),
sel(:task, {
'freebuild' => o('logFiles', "./#{$path}/queries/freebuild.json.gz"),
'freebuilddef' => o('logFiles', "./#{$path}/queries/freebuild.def.json.gz"),
'qual1' => o('logFiles', "./#{$path}/queries/rawqueries/qualifier1-0118.json.gz"),
'qual2' => o('logFiles', "./#{$path}/queries/rawqueries/qualifier2-0129.json.gz"),
'qual3' => o('logFiles', "./#{$path}/queries/rawqueries/qualifier3-0201.json.gz"), # both 2 and 3
'free1' => o('logFiles', "./#{$path}/queries/rawqueries/freebuild1-0121.json.gz"),
'free2' => o('logFiles', "./#{$path}/queries/rawqueries/freebuild2-0127.json.gz"),
}),
nil)})
############################################################
# {2016-07-02} [sidaw]: interactive semantic parsing
addMode('voxelurn', 'interactive semantic parsing in a VoxelWorld', lambda { |e| l(
#rlwrap,
header('core,interactive'),
'edu.stanford.nlp.sempre.Main',
#figOpts,
o('server'),
o('masterType', 'edu.stanford.nlp.sempre.interactive.InteractiveMaster'),
o('Executor', 'interactive.DALExecutor'),
o('LanguageAnalyzer', 'interactive.DALAnalyzer'),
o('DALExecutor.convertNumberValues', true),
o('DALExecutor.printStackTrace', true),
o('VoxelWorld.maxBlocks', 100000),
selo(0, 'DALExecutor.worldType', 'VoxelWorld', 'CalendarWorld', 'Otherworld'),
selo(0, 'Grammar.inPaths', "./#{$path}/voxelurn.grammar"),
o('Params.initWeightsRandomly', false),
o('Grammar.binarizeRules', false),
o('Grammar.useApplyFn', 'interactive.ApplyFn'),
o('LanguageAnalyzer.lowerCaseTokens', true),
o('Parser.pruneErrorValues', true),
o('Parser', 'interactive.InteractiveBeamParser'),
o('Parser.callSetEvaluation', false),
o('Parser.coarsePrune', true),
o('Parser.beamSize', 50),
o('InteractiveBeamParser.maxNewTreesPerSpan', 5001),
o('ParserState.customExpectedCounts', 'None'),
selo(0, 'InteractiveBeamParser.floatStrategy', 'Never', 'NoParse', 'Always'),
o('InteractiveBeamParser.trackedCats', 'Number', 'Numbers', 'Color', 'Direction', 'Set', 'Sets', 'Action', 'Actions'),
o('Derivation.derivComparator', 'AnchorPriorityScoreComparator'),
o('Params.l1Reg', 'nonlazy'),
o('Params.l1RegCoeff', 0.0001),
o('Params.initStepSize', 0.1),
o('Params.adaptiveStepSize', true),
#o('Params.stepSizeReduction', 0.25),
o('FeatureExtractor.featureComputers', 'interactive.DALFeatureComputer'),
o('FeatureExtractor.featureDomains', ':rule', ':span', ':stats', ':scope', ':social', ':window'),
# o('FeatureExtractor.featureDomains', ':rule'),
o('InteractiveMaster.intOutputPath', './int-output/'),
o('InteractiveMaster.onlyInteractive', true),
o('InteractiveUtils.citationPath', './int-output/citation/'),
o('InteractiveMaster.useAligner', false),
o('InteractiveMaster.maxSequence', 20),
o('InteractiveMaster.maxChars', 200),
o('DefinitionAligner.strategies', 'ExactExclusion'),
o('InteractiveServer.numThreads', 16),
o('InteractiveServer.maxCandidates', 50),
o('InteractiveServer.queryLogPath', './int-output/query.log'),
o('InteractiveServer.responseLogPath', './int-output/response.log'),
o('InteractiveServer.port', 8410),
o('GrammarInducer.useBestPacking', true),
o('GrammarInducer.useSimplePacking', true),
o('GrammarInducer.maxNonterminals', 3),
o('Derivation.showTypes', false),
o('Derivation.showValues', false),
o('Derivation.showRules', false),
o('Derivation.anchoredBonus', 1.0),
o('NumberFn.allowedRange', 0, 100),
o('SimpleLexicon.inPaths', "./#{$path}/csscolors.lexicon"),
lambda { |e| system 'mkdir -p ./int-output/'; nil},
lambda { |e| system 'mkdir -p ./int-output/log/'; nil},
lambda { |e| system 'mkdir -p ./int-output/citation/'; nil},
nil) })
############################################################
if ARGV.size == 0
puts "#{$0} @mode=<mode> [options]"
puts
puts 'This is the main entry point for all interactive related modes.'
puts "Modes:"
$modes.each { |name,description,func|
puts " #{name}: #{description}"
}
end
modesMap = {}
$modes.each { |name,description,func|
modesMap[name] = func
}
run!(sel(:mode, modesMap))

16
interactive/testng.xml Normal file
View File

@ -0,0 +1,16 @@
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="SempreInteractiveTestSuite" verbose="10">
<test name="InteractiveTests">
<classes>
<class name="edu.stanford.nlp.sempre.interactive.test.GrammarInducerTest">
</class>
<class name="edu.stanford.nlp.sempre.interactive.test.DALExecutorTest">
</class>
<!--
<class name="edu.stanford.nlp.sempre.interactive.test.FloatingParsingTest">
</class>
-->
</classes>
</test>
</suite>

View File

@ -0,0 +1,74 @@
# domain specific grammar for voxelurn
(include dal.grammar)
# domain specific actions:
(def @put put)
(def @base base)
(def @add add)
(def @move move)
# syntactic sugar
(def @veryx veryx)
# typed lambdas
# Action a, ItemSet i, ValueSet v, Rel r, Direction d, Color c, Number n
# Rule.defaultIsFloating should be false
# utilities
(rule $Action (base $Number $Number) (lambda x (lambda y (: @base (var x) (var y)))) (anchored 1))
(rule $Action (noop) (ConstantFn (: noop)) (anchored 1))
(rule $Set (origin) (ConstantFn (call origin)) (anchored 1))
# primitive actions
(rule $Action (add $Color) (lambda c (: @add (var c) here)) (anchored 1))
(rule $Action (add $Color $Direction) (lambda c (lambda d (: @add (var c) (var d)))) (anchored 1))
(rule $Action (move $Direction) (lambda d (: @move (var d))) (anchored 1))
# primitive actions with arguments
# cube to cube relations
(rule $Set ($Direction of $Set) (lambda d (lambda s
(call adj (var d) (var s)))) (anchored 1))
(rule $Set ($Extreme of $Set) (lambda e (lambda s
(call @veryx (var e) (var s)))) (anchored 1))
(rule $Set ($Direction) (lambda d
(call adj (var d))) (anchored 1))
(rule $Set ($Extreme) (lambda e
(call @veryx (var e))) (anchored 1))
(for @dir (top bot left right front back)
(rule $Direction (@dir) @dir (anchored 1))
)
(rule $Extreme (very $Direction) (IdentityFn) (anchored 1))
(for @rel (col row height color name age)
(rule $Rel (@rel) (ConstantFn @rel) (anchored 1))
)
(rule $ValueSet ($Color) (IdentityFn) (anchored 1))
(rule $ValueSet ($Number) (IdentityFn) (anchored 1))
# set the range via NumberFn options
(rule $Number ($TOKEN) (NumberFn) (anchored 1))
(rule $Color ($TOKEN) (SimpleLexiconFn (type color)) (anchored 1))
####### domain specific floating rules
# red means has color red
# (rule $Sets ($Color) (lambda c (color (var c))))
# various actions can be performed
# (rule $Action ($Color) (lambda c (: @add (var c) here)))
# (rule $Action ($Color $Direction) (lambda c (lambda d (: @add (var c) (var d)))))
# (rule $Action ($Direction) (lambda d (: @move (var d))))
# (rule $Set ($Direction $Sets) (lambda d (lambda s
# (call adj (var d) (var s)))))
# (rule $Set ($Extreme $Sets) (lambda e (lambda s
# (call @veryx (var e) (var s)))))
# (rule $Set ($Direction) (lambda d
# (call adj (var d))))
# (rule $Set ($Extreme) (lambda e
# (call @veryx (var e))))

44
overnight/README.md Normal file
View File

@ -0,0 +1,44 @@
# Files for Building a Semantic Parser Overnight
## Generating canonical utterances
To generate all the canonical utterances, run:
./pull-dependencies freebase overnight
ant corenlp freebase overnight
./run @mode=genovernight-wrapper
To generate each individual domain:
./run @mode=genovernight @gen=1 @domain=<domain>
## Training
After generating the paraphrases via AMT and setting up the appropriate example
files, we train a model.
Run the following to train with all the features:
./run @mode=overnight @domain=<domain>
To run with a subset of the features for ablation studies:
Baseline:
./run @mode=overnight @domain=<domain> -OvernightFeatureComputer.featureDomains match skip-bigram root lf simpleworld
No Lexical features:
./run @mode=overnight @domain=<domain> -OvernightFeatureComputer.featureDomains match ppdb skip-bigram root lf simpleworld
No PPDB features:
./run @mode=overnight @domain=<domain> -OvernightFeatureComputer.featureDomains match skip-bigram root lf alignment lexical root_lexical simpleworld
Full system:
./run @mode=overnight @domain=<domain> -OvernightFeatureComputer.featureDomains match ppdb skip-bigram root alignment lexical root_lexical lf simpleworld
# Generating alignment files for a new domain
[See the instructions here](https://docs.google.com/document/d/1cgqThUAyArbgjQi0P7l--kCLH10copd1EXFnk_bHkY0/edit?usp=sharing) (work in progress).

View File

@ -0,0 +1,38 @@
(include general.grammar)
# Types
(rule $TypeNP (player) (ConstantFn en.player))
(rule $EntityNP1 (kobe bryant) (ConstantFn en.player.kobe_bryant))
(rule $EntityNP2 (lebron james) (ConstantFn en.player.lebron_james))
(rule $TypeNP (team) (ConstantFn en.team))
(rule $EntityNP1 (los angeles lakers) (ConstantFn en.team.lakers))
(rule $EntityNP2 (cleveland cavaliers) (ConstantFn en.team.cavaliers))
(rule $TypeNP (position) (ConstantFn en.position))
(rule $EntityNP1 (point guard) (ConstantFn en.position.point_guard))
(rule $EntityNP2 (forward) (ConstantFn en.position.forward))
(rule $EntityNP1 (2004) (ConstantFn (date 2004 -1 -1)))
(rule $EntityNP2 (2010) (ConstantFn (date 2010 -1 -1)))
(for @x (point assist steal turnover rebound block foul game fg ft)
(rule $EntityNP1 (3) (ConstantFn (number 3 @x)))
#(rule $EntityNP2 (6) (ConstantFn (number 6 @x)))
)
# Season statistics
(rule $Rel0NP (player) (ConstantFn (string player)))
(rule $RelNP (position) (ConstantFn (string position)))
(rule $RelNP (team) (ConstantFn (string team)))
(rule $RelNP (season) (ConstantFn (string season)))
(rule $RelNP (number of points "(over a season)") (ConstantFn (string num_points)))
(rule $RelNP (number of assists "(over a season)") (ConstantFn (string num_assists)))
(rule $RelNP (number of steals "(over a season)") (ConstantFn (string num_steals)))
(rule $RelNP (number of turnovers "(over a season)") (ConstantFn (string num_turnovers)))
(rule $RelNP (number of rebounds "(over a season)") (ConstantFn (string num_rebounds)))
(rule $RelNP (number of blocks "(over a season)") (ConstantFn (string num_blocks)))
(rule $RelNP (number of fouls "(over a season)") (ConstantFn (string num_fouls)))
(rule $RelNP (number of played games "(over a season)") (ConstantFn (string num_games_played)))

28
overnight/blocks.grammar Normal file
View File

@ -0,0 +1,28 @@
(include general.grammar)
# Types
(rule $TypeNP (block) (ConstantFn en.block))
(rule $EntityNP1 (block 1) (ConstantFn en.block.block1))
(rule $EntityNP2 (block 2) (ConstantFn en.block.block2))
# Properties
(rule $RelNP (shape) (ConstantFn (string shape)))
(rule $EntityNP1 (a pyramid) (ConstantFn en.shape.pyramid))
(rule $EntityNP2 (a cube) (ConstantFn en.shape.cube))
(rule $RelNP (color) (ConstantFn (string color)))
(rule $EntityNP1 (red) (ConstantFn en.color.red))
(rule $EntityNP2 (green) (ConstantFn en.color.green))
(rule $RelNP (length) (ConstantFn (string length)))
(rule $RelNP (width) (ConstantFn (string width)))
(rule $RelNP (height) (ConstantFn (string height)))
(rule $EntityNP1 (3 inches) (ConstantFn (number 3 en.inch)))
(rule $EntityNP2 (6 inches) (ConstantFn (number 6 en.inch)))
(rule $VP/NP (is left of) (ConstantFn (string left)))
(rule $VP/NP (is right of) (ConstantFn (string right)))
(rule $VP/NP (is above) (ConstantFn (string above)))
(rule $VP/NP (is below) (ConstantFn (string below)))
(rule $VP (is special) (ConstantFn (string is_special)))

View File

@ -0,0 +1,6 @@
# Make sure these test cases always parse
(example (utterance "create a meeting with start time 3pm"))
(example (utterance "what is the meeting whose start time is 9am or 3pm"))
(example (utterance "remove the meeting whose date is day 2"))
(example (utterance "what is the location of the meeting whose start time is 9am"))
(example (utterance "what is the length of the free block whose date is day 1 with the largest end time"))

View File

@ -0,0 +1,33 @@
(include general.grammar)
# Types
(rule $TypeNP (meeting) (ConstantFn en.meeting))
(rule $EntityNP1 (weekly standup) (ConstantFn en.meeting.weekly_standup))
(rule $EntityNP2 (annual review) (ConstantFn en.meeting.annual_review))
# Properties
(rule $RelNP (date) (ConstantFn (string date)))
(rule $EntityNP1 (jan 2) (ConstantFn (date 2015 1 2)))
(rule $EntityNP2 (jan 3) (ConstantFn (date 2015 1 3)))
(rule $RelNP (start time) (ConstantFn (string start_time)))
(rule $RelNP (end time) (ConstantFn (string end_time)))
(rule $EntityNP1 (10am) (ConstantFn (time 10 0)))
(rule $EntityNP2 (3pm) (ConstantFn (time 15 0)))
(rule $RelNP (length) (ConstantFn (string length)))
(rule $EntityNP1 (three hours) (ConstantFn (number 3 en.hour)))
(rule $EntityNP2 (one hour) (ConstantFn (number 1 en.hour)))
(rule $RelNP (attendee) (ConstantFn (string attendee)))
(rule $TypeNP (person) (ConstantFn en.person))
(rule $EntityNP1 (alice) (ConstantFn en.person.alice))
(rule $EntityNP2 (bob) (ConstantFn en.person.bob))
(rule $RelNP (location) (ConstantFn (string location)))
(rule $TypeNP (location) (ConstantFn en.location))
(rule $EntityNP1 (greenberg cafe) (ConstantFn en.location.greenberg_cafe))
(rule $EntityNP2 (central office) (ConstantFn en.location.central_office))
# Unaries
(rule $VP (is important) (ConstantFn (string is_important)))

View File

@ -0,0 +1,428 @@
(example
(utterance "What meeting is on Jan 3?")
(original "meeting whose date is jan 3")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 1 3)))
)
)
(example
(utterance "How many meetings after 1pm?")
(original "number of meeting whose start time is larger than 1pm")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string start_time)) (string >) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericEntity (time 13 0)))))
)
)
(example
(utterance "What meeting is on Wed Jan 5")
(original "meeting whose date is jan 5")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 1 5)))
)
)
(example
(utterance "Am I free on mar 6?")
(original "number of meeting whose date is mar 6")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string date)) (string =) (date 2015 3 6))))
)
)
(example
(utterance "Which meetings are about the office chair?")
(original "meeting whose subject is office chair")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string subject) (string =) (en.subject.office_chair)))
)
)
(example
(utterance "What time does the office meeting start?")
(original "start time of meeting whose location is office")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string location) (string =) en.location.office) (string start_time)))
)
)
(example
(utterance "Who is attending the meeting on June 9?")
(original "attendee of meeting whose date is jun 9")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 6 9)) (string attendee)))
)
)
(example
(utterance "How long is the meeting on May 23?")
(original "length of meeting whose date is may 23")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 5 23)) (string length)))
)
)
(example
(utterance "Where is the meeting on Jun 12?")
(original "location of meeting whose date is jun 12")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 6 12)) (string location)))
)
)
(example
(utterance "What time is my weekly standup?")
(original "start time of weekly standup")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty en.meeting.weekly_standup (string start_time)))
)
)
(example
(utterance "How many times have I visited greenburg cafe at noon?")
(original "Number of meetings whose location is greenburg cafe and whose start time is 12pm")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string location) (string =) en.location.greenburg_cafe) (string start_time) (string =) (time 12 0))))
)
)
(example
(utterance "Are there any meetings in June?")
(original "number of meeting whose date is at least jun 1 and whose date is at most jun 30")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string >=) (date 2015 6 1)) (string date) (string <=) (date 2015 6 30))))
)
)
(example
(utterance "Do I have meetings on May 8?")
(original "number of meeting whose date is may 8")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld. getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string date)) (string =) (date 2015 5 8))))
)
)
(example
(utterance "What do I have scheduled on May 7?")
(original "meeting whose date may 7")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 5 7)))
)
)
(example
(utterance "How many meetings does Alice have on May 12?")
(original "Number of meetings whose attendee is alice and whose date is may 12")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string attendee) (string =) en.person.alice) (string date) (string =) (date 2015 5 12))))
)
)
(example
(utterance "Who is attending the same meetings as me on May 7th?")
(original "attendee of meeting whose date is may 7")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 5 7)) (string attendee)))
)
)
(example
(utterance "Who is attending the 2:00 pm meeting on January 3rd?")
(original "attendee of meeting whose start time is 2pm and whose date is jan 3)
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string start_time) (string =) (time 14 0)) (string date) (string =) (date 2015 1 3)) (string attendee)))
)
)
(example
(utterance "What time does my first meeting start on May 17?")
(original "start time of meeting whose date is may 17 that has smallest start time")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.superlative (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 5 17)) (string min) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string start_time))) (string start_time)))
)
)
(example
(utterance "How many people will be attending the meeting on December 23?")
(original "number of attendee of meeting whose date is dec 23")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 12 23)) (string attendee))))
)
)
(example
(utterance "Where are my meetings on Feb 3?")
(original "location of meeting whose date is feb 3")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 2 3)) (string location)))
)
)
(example
(utterance "Who will be at the meeting on Feb 3?")
(original "attendee of meeting whose date is feb 3")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 2 3)) (string attendee)))
)
)
(example
(utterance "When is my first meeting on Feb 3?")
(original "start time of meeting whose date is feb 3 that has smallest start time")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.superlative (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 2 3)) (string min) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string start_time))) (string start_time)))
)
)
(example
(utterance "When is my last meeting on Feb 3?")
(original "start time of meeting whose date is feb 3 that has largest start time")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.superlative (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 2 3)) (string max) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string start_time))) (string start_time)))
)
)
(example
(utterance "Who is attending the meeting on My6?")
(original "attendee of meeting whose date is may 6")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 5 6)) (string attendee)))
)
)
(example
(utterance "Where is the location of the meeting on May 7?")
(original "location of meeting whose date is may 7")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 5 7)) (string location)))
)
)
(example
(utterance "What is the subject of my June 6 meeting?")
(original "subject of meeting whose date is jun 6")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 6 6)) (string subject)))
)
)
(example
(utterance "Where is my June 6 meeting?")
(original "location of meeting whose date is jun 6")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 6 6)) (string location)))
)
)
(example
(utterance Who is attending my June 6 meeting?")
(original "attendee of meeting whose date is jun 6")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 6 6)) (string attendee)))
)
)
(example
(utterance "What is the subject of my June 6 meeting?")
(original "subject of meeting whose date is jun 6")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 6 6)) (string subject)))
)
)
(example
(utterance "What time does the June 6 meeting start?")
(original "start time of meeting whose date is jun 6")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 6 6)) (string start_time)))
)
)
(example
(utterance "Which meetings are in the afternoon?)
(original "meeting whose start time is at least 12pm")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string start_time)) (string >=) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericEntity (time 12 0)))))
)
)
(example
(utterance "How many meetings are on Dec 12?")
(original "number of meeting whose date is dec 12")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld. getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string date)) (string =) (date 2015 12 12))))
)
)
(example
(utterance "How many meetings is Alice going to in April?")
(original "number of meeting whose attendee is alice and whose date is at least apr 1 and whose date is at most apr 30")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string attendee) (string =) en.person.alice) (string date) (string >=) (date 2015 4 1)) (string date) (string <=) (date 2015 4 30))))
)
)
(example
(utterance "What is the longest meeting scheduled for the week of May 4-8?")
(original "meeting whose date is at least may 4 and whose date is at most may 8 that has the largest length")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call edu.stanford.nlp.sempre.agile.SimpleWorld.superlative (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string >=) (date 2015 5 4)) (string date) (string <=) (date 2015 5 8)) (string max) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string length))))
)
)
(example
(utterance "Do I have any meetings on May 8th?")
(original "number of meeting whose date is may 8")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld. getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (call edu.stanford.nlp.sempre.agile.SimpleWorld.ensureNumericProperty (string date)) (string =) (date 2015 5 8))))
)
)
(example
(utterance "When does my meeting on June 3rd end?")
(original "end time of meeting whose date is jun 3")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 6 3)) (string end_time)))
)
)
(example
(utterance "What time is my meeting on May 7th?")
(original "start time of meeting whose date is may 7")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 5 7)) (string start_time)))
)
)
(example
(utterance "How many people will be in the May 10th meeting?")
(original "number of attendee of meeting whose date is may 10")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call @getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 5 10)) (string attendee))))
)
)
(example
(utterance "Do I have any important meetings in April?")
(original "number of meeting that is important and whose date is at least apr 1 and whose date is at most april 30")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (cal l edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string is_important)) (string date) (string >=) (date 2015 4 1)) (string date) (string <=) (date 2015 4 30))))
)
)
(example
(utterance "How many important meetings do I have in April?")
(original "number of meeting that is important and whose date is at least apr 1 and whose date is at most april 30")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (cal l edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string is_important)) (string date) (string >=) (date 2015 4 1)) (string date) (string <=) (date 2015 4 30))))
)
)
(example
(utterance "Will Alice be at the meeting on May 10th?")
(original "meeting whose attendee is alice and whose date is may 10")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call .size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string attendee) (string =) en.person.alice) (string date) (string =) (date 2015 5 10))))
)
)
(example
(utterance "Is there a meeting on February 3?")
(original "meeting whose date is feb 3")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 2 3)))
)
)
(example
(utterance "Which meetings are scheduled for August 1?")
(original "meeting whose date is aug 1")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (call edu.stanford.nlp.sempre.agile.SimpleWorld.getProperty (call edu.stanford.nlp.sempre.agile.SimpleWorld.singleton en.meeting) (string !type)) (string date) (string =) (date 2015 8 1)))
)
)
(example
(utterance "how many meetings do I have to attend in July?")
(original "number of meeting whose date is at least aug 1 and whose date is at most aug 31")
(targetFormula
(call edu.stanford.nlp.sempre.agile.SimpleWorld.listValue (call.size (call edu.stanford.nlp.sempre.agile.SimpleWorld.filter (edu.stanford.nlp.sempre.agile.SimpleWorld.)
)
)
how many meetings do I have to attend in July?
where is the 2pm meeting being held?
Which meetings in May 1-7 are in the morning?
Who is attending the May 19th meeting?
which is my next day without a meeting?
When is my next meeting with Alice?
What is happening on the third?
when does my last meeting end on feb 14?
how many people will be at the march 4 meeting?
What time is my meeting on Monday May 11th?
Do I have anything scheduled on Wednesday May 13th?
where is the last meeting of the year?
how many meeting are in February?
How many meetings are after noon?
How many meetings are after noon on May 9th?
How many meetings are before 4 pm on May 10th?
Which meeting is Jami attending on May 11th?
What is the agenda of the meeting?
How long will the meeting prolong?
How many important meetings do I have before noon on May 9th?
What meetings are in March?
how many meetings on jul 23 are longer than 1 hour?
how many meetings have more than 2 attendees?
what is the subject of the meeting on nov 23 at 4 pm?
do i have any plans for 15th march
can you check my appointments for the evening of the 5th
What meetings are scheduled for May 5th?
Where is the meeting scheduled for May 5th?
How many will be attending the May 5th meeting?
What time does the May 5th meeting start?
what time is my first meeting on February 22?
What meetings are scheduled with the CEO, Bob?
What time does my last meeting end on June 22?
Which meetings are about the annual budget review?
what time is my next meeting with bob?
==== Requires "now"/"today"/"tomorrow" ====
How many meetings do I have next week?
Is Alice going to the meeting tomorrow?
Where are the meetings for tomorrow?
How many meetings do I have today?
When do I have an important meeting in the next three days?
What meetings are scheduled for next week?
What time is tomorrow's meeting?
How many meetings are this month?
What is the earliest meeting tomorrow?
What is the latest meeting tomorrow?
What time is my next meeting?
How many people will attend the meeting tomorrow?
What time does today's meeting start?
Where is my first meeting of the day at?
When does my last meeting of the day end?
Find the address for my next meeting?
How much time do I have until my next meeting with Sam?
How many meetings are today?
Am I free at 2 pm today?
How many meetings do I have this week?
What is on today's calendar?
When is my next standup?
How many meetings are this month?
==== Implicit reference ====
How many attendees are planning on going to the meeting?
What time do I have to be at the meeting on May 9?
==== Not in grammar =====
Is it possible to schedule a meeting before 2 pm?
When do I call my boss Bob?
When is my date with Alice?
What meetings are with my Client Adam?
Which month is most popular for meetings?
When is the annual report due?
==== yes/no ====
Do I have more than 2 meetings on April 5?

416
overnight/general.grammar Normal file
View File

@ -0,0 +1,416 @@
############################################################
# General grammar
# There are two types of grammars
# - generate: used to generate canonical utterances
# - parse: used to actually parse
(def @domain edu.stanford.nlp.sempre.overnight.SimpleWorld.domain)
(def @singleton edu.stanford.nlp.sempre.overnight.SimpleWorld.singleton)
(def @filter edu.stanford.nlp.sempre.overnight.SimpleWorld.filter)
(def @getProperty edu.stanford.nlp.sempre.overnight.SimpleWorld.getProperty)
(def @superlative edu.stanford.nlp.sempre.overnight.SimpleWorld.superlative)
(def @countSuperlative edu.stanford.nlp.sempre.overnight.SimpleWorld.countSuperlative)
(def @countComparative edu.stanford.nlp.sempre.overnight.SimpleWorld.countComparative)
(def @aggregate edu.stanford.nlp.sempre.overnight.SimpleWorld.aggregate)
(def @concat edu.stanford.nlp.sempre.overnight.SimpleWorld.concat)
(def @reverse edu.stanford.nlp.sempre.overnight.SimpleWorld.reverse)
(def @arithOp edu.stanford.nlp.sempre.overnight.SimpleWorld.arithOp)
(def @sortAndToString edu.stanford.nlp.sempre.overnight.SimpleWorld.sortAndToString)
(def @ensureNumericProperty edu.stanford.nlp.sempre.overnight.SimpleWorld.ensureNumericProperty)
(def @ensureNumericEntity edu.stanford.nlp.sempre.overnight.SimpleWorld.ensureNumericEntity)
(def @listValue edu.stanford.nlp.sempre.overnight.SimpleWorld.listValue)
############################################################
# Base cases
(when parse
# G1
# Generic values
(rule $EntityNP ($PHRASE) (NumberFn) (anchored 1))
(rule $EntityNP ($PHRASE) (DateFn) (anchored 1))
# Currently, just cheat and use the entities defined in the base grammar.
# In the future, want actually NER.
(rule $EntityNP ($EntityNP1) (IdentityFn))
(rule $EntityNP ($EntityNP2) (IdentityFn))
#(rule $EntityNP ($PHRASE) (FilterNerSpanFn PERSON ORGANIZATION LOCATION MISC) (anchored 1))
#(rule $EntityNP ($PHRASE) (FilterPosTagFn span NNP) (anchored 1))
(rule $Num ($PHRASE) (NumberFn) (anchored 1))
)
(when generate
(rule $Num (two) (ConstantFn (number 2)))
)
(when (and parse general)
# G1
(rule $NP ($EntityNP) (IdentityFn))
# G2
(rule $NP ($TypeNP) (lambda t (call @getProperty (call @singleton (var t)) (string !type)))) # Unary
)
(when (and generate general)
(rule $UnaryNP ($TypeNP) (lambda t (call @getProperty (call @singleton (var t)) (string !type)))) # Unary
)
(when (and parse regex)
(rule $NP ($EntityNP) (IdentityFn))
(rule $NP ($TypeNP) (IdentityFn))
)
(when (and generate regex)
(rule $UnaryNP ($TypeNP) (IdentityFn))
)
(when (and parse general)
(rule $NumberRelNP ($RelNP) (lambda r (call @ensureNumericProperty (var r))))
(rule $NumberNP ($NP) (lambda r (call @ensureNumericEntity (var r))))
)
(when (and generate general)
(rule $NumberRelNP ($RelNP) (lambda r (call @ensureNumericProperty (var r))))
(rule $NumberEntityNP ($EntityNP1) (lambda r (call @ensureNumericEntity (var r))))
(rule $NumberNP0 ($NP0) (lambda r (call @ensureNumericEntity (var r))))
)
############################################################
# Complementizer phrase (filtering)
(when (and parse general)
# R0
(rule $CP (that $VP) (lambda r (lambda s (call @filter (var s) (var r))))) # Vunary
# R1
(rule $CP (whose $RelNP is $NP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Req
(rule $CP (whose $RelNP is not $NP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string !=) (var n)))))) # Rnot
(rule $CP (whose $NumberRelNP is smaller than $NumberNP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string <) (var n)))))) # Rl
(rule $CP (whose $NumberRelNP is larger than $NumberNP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string >) (var n)))))) # Rg
(rule $CP (whose $NumberRelNP is at most $NumberNP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string <=) (var n)))))) # Rle
(rule $CP (whose $NumberRelNP is at least $NumberNP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string >=) (var n)))))) # Rge
# R2
(rule $CP (that $VP/NP $NP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Vobj
(rule $CP (that not $VP/NP $NP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string !=) (var n)))))) # Vobj-not
# R3
(rule $CP (that is $RelNP of $NP) (lambda r (lambda n (lambda s (call @filter (var s) (call @reverse (var r)) (string =) (var n)))))) # Reqrev
(rule $CP (that is not $RelNP of $NP) (lambda r (lambda n (lambda s (call @filter (var s) (call @reverse (var r)) (string !=) (var n)))))) # Reqrev-not
# R4
(rule $CP (that $NP $VP/NP) (lambda n (lambda r (lambda s (call @filter (var s) (call @reverse (var r)) (string =) (var n)))))) # Vsubj
(rule $CP (that $NP not $VP/NP) (lambda n (lambda r (lambda s (call @filter (var s) (call @reverse (var r)) (string !=) (var n)))))) # Vsubj-not
)
(when (and generate general)
# R0
(rule $CP00 (that $VP) (lambda r (lambda s (call @filter (var s) (var r))))) # Vunary
# R1
(rule $CP00 (whose $RelNP is $EntityNP1) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Req
(rule $CP1 (whose $RelNP is $NP0) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Req
(rule $CP0 (whose $RelNP is not $EntityNP1) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string !=) (var n)))))) # Rnot
(rule $CP0 (whose $NumberRelNP is smaller than $NumberEntityNP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string <) (var n)))))) # Rl
(rule $CP1 (whose $NumberRelNP is smaller than $NumberNP0) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string <) (var n)))))) # Rl
(rule $CP0 (whose $NumberRelNP is larger than $NumberEntityNP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string >) (var n)))))) # Rg
(rule $CP1 (whose $NumberRelNP is larger than $NumberNP0) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string >) (var n)))))) # Rg
(rule $CP0 (whose $NumberRelNP is at most $NumberEntityNP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string <=) (var n)))))) #Rle
(rule $CP1 (whose $NumberRelNP is at most $NumberNP0) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string <=) (var n)))))) # Rle
(rule $CP0 (whose $NumberRelNP is at least $NumberEntityNP) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string >=) (var n)))))) # Rge
(rule $CP1 (whose $NumberRelNP is at least $NumberNP0) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string >=) (var n)))))) # Rge
# R2
(rule $CP00 (that $VP/NP $EntityNP1) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Vobj
(rule $CP0 (that not $VP/NP $EntityNP1) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string !=) (var n)))))) # Vobj-neg
(rule $CP1 (that $VP/NP $NP0) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Vobj
# R3
(rule $CP00 (that is $RelNP of $EntityNP1) (lambda r (lambda n (lambda s (call @filter (var s) (call @reverse (var r)) (string =) (var n)))))) # Req2
(rule $CP0 (that is not $RelNP of $EntityNP1) (lambda r (lambda n (lambda s (call @filter (var s) (call @reverse (var r)) (string !=) (var n)))))) # Req2
(rule $CP1 (that is $RelNP of $NP0) (lambda r (lambda n (lambda s (call @filter (var s) (call @reverse (var r)) (string =) (var n)))))) # Req2
# R4
(rule $CP00 (that $EntityNP1 $VP/NP) (lambda n (lambda r (lambda s (call @filter (var s) (call @reverse (var r)) (string =) (var n)))))) # Vsubj
(rule $CP0 (that $EntityNP1 not $VP/NP) (lambda n (lambda r (lambda s (call @filter (var s) (call @reverse (var r)) (string !=) (var n)))))) # Vsubj
(rule $CP1 (that $NP0 $VP/NP) (lambda n (lambda r (lambda s (call @filter (var s) (call @reverse (var r)) (string =) (var n)))))) # Vsubj
)
(when geo880
(rule $CP2 (that $NP1 $VP/NP) (lambda n (lambda r (lambda s (call @filter (var s) (call @reverse (var r)) (string =) (var n)))))) # Vsubj
(rule $CP2 (that $VP/NP $NP1) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Vobj
(rule $CP2 (that is $RelNP of $NP1) (lambda r (lambda n (lambda s (call @filter (var s) (call @reverse (var r)) (string =) (var n)))))) # Req2
(rule $CP2 (whose $RelNP is $NP1) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Req
)
(when geo440
(rule $CP2 (that $VP/NP $NP1) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Vobj
(rule $CP2 (whose $RelNP is $NP1) (lambda r (lambda n (lambda s (call @filter (var s) (var r) (string =) (var n)))))) # Req
)
(when (and parse regex)
# I use modifier for negation, we did not have this negation in previous grammars
(rule $Modifier ($VP/NP $NP) (JoinFn forward betaReduce))
(rule $Modifier ($VP/NP1 $NP) (JoinFn forward betaReduce))
(rule $CP (that $Modifier) (IdentityFn))
(rule $CP (that not $Modifier) (lambda m (call + (string "~\(") (var m) (string "\)"))))
)
(when (and generate regex)
(rule $Modifier0 ($VP/NP $EntityNP1) (JoinFn forward betaReduce))
(rule $Modifier1 ($VP/NP $NP0) (JoinFn forward betaReduce))
(rule $Modifier0 ($VP/NP1 $EntityNP1) (JoinFn forward betaReduce))
(rule $Modifier1 ($VP/NP1 $NP0) (JoinFn forward betaReduce))
(rule $CP00 (that $Modifier0) (IdentityFn))
(rule $CP1 (that $Modifier1) (IdentityFn))
(rule $CP1 (that not $Modifier0) (lambda m (call + (string "~\(") (var m) (string "\)"))))
)
############################################################
# Complementizer phrase (superlatives and comparatives)
(when (and parse general)
# S0
(rule $CP (that has the smallest $NumberRelNP) (lambda r (lambda s (call @superlative (var s) (string min) (var r))))) # Smin
(rule $CP (that has the largest $NumberRelNP) (lambda r (lambda s (call @superlative (var s) (string max) (var r))))) # Smax
# S1
(rule $CP (that has the least number of $RelNP) (lambda r (lambda s (call @countSuperlative (var s) (string min) (var r))))) # Scmin
(rule $CP (that has the most number of $RelNP) (lambda r (lambda s (call @countSuperlative (var s) (string max) (var r))))) # Scmax
# S2
(rule $CP (that $VP/NP the least number of $NP) (lambda r (lambda s2 (lambda s1 (call @countSuperlative (var s1) (string min) (var r) (var s2)))))) # Scvmin
(rule $CP (that $VP/NP the most number of $NP) (lambda r (lambda s2 (lambda s1 (call @countSuperlative (var s1) (string max) (var r) (var s2)))))) # Scvmax
# S3
(rule $CP (that is $RelNP of the least number of $NP) (lambda r (lambda np (lambda s (call @countSuperlative (var s) (string min) (call @reverse (var r)) (var np)))))) # Scmin
(rule $CP (that is $RelNP of the most number of $NP) (lambda r (lambda np (lambda s (call @countSuperlative (var s) (string max) (call @reverse (var r)) (var np)))))) # Scmax
# S4
(rule $CP (that the least number of $NP $VP/NP) (lambda np (lambda r (lambda s (call @countSuperlative (var s) (string min) (call @reverse (var r)) (var np)))))) # Scvmin
(rule $CP (that the most number of $NP $VP/NP) (lambda np (lambda r (lambda s (call @countSuperlative (var s) (string max) (call @reverse (var r)) (var np)))))) # Scvmax
# C1
(rule $CP (that has $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string =) (var num)))))) # Ceq
(rule $CP (that has less than $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string <) (var num)))))) # Cl
(rule $CP (that has more than $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string >) (var num)))))) # Cg
(rule $CP (that has at most $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string <=) (var num)))))) # Cleq
(rule $CP (that has at least $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string >=) (var num)))))) # Cgeq
# C2
(rule $CP (that $VP/NP $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string =) (var num) (var np))))))) # Ceq
(rule $CP (that $VP/NP less than $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string <) (var num) (var np))))))) # Cl
(rule $CP (that $VP/NP more than $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string >) (var num) (var np))))))) # Cg
(rule $CP (that $VP/NP at most $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string <=) (var num) (var np))))))) # Cleq
(rule $CP (that $VP/NP at least $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string >=) (var num) (var np))))))) # Cgeq
# C3
(rule $CP (that is $RelNP of $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string =) (var num) (var np))))))) # Ceq
(rule $CP (that is $RelNP of less than $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string <) (var num) (var np))))))) # Cl
(rule $CP (that is $RelNP of more than $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string >) (var num) (var np))))))) # Cg
(rule $CP (that is $RelNP of at most $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string <=) (var num) (var np))))))) # Cleq
(rule $CP (that is $RelNP of at least $Num $NP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string >=) (var num) (var np))))))) # Cgeq
# C4
(rule $CP (that $Num $NP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string =) (var num) (var np))))))) # Ceq
(rule $CP (that less than $Num $NP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string <) (var num) (var np))))))) # Cl
(rule $CP (that more than $Num $NP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string >) (var num) (var np))))))) # Cg
(rule $CP (that at most $Num $NP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string <=) (var num) (var np))))))) # Cleq
(rule $CP (that at least $Num $NP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string >=) (var num) (var np))))))) # Cgeq
)
(when (and generate general) # $CP => $CP1, $NP => $UnaryNP
# S1
(rule $CP1 (that has the smallest $NumberRelNP) (lambda r (lambda s (call @superlative (var s) (string min) (var r))))) # Smin
(rule $CP1 (that has the largest $NumberRelNP) (lambda r (lambda s (call @superlative (var s) (string max) (var r))))) # Smax
# S2
(rule $CP1 (that has the least number of $RelNP) (lambda r (lambda s (call @countSuperlative (var s) (string min) (var r))))) # Scmin
(rule $CP1 (that has the most number of $RelNP) (lambda r (lambda s (call @countSuperlative (var s) (string max) (var r))))) # Scmax
# S3
(rule $CP1 (that $VP/NP the least number of $UnaryNP) (lambda r (lambda s2 (lambda s1 (call @countSuperlative (var s1) (string min) (var r) (var s2)))))) # Scvmin
(rule $CP1 (that $VP/NP the most number of $UnaryNP) (lambda r (lambda s2 (lambda s1 (call @countSuperlative (var s1) (string max) (var r) (var s2)))))) # Scvmax
# S4
(rule $CP1 (that is $RelNP of the least number of $UnaryNP) (lambda r (lambda np (lambda s (call @countSuperlative (var s) (string min) (call @reverse (var r)) (var np)))))) # Scmin
(rule $CP1 (that is $RelNP of the most number of $UnaryNP) (lambda r (lambda np (lambda s (call @countSuperlative (var s) (string max) (call @reverse (var r)) (var np)))))) # Scmax
# S5
(rule $CP1 (that the least number of $UnaryNP $VP/NP) (lambda np (lambda r (lambda s (call @countSuperlative (var s) (string min) (call @reverse (var r)) (var np)))))) # Scvmin
(rule $CP1 (that the most number of $UnaryNP $VP/NP) (lambda np (lambda r (lambda s (call @countSuperlative (var s) (string max) (call @reverse (var r)) (var np)))))) # Scvmax
# C1
(rule $CP1 (that has $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string =) (var num)))))) # Ceq
(rule $CP1 (that has less than $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string <) (var num)))))) # Cl
(rule $CP1 (that has more than $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string >) (var num)))))) # Cg
(rule $CP1 (that has at most $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string <=) (var num)))))) # Cleq
(rule $CP1 (that has at least $Num $RelNP) (lambda num (lambda r (lambda s (call @countComparative (var s) (var r) (string >=) (var num)))))) # Cgeq
# C2
(rule $CP1 (that $VP/NP $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string =) (var num) (var np))))))) # Ceq
(rule $CP1 (that $VP/NP less than $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string <) (var num) (var np))))))) # Cl
(rule $CP1 (that $VP/NP more than $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string >) (var num) (var np))))))) # Cg
(rule $CP1 (that $VP/NP at most $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string <=) (var num) (var np))))))) # Cleq
(rule $CP1 (that $VP/NP at least $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (var r) (string >=) (var num) (var np))))))) # Cgeq
# C3
(rule $CP1 (that is $RelNP of $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string =) (var num) (var np))))))) # Ceq
(rule $CP1 (that is $RelNP of less than $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string <) (var num) (var np))))))) # Cl
(rule $CP1 (that is $RelNP of more than $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string >) (var num) (var np))))))) # Cg
(rule $CP1 (that is $RelNP of at most $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string <=) (var num) (var np))))))) # Cleq
(rule $CP1 (that is $RelNP of at least $Num $UnaryNP) (lambda r (lambda num (lambda np (lambda s (call @countComparative (var s) (call @reverse (var r)) (string >=) (var num) (var np))))))) # Cgeq
# C4
(rule $CP1 (that $Num $UnaryNP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string =) (var num) (var np))))))) # Ceq
(rule $CP1 (that less than $Num $UnaryNP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string <) (var num) (var np))))))) # Cl
(rule $CP1 (that more than $Num $UnaryNP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string >) (var num) (var np))))))) # Cg
(rule $CP1 (that at most $Num $UnaryNP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string <=) (var num) (var np))))))) # Cleq
(rule $CP1 (that at least $Num $UnaryNP $VP/NP) (lambda num (lambda np (lambda r (lambda s (call @countComparative (var s) (call @reverse (var r)) (string >=) (var num) (var np))))))) # Cgeq
)
# Regex
(when (and parse regex)
(rule $CP (that $VP/NP1 at least $Num $NP) (lambda v (lambda num (lambda n (call + (string "\(") ((var v) (var n)) (string "\)") (string "{") (var num) (string ",}"))))))
(rule $CP (that $VP/NP1 at most $Num $NP) (lambda v (lambda num (lambda n (call + (string "\(") ((var v) (var n)) (string "\)") (string "{0,") (var num) (string "}"))))))
(rule $CP (that $VP/NP1 $Num $NP) (lambda v (lambda num (lambda n (call + (string "\(") ((var v) (var n)) (string "\)") (string "{") (var num) (string "}"))))))
(rule $CP (that $VP/NP at least $Num $NP) (lambda v (lambda num (lambda n ((var v) (call + (string "\(") (var n) (string "\)") (string "{") (var num) (string ",}")))))))
(rule $CP (that $VP/NP at most $Num $NP) (lambda v (lambda num (lambda n ((var v) (call + (string "\(") (var n) (string "\)") (string "{0,") (var num) (string "}")))))))
(rule $CP (that $VP/NP $Num $NP) (lambda v (lambda num (lambda n ((var v) (call + (string "\(") (var n) (string "\)") (string "{") (var num) (string "}")))))))
)
(when (and generate regex)
(rule $CP1 (that $VP/NP1 at least $Num $UnaryNP) (lambda v (lambda num (lambda n (call + (string "\(") ((var v) (var n)) (string "\)") (string "{") (var num) (string ",}"))))))
(rule $CP1 (that $VP/NP1 at most $Num $UnaryNP) (lambda v (lambda num (lambda n (call + (string "\(") ((var v) (var n)) (string "\)") (string "{0,") (var num) (string "}"))))))
(rule $CP1 (that $VP/NP1 $Num $UnaryNP) (lambda v (lambda num (lambda n (call + (string "\(") ((var v) (var n)) (string "\)") (string "{") (var num) (string "}"))))))
(rule $CP1 (that $VP/NP at least $Num $UnaryNP) (lambda v (lambda num (lambda n ((var v) (call + (string "\(") (var n) (string "\)") (string "{") (var num) (string ",}")))))))
(rule $CP1 (that $VP/NP at most $Num $UnaryNP) (lambda v (lambda num (lambda n ((var v) (call + (string "\(") (var n) (string "\)") (string "{0,") (var num) (string "}")))))))
(rule $CP1 (that $VP/NP $Num $UnaryNP) (lambda v (lambda num (lambda n ((var v) (call + (string "\(") (var n) (string "\)") (string "{") (var num) (string "}")))))))
)
############################################################
# Construct NPs from CPs
(when (and parse general)
# G3
(rule $NPCP ($NP $CP) (JoinFn backward betaReduce))
(rule $NPCP ($NPCP and $CP) (JoinFn backward betaReduce))
(rule $NP ($NPCP) (IdentityFn))
)
(when (and generate general)
# G3
(rule $NP0 ($UnaryNP $CP00) (JoinFn backward betaReduce))
(rule $NP1 ($UnaryNP $CP0) (JoinFn backward betaReduce))
(rule $NP1 ($UnaryNP $CP1) (JoinFn backward betaReduce))
(rule $NPCP1 ($UnaryNP $CP00) (JoinFn backward betaReduce))
(rule $NP1 ($NPCP1 and $CP00) (JoinFn backward betaReduce))
)
(when geo880
(rule $NP2 ($NP0 $CP00) (JoinFn backward betaReduce))
(rule $NP2 ($NP0 $CP0) (JoinFn backward betaReduce))
(rule $NP2 ($NP0 $CP1) (JoinFn backward betaReduce))
(rule $NP2 ($UnaryNP $CP2) (JoinFn backward betaReduce))
)
(when geo440
(rule $NP2 ($NP0 $CP00) (JoinFn backward betaReduce))
(rule $NP2 ($NP0 $CP0) (JoinFn backward betaReduce))
(rule $NP2 ($UnaryNP $CP2) (JoinFn backward betaReduce))
)
# Regex
(when (and parse regex)
(rule $CP ($CP and $CP) (lambda c1 (lambda c2 (call + (string "\(\(") (var c1) (string "\)&\(") (var c2) (string "\)\)")))))
(rule $NP ($NP $CP) (JoinFn betaReduce forward))
)
(when (and generate regex)
(rule $CP1 ($CP00 and $CP00) (lambda c1 (lambda c2 (call + (string "\(\(") (var c1) (string "\)&\(") (var c2) (string "\)\)")))))
(rule $NP1 ($UnaryNP $CP0) (JoinFn betaReduce forward))
(rule $NP1 ($UnaryNP $CP1) (JoinFn betaReduce forward))
)
############################################################
# Transformations
(when (and parse general)
# T1
(rule $NP ($RelNP of $NP) (lambda r (lambda s (call @getProperty (var s) (var r))))) # Tr
# T3
(rule $NP ($NP or $NP) (lambda n1 (lambda n2 (call @concat (var n1) (var n2))))) # Tdisj
)
(when (and generate general)
# T1
(rule $NP0 ($RelNP of $EntityNP1) (lambda r (lambda s (call @getProperty (var s) (var r))))) # Tr
# T3
(rule $NP0 ($EntityNP1 or $EntityNP2) (lambda n1 (lambda n2 (call @concat (var n1) (var n2))))) # Tdisj
)
(when (or geo880 geo440)
(rule $NP2 ($RelNP of $NP0) (lambda r (lambda s (call @getProperty (var s) (var r))))) # Tr
(rule $NP2 ($RelNP of $NP1) (lambda r (lambda s (call @getProperty (var s) (var r))))) # Tr
)
(when (and parse regex)
(rule $NP ($NP or $NP) (lambda n1 (lambda n2 (call + (string "\(") (var n1) (string "|") (var n2) (string "\)")))))
)
(when (and generate regex)
# TODO - do we want "location of meeting"? I think not, probably only "area of california"??
(rule $NP0 ($EntityNP1 or $EntityNP2) (lambda n1 (lambda n2 (call + (string "\(") (var n1) (string "|") (var n2) (string "\)")))))
)
############################################################
# Transformations: events
(when parse
# T2
(rule $EventNP ($Rel0NP $NP) (lambda r0 (lambda e (call @getProperty (var e) (call @reverse (var r0)))))) # student John
(rule $EventNPCP ($EventNP $CP) (JoinFn backward betaReduce)) # ... whose field of study is history
(rule $EventNPCP ($EventNPCP and $CP) (JoinFn backward betaReduce))
(rule $EventNP ($EventNPCP) (IdentityFn))
(rule $NP ($RelNP of $EventNP) (lambda r (lambda x (call @getProperty (var x) (var r))))) # university of ...
# T2'
(rule $NP ($Rel0NP $CP) (lambda r (lambda cp (call @getProperty ((var cp) (call @domain (var r))) (var r))))) # student whose field of study is history
)
(when generate
# T2
(rule $EventNP0 ($Rel0NP $EntityNP1) (lambda r0 (lambda e (call @getProperty (var e) (call @reverse (var r0)))))) # student John
(rule $EventNP1 ($EventNP0 $CP00) (JoinFn backward betaReduce)) # ... whose field of study is history
(rule $NP0 ($RelNP of $EventNP0) (lambda r (lambda x (call @getProperty (var x) (var r))))) # university of ...
(rule $NP1 ($RelNP of $EventNP1) (lambda r (lambda x (call @getProperty (var x) (var r))))) # university of ...
# T2'
(rule $NP0 ($Rel0NP $CP0) (lambda r (lambda cp (call @getProperty ((var cp) (call @domain (var r))) (var r))))) # student whose field of study is history
(rule $NP1 ($Rel0NP $CP1) (lambda r (lambda cp (call @getProperty ((var cp) (call @domain (var r))) (var r))))) # student whose field of study is history
)
############################################################
# Transformations: binary operators
(when parse
# T4
(rule $BinaryOpRight ($BinaryOp $NP) (JoinFn betaReduce forward))
(rule $NP ($NP $BinaryOpRight) (JoinFn betaReduce backward))
)
(when generate
# T4
(rule $BinaryOpRight ($BinaryOp $EntityNP2) (JoinFn betaReduce forward))
(rule $NP0 ($EntityNP1 $BinaryOpRight) (JoinFn betaReduce backward))
)
############################################################
# Aggregation
(when (and parse general)
# A1
(rule $NP (number of $NP) (lambda x (call .size (var x)))) # An
# A2
(rule $NP (total $RelNP of $NP) (lambda r (lambda n (call @aggregate (string sum) (call @getProperty (var n) (var r)))))) # At
# A3
(rule $NP (average $RelNP of $NP) (lambda r (lambda n (call @aggregate (string avg) (call @getProperty (var n) (var r)))))) # Am
# TODO: add 'all' before $NP's
)
(when (and generate general)
# A1
(rule $NP1 (number of $UnaryNP) (lambda x (call .size (var x)))) # An
# A2
(rule $NP1 (total $RelNP of $UnaryNP) (lambda r (lambda n (call @aggregate (string sum) (call @getProperty (var n) (var r)))))) # At
# A3
(rule $NP1 (average $RelNP of $UnaryNP) (lambda r (lambda n (call @aggregate (string avg) (call @getProperty (var n) (var r)))))) # Am
)
# Supporting more for geo880
(when (or geo880 geo440)
# A1
(rule $NP2 (number of $NP0) (lambda x (call .size (var x)))) # An
(rule $NP2 (number of $NP1) (lambda x (call .size (var x)))) # An
# A2
(rule $NP2 (total $RelNP of $NP0) (lambda r (lambda n (call @aggregate (string sum) (call @getProperty (var n) (var r)))))) # At
(rule $NP2 (total $RelNP of $NP1) (lambda r (lambda n (call @aggregate (string sum) (call @getProperty (var n) (var r)))))) # At
# A3
(rule $NP2 (average $RelNP of $NP0) (lambda r (lambda n (call @aggregate (string avg) (call @getProperty (var n) (var r)))))) # Am
(rule $NP2 (average $RelNP of $NP1) (lambda r (lambda n (call @aggregate (string avg) (call @getProperty (var n) (var r)))))) # Am
)
############################################################
# Top-level
(when (and parse general)
(rule $ROOT ($NP) (lambda x (call @listValue (var x))))
)
(when (and generate general)
(rule $ROOT ($NP0) (lambda x (call @listValue (var x))))
(rule $ROOT ($NP1) (lambda x (call @listValue (var x))))
)
(when (or geo880 geo440)
(rule $ROOT ($NP2) (lambda x (call @listValue (var x))))
(rule $ROOT ($UnaryNP) (lambda x (call @listValue (var x))))
)
(when (and parse regex)
(rule $ROOT ($NP) (IdentityFn))
)
(when (and generate regex)
(rule $ROOT ($NP0) (IdentityFn))
(rule $ROOT ($NP1) (IdentityFn))
)

View File

@ -0,0 +1,49 @@
# Unittest
# R1
(example (utterance "state whose capital is sacramento"))
(example (utterance "state whose capital is not sacramento"))
(example (utterance "state whose capital is capital of california"))
(example (utterance "mountain whose elevation is smaller than elevation of mount whitney"))
(example (utterance "mountain whose elevation is larger than elevation of mount whitney"))
(example (utterance "mountain whose elevation is at most elevation of mount whitney"))
(example (utterance "mountain whose elevation is at least elevation of mount whitney"))
(example (utterance "city that is in california and that is capital of california"))
# R2
(example (utterance "city that is in california"))
(example (utterance "city that not is in california"))
# R3
# R4
(example (utterance "state that california borders"))
(example (utterance "state that california not borders"))
(example (utterance "river that traverses california"))
# R5
(example (utterance "city that is major"))
# S1
(example (utterance "state that has the largest area"))
(example (utterance "state that has the smallest area"))
# S2
# S3
(example (utterance "state that borders the most number of state"))
(example (utterance "state that borders the least number of state"))
# C1
(example (utterance "river that is in two state"))
(example (utterance "river that is in more than two state"))
(example (utterance "river that is in less than two state"))
(example (utterance "river that is in at most two state"))
(example (utterance "river that is in at least two state"))
# T1
(example (utterance "population of sacramento"))
# T2: TODO
# T3
(example (utterance "california or texas"))
# T4
# A1
(example (utterance "number of lake"))
# A2
(example (utterance "total elevation of mountain"))
(example (utterance "average elevation of mountain"))

69
overnight/geo880.grammar Normal file
View File

@ -0,0 +1,69 @@
(include general.grammar)
# Types
(rule $TypeNP (city) (ConstantFn fb:en.city))
(rule $EntityNP1 (sacramento) (ConstantFn fb:en.city.sacramento_ca))
(rule $EntityNP2 (austin) (ConstantFn fb:en.city.austin_tx))
(rule $TypeNP (state) (ConstantFn fb:en.state))
(rule $EntityNP1 (california) (ConstantFn fb:en.state.california))
(rule $EntityNP2 (texas) (ConstantFn fb:en.state.texas))
(rule $TypeNP (river) (ConstantFn fb:en.river))
(rule $EntityNP1 (colorado river) (ConstantFn fb:en.river.colorado))
(rule $EntityNP2 (red river) (ConstantFn fb:en.river.red))
(rule $TypeNP (lake) (ConstantFn fb:en.lake))
(rule $EntityNP1 (lake tahoe) (ConstantFn fb:en.lake.tahoe))
(rule $EntityNP2 (lake huron) (ConstantFn fb:en.lake.huron))
(rule $TypeNP (mountain) (ConstantFn fb:en.mountain))
(rule $EntityNP1 (mount whitney) (ConstantFn fb:en.mountain.whitney))
(rule $EntityNP2 (mount rainier) (ConstantFn fb:en.mountain.rainier))
(rule $TypeNP (place) (ConstantFn fb:en.place))
(rule $EntityNP1 (death valley) (ConstantFn fb:en.place.death_valley))
(rule $EntityNP2 (pacific ocean) (ConstantFn fb:en.place.pacific_ocean))
# Unaries
(rule $VP (is major) (ConstantFn (string major_city)))
(rule $VP (is major) (ConstantFn (string major_river)))
(rule $VP (is major) (ConstantFn (string major_lake)))
(rule $VP (is a capital) (ConstantFn (string capital_city)))
# Properties
(rule $VP/NP (is contained by) (ConstantFn (string loc_city_state)))
(rule $VP/NP (is contained by) (ConstantFn (string loc_lake_state)))
(rule $VP/NP (is contained by) (ConstantFn (string loc_mountain_state)))
(rule $VP/NP (is contained by) (ConstantFn (string loc_state_country)))
(rule $VP/NP (is contained by) (ConstantFn (string loc_place_state)))
(rule $VP/NP (traverses) (ConstantFn (string traverse_river_state)))
(rule $VP/NP (borders) (ConstantFn (string next_to_state_state)))
(rule $RelNP (capital) (ConstantFn (string capital_state_city)))
(rule $RelNP (area) (ConstantFn (string area_state_length^2)))
(rule $RelNP (area) (ConstantFn (string area_city_length^2)))
(rule $RelNP (area) (ConstantFn (string area_country_length^2)))
(rule $RelNP (area) (ConstantFn (string area_lake_length^2)))
(rule $RelNP (length) (ConstantFn (string len_river_length)))
(rule $RelNP (elevation) (ConstantFn (string elevation_mountain_length)))
(rule $RelNP (elevation) (ConstantFn (string elevation_place_length)))
(rule $RelNP (population) (ConstantFn (string population_city_count)))
(rule $RelNP (population) (ConstantFn (string population_state_count)))
(rule $RelNP (population) (ConstantFn (string population_country_count)))
(rule $RelNP (density) (ConstantFn (string density_state_count)))
(rule $RelNP (density) (ConstantFn (string density_city_count)))
(rule $RelNP (density) (ConstantFn (string density_country_count)))
# simple lexicon
(rule $EntityNP1 ($PHRASE) (SimpleLexiconFn))
(rule $EntityNP2 ($PHRASE) (SimpleLexiconFn))
# TODO: named is a funny relation: do we really want to include it?
# I estimate less than 2% requires the 'name' property, so let's punt
#(rule $EntityNP1 (sacramento) (ConstantFn (string Sacramento)))
#(rule $EntityNP1 (california) (ConstantFn (string California)))
#(rule $EntityNP1 (carson river) (ConstantFn (string Carson River)))
#(rule $EntityNP1 (lake austin) (ConstantFn (string Lake Austin)))
#(rule $EntityNP1 (mount whitney) (ConstantFn (string Mount Whitney)))

View File

@ -0,0 +1,12 @@
# R1
(example (utterance "housing unit whose neighborhood is chelsea"))
(example (utterance "housing unit whose housing type is apartment"))
# R2
(example (utterance "housing unit that allows cats"))
(example (utterance "housing unit that allows dogs"))
# R3
(example (utterance "housing unit whose size is at least 800 square feet"))
(example (utterance "number of housing type"))

42
overnight/housing.grammar Normal file
View File

@ -0,0 +1,42 @@
# Agile grammar for housing (based on craigslist)
# - What is the price of house?
# - How many apartments are there?
# - Create house with price 225000
# - Move price of house from 225000 to 250000
# - Is there any apartment whose rent is less than 2000
(include general.grammar)
# Types
(rule $TypeNP (housing unit) (ConstantFn en.housing_unit))
(rule $EntityNP1 (123 sesame street) (ConstantFn en.housing_unit.123_sesame_street))
(rule $EntityNP2 (900 mission ave) (ConstantFn en.housing_unit.900_mission_ave))
# Properties
(rule $RelNP (monthly rent) (ConstantFn (string rent)))
(rule $EntityNP1 (1500 dollars) (ConstantFn (number 1500 en.dollar)))
(rule $EntityNP2 (2000 dollars) (ConstantFn (number 2000 en.dollar)))
(rule $RelNP (size) (ConstantFn (string size)))
(rule $EntityNP1 (800 square feet) (ConstantFn (number 800 en.square_feet)))
(rule $EntityNP2 (1000 square feet) (ConstantFn (number 1000 en.square_feet)))
(rule $RelNP (posting date) (ConstantFn (string posting_date)))
(rule $EntityNP1 (jan 2) (ConstantFn (date 2015 1 2)))
(rule $EntityNP2 (feb 3) (ConstantFn (date 2015 2 3)))
(rule $RelNP (neighborhood) (ConstantFn (string neighborhood)))
(rule $TypeNP (neighborhood) (ConstantFn en.neighborhood))
(rule $EntityNP1 (midtown west) (ConstantFn en.neighborhood.midtown_west))
(rule $EntityNP2 (chelsea) (ConstantFn en.neighborhood.chelsea))
(rule $RelNP (housing type) (ConstantFn (string housing_type)))
(rule $TypeNP (housing type) (ConstantFn en.housing))
(rule $EntityNP1 (apartment) (ConstantFn en.housing.apartment))
(rule $EntityNP2 (condo) (ConstantFn en.housing.condo))
# Unaries
(rule $VP (allows cats) (ConstantFn (string allows_cats)))
(rule $VP (allows dogs) (ConstantFn (string allows_dogs)))
(rule $VP (has a private bath) (ConstantFn (string has_private_bath)))
(rule $VP (has a private room) (ConstantFn (string has_private_room)))

2
overnight/null.examples Normal file
View File

@ -0,0 +1,2 @@
# Used to trigger generation (without looking at utterance).
(example (utterance null))

View File

@ -0,0 +1,27 @@
# Agile grammar for publications
(include general.grammar)
# Types
(rule $TypeNP (article) (ConstantFn en.article))
(rule $EntityNP1 (multivariate data analysis) (ConstantFn en.article.multivariate_data_analysis))
# Properties
(rule $RelNP (author) (ConstantFn (string author)))
(rule $TypeNP (person) (ConstantFn en.person))
(rule $EntityNP1 (efron) (ConstantFn en.person.efron))
(rule $EntityNP2 (lakoff) (ConstantFn en.person.lakoff))
(rule $RelNP (venue) (ConstantFn (string venue)))
(rule $TypeNP (venue) (ConstantFn en.venue))
(rule $EntityNP1 (annals of statistics) (ConstantFn en.venue.annals_of_statistics))
(rule $EntityNP2 (computational linguistics) (ConstantFn en.venue.computational_linguistics))
(rule $RelNP (publication date) (ConstantFn (string publication_date)))
(rule $EntityNP1 (2004) (ConstantFn (date 2004 -1 -1)))
(rule $EntityNP2 (2010) (ConstantFn (date 2010 -1 -1)))
(rule $VP/NP (cites) (ConstantFn (string cites)))
# Unaries
(rule $VP (won an award) (ConstantFn (string won_award)))

33
overnight/recipes.grammar Normal file
View File

@ -0,0 +1,33 @@
# Agile grammar for recipes (based on allrecipes.com)
(include general.grammar)
# Types
(rule $TypeNP (recipe) (ConstantFn en.recipe))
(rule $EntityNP1 (rice pudding) (ConstantFn en.recipe.rice_pudding))
(rule $EntityNP2 (quiche) (ConstantFn en.recipe.quiche))
# Properties
(rule $RelNP (preparation time) (ConstantFn (string preparation_time)))
(rule $RelNP (cooking time) (ConstantFn (string cooking_time)))
(rule $Value (10) (ConstantFn (number 10 en.minute)))
(rule $Value (30) (ConstantFn (number 300 en.minute)))
(rule $RelNP (cuisine) (ConstantFn (string cuisine)))
(rule $TypeNP (cuisine) (ConstantFn fb:en.cuisine))
(rule $EntityNP1 (chinese) (ConstantFn (string chinese)))
(rule $EntityNP2 (french) (ConstantFn (string french)))
(rule $VP/NP (requires) (ConstantFn (string requires)))
(rule $TypeNP (ingredient) (ConstantFn en.ingredient))
(rule $EntityNP1 (milk) (ConstantFn en.ingredient.milk))
(rule $EntityNP2 (spinach) (ConstantFn en.ingredient.spinach))
(rule $VP/NP (is for) (ConstantFn (string meal)))
(rule $TypeNP (meal) (ConstantFn en.meal))
(rule $EntityNP1 (lunch) (ConstantFn en.meal.lunch))
(rule $EntityNP2 (dinner) (ConstantFn en.meal.dinner))
(rule $RelNP (posting date) (ConstantFn (string posting_date)))
(rule $EntityNP1 (2004) (ConstantFn (date 2004 -1 -1)))
(rule $EntityNP2 (2010) (ConstantFn (date 2010 -1 -1)))

View File

@ -0,0 +1,19 @@
# Unittest
# Type
(example (utterance "restaurant"))
# R1
(example (utterance "restaurant that takes reservations"))
(example (utterance "restaurant that has outdoor seating"))
# R2
(example (utterance "restaurant whose cuisine is chinese"))
(example (utterance "restaurant whose neighborhood is tribeca"))
# R3
(example (utterance "restaurant whose price rating is 2 dollar signs"))
(example (utterance "restaurant whose star rating is at least 3 stars"))
# R4
(example (utterance "restaurant that serves lunch"))

View File

@ -0,0 +1,46 @@
# Agile grammar for restaurants (based on yelp)
(include general.grammar)
# Types
(rule $TypeNP (restaurant) (ConstantFn en.restaurant))
(rule $EntityNP1 (thai cafe) (ConstantFn en.restaurant.thai_cafe))
(rule $EntityNP2 (pizzeria juno) (ConstantFn en.restaurant.pizzeria_juno))
# Properties
(rule $RelNP (star rating) (ConstantFn (string star_rating)))
(rule $EntityNP1 (3 stars) (ConstantFn (number 3 en.star)))
(rule $EntityNP2 (5 stars) (ConstantFn (number 5 en.star)))
(rule $RelNP (price rating) (ConstantFn (string price_rating)))
(rule $EntityNP1 (2 dollar signs) (ConstantFn (number 2 en.dollar_sign)))
(rule $EntityNP2 (3 dollar signs) (ConstantFn (number 3 en.dollar_sign)))
(rule $RelNP (number of reviews) (ConstantFn (string reviews)))
(rule $EntityNP1 (30 reviews) (ConstantFn (number 30 en.review)))
(rule $EntityNP2 (40 reviews) (ConstantFn (number 40 en.review)))
(rule $RelNP (neighborhood) (ConstantFn (string neighborhood)))
(rule $TypeNP (neighborhood) (ConstantFn en.neighborhood))
(rule $EntityNP1 (midtown west) (ConstantFn en.neighborhood.midtown_west))
(rule $EntityNP2 (chelsea) (ConstantFn en.neighborhood.chelsea))
(rule $RelNP (cuisine) (ConstantFn (string cuisine)))
(rule $TypeNP (cuisine) (ConstantFn en.cuisine))
(rule $EntityNP1 (thai) (ConstantFn en.cuisine.thai))
(rule $EntityNP2 (italian) (ConstantFn en.cuisine.italian))
(rule $VP/NP (serves) (ConstantFn (string meals)))
(rule $TypeNP (meal) (ConstantFn en.food))
(rule $EntityNP1 (lunch) (ConstantFn en.food.lunch))
(rule $EntityNP2 (dinner) (ConstantFn en.food.dinner))
# Unaries
(rule $VP (takes reservations) (ConstantFn (string reserve)))
(rule $VP (takes credit cards) (ConstantFn (string credit)))
(rule $VP (has outdoor seating) (ConstantFn (string outdoor)))
(rule $VP (has take-out) (ConstantFn (string takeout)))
(rule $VP (has delivery) (ConstantFn (string delivery)))
(rule $VP (has waiter service) (ConstantFn (string waiter)))
(rule $VP (is good for kids) (ConstantFn (string kids)))
(rule $VP (is good for groups) (ConstantFn (string groups)))

View File

@ -0,0 +1,59 @@
# Unittest
# G1
(example (utterance "google"))
# G2
(example (utterance "gender"))
# G3
(example (utterance "person whose gender is male and that is friends with alice"))
# R1
(example (utterance "person whose gender is male"))
(example (utterance "person whose gender is not male"))
(example (utterance "person whose birthdate is smaller than 2010"))
(example (utterance "person whose birthdate is larger than 2010"))
(example (utterance "person whose birthdate is at most 2010"))
(example (utterance "person whose birthdate is at least 2010"))
(example (utterance "person whose height is at least 200 cm"))
# R2
(example (utterance "person that is friends with alice"))
(example (utterance "person that not is friends with alice"))
# R3
(example (utterance "city that is birthplace of alice"))
(example (utterance "city that is not birthplace of alice"))
# R4
(example (utterance "person that is friends with alice"))
(example (utterance "person that not is friends with alice"))
# R5
(example (utterance "person that is logged in"))
# S1
(example (utterance "person that has the smallest birthdate"))
(example (utterance "person that has the largest birthdate"))
# S2
(example (utterance "person that has the most birthplace"))
(example (utterance "person that has the least birthplace"))
# S3
(example (utterance "person that is friends with the most person"))
(example (utterance "person that is friends with the least person"))
# C1
(example (utterance "person that is friends with 1 person"))
(example (utterance "person that is friends with less than 1 person"))
(example (utterance "person that is friends with more than 1 person"))
(example (utterance "person that is friends with at most 1 person"))
(example (utterance "person that is friends with at least 1 person"))
# T1
(example (utterance "birthdate of alice"))
# T2
(example (utterance "employer of employee bob"))
(example (utterance "employer of employee bob whose start date is 2004"))
# T3
(example (utterance "alice or bob"))
# T4 (none)
# A1
(example (utterance "number of person"))
# A2
(example (utterance "total height of person"))

View File

@ -0,0 +1,72 @@
# Agile grammar for social network (think Facebook Graph Search)
(include general.grammar)
# Types
(rule $TypeNP (person) (ConstantFn en.person))
(rule $EntityNP1 (alice) (ConstantFn en.person.alice))
(rule $EntityNP2 (bob) (ConstantFn en.person.bob))
(rule $VP/NP (is friends with) (ConstantFn (string friend)))
# Properties
(rule $RelNP (birthdate) (ConstantFn (string birthdate)))
(rule $EntityNP1 (2004) (ConstantFn (date 2004 -1 -1)))
(rule $EntityNP2 (2010) (ConstantFn (date 2010 -1 -1)))
(rule $RelNP (gender) (ConstantFn (string gender)))
(rule $TypeNP (gender) (ConstantFn en.gender))
(rule $EntityNP1 (male) (ConstantFn en.gender.male))
(rule $EntityNP2 (female) (ConstantFn en.gender.female))
(rule $RelNP (relationship status) (ConstantFn (string relationship_status)))
(rule $TypeNP (relationship status) (ConstantFn en.relationship_status))
(rule $EntityNP1 (single) (ConstantFn en.relationship_status.single))
(rule $EntityNP2 (married) (ConstantFn en.relationship_status.married))
(rule $RelNP (birthplace) (ConstantFn (string birthplace)))
(rule $TypeNP (city) (ConstantFn en.city))
(rule $EntityNP1 (new york) (ConstantFn en.city.new_york))
(rule $EntityNP2 (beijing) (ConstantFn en.city.bejing))
(rule $RelNP (height) (ConstantFn (string height)))
(rule $EntityNP1 (180 cm) (ConstantFn (number 180 en.cm)))
(rule $EntityNP2 (200 cm) (ConstantFn (number 200 en.cm)))
# Education
#(rule $EventNP (education) (ConstantFn (call @getProperty (call @singleton en.education) (string !type)))) # for debugging
(rule $Rel0NP (student) (ConstantFn (string student)))
(rule $RelNP (university) (ConstantFn (string university)))
(rule $TypeNP (university) (ConstantFn en.university))
(rule $EntityNP1 (brown university) (ConstantFn en.university.brown))
(rule $EntityNP2 (ucla) (ConstantFn en.university.ucla))
(rule $RelNP (field of study) (ConstantFn (string field_of_study)))
(rule $TypeNP (field) (ConstantFn en.field))
(rule $EntityNP1 (computer science) (ConstantFn en.field.computer_science))
(rule $EntityNP2 (history) (ConstantFn en.field.history))
(rule $RelNP (start date) (ConstantFn (string education_start_date)))
(rule $RelNP (end date) (ConstantFn (string education_end_date)))
# Employment
(rule $Rel0NP (employee) (ConstantFn (string employee)))
(rule $RelNP (employer) (ConstantFn (string employer)))
(rule $TypeNP (company) (ConstantFn en.company))
(rule $EntityNP1 (mckinsey) (ConstantFn en.company.mckinsey))
(rule $EntityNP2 (google) (ConstantFn en.company.google))
(rule $RelNP (job title) (ConstantFn (string job_title)))
(rule $TypeNP (job title) (ConstantFn en.job_title))
(rule $EntityNP1 (software engineer) (ConstantFn en.job_title.software_engineer))
(rule $EntityNP2 (program manager) (ConstantFn en.job_title.program_manager))
(rule $RelNP (start date) (ConstantFn (string employment_start_date)))
(rule $RelNP (end date) (ConstantFn (string employment_end_date)))
# Unaries
(rule $VP (is logged in) (ConstantFn (string logged_in)))

View File

@ -0,0 +1,68 @@
############################################################
# Domain general
# Keep track of coarse types:
# - Entity: "day 1"
# - Value: "3pm"
# - EntitySet: "meeting"
# - ValueSet: "start time of meeting"
(def @allEntities edu.stanford.nlp.sempre.SimpleWorld.allEntities)
(def @filter edu.stanford.nlp.sempre.SimpleWorld.filter)
(def @merge edu.stanford.nlp.sempre.SimpleWorld.merge)
(def @getProperty edu.stanford.nlp.sempre.SimpleWorld.getProperty)
(def @superlative edu.stanford.nlp.sempre.SimpleWorld.superlative)
(def @sum edu.stanford.nlp.sempre.SimpleWorld.sum)
(def @list edu.stanford.nlp.sempre.SimpleWorld.list)
(def @act edu.stanford.nlp.sempre.SimpleWorld.act)
# Operations
(def @create edu.stanford.nlp.sempre.SimpleWorld.create)
(def @remove edu.stanford.nlp.sempre.SimpleWorld.remove)
(def @change edu.stanford.nlp.sempre.SimpleWorld.change)
# General values
(rule $Value ($PHRASE) (NumberFn) (anchored 1))
(rule $Value ($PHRASE) (DateFn) (anchored 1))
(rule $TypeSet ($Type) (lambda t (call @filter (call @allEntities) (string type) (string =) (var t))))
# 0. Show me all meetings
(rule $Command (show me all $TypeSet) (IdentityFn))
# 1. Get property: "what is the location of meeting"
(rule $Command (what is the $EntityProperty of the $TypeSet) (lambda p (lambda s (call @getProperty (var s) (var p)))))
(rule $Command (what is the $ValueProperty of the $TypeSet) (lambda p (lambda s (call @getProperty (var s) (var p)))))
# what is the block left of block whose color is red
(rule $Command (what is the $TypeSet $BinaryProperty the $TypeSet) (lambda s1 (lambda p (lambda s2 (call @getProperty (var s2) (var p))))))
# 2. Filter: "what is the meeting whose location is cafe"
(rule $Command (what is the $TypeSet whose $EntityProperty is $Entity) (lambda s (lambda p (lambda v (call @filter (var s) (var p) (string =) (var v))))))
(rule $Command (what is the $TypeSet whose $ValueProperty is $Value) (lambda s (lambda p (lambda v (call @filter (var s) (var p) (string =) (var v))))))
(rule $Command (what is the $TypeSet whose $EntityProperty is not $Entity) (lambda s (lambda p (lambda v (call @filter (var s) (var p) (string !=) (var v))))))
(rule $Command (what is the $TypeSet whose $ValueProperty is not $Value) (lambda s (lambda p (lambda v (call @filter (var s) (var p) (string !=) (var v))))))
# 3. Count: what is the number of meeting whose location is cafe
(rule $Command (what is the number of $TypeSet whose $EntityProperty is $Entity) (lambda s (lambda p (lambda v (call .size (call @filter (var s) (var p) (string =) (var v)))))))
# 4. Sum: what is the total length of meeting
(rule $Command (what is the total $ValueProperty of all $TypeSet) (lambda p (lambda s (call @sum (call @getProperty (var s) (var p))))))
# 5. Comparatives: what is the meeting whose start time is smaller than 10am
(rule $Command (what is the $TypeSet whose $ValueProperty is smaller than $Value) (lambda s (lambda p (lambda v (call @filter (var s) (var p) (string <) (var v))))))
(rule $Command (what is the $TypeSet whose $ValueProperty is larger than $Value) (lambda s (lambda p (lambda v (call @filter (var s) (var p) (string >) (var v))))))
(rule $Command (what is the $TypeSet whose $ValueProperty is at most $Value) (lambda s (lambda p (lambda v (call @filter (var s) (var p) (string <=) (var v))))))
(rule $Command (what is the $TypeSet whose $ValueProperty is at least $Value) (lambda s (lambda p (lambda v (call @filter (var s) (var p) (string >=) (var v))))))
# 6. Superlatives - what is the meeting with the smallest start time
(rule $Command (what is the $TypeSet with the smallest $ValueProperty) (lambda s (lambda p (call @superlative (var s) (string min) (var p)))))
(rule $Command (what is the $TypeSet with the largest $ValueProperty) (lambda s (lambda p (call @superlative (var s) (string max) (var p)))))
# 7. create and remove
(rule $Command (create a $Type with $EntityProperty $Entity) (lambda t (lambda p (lambda v (call @create (var t) (var p) (var v))))))
(rule $Command (create a $Type with $ValueProperty $Value) (lambda t (lambda p (lambda v (call @create (var t) (var p) (var v))))))
(rule $Command (remove the $TypeSet with $EntityProperty $Entity) (lambda s (lambda p (lambda v (call @remove (call @filter (var s) (var p) (string =) (var v)))))))
# 8. Two joins
(rule $Command (what is the $TypeSet whose $ValueProperty is $ValueProperty of $TypeSet) (lambda s1 (lambda p1 (lambda p2 (lambda s2 (call @filter (var s1) (var p1) (string =) (call @getProperty (var s2) (var p2))))))))
(rule $ROOT ($Command) (lambda x (call .toString (var x))))

5
overnight/unittest.db Normal file
View File

@ -0,0 +1,5 @@
friend fb:en.person.alice fb:en.person.bob
enemy fb:en.person.alice fb:en.person.eve
person fb:en.person.alice
person fb:en.person.bob
person fb:en.person.eve

View File

@ -0,0 +1,4 @@
(include general.grammar)
# Types
(rule $TypeNP (person) (ConstantFn en.person))

View File

@ -1,23 +1,38 @@
#!/usr/bin/env ruby
# SEMPRE depends on several library/data files into *lib*. Run this script to
# SEMPRE depends on several library/data files into |lib|. Run this script to
# copy those dependencies to your local directory. This allows you to run
# SEMPRE from anywhere. This file consists of a set of modules (which loosely
# correspond to the code modules).
#
# The master copy of these dependencies are stored on the Stanford NLP machines.
#
# Usage:
# ./pull-dependencies <module-1> ... <module-n>
#
# For developers with ssh access to NLP machines, there are two more local commands:
# - Copy or link |sourcePath| into lib/|dir|.
# ./pull-dependencies -l <module-1> ... <module-n>
# - Deploy the dependencies to the NLP machines's public www.
# ./pull-dependencies -l -r <module-1> ... <module-n>
# The master copy of these dependencies are stored on the Stanford NLP
# machines.
# Specify the version of the dependencies
# (To developer: Update this before releasing a new version!)
$version = '2.0'
$isPublic = true
$isLocal = ARGV.index('-l')
$isRelease = ARGV.index('-r')
if $isRelease and not $isLocal
puts "ERROR: To release, must use both -l and -r"
exit 1
end
ARGV.delete_if { |x| x == '-l' or x == '-r' }
def isZip(name)
# Directories are zipped
name.end_with?('.exec') or name !~ /\./
end
# - Download the dependencies from the Stanford SEMPRE servers.
def pull(sourcePath, dir=nil, opts={})
puts sourcePath
destDir = 'lib' + (dir ? '/' + dir : '')
@ -26,9 +41,13 @@ def pull(sourcePath, dir=nil, opts={})
name = File.basename(sourcePath)
ext = isZip(name) ? '.zip' : ''
if $isPublic
if not $isLocal and not $isRelease
# Download url => localPath
url = 'http://nlp.stanford.edu/software/sempre/dependencies-' + $version + sourcePath + ext
if sourcePath.start_with?('http://') || sourcePath.start_with?('https://')
url = sourcePath
else
url = 'http://nlp.stanford.edu/software/sempre/dependencies-' + $version + sourcePath + ext
end
localPath = destDir + '/' + name + ext
system "mkdir -p #{File.dirname(localPath)}" or exit 1
system "wget -c '#{url}' -O #{localPath}" or exit 1
@ -38,6 +57,38 @@ def pull(sourcePath, dir=nil, opts={})
system "rm #{localPath}" or exit 1
end
else
rsyncOpts = '-rlptDzi' # Preserve everything except groups and permissions
if $isRelease
# Copy sourcePath to cluster
baseDeployPath = '/u/apache/htdocs/static/software/sempre/dependencies-' + $version
deployPath = baseDeployPath + sourcePath + ext
system "mkdir -p #{File.dirname(deployPath)}" or exit 1
if File.exists?(sourcePath)
if isZip(name)
system "cd #{File.dirname(sourcePath)} && zip -r #{deployPath} #{File.basename(sourcePath)}" or exit 1
else
if opts[:symlink]
system "ln -sf #{File.expand_path(sourcePath)} #{deployPath}" or exit 1
else
system "rsync #{rsyncOpts} #{sourcePath} #{deployPath}" or exit 1
end
end
else
system "rsync #{rsyncOpts} jamie.stanford.edu:#{sourcePath} #{deployPath}" or exit 1
end
system "chmod -R og=u #{baseDeployPath}" #or exit 1
else
# Download sourcePath from cluster to destDir
if File.exists?(sourcePath)
if opts[:symlink]
system "ln -sf #{File.expand_path(sourcePath)} #{destDir}" or exit 1
else
system "rsync #{rsyncOpts} #{sourcePath} #{destDir}" or exit 1
end
else
system "rsync #{rsyncOpts} jamie.stanford.edu:#{sourcePath} #{destDir}" or exit 1
end
end
end
end
@ -86,17 +137,54 @@ addModule('core', 'Core utilities (need to compile)', lambda {
pull('/u/nlp/data/semparse/resources/jackson-core-2.2.0.jar')
pull('/u/nlp/data/semparse/resources/jackson-annotations-2.2.0.jar')
pull('/u/nlp/data/semparse/resources/jackson-databind-2.2.0.jar')
# jLine from maven central
pull('https://repo1.maven.org/maven2/jline/jline/2.14.6/jline-2.14.6.jar')
})
addModule('corenlp', 'Stanford CoreNLP (code and modules)', lambda {
addModule('corenlp', 'Stanford CoreNLP 3.6.0', lambda {
pull('/u/nlp/data/semparse/resources/stanford-corenlp-full-2015-12-09.zip', '', {:symlink => true})
if not File.exists?('lib/stanford-corenlp-full-2015-12-09')
system "cd lib && unzip stanford-corenlp-full-2015-12-09.zip" or exit 1
end
pull('/u/nlp/data/semparse/resources/stanford-corenlp-caseless-2015-04-20-models.jar',
'stanford-corenlp-full-2015-12-09', {:symlink => true})
# Remove old file (for backward compatibility)
if Dir.glob('lib/stanford-corenlp*.jar').any?
system 'rm -v lib/stanford-corenlp*.jar' or exit 1
end
{'stanford-corenlp-3.6.0.jar' => 'stanford-corenlp.jar',
'stanford-corenlp-3.6.0-models.jar' => 'stanford-corenlp-models.jar',
'stanford-corenlp-caseless-2015-04-20-models.jar' => 'stanford-corenlp-caseless-models.jar',
'joda-time.jar' => 'joda-time.jar',
'jollyday.jar' => 'jollyday.jar',
'ejml-0.23.jar' => 'ejml.jar',
'slf4j-api.jar' => 'slf4j-api.jar',
'slf4j-simple.jar' => 'slf4j-simple.jar',
}.each { |key, value|
system "ln -sfv stanford-corenlp-full-2015-12-09/#{key} lib/#{value}" or exit 1
}
})
addModule('corenlp-3.2.0', 'Stanford CoreNLP 3.2.0 (for backward reproducibility)', lambda {
pull('/u/nlp/data/semparse/resources/stanford-corenlp-full-2013-06-20.zip', '', {:symlink => true})
if not File.exists?('lib/stanford-corenlp-full-2013-06-20')
system "cd lib && unzip stanford-corenlp-full-2013-06-20.zip" or exit 1
end
['stanford-corenlp-3.2.0.jar', 'stanford-corenlp-3.2.0-models.jar', 'joda-time.jar', 'jollyday.jar'].each { |file|
system "ln -sfv stanford-corenlp-full-2013-06-20/#{file} lib" or exit 1
pull('/u/nlp/data/semparse/resources/stanford-corenlp-caseless-2013-06-07-models.jar',
'stanford-corenlp-full-2013-06-20', {:symlink => true})
# Remove old file (for backward compatibility)
if Dir.glob('lib/stanford-corenlp*.jar').any?
system 'rm -v lib/stanford-corenlp*.jar' or exit 1
end
{'stanford-corenlp-3.2.0.jar' => 'stanford-corenlp.jar',
'stanford-corenlp-3.2.0-models.jar' => 'stanford-corenlp-models.jar',
'stanford-corenlp-caseless-2013-06-07-models.jar' => 'stanford-corenlp-caseless-models.jar',
'joda-time.jar' => 'joda-time.jar',
'jollyday.jar' => 'jollyday.jar'
}.each { |key, value|
system "ln -sfv stanford-corenlp-full-2013-06-20/#{key} lib/#{value}" or exit 1
}
pull('/u/nlp/data/semparse/resources/stanford-corenlp-caseless-2013-06-07-models.jar', '', {:symlink => true})
})
addModule('freebase', 'Freebase: need to construct Freebase schemas', lambda {
@ -143,7 +231,84 @@ addModule('fullfreebase-types', 'Freebase types', lambda {
# You need to unzip these yourself and move these files to the right place.
})
addModule('tables', 'Semantic parsing with execution on tables', lambda {
# CSV reader
pull('/u/nlp/data/semparse/resources/opencsv-3.0.jar')
})
addModule('tables-data', 'WikiTableQuestions dataset v1.0.2', lambda {
# Compact version of the dataset
pull('https://github.com/ppasupat/WikiTableQuestions/releases/download/v1.0.2/WikiTableQuestions-1.0.2-compact.zip', 'data')
# Remove old file (for backward compatibility)
if File.directory?('lib/data/WikiTableQuestions')
system 'rm -rv lib/data/WikiTableQuestions' or exit 1
end
system "cd lib/data && unzip WikiTableQuestions-1.0.2-compact.zip" or exit 1
})
addModule('tables-data-0.5', 'WikiTableQuestions dataset v0.5 (for backward reproducibility)', lambda {
# Compact version of the dataset
pull('https://github.com/ppasupat/WikiTableQuestions/releases/download/v0.5/WikiTableQuestions-0.5-compact.zip', 'data')
# Remove old file (for backward compatibility)
if File.directory?('lib/data/WikiTableQuestions')
system 'rm -rv lib/data/WikiTableQuestions' or exit 1
end
system "cd lib/data && unzip WikiTableQuestions-0.5-compact.zip" or exit 1
})
addModule('tables-cprune', 'Neighbor information for applying macro grammar on tables', lambda {
pull('/u/nlp/data/semparse/cprune/nn_0.zip', 'data/nn_0', {:symlink => true})
system "cd lib/data/nn_0 && unzip nn_0.zip" or exit 1
})
addModule('overnight', 'Creating a parser for multiple domains', lambda {
# Geo evaluation
pull('/u/nlp/data/semparse/overnight/geo880.db', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/geo880/geo880-train.examples', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/geo880/geo880-test.examples', 'data/overnight/', {:symlink => true})
# Cache for turking
pull('/u/nlp/data/semparse/overnight/cache/', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/layouts/', 'data/overnight/', {:symlink => true})
# Pull testing code
pull('/u/nlp/data/semparse/overnight/test/', 'data/overnight/', {:symlink => true})
# Pull geo880
pull('/u/nlp/data/semparse/overnight/geo880/geo880.paraphrases.train.superlatives.examples', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/geo880/geo880.paraphrases.train.superlatives2.examples', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/geo880/geo880.lexicon', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/geo880/geo880.predicate.dict', 'data/overnight/', {:symlink => true})
# Pull dependencies for everything else
domains = ['geo880', 'regex', 'publications', 'socialnetwork', 'restaurants', 'blocks', 'calendar', 'housing', 'basketball', 'recipes', 'calendarplus']
domains.each do |domain|
pull('/u/nlp/data/semparse/overnight/' + domain + '/' + domain + '.paraphrases.train.examples', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/' + domain + '/' + domain + '.paraphrases.test.examples', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/' + domain + '/' + domain + '.paraphrases.groups', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/' + domain + '/' + domain + '.word_alignments.berkeley', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/' + domain + '/' + domain + '.phrase_alignments', 'data/overnight/', {:symlink => true})
pull('/u/nlp/data/semparse/overnight/' + domain + '/' + domain + '-ppdb.txt', 'data/overnight/', {:symlink => true})
end
# Pull the independent sets for calendar
pull('/u/nlp/data/semparse/overnight/calendar/eval/calendar.test.turk.examples', 'data/overnight/', {:symlink => true})
})
addModule('esslli_2016', 'Data for ESSLLI 2016 semantic parsing class', lambda {
pull('/u/nlp/data/semparse/esslli_2016', 'data/esslli_2016/', {:symlink => true})
})
addModule('geo880', 'Data, lexicon, grammars and KB for geo880', lambda {
pull('/u/nlp/data/semparse/geo880/geo880-test.examples', 'data/geo880', {:symlink => true})
pull('/u/nlp/data/semparse/geo880/geo880-test.preprocessed.examples', 'data/geo880', {:symlink => true})
pull('/u/nlp/data/semparse/geo880/geo880-train.preprocessed.examples', 'data/geo880', {:symlink => true})
pull('/u/nlp/data/semparse/geo880/geo880.grammar', 'data/geo880', {:symlink => true})
pull('/u/nlp/data/semparse/geo880/geo880.lexicon', 'data/geo880', {:symlink => true})
pull('/u/nlp/data/semparse/geo880/geo880.kg', 'data/geo880', {:symlink => true})
pull('/u/nlp/data/semparse/geo880/geo880.type_hierarchy', 'data/geo880', {:symlink => true})
})
############################################################
if ARGV.size == 0
@ -153,6 +318,10 @@ if ARGV.size == 0
$modules.each { |name,description,func|
puts " #{name}: #{description}"
}
puts
puts "Internal use (Stanford NLP only):"
puts " #{$0} -l <module-1> ...: Get the files from the local Stanford NLP server instead"
puts " #{$0} -l -r <module-1> ...: Release to the public www directory on the server"
end
$modules.each { |name,description,func|

714
run
View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
# This is the main entry point for running all SEMPRE programs. See
# fig/lib/execrunner.rb for more documentation for how commands are generated.
@ -7,31 +7,55 @@
$: << 'fig/lib'
require 'execrunner'
$optPrefix = '-'
$modes = []
def addMode(name, description, func)
$modes << [name, description, func]
end
def header(modules='core')
def codalab(dependencies=nil)
# Set @cl=1 to run job on CodaLab
dependencies ||= l(':fig', ':lib', ':module-classes.txt', ':libsempre')
l(
letDefault(:cl, 0),
sel(:cl,
l(),
l('cl', 'run', dependencies, '---', 'LC_ALL=C.UTF-8'),
nil),
nil)
end
def header(modules='core', codalabDependencies=nil)
l(
codalab(codalabDependencies),
# Queuing system
letDefault(:q, 0), sel(:q, l(), l('fig/bin/q', '-shareWorkingPath', o('mem', '5g'), o('memGrace', 10), '-add', '---')),
# Create execution directory
'fig/bin/qcreate',
letDefault(:pooldir, 1),
sel(:pooldir, l(), 'fig/bin/qcreate'),
# Run the Java command...
'java',
'-ea',
'-Dmodules='+modules,
'-Xmx10g',
# Memory size
letDefault(:memsize, 'default'),
sel(:memsize, {
'tiny' => l('-Xms2G', '-Xmx4G'),
'low' => l('-Xms5G', '-Xmx7G'),
'default' => l('-Xms8G', '-Xmx10G'),
'medium' => l('-Xms12G', '-Xmx14G'),
'high' => l('-Xms20G', '-Xmx24G'),
'higher' => l('-Xms40G', '-Xmx50G'),
'impressive' => l('-Xms75G', '-Xmx90G'),
}),
# Classpath
'-cp', 'libsempre/*:lib/*',
# Profiling
letDefault(:prof, 0), sel(:prof, l(), '-Xrunhprof:cpu=samples,depth=100,file=_OUTPATH_/java.hprof.txt'),
nil)
end
def rlwrap; system('which rlwrap') ? 'rlwrap' : nil end
def unbalancedTrainDevSplit
l(o('Dataset.trainFrac', 0.8), o('Dataset.devFrac', 0.2))
end
@ -39,14 +63,18 @@ def balancedTrainDevSplit
l(o('Dataset.trainFrac', 0.5), o('Dataset.devFrac', 0.5))
end
def figOpts; l(o('execDir', '_OUTPATH_'), o('overwriteExecDir'), o('addToView', 0)) end
def figOpts; l(selo(:pooldir, 'execDir', 'exec', '_OUTPATH_'), o('overwriteExecDir'), o('addToView', 0)) end
############################################################
# Unit tests
addMode('test', 'Run unit tests', lambda { |e|
l(
'java', '-ea', '-Xmx12g', '-cp', 'libsempre/*:lib/*', 'org.testng.TestNG',
'java', '-ea', '-Xmx12g', '-cp', 'libsempre/*:lib/*',
lambda { |e|
e.key?(:sparqlserver) ? "-Dsparqlserver=http://#{e[:sparqlserver]}/sparql" : l()
},
'org.testng.TestNG',
lambda { |e|
if e[:class]
l('-testclass', 'edu.stanford.nlp.sempre.' + e[:class])
@ -115,8 +143,11 @@ def freebaseOpts
o('BinaryLexicon.binaryLexiconFilesPath', 'lib/fb_data/7/binaryInfoStringAndAlignment.txt'),
o('BinaryLexicon.keyToSortBy', 'Intersection_size_typed'),
nil),
o('UnaryLexicon.unaryLexiconFilePath', 'lib/fb_data/7/unaryInfoStringAndAlignment.txt'), # unary
o('EntityLexicon.entityPopularityPath', 'lib/fb_data/7/entityPopularity.txt'), # entity
o('UnaryLexicon.unaryLexiconFilePath','lib/fb_data/7/unaryInfoStringAndAlignment.txt'), # unary
o('EntityLexicon.entityPopularityPath','lib/fb_data/7/entityPopularity.txt'), # entity
#Jonathan - added this 3/5/2015
o('TypeInference.typeLookup','freebase.FreebaseTypeLookup'),
o('FreebaseSearch.cachePath', '/u/nlp/data/semparse/scr/cache/fbsearch/1.cache'),
nil)
end
@ -131,6 +162,7 @@ def cachePaths(lexiconFnCachePath, sparqlExecutorCachePath)
when 'local' then l( # Use files directly - don't run more than one job that does this!
o('Lexicon.cachePath', 'LexiconFn.cache'),
o('SparqlExecutor.cachePath', 'SparqlExecutor.cache'),
o('FreebaseSearch.cachePath', 'FreebaseSearch.cache'),
nil)
else l(
o('Lexicon.cachePath', cacheserver+':/u/nlp/data/semparse/cache/'+lexiconFnCachePath),
@ -225,15 +257,16 @@ def webquestions
nil),
# Grammar
o('Grammar.inPaths', 'freebase/data/emnlp2013.grammar'),
letDefault(:grammar, 1),
sel(:grammar, l(), l(o('Grammar.inPaths', 'freebase/data/emnlp2013.grammar'))),
o('Parser.beamSize', 200), # {07/03/13}: WebQuestions is too slow to run with default 500, so set to 200 for now...
# Caching
letDefault(:entitysearch, 1),
letDefault(:entitysearch, 0),
sel(:entitysearch, # Used for EMNLP 2013
l(
cachePaths('lucene/0.cache', 'sparql/1.cache'),
cachePaths('lucene/0.cache', 'sparql/3.cache'),
o('EntityLexicon.inexactMatchIndex','lib/lucene/4.4/inexact/'),
o('LexiconFn.maxEntityEntries',10),
o('Grammar.tags', 'webquestions', 'bridge', 'join', 'inject','inexact'), # specify also strategy
@ -255,7 +288,15 @@ addMode('freebase', 'Freebase (for EMNLP 2013, ACL 2014, TACL 2014)', lambda { |
letDefault(:train, 0),
letDefault(:interact, 0),
sel(:interact, l(), rlwrap),
# nlpsub: for running commands on PBS
letDefault(:nlpsub, 0),
sel(:nlpsub,
l(),
l('nlpsub', '-d/scr/yonatan/sandbox/blackhole', '-nyonatan', '-c3'),
l('nlpsub', '-d/scr/yonatan/sandbox/blackhole', '-nyonatan', '-qjag', '-c3'),
l('nlpsub', '-d/scr/yonatan/sandbox/blackhole', '-nyonatan', '-qjohn', '-c3'),
nil),
sel(:interact, l()),
freebaseHeader,
'edu.stanford.nlp.sempre.Main',
freebaseOpts,
@ -266,11 +307,6 @@ addMode('freebase', 'Freebase (for EMNLP 2013, ACL 2014, TACL 2014)', lambda { |
'free917' => free917,
}),
# Training
sel(:train, l(), l(
letDefault(:agenda, 0),
sel(:agenda, l(), agendaExperiments, agendaFree917Experiments),
nil)),
sel(:interact, l(), l(
# After training, run interact, which loads up a set of parameters and
@ -304,7 +340,7 @@ addMode('cacheserver', 'Start the general-purpose cache server that serves files
letDefault(:port, 4000),
lambda { |e| o('port', e[:port]) },
letDefault(:cachetype, 1),
letDefault(:cachetype, 0),
sel(:cachetype,
l(
o('FileStringCache.appendMode'),
@ -350,9 +386,19 @@ nil) })
addMode('sparqlserver', '(2) Start the SPARQL server [do this every time]', lambda { |e| l(
scrOptions,
required(:exec),
'freebase/scripts/virtuoso', 'start',
lambda{|e| e[:scr]+'/state/execs/'+e[:exec].to_s+'.exec/vdb'}, # DB directory
lambda{|e| 3000+e[:exec]}, # port
sel(nil,
l(
'freebase/scripts/virtuoso', 'start',
lambda{|e| e[:scr]+'/state/execs/'+e[:exec].to_s+'.exec/vdb'}, # DB directory
lambda{|e| 3000+e[:exec]}, # port
nil),
# Give everyone permissions so that anyone can kill the server if needed.
l(
'chmod', '-R', 'og=u',
lambda{|e| e[:scr]+'/state/execs/'+e[:exec].to_s+'.exec/vdb'}, # DB directory
nil),
# To stop the server: freebase/scripts/virtuoso stop 3093
nil),
nil) })
# (3) Index the filtered RDF dump [takes 48 hours]
@ -387,6 +433,7 @@ addMode('convertfree917', 'Convert the Free917 dataset', lambda { |e| l(
nil) })
addMode('query', 'Query a single logical form or SPARQL', lambda { |e| l(
codalab,
'java', '-ea',
'-cp', 'libsempre/*:lib/*',
'edu.stanford.nlp.sempre.freebase.SparqlExecutor',
@ -395,21 +442,30 @@ nil) })
############################################################
# Just start a simple interactive shell to try out SEMPRE commands
addMode('simple', 'Simple shell', lambda { |e| l(
rlwrap, 'java', '-cp', 'libsempre/*:lib/*', '-ea', 'edu.stanford.nlp.sempre.Main',
o('interactive'),
codalab, 'java', '-cp', 'libsempre/*:lib/*', '-ea', 'edu.stanford.nlp.sempre.Main',
o('Main.interactive'),
nil) })
addMode('simple-sparql', 'Simple shell for querying SPARQL', lambda { |e| l(
rlwrap, 'java', '-Dmodules=core,freebase', '-cp', 'libsempre/*:lib/*', '-ea', 'edu.stanford.nlp.sempre.Main',
codalab, 'java', '-Dmodules=core,freebase', '-cp', 'libsempre/*:lib/*', '-ea', 'edu.stanford.nlp.sempre.Main',
o('executor', 'freebase.SparqlExecutor'),
sparqlOpts,
o('interactive'),
o('Main.interactive'),
nil) })
addMode('simple-lambdadcs', 'Simple shell for querying with the LambdaDCSExecutor', lambda { |e| l(
codalab, 'java', '-Dmodules=core,tables,corenlp', '-cp', 'libsempre/*:lib/*', '-ea', 'edu.stanford.nlp.sempre.Main',
o('executor', 'tables.lambdadcs.LambdaDCSExecutor'),
o('FeatureExtractor.featureDomains', 'denotation lexAlign joinPos skipPos'.split),
o('LanguageAnalyzer.languageAnalyzer', 'corenlp.CoreNLPAnalyzer'),
o('Main.interactive'),
nil) })
addMode('simple-freebase', 'Simple shell for using Freebase', lambda { |e| l(
rlwrap, 'java', '-Dmodules=core,freebase', '-cp', 'libsempre/*:lib/*', '-ea', 'edu.stanford.nlp.sempre.Main',
'java', '-Dmodules=core,freebase', '-cp', 'libsempre/*:lib/*', '-ea', 'edu.stanford.nlp.sempre.Main',
o('executor', 'freebase.SparqlExecutor'),
letDefault(:sparqlserver, 'freebase.cloudapp.net:3093'),
letDefault(:cacheserver, 'freebase.cloudapp.net:4000'),
@ -434,9 +490,611 @@ addMode('simple-freebase', 'Simple shell for using Freebase', lambda { |e| l(
o('Main.interactive'),
nil) })
addMode('simple-freebase-nocache', 'Simple shell for using Freebase (without a cache server)', lambda { |e| l(
'java', '-Dmodules=core,freebase', '-cp', 'libsempre/*:lib/*', '-ea', 'edu.stanford.nlp.sempre.Main',
o('executor', 'freebase.SparqlExecutor'),
letDefault(:sparqlserver, 'freebase.cloudapp.net:3093'),
sparqlOpts,
o('FeatureExtractor.featureDomains', 'rule'),
o('Parser.coarsePrune'),
o('JoinFn.typeInference'),
o('UnaryLexicon.unaryLexiconFilePath', '/dev/null'),
o('BinaryLexicon.binaryLexiconFilesPath', '/dev/null'),
#o('JoinFn.showTypeCheckFailures'), # Use this to debug
o('Grammar.inPaths', 'freebase/data/demo1.grammar'), # Override with your own custom grammar
#o('SparqlExecutor.includeSupportingInfo'), # Show full information
o('Main.interactive'),
nil) })
############################################################
# {2014-12-27} [Percy]: Overnight semantic parsing
def overnightFeatureDomains
[
'match',
'ppdb',
'skip-bigram',
'root',
'alignment',
'lexical',
'root_lexical',
'lf',
'simpleworld',
nil].compact
end
addMode('overnight', 'Overnight semantic parsing', l(
header('core,freebase,overnight'),
'edu.stanford.nlp.sempre.Main',
figOpts,
o('JavaExecutor.convertNumberValues', false),
o('useAnchorsOnce', true),
o('trackLocalChoices'),
o('JoinFn.typeInference', true),
o('Builder.parser', 'FloatingParser'),
o('FloatingParser.executeAllDerivations', 'true'),
o('LanguageAnalyzer', 'corenlp.CoreNLPAnalyzer'),
o('Learner.maxTrainIters', 1),
#o('printAllPredictions'),
o('Derivation.showUtterance'),
letDefault(:debug, 0),
selo(1, 'maxExamples', 'train:10', 'train:MAX'),
# Exact matching is needed on most simple domains
# o('executor', 'FormulaMatchExecutor'),
# o('Builder.valueEvaluator', 'ExactValueEvaluator'),
# Features
o('FeatureExtractor.featureDomains', 'denotation'), # denotation features from general feature extractor
o('FeatureExtractor.featureComputers', 'overnight.OvernightFeatureComputer'), #
o('OvernightFeatureComputer.featureDomains', *overnightFeatureDomains),
#o('initialization', 'paraphrase :: match,1', 'paraphrase :: size,-0.1', 'paraphrase :: ppdb,0.3',
# 'paraphrase :: skip-bigram,0.8', 'paraphrase :: skip-ppdb,0.2','denotation :: error,-1000'),
o('coarsePrune'),
sel(2,
l(), # no reg
l(o('Params.l1Reg','lazy'),o('Params.l1RegCoeff',0)),
l(o('Params.l1Reg','lazy'),o('Params.l1RegCoeff',0.001)),
nil),
# Set up the domain
required(:domain),
o('Grammar.inPaths', lambda { |e| 'overnight/' + e[:domain] + '.grammar' }),
o('SimpleWorld.domain', lambda { |e| e[:domain] }),
o('PPDBModel.ppdbModelPath', lambda { |e| 'lib/data/overnight/' + e[:domain] + '-ppdb.txt' }),
o('Dataset.trainFrac', 0.8), o('Dataset.devFrac', 0.2),
o('FloatingParser.maxDepth', 11),
o('Parser.beamSize', 20),
letDefault(:alignment, 1),
sel(:alignment,
o('wordAlignmentPath', lambda { |e| 'lib/data/overnight/' + e[:domain] + '.word_alignments.heuristic' }),
o('wordAlignmentPath', lambda { |e| 'lib/data/overnight/' + e[:domain] + '.word_alignments.berkeley' }),
nil),
o('phraseAlignmentPath', lambda { |e| 'lib/data/overnight/' + e[:domain] + '.phrase_alignments' }),
o('PPDBModel.ppdbModelPath', lambda { |e| 'lib/data/overnight/' + e[:domain] + '-ppdb.txt' }),
o('DerivationPruner.pruningComputers', ['overnight.OvernightDerivationPruningComputer']),
o('DerivationPruner.pruningStrategies', ['violateHardConstraints']),
o('Dataset.inPaths',
lambda { |e| 'train:lib/data/overnight/' + e[:domain] + '.paraphrases.train.examples' },
lambda { |e| 'test:lib/data/overnight/' + e[:domain] + '.paraphrases.test.examples' }),
sel(:domain, {
'geo880' => l(
letDefault(:data,0),
sel(:data,
l(o('Dataset.inPaths', 'train:lib/data/overnight/geo880.paraphrases.train.superlatives.examples')),
l(o('Dataset.inPaths', 'train:lib/data/overnight/geo880.paraphrases.train.superlatives.examples', 'test:lib/data/overnight/geo880-train.examples')),
l(o('Dataset.inPaths', 'train:lib/data/overnight/geo880.paraphrases.train.superlatives2.examples', 'test:lib/data/overnight/geo880-train.examples')),
l(o('Dataset.inPaths', 'train:lib/data/overnight/geo880.paraphrases.train.superlatives.examples', 'test:lib/data/overnight/geo880-test.examples')),
l(o('Dataset.inPaths', 'train:lib/data/overnight/geo880.paraphrases.train.superlatives2.examples', 'test:lib/data/overnight/geo880-test.examples')),
nil),
o('Parser.beamSize', 20),
o('initialization', 'paraphrase :: match,1', 'paraphrase :: size,-0.1', 'paraphrase :: ppdb,0.3',
'lf :: edu.stanford.nlp.sempre.SimpleWorld.superlative& superlative,10',
'root :: pos0=WRB&returnType=class edu.stanford.nlp.sempre.NumberValue,10'),
o('FloatingParser.maxDepth', 11),
o('Grammar.tags','generate','general', 'geo880'),
o('SimpleLexicon.inPaths', 'lib/data/overnight/geo880.lexicon'),
nil),
'calendar' => l(
o('Grammar.tags','generate','general'),
nil),
'calendarplus' => l(
o('Grammar.tags','generate','general','geo440'),
o('Grammar.inPaths','overnight/calendar.grammar'),
o('SimpleWorld.domain', 'calendar'),
nil),
'blocks' => l(
o('Grammar.tags','generate','general'),
nil),
'restaurants' => l(
o('Grammar.tags','generate','general'),
nil),
'housing' => l(
o('Grammar.tags','generate','general'),
nil),
'socialnetwork' => l(
o('Grammar.tags','generate','general'),
nil),
'publications' => l(
o('Grammar.tags','generate','general'),
nil),
'basketball' => l(
o('Grammar.tags','generate','general'),
nil),
'recipes' => l(
o('Grammar.tags','generate','general'),
nil),
}),
nil))
############################################################
# {5/27/15} [Ice]
addMode('tables', 'QA on HTML tables', lambda { |e| l(
# Add @cldir=1 to use CodaLab's directory paths
letDefault(:cldir, 0),
# Usual header
header('core,tables,corenlp,cprune'),
# Select class
letDefault(:class, 'main'),
sel(:class, {
'main' => 'edu.stanford.nlp.sempre.Main',
'check' => 'edu.stanford.nlp.sempre.tables.test.DPDParserChecker',
'dump' => 'edu.stanford.nlp.sempre.tables.serialize.SerializedDumper',
'load' => l('edu.stanford.nlp.sempre.tables.serialize.SerializedLoader', let(:parser, 'serialized')),
'stats' => 'edu.stanford.nlp.sempre.tables.test.TableStatsComputer',
'tag-data' => 'edu.stanford.nlp.sempre.tables.serialize.TaggedDatasetGenerator',
'tag-table' => 'edu.stanford.nlp.sempre.tables.serialize.TaggedTableGenerator',
'tag-fuzzy' => 'edu.stanford.nlp.sempre.tables.serialize.TaggedFuzzyGenerator',
'alter' => l('edu.stanford.nlp.sempre.tables.alter.BatchTableAlterer', let(:parser, 'serialized')),
'alter-ex' => l('edu.stanford.nlp.sempre.tables.alter.AlteredTablesExecutor', let(:parser, 'serialized')),
'filter' => 'edu.stanford.nlp.sempre.tables.serialize.DumpFilterer',
'column' => 'edu.stanford.nlp.sempre.tables.test.TableColumnAnalyzer',
'execute' => 'edu.stanford.nlp.sempre.tables.test.BatchTableExecutor',
}),
# Fig parameters
selo(:cldir, 'execDir', '_OUTPATH_', '.'),
o('overwriteExecDir'), o('addToView', 15), o('jarFiles', 'libsempre/*'),
sel(:cldir, l(), '>/dev/null'),
# Set environment for table execution
o('executor', 'tables.lambdadcs.LambdaDCSExecutor'),
o('targetValuePreprocessor', 'tables.TableValuePreprocessor'),
o('NumberFn.unitless'), o('NumberFn.alsoTestByConversion'),
o('TypeInference.typeLookup', 'tables.TableTypeLookup'),
o('JoinFn.specializedTypeCheck', false), o('JoinFn.typeInference', true),
o('Learner.outputPredValues'),
# Value Evaluator
letDefault(:eval, 'value'),
sel(:eval, {
'value' => o('Builder.valueEvaluator', 'tables.TableValueEvaluator'),
'denotation' => o('Builder.valueEvaluator', 'tables.TableValueEvaluator'), # alias of 'value'
'formula' => l(
o('Builder.valueEvaluator', 'tables.TableFormulaEvaluator'),
o('fallBackToValueEvaluator', false),
nil),
}),
# Parser
letDefault(:parser, 'floatsize'),
o('beamSize', 50),
o('useSizeInsteadOfDepth'),
sel(:parser, {
'floatsize' => l(
o('Builder.parser', 'FloatingParser'),
o('FloatingParser.maxDepth', 15),
nil),
'baseline' => o('Builder.parser', 'tables.baseline.TableBaselineParser'),
'serialized' => o('Builder.parser', 'tables.serialize.SerializedParser'),
# ACL 2016
'grow-dpd' => l(
o('Builder.parser', 'tables.dpd.DPDParser'),
o('FloatingParser.maxDepth', 8),
nil),
'grow-float' => l(
o('Builder.parser', 'FloatingParser'),
o('FloatingParser.maxDepth', 8),
o('FloatingParser.betaReduce'), o('initialFloatingHasZeroDepth'),
nil),
'grow-mix' => l(
o('Builder.parser', 'MixParser'),
o('MixParser.parsers', 'FloatingParser', 'tables.serialize.SerializedParser:train-0xc'),
o('FloatingParser.maxDepth', 8),
o('FloatingParser.betaReduce'), o('initialFloatingHasZeroDepth'),
nil),
# EMNLP 2017
'cprune' => l(
o('Builder.parser', 'cprune.CPruneFloatingParser'),
o('FloatingParser.maxDepth', 15),
o('maxNumNeighbors', 40),
o('maxPredictedPatterns', 1000),
nil),
}),
o('Parser.verbose', 0),
letDefault(:pruning, 1),
sel(:pruning,
l(),
l(
o('DerivationPruner.pruningStrategies', *tablesPruningStrategies),
o('DerivationPruner.pruningComputers', 'tables.TableDerivationPruningComputer'),
nil),
nil),
# Grammar
tablesGrammarPaths,
letDefault(:fuzzy, 'original'),
sel(:fuzzy, {
'original' => o('FuzzyMatcher.fuzzyMatcher', 'tables.match.OriginalMatcher'),
'editdist-exact' => l(
o('FuzzyMatcher.fuzzyMatcher', 'tables.match.EditDistanceFuzzyMatcher'),
o('fuzzyMatchMaxEditDistanceRatio', 0.0),
nil),
'editdist-fuzzy' => l(
o('FuzzyMatcher.fuzzyMatcher', 'tables.match.EditDistanceFuzzyMatcher'),
o('fuzzyMatchSubstring'), o('fuzzyMatchMaxEditDistanceRatio', 0.15),
o('alsoMatchPart'),
nil),
}),
letDefault(:normalize, 1),
sel(:normalize,
l(),
l(o('genericDateValue'), o('numberCanStartAnywhere'), o('num2CanStartAnywhere')),
nil),
letDefault(:anchor, 1),
sel(:anchor, {
1 => o('FloatingParser.useAnchorsOnce', true),
2 => l(o('FloatingParser.useAnchorsOnce', false), o('FloatingParser.useMaxAnchors', 2)),
}),
# Dataset
letDefault(:data, 'none'),
tablesDataPaths,
# Verbosity
o('FeatureVector.ignoreZeroWeight'),
o('logFeaturesLimit', 10),
o('LambdaDCSException.noErrorMessage'),
letDefault(:verbose, 0),
sel(:verbose,
l(
o('maxPrintedPredictions', 1), o('maxPrintedTrue', 1),
nil),
l(
o('maxPrintedPredictions', 10), o('maxPrintedTrue', 10),
o('putCellNameInCanonicalUtterance'), o('showUtterance'),
nil),
l(
o('maxPrintedPredictions', 10), o('maxPrintedTrue', 10),
o('putCellNameInCanonicalUtterance'), o('showUtterance'),
o('summarizeRuleTime'), o('summarizeDenotations'),
nil),
l(
o('maxPrintedPredictions', 10), o('maxPrintedTrue', 10),
o('putCellNameInCanonicalUtterance'), o('showUtterance'),
o('summarizeRuleTime'), o('summarizeDenotations'),
o('showRules'),
o('Parser.verbose', 2),
o('JoinFn.verbose', 3),
o('JoinFn.showTypeCheckFailures'),
nil),
nil),
# Language Analyzer
letDefault(:lang, 'corenlp'),
sel(:lang, {
'simple' => o('LanguageAnalyzer', 'SimpleAnalyzer'),
'corenlp' => l(o('LanguageAnalyzer', 'corenlp.CoreNLPAnalyzer'), o('annotators', *'tokenize ssplit pos lemma ner'.split)),
'fullcorenlp' => l(o('LanguageAnalyzer', 'corenlp.CoreNLPAnalyzer'), o('annotators', *'tokenize ssplit pos lemma ner parse'.split)),
}),
# Training
letDefault(:train, 0),
sel(:train,
l(
let(:l1, 0),
nil),
l(
o('combineFromFloatingParser'),
o('maxTrainIters', 3),
o('showValues', false), o('showFirstValue'),
o('customExpectedCounts', 'TOP'),
nil),
l(
# for dumping derivations (@class=dump)
# force unbalancedTrainDevSplit + combine from floating parser
o('combineFromFloatingParser'), o('DPDParser.cheat'),
nil),
nil),
# Regularization
letDefault(:l1, 1),
sel(:l1,
l(),
l(o('Params.l1Reg','lazy'), o('Params.l1RegCoeff', '3e-5')), # Default
l(o('Params.l1Reg','lazy'), selo(nil, 'Params.l1RegCoeff', 0, 0.00001, 0.0001, 0.001, 0.01)),
l(o('Params.l1Reg','lazy'), selo(nil, 'Params.l1RegCoeff', 0.00001, 0.00003, 0.0001, 0.0003)),
l(o('Params.l1Reg','lazy'), selo(nil, 'Params.l1RegCoeff', 0.00001, 0.00003, 0.0005)),
nil),
# Features
letDefault(:feat, 'none'),
sel(:feat, {
'none' => l(), # No features (random)
'some' => l( # Add your own features! (only set up the feature computers)
o('FeatureExtractor.featureComputers', 'tables.features.PhrasePredicateFeatureComputer tables.features.PhraseDenotationFeatureComputer'.split),
nil),
'all' => l( # All ACL 2015 features
o('FeatureExtractor.featureDomains', 'custom-denotation phrase-predicate phrase-denotation headword-denotation missing-predicate'.split),
o('FeatureExtractor.featureComputers', 'tables.features.PhrasePredicateFeatureComputer tables.features.PhraseDenotationFeatureComputer'.split),
nil),
'more' => l( # All ACL 2015 features + more experimental features
o('FeatureExtractor.featureDomains', 'custom-denotation phrase-predicate phrase-denotation headword-denotation missing-predicate anchored-entity'.split),
o('FeatureExtractor.featureComputers', 'tables.features.PhrasePredicateFeatureComputer tables.features.PhraseDenotationFeatureComputer tables.features.AnchorFeatureComputer'.split),
nil),
'baseline' => l( # For the baseline classifier
o('FeatureExtractor.featureDomains', 'custom-denotation phrase-denotation headword-denotation table-baseline'.split),
o('FeatureExtractor.featureComputers', 'tables.baseline.TableBaselineFeatureComputer tables.features.PhraseDenotationFeatureComputer'.split),
nil),
'ablate' => l(
o('FeatureExtractor.featureComputers', 'tables.features.PhrasePredicateFeatureComputer tables.features.PhraseDenotationFeatureComputer'.split),
selo(nil,
'FeatureExtractor.featureDomains',
'phrase-predicate phrase-denotation headword-denotation missing-predicate'.split,
'custom-denotation phrase-denotation headword-denotation missing-predicate'.split,
'custom-denotation phrase-predicate headword-denotation missing-predicate'.split,
'custom-denotation phrase-predicate phrase-denotation missing-predicate'.split,
'custom-denotation phrase-predicate phrase-denotation headword-denotation'.split,
nil),
nil),
}),
letDefault(:featOp, 'careful'),
sel(:featOp, {
'none' => l(),
'careful' => l(
o('maxNforLexicalizeAllPairs', 2),
o('computeFuzzyMatchPredicates'),
nil),
}),
nil) })
def tablesGrammarPaths
lambda { |e|
baseDir = ['tables/grammars/', 'grammars/'][e[:cldir]]
l(
letDefault(:grammar, 'combined-all'),
sel(:grammar, {
'custom' => l(),
'restrict' => o('Grammar.inPaths', "#{baseDir}restrict.grammar"),
'simple' => o('Grammar.inPaths', "#{baseDir}simple.grammar"),
'combined' => o('Grammar.inPaths', "#{baseDir}combined.grammar"),
'combined-jnc' => l( # WQ baseline
o('Grammar.inPaths', "#{baseDir}combined.grammar"),
o('Grammar.tags', *'movement count'.split),
nil),
'combined-cut' => l( # No intersection / union
o('Grammar.inPaths', "#{baseDir}combined.grammar"),
o('Grammar.tags', *'movement comparison count aggregate superlative arithmetic'.split),
nil),
'combined-all' => l( # Default
o('Grammar.inPaths', "#{baseDir}combined.grammar"),
o('Grammar.tags', *'alternative movement comparison count aggregate superlative arithmetic merge'.split),
nil),
'combined-more' => l(
o('Grammar.inPaths', "#{baseDir}combined.grammar"),
o('Grammar.tags', *'alternative movement comparison count aggregate superlative arithmetic merge v-superlative'.split),
nil),
'combined-trigger' => l( # Use trigger words for operations
o('Grammar.inPaths', "#{baseDir}combined.grammar"),
o('Grammar.tags', *'t-alternative t-movement t-comparison t-count t-aggregate t-superlative t-arithmetic merge'.split),
nil),
# ACL 2016
'grow-custom' => l(
o('Grammar.inPaths', "#{baseDir}grow.grammar"),
o('Grammar.binarizeRules', false),
nil),
'grow-default' => l(
o('Grammar.inPaths', "#{baseDir}grow.grammar"),
o('Grammar.binarizeRules', false),
o('Grammar.tags', *'scoped merge-and arithmetic comparison alternative neq yearrange part closedclass scoped-2args-merge-and'.split),
let(:anchor, 2),
nil),
'grow-strict' => l(
o('Grammar.inPaths', "#{baseDir}grow.grammar"),
o('Grammar.binarizeRules', false),
o('Grammar.tags', *'scoped merge-and arithmetic comparison alternative neq yearrange part closedclass-generic scoped-2args-merge-and'.split),
let(:anchor, 2),
nil),
# EMNLP 2017
'extended' => l(
o('Grammar.inPaths', "#{baseDir}extended.grammar"),
o('Grammar.tags', *'alternative movement comparison count aggregate superlative arithmetic merge v-superlative'.split),
nil),
}),
nil)
}
end
def tablesDataPaths
lambda { |e|
baseDir = ['lib/data/WikiTableQuestions/data/', 'WikiTableQuestions/data/'][e[:cldir]]
csvDir = ['lib/data/WikiTableQuestions/', 'WikiTableQuestions/'][e[:cldir]]
nnDir = ['lib/data/nn_0/', 'nn_0/'][e[:cldir]]
datasets = {
'none' => l(),
'train' => o('Dataset.inPaths', "train,#{baseDir}training.examples"),
# Pristine test test
'test' => l(
o('Dataset.inPaths',
"train,#{baseDir}training.examples",
"test,#{baseDir}pristine-unseen-tables.examples"),
o('neighborFilePath', "#{nnDir}/exact_nearest_neighbors.all"),
nil),
# @data=annotated can be used with @class=check only
'annotated' => o('Dataset.inPaths', "train,#{baseDir}annotated-all.examples"),
'before300' => o('Dataset.inPaths', "train,#{baseDir}training-before300.examples"),
}
# Development sets: 80:20 random split of training data
['1', '2', '3', '4', '5'].each do |x|
datasets['u-' + x] = l(
o('Dataset.inPaths',
"train,#{baseDir}random-split-#{x}-train.examples",
"dev,#{baseDir}random-split-#{x}-dev.examples",
nil),
o('neighborFilePath', "#{nnDir}/exact_nearest_neighbors.seed-#{x}.train"),
nil)
end
# That's it!
l(
o('TableKnowledgeGraph.baseCSVDir', csvDir),
# To use the normalized values from the tagged file, which were checked by hand,
# add @useTaggedFile=1
letDefault(:useTaggedFile, 0),
selo(:useTaggedFile, 'TableValuePreprocessor.taggedFiles', '', "#{csvDir}/tagged/data/"),
sel(:data, datasets),
nil)
}
end
def tablesPruningStrategies
[
### Critical strategies
"emptyDenotation",
"nonLambdaError",
### Strategies that do not depend on the children's actual formulas
"atomic",
"tooManyValues",
"badSummarizerHead",
"mistypedMerge",
### Strategies that depend on the children's formulas
"doubleNext",
"multipleSuperlatives",
"sameMerge",
"forwardBackward",
"unsortedMerge",
"typeRowMerge",
nil].compact
end
############################################################
# {2015-01-18} Generate utterances [Percy]
addMode('genovernight', 'Generate utterances for overnight semantic parsing', lambda { |e| l(
header('core,overnight'),
'edu.stanford.nlp.sempre.overnight.GenerationMain',
figOpts,
o('JoinFn.typeInference', true),
o('JoinFn.specializedTypeCheck', false),
o('JavaExecutor.convertNumberValues', false),
o('JavaExecutor.printStackTrace', false),
# These domains are all based on SimpleWorld
required(:domain),
o('Grammar.inPaths', lambda { |e| 'overnight/' + e[:domain] + '.grammar' }),
o('SimpleWorld.domain', lambda { |e| e[:domain] }),
o('initialization', 'denotation :: error,-1000', 'denotation :: empty,-100', 'paraphrase :: size,+0.01', 'denotation :: value_in_formula,-100'),
o('FeatureExtractor.featureComputers','overnight.OvernightFeatureComputer'),
o('OvernightFeatureComputer.featureDomains', ''),
o('OvernightFeatureComputer.itemAnalysis',false),
letDefault(:gen, 1),
sel(:gen,
l( # For debugging the grammar
o('FeatureExtractor.featureDomains', 'denotation'),
o('Dataset.inPaths', lambda { |e| 'train:overnight/' + e[:domain] + '-unittest.examples'}),
selo(:parse, 'Grammar.tags', 'generate', 'parse'),
o('interactive'),
nil),
l( # For generating utterances
o('parser', 'FloatingParser'),
o('maxDepth', 30), o('beamSize', 10000),
o('derivationScoreNoise', 1),
o('Dataset.inPaths', 'train:overnight/null.examples'),
o('Derivation.showUtterance'),
o('FeatureExtractor.featureDomains', 'denotation'),
o('printAllPredictions'),
o('printPredictedUtterances'),
o('executeAllDerivations'),
o('Parser.pruneErrorValues', true),
o('Grammar.tags', 'generate'),
nil),
nil),
a('Grammar.tags', 'general'),
nil) })
# Generate for all the domains
addMode('genovernight-wrapper', 'Generate utterances for overnight semantic parsing', lambda { |e| l(
'./run', '@mode=genovernight', '@gen=1',
sel(nil, {
'calendar' => let(:domain, 'calendar'),
'blocks' => let(:domain, 'blocks'),
'housing' => let(:domain, 'housing'),
'restaurants' => let(:domain, 'restaurants'),
'publications' => let(:domain, 'publications'),
'socialnetwork' => let(:domain, 'socialnetwork'),
'basketball' => let(:domain, 'basketball'),
'geo880' => let(:domain, 'geo880'),
'recipes' => let(:domain, 'recipes'),
}),
lambda { |e| '@domain=' + e[:domain] },
lambda { |e| system 'mkdir -p genovernight.out'; o('execDir', 'genovernight.out/' + e[:domain]) },
nil) })
addMode('geo880', 'Semantic parsing on the geo880 dataset', lambda { |e| l(
# Usual header
header('core,tables,corenlp,geo880'),
'edu.stanford.nlp.sempre.Main',
# Fig parameters
figOpts,
o('executor', 'tables.lambdadcs.LambdaDCSExecutor'),
o('JoinFn.specializedTypeCheck', false), o('JoinFn.typeInference', false),
# Parser
o('Builder.parser', 'BeamParser'),
o('Parser.coarsePrune'),
# Evaluation
o('Builder.valueEvaluator', 'geo880.Geo880ValueEvaluator'),
# Grammar
o('Grammar.inPaths','lib/data/geo880/geo880.grammar'),
# Type hierarchy
o('Geo880TypeLookup.typeHierarchyPath', 'lib/data/geo880/geo880.type_hierarchy'),
o('TypeInference.typeLookup','geo880.Geo880TypeLookup'),
# Yrkvpba
o('SimpleLexicon.inPaths', 'lib/data/geo880/geo880.lexicon'),
# Learner
o('Learner.maxTrainIters', 3),
# Dataset
letDefault(:data, 0),
sel(:data,
l(o('Dataset.inPaths', 'train,lib/data/geo880/geo880-train.preprocessed.examples'), unbalancedTrainDevSplit), # (0) train 0.8, dev 0.2
l(o('Dataset.inPaths', 'train,lib/data/geo880/geo880-train.examples', 'test,lib/data/geo880/geo880-test.preprocessed/examples')), # (1) Don't run on test yet!
nil),
# Load the graph
o('Dataset.globalGraphPath', 'lib/data/geo880/geo880.kg'),
# Verbosity
letDefault(:verbose, 0),
sel(:verbose,
l(),
l(
o('showRules'),
o('Parser.verbose', 2),
o('JoinFn.verbose', 3),
o('JoinFn.showTypeCheckFailures'),
nil),
nil),
# Language Analyzer
l(o('LanguageAnalyzer', 'corenlp.CoreNLPAnalyzer'), o('annotators', *'tokenize ssplit pos lemma ner'.split)),
# Regularization
letDefault(:l1, 0),
sel(:l1,
l(),
l(o('Params.l1Reg','lazy'), o('Params.l1RegCoeff', '3e-5')),
l(o('Params.l1Reg','lazy'), selo(nil, 'Params.l1RegCoeff', 0, 0.00001, 0.0001, 0.001, 0.01)),
nil),
# Features
letDefault(:feat, 'freebase'),
sel(:feat, {
'none' => l(), # No features (random)
'freebase' => l(
o('FeatureExtractor.featureDomains', 'rule opCount constant whType span lemmaAndBinaries denotation lexAlign joinPos skipPos'.split),
# o('FeatureExtractor.featureDomains', 'rule opCount constant whType lemmaAndBinaries denotation lexAlign joinPos skipPos'.split),
nil),
}),
nil) })
############################################################

View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
ARGV.each { |e|
e = e.sub(/\.exec$/, '')

View File

@ -7,4 +7,5 @@ else
fi
d=`dirname $0`
java -cp $d/../lib/checkstyle/checkstyle-6.1.1-all.jar com.puppycrawl.tools.checkstyle.Main -c `dirname $0`/checkstyle.xml $files
prog="$d/../lib/checkstyle/checkstyle-6.6-all.jar"
java -cp $prog com.puppycrawl.tools.checkstyle.Main -c `dirname $0`/checkstyle.xml $files

View File

@ -39,6 +39,8 @@
<property name="basedir" value="${basedir}"/>
-->
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Checks that a package-info.java file exists for each package. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
<!-- RELAX -->
@ -76,8 +78,16 @@
<!-- <property name="fileExtensions" value="java"/> -->
<!-- </module> -->
<!-- RELAX: Allow warning suppression -->
<!-- Usage: Add @SuppressWarnings({"checkname"}) -->
<!-- checkname must be lowercased -->
<module name="SuppressWarningsFilter" />
<module name="TreeWalker">
<!-- RELAX: Allow warning suppression -->
<module name="SuppressWarningsHolder" />
<!-- Checks for Javadoc comments. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
<!-- RELAX -->
@ -167,9 +177,6 @@
<!-- RELAX: allow numbers -->
<!--<module name="MagicNumber"/>-->
<module name="MissingSwitchDefault"/>
<module name="RedundantThrows">
<property name="suppressLoadErrors" value="true"/>
</module>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>

View File

@ -0,0 +1,68 @@
#!/usr/bin/python
import sys
import json
class LexicalEntry:
def __init__(self, l, f, t):
self.lexeme=l.strip()
self.formula=f.strip()
self.type=t.strip()
out = open(sys.argv[2],'w')
with open(sys.argv[1]) as f:
for line in f:
tokens = line.split("\t")
if len(tokens) > 2:
continue
if(tokens[0] == "loc_city"):
index = tokens[1].rfind('.')
citystate = tokens[1][index+1:]
city = citystate[0:citystate.rfind('_')]
city = city.replace('_',' ').strip()
entry = LexicalEntry(city, tokens[1], "fb:en.city")
out.write(json.dumps(entry.__dict__)+'\n')
elif (tokens[0] == "loc_state"):
index = tokens[1].rfind('.')
state = tokens[1][index+1:].strip()
state = state.replace('_',' ').strip()
entry = LexicalEntry(state, tokens[1], "fb:en.state")
out.write(json.dumps(entry.__dict__)+'\n')
elif tokens[0] == "loc_river":
index = tokens[1].rfind('.')
river = tokens[1][index+1:].strip()
river = river.replace('_',' ').strip()
entry = LexicalEntry(river+" river", tokens[1], "fb:en.river")
out.write(json.dumps(entry.__dict__)+'\n')
elif (tokens[0] == "loc_place"):
index = tokens[1].rfind('.')
place = tokens[1][index+1:].strip()
place = place.replace('_',' ').strip()
entry = LexicalEntry(place, tokens[1], "fb:en.place")
out.write(json.dumps(entry.__dict__)+'\n')
elif (tokens[0] == "loc_lake"):
index = tokens[1].rfind('.')
lake = tokens[1][index+1:].strip()
lake = lake.replace('_',' ').strip()
if not 'lake' in lake:
lake = lake + " lake"
entry = LexicalEntry(lake, tokens[1], "fb:en.lake")
out.write(json.dumps(entry.__dict__)+'\n')
elif (tokens[0] == "loc_mountain"):
index = tokens[1].rfind('.')
mountain = tokens[1][index+1:].strip()
mountain = mountain.replace('_',' ').strip()
entry = LexicalEntry("mount " + mountain, tokens[1], "fb:en.mountain")
out.write(json.dumps(entry.__dict__)+'\n')
elif (tokens[0] == "loc_country"):
index = tokens[1].rfind('.')
country = tokens[1][index+1:].strip()
country = country.replace('_',' ').strip()
entry = LexicalEntry(country, tokens[1], "fb:en.country")
out.write(json.dumps(entry.__dict__)+'\n')
out.close()

View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
# Input: src
# Output: module-classes.txt

View File

@ -0,0 +1,29 @@
#!/usr/bin/python
import sys
import json
# Official evaluation script used to evaluate Freebase question answering
# systems. Used for EMNLP 2013, ACL 2014 papers, etc.
if len(sys.argv) != 3:
sys.exit("Usage: %s <generated_file> <filtered_file>" % sys.argv[0])
generated = set()
with open(sys.argv[1]) as f:
for line in f:
generated.add(line)
out = open(sys.argv[2],'w')
with open(sys.argv[1]) as f:
for line in f:
index = line.find(" not")
if index != -1:
newStr = line[0:index] + line[index+4:len(line)]
if newStr in generated:
out.write(line)
else:
out.write(line)
out.close()

View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
# Heuristically find all hard-coded paths in the source code.
# There should be no absolute paths.

View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
# Hacky script for automatically fixing style errors. This script is far from
# perfect and you should manually inspect all changes before making changes.

View File

@ -0,0 +1,7 @@
#!/bin/sh
#Generate predictions file for evaluation script
#arguments: (1) execution numebr (2) iteration number (3) final output file
fig/bin/tab e/$1.exec/learner.events iter group utterance targetValue predValue | grep -P "$2\ttest" | cut -f3,4,5 > pred_temp
java -cp "libsempre/*:lib/*" edu.stanford.nlp.sempre.freebase.utils.FileUtils pred_temp $3
rm pred_temp

View File

@ -20,6 +20,14 @@ pid=$(ps ax | grep ssh.*:$port | grep -v grep | awk '{print $1}')
if [ -n "$pid" ]; then kill $pid; fi
ssh -N -n -L $port:$host:$port jacob.stanford.edu &
# Sparql server for geo
host=jonsson
port=3094
echo "Tunnel localhost:$port => $host:$port"
pid=$(ps ax | grep ssh.*:$port | grep -v grep | awk '{print $1}')
if [ -n "$pid" ]; then kill $pid; fi
ssh -N -n -L $port:$host:$port jacob.stanford.edu &
# Sparql server for Paleo
host=jonsson
port=3021

View File

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
# Verifies that the codebase is sane (compiles, doesn't crash, gets reasonable
# accuracy) every once in a while. If something fails, an email is sent out
@ -92,8 +92,8 @@ while true
log("Testing...")
run('git log -3', true) or restart # Print out last commit messages
run('./pull-dependencies', true) or restart
run('make clean', true) or restart
run('make', true) or restart
run('ant clean', true) or restart
run('ant', true) or restart
run('scripts/find-hard-coded-paths.rb', true) or restart

View File

@ -47,9 +47,7 @@ abstract class AbstractReinforcementParserState extends ChartParserState {
derivations.add(deriv);
Collections.sort(derivations, Derivation.derivScoreComparator); // todo - perhaps can be removed
return true;
} else {
return false;
}
} else return false;
}
// for [start, end) we try to create [start, end + i) or [start - i, end) and add unary rules

View File

@ -0,0 +1,130 @@
package edu.stanford.nlp.sempre;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import fig.basic.LispTree;
/**
* An ActionFormula represent a compositional action used in the interactive
* package : is used as a prefix to denote an ActionFormula primitive (:
* actioname args) sequential (:s ActionFormula ActionFormula ...) repeat (:loop
* Number ActionFormula) conditional (:if Set ActionFormula) block scoping (:blk
* ActionFormula)
*
* @author sidaw
*/
public class ActionFormula extends Formula {
public enum Mode {
primitive(":"), // (: remove *)
sequential(":s"), // (:s (: add red top) (: remove this))
repeat(":loop"), // (:loop (count (has color green)) (: add red top))
conditional(":if"), // (:if (count (has color green)) (: add red top))
whileloop(":while"), // (:while (count (has color green)) (: add red top))
forset(":for"), // (:for (and this (color red)) (:s (: add red top) (: add
// yellow top) (: remove)))
foreach(":foreach"), // (:foreach * (add ((reverse color) this) top))
// primitives for declaring variables
// let(":let"), // (:let X *),
// set(":set"), // (:set X *)
block(":blk"), // start a block of code (like {}) with a new scope
blockr(":blkr"), // also return a result after finishing the block
isolate(":isolate"), other(":?");
private final String value;
Mode(String value) {
this.value = value;
}
@Override
public String toString() {
return this.value;
}
};
public final Mode mode;
public final List<Formula> args;
public ActionFormula(Mode mode, List<Formula> args) {
this.mode = mode;
this.args = args;
}
public static Mode parseMode(String mode) {
if (mode == null)
return null;
for (Mode m : Mode.values()) {
// LogInfo.logs("mode string %s \t== %s \t!= %s", m.toString(), mode,
// m.name());
if (m.toString().equals(mode))
return m;
}
if (mode.startsWith(":"))
throw new RuntimeException("Unsupported ActionFormula mode");
return null;
}
@Override
public LispTree toLispTree() {
LispTree tree = LispTree.proto.newList();
tree.addChild(this.mode.toString());
for (Formula arg : args)
tree.addChild(arg.toLispTree());
return tree;
}
@Override
public void forEach(Function<Formula, Boolean> func) {
if (!func.apply(this)) {
for (Formula arg : args)
arg.forEach(func);
}
}
@Override
public Formula map(Function<Formula, Formula> transform) {
Formula result = transform.apply(this);
if (result != null)
return result;
List<Formula> newArgs = Lists.newArrayList();
for (Formula arg : args)
newArgs.add(arg.map(transform));
return new ActionFormula(this.mode, newArgs);
}
@Override
public List<Formula> mapToList(Function<Formula, List<Formula>> transform, boolean alwaysRecurse) {
List<Formula> res = transform.apply(this);
if (res.isEmpty() || alwaysRecurse) {
for (Formula arg : args)
res.addAll(arg.mapToList(transform, alwaysRecurse));
}
return res;
}
@SuppressWarnings({ "equalshashcode" })
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof ActionFormula))
return false;
ActionFormula that = (ActionFormula) thatObj;
if (!this.mode.equals(that.mode))
return false;
if (!this.args.equals(that.args))
return false;
return true;
}
@Override
public int computeHashCode() {
int hash = 0x7ed55d16;
hash = hash * 0xd3a2646c + mode.hashCode();
hash = hash * 0xd3a2646c + args.hashCode();
return hash;
}
}

View File

@ -36,6 +36,12 @@ public class AggregateFormula extends Formula {
return null;
}
@Override
public void forEach(Function<Formula, Boolean> func) {
if (!func.apply(this)) child.forEach(func);
}
@Override
public Formula map(Function<Formula, Formula> func) {
Formula result = func.apply(this);
return result == null ? new AggregateFormula(mode, child.map(func)) : result;
@ -49,6 +55,7 @@ public class AggregateFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof AggregateFormula)) return false;

View File

@ -32,6 +32,12 @@ public class ArithmeticFormula extends Formula {
return tree;
}
@Override
public void forEach(Function<Formula, Boolean> func) {
if (!func.apply(this)) { child1.forEach(func); child2.forEach(func); }
}
@Override
public Formula map(Function<Formula, Formula> func) {
Formula result = func.apply(this);
return result == null ? new ArithmeticFormula(mode, child1.map(func), child2.map(func)) : result;
@ -65,6 +71,7 @@ public class ArithmeticFormula extends Formula {
}
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof ArithmeticFormula)) return false;

View File

@ -1,7 +1,6 @@
package edu.stanford.nlp.sempre;
import fig.basic.LispTree;
import java.util.*;
// Represents an atomic type (strings, entities, numbers, dates, etc.).
public class AtomicSemType extends SemType {

View File

@ -19,6 +19,9 @@ public class BooleanValue extends Value {
return tree;
}
@Override public String sortString() { return "" + value; }
@Override public String pureString() { return "" + value; }
@Override public int hashCode() { return Boolean.valueOf(value).hashCode(); }
@Override public boolean equals(Object o) {
if (this == o) return true;

View File

@ -86,6 +86,7 @@ public class Builder {
} catch (ClassNotFoundException e1) {
throw new RuntimeException("Illegal parser: " + opts.parser);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error while instantiating parser: " + opts.parser + "\n" + e);
}
}

View File

@ -35,6 +35,16 @@ public class CallFormula extends Formula {
return tree;
}
@Override
public void forEach(Function<Formula, Boolean> func) {
if (!func.apply(this)) {
this.func.forEach(func);
for (Formula arg: args)
arg.forEach(func);
}
}
@Override
public Formula map(Function<Formula, Formula> transform) {
Formula result = transform.apply(this);
if (result != null) return result;
@ -56,6 +66,7 @@ public class CallFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof CallFormula)) return false;

View File

@ -5,7 +5,8 @@ import java.util.*;
/**
* List of canonical names that we borrowed from Freebase.
*
* These names and helper methods are independent from the Freebase schema.
* These names and helper methods are independent from the Freebase schema
* (even though the names begin with "fb:").
*
* @author ppasupat
*/
@ -13,10 +14,12 @@ public final class CanonicalNames {
private CanonicalNames() { }
// Standard type names
public static final String PREFIX = "fb:";
public static final String BOOLEAN = "fb:type.boolean";
public static final String INT = "fb:type.int";
public static final String FLOAT = "fb:type.float";
public static final String DATE = "fb:type.datetime";
public static final String TIME = "fb:type.time";
public static final String TEXT = "fb:type.text";
public static final String NUMBER = "fb:type.number";
public static final String ENTITY = "fb:common.topic";
@ -29,14 +32,86 @@ public final class CanonicalNames {
public static final String TYPE = "fb:type.object.type";
public static final String NAME = "fb:type.object.name";
// Special Unary: star (*)
public static final String STAR = "*";
// Special Binaries: comparison
public static final Map<String, String> COMPARATOR_REVERSE = new HashMap<>();
static {
COMPARATOR_REVERSE.put("!=", "!="); // a != b implies b != a
COMPARATOR_REVERSE.put("<", ">=");
COMPARATOR_REVERSE.put(">", "<=");
COMPARATOR_REVERSE.put("<=", ">");
COMPARATOR_REVERSE.put(">=", "<");
}
public static final Set<String> COMPARATORS = COMPARATOR_REVERSE.keySet();
// Special Binary: colon (:)
public static final String COLON = ":";
// SemType for special unaries and binaries
public static final Map<String, SemType> SPECIAL_SEMTYPES = new HashMap<>();
static {
SPECIAL_SEMTYPES.put("*", SemType.anyType);
SPECIAL_SEMTYPES.put("!=", SemType.anyAnyFunc);
SPECIAL_SEMTYPES.put("<", SemType.compareFunc);
SPECIAL_SEMTYPES.put(">", SemType.compareFunc);
SPECIAL_SEMTYPES.put("<=", SemType.compareFunc);
SPECIAL_SEMTYPES.put(">=", SemType.compareFunc);
SPECIAL_SEMTYPES.put(":", SemType.anyAnyFunc);
}
// Unary: fb:domain.type [contains exactly one period]
// Special Unary: star (*)
public static boolean isUnary(String s) {
if (STAR.equals(s)) return true;
int i = s.indexOf('.');
if (i == -1) return false;
i = s.indexOf('.', i + 1);
if (i == -1) return true;
return false;
}
public static boolean isUnary(Value value) {
return value instanceof NameValue && isUnary((((NameValue) value).id));
}
// Binary: fb:domain.type.property [contains two periods]
// Also catch reversed binary shorthand [!fb:people.person.parent]
// Special Binaries: comparison (<, >, etc.) and colon (:)
public static boolean isBinary(String s) {
if (COMPARATORS.contains(s) || COLON.equals(s)) return true;
int i = s.indexOf('.');
if (i == -1) return false;
i = s.indexOf('.', i + 1);
if (i == -1) return false;
return true;
}
public static boolean isBinary(Value value) {
return value instanceof NameValue && isBinary((((NameValue) value).id));
}
// Return whether |property| is the name of a reverse property.
// Convention: ! is the prefix for reverses.
public static boolean isReverseProperty(String property) {
return property.startsWith("!") && !property.equals("!=");
}
public static String reverseProperty(String property) {
if (isReverseProperty(property)) return property.substring(1);
else return "!" + property;
public static boolean isReverseProperty(Value value) {
return value instanceof NameValue && isReverseProperty(((NameValue) value).id);
}
// Return the reverse property as a String
public static String reverseProperty(String property) {
if (COMPARATORS.contains(property))
return COMPARATOR_REVERSE.get(property);
if (isReverseProperty(property))
return property.substring(1);
else return "!" + property;
}
public static NameValue reverseProperty(Value value) {
if (!(value instanceof NameValue))
throw new RuntimeException("Cannot call reverseProperty on " + value);
return new NameValue(reverseProperty(((NameValue) value).id));
}
}

View File

@ -0,0 +1,78 @@
package edu.stanford.nlp.sempre;
import java.util.*;
import fig.basic.*;
/**
* Given the maximum formula size in a floating grammar, compute the maximum size
* that each floating grammar category can have.
*
* For example, if the grammar looks like this:
* $ROOT -> $A | $A $B
* $A -> $C $A
* $B -> $C
* $C -> $D $B | nothing
* ...
* and the maximum formula size (for $ROOT) is 10, then the maximum formula sizes for
* $A, $B, $C and $D are 9, 9, 8, and 7, respectively.
*
* The bound is = maxFormulaSize - (shortest distance from $ROOT to cat)
*
* @author ppasupat
*/
public class CatSizeBound {
public static class Options {
@Option(gloss = "verbosity") public int verbose = 0;
}
public static Options opts = new Options();
private final int maxFormulaSize;
private final Map<String, Integer> bound = new HashMap<>();
public CatSizeBound(int maxFormulaSize, Grammar grammar) {
this(maxFormulaSize, grammar.getRules());
}
public CatSizeBound(int maxFormulaSize, List<Rule> rules) {
this.maxFormulaSize = maxFormulaSize;
if (!FloatingParser.opts.useSizeInsteadOfDepth) {
LogInfo.warnings("Currently CatSizeBound is usable only when useSizeInsteadOfDepth = true.");
return;
}
// Construct graph
Map<String, Set<String>> graph = new HashMap<>();
for (Rule rule : rules) {
if (!Rule.isCat(rule.lhs))
throw new RuntimeException("Non-cat found in LHS of rule " + rule);
for (String rhsCat : rule.rhs) {
if (Rule.isCat(rhsCat))
MapUtils.addToSet(graph, rule.lhs, rhsCat);
}
}
// Breadth first search
bound.put(Rule.rootCat, maxFormulaSize);
Queue<String> queue = new ArrayDeque<>();
queue.add(Rule.rootCat);
while (!queue.isEmpty()) {
String cat = queue.remove();
if (!graph.containsKey(cat)) continue;
for (String rhsCat : graph.get(cat)) {
if (bound.containsKey(rhsCat)) continue;
bound.put(rhsCat, bound.get(cat) - 1);
queue.add(rhsCat);
}
}
if (opts.verbose >= 1) {
LogInfo.begin_track("CatSizeBound: distances");
for (Map.Entry<String, Integer> entry : bound.entrySet())
LogInfo.logs("%25s : %2d", entry.getKey(), entry.getValue());
LogInfo.end_track();
}
}
public int getBound(String cat) {
return bound.getOrDefault(cat, maxFormulaSize);
}
}

View File

@ -22,7 +22,7 @@ public abstract class ChartParserState extends ParserState {
protected final Map<String, List<Derivation>>[][] chart;
// For visualizing how chart is filled
List<CatSpan> chartFillingList = new ArrayList<>();
protected List<CatSpan> chartFillingList = new ArrayList<>();
protected String[][] phrases; // the phrases in the example
@ -74,9 +74,11 @@ public abstract class ChartParserState extends ParserState {
}
}
void addToChart(Derivation deriv) {
protected void addToChart(Derivation deriv) {
if (parser.verbose(3)) LogInfo.logs("addToChart %s: %s", deriv.cat, deriv);
if (Parser.opts.pruneErrorValues && deriv.value instanceof ErrorValue) return;
List<Derivation> derivations = chart[deriv.start][deriv.end].get(deriv.cat);
if (chart[deriv.start][deriv.end].get(deriv.cat) == null)
chart[deriv.start][deriv.end].put(deriv.cat, derivations = new ArrayList<>());
@ -88,6 +90,10 @@ public abstract class ChartParserState extends ParserState {
}
}
public Map<String, List<Derivation>>[][] getChart() {
return chart;
}
// TODO(joberant): move to visualization utility class
public static class CatSpan {
@JsonProperty

View File

@ -0,0 +1,36 @@
package edu.stanford.nlp.sempre;
import java.util.List;
/**
* A group containing one or two lists of potential child derivations.
*
* The motivation is to group potential child derivations based on type compatibility.
* For example, when building (and __ __), considering all pairs of derivations
* is time-wasting since a lot of pairs don't type-check. We instead group
* derivations by type, and only apply the rule to the pairs that type-check.
*
* This idea also extends to one-argument rules. For example, for (sum ___),
* we should only look at child derivations with number type.
*
* During parsing, for each DerivationGroup:
* - For a one-argument rule (derivations2 == null):
* Apply the rule on all derivations in derivations1
* - For a two-argument rule (derivations2 != null):
* Apply the rule to all pairs (d1, d2) where d1 is in derivations1 and d2 is in derivations2
*
* @author ppasupat
*/
public class ChildDerivationsGroup {
public final List<Derivation> derivations1, derivations2;
public ChildDerivationsGroup(List<Derivation> derivations1) {
this.derivations1 = derivations1;
this.derivations2 = null;
}
public ChildDerivationsGroup(List<Derivation> derivations1, List<Derivation> derivations2) {
this.derivations1 = derivations1;
this.derivations2 = derivations2;
}
}

View File

@ -68,7 +68,7 @@ public class ContextValue extends Value {
}
public ContextValue(KnowledgeGraph graph) {
this(null, null, null, graph);
this(null, null, new ArrayList(), graph);
}
// Example:
@ -107,8 +107,11 @@ public class ContextValue extends Value {
tree.addChild(LispTree.proto.newList("user", user));
if (date != null)
tree.addChild(date.toLispTree());
// When logging examples, logging the entire graph takes too much screen space.
// I don't think that we ever deserialize a graph from a serialized context,
// so this should be fine.
if (graph != null)
tree.addChild(graph.toLispTree());
tree.addChild(graph.toShortLispTree());
for (Exchange e : exchanges)
tree.addChild(LispTree.proto.newList("exchange", e.toLispTree()));
return tree;

View File

@ -33,9 +33,14 @@ public class Dataset {
public double devFrac = 0;
@Option(gloss = "Used to randomly divide training examples")
public Random splitRandom = new Random(1);
@Option(gloss = "whether to split dev from train")
public boolean splitDevFromTrain = true;
@Option(gloss = "Only keep examples which have at most this number of tokens")
public int maxTokens = Integer.MAX_VALUE;
@Option(gloss = "Path to a knowledge graph that will be uploaded as global context")
public String globalGraphPath;
}
public static Options opts = new Options();
@ -44,8 +49,8 @@ public class Dataset {
private LinkedHashMap<String, List<Example>> allExamples = new LinkedHashMap<String, List<Example>>();
// General statistics about the examples.
private HashSet<String> tokenTypes = new HashSet<String>();
private StatFig numTokensFig = new StatFig(); // For each example, number of tokens
private final HashSet<String> tokenTypes = new HashSet<String>();
private final StatFig numTokensFig = new StatFig(); // For each example, number of tokens
public Set<String> groups() { return allExamples.keySet(); }
public List<Example> examples(String group) { return allExamples.get(group); }
@ -94,10 +99,22 @@ public class Dataset {
return;
}
}
readLispTreeFromPathPairs(pathPairs);
updateGlobalContext();
}
private void updateGlobalContext() {
if (opts.globalGraphPath != null) {
KnowledgeGraph graph = NaiveKnowledgeGraph.fromFile(opts.globalGraphPath);
for (String group : allExamples.keySet()) {
for (Example ex : allExamples.get(group)) {
ex.setContext(new ContextValue(graph));
}
}
}
}
private void readJsonFromPathPairs(List<Pair<String, String>> pathPairs) {
List<GroupInfo> groups = Lists.newArrayListWithCapacity(pathPairs.size());
for (Pair<String, String> pathPair : pathPairs) {
@ -123,7 +140,7 @@ public class Dataset {
allExamples.put(groupInfo.group, examples = new ArrayList<Example>());
readHelper(groupInfo.examples, maxExamples, examples, groupInfo.path);
}
splitDevFromTrain();
if (opts.splitDevFromTrain) splitDevFromTrain();
collectStats();
LogInfo.end_track();
@ -140,8 +157,16 @@ public class Dataset {
List<Example> trainExamples = new ArrayList<Example>();
allExamples.put("train", trainExamples);
List<Example> devExamples = allExamples.get("dev");
if (devExamples == null)
allExamples.put("dev", devExamples = new ArrayList<Example>());
if (devExamples == null) {
// Preserve order
LinkedHashMap<String, List<Example>> newAllExamples = new LinkedHashMap<>();
for (Map.Entry<String, List<Example>> entry : allExamples.entrySet()) {
newAllExamples.put(entry.getKey(), entry.getValue());
if (entry.getKey().equals("train"))
newAllExamples.put("dev", devExamples = new ArrayList<>());
}
allExamples = newAllExamples;
}
for (int i = 0; i < split1; i++)
trainExamples.add(origTrainExamples.get(perm[i]));
for (int i = split2; i < origTrainExamples.size(); i++)
@ -165,7 +190,7 @@ public class Dataset {
ex = new Example.Builder().withExample(ex).setId(id).createExample();
}
i++;
ex.preprocess(LanguageAnalyzer.getSingleton());
ex.preprocess();
// Skip example if too long
if (ex.numTokens() > opts.maxTokens) continue;
@ -190,7 +215,7 @@ public class Dataset {
allExamples.put(group, examples = new ArrayList<Example>());
readLispTreeHelper(path, maxExamples, examples);
}
splitDevFromTrain();
if (opts.splitDevFromTrain) splitDevFromTrain();
LogInfo.end_track();
}
@ -203,12 +228,14 @@ public class Dataset {
while (examples.size() < maxExamples && trees.hasNext()) {
// Format: (example (id ...) (utterance ...) (targetFormula ...) (targetValue ...))
LispTree tree = trees.next();
if (tree.children.size() < 2 && !"example".equals(tree.child(0).value))
if (tree.children.size() < 2 || !"example".equals(tree.child(0).value)) {
if ("metadata".equals(tree.child(0).value)) continue;
throw new RuntimeException("Invalid example: " + tree);
}
Example ex = Example.fromLispTree(tree, path + ":" + n); // Specify a default id if it doesn't exist
n++;
ex.preprocess(LanguageAnalyzer.getSingleton());
ex.preprocess();
// Skip example if too long
if (ex.numTokens() > opts.maxTokens) continue;
@ -231,7 +258,7 @@ public class Dataset {
LogInfo.end_track();
}
private static int getMaxExamplesForGroup(String group) {
public static int getMaxExamplesForGroup(String group) {
int maxExamples = Integer.MAX_VALUE;
for (Pair<String, Integer> maxPair : opts.maxExamples)
if (maxPair.getFirst().equals(group))

View File

@ -0,0 +1,64 @@
package edu.stanford.nlp.sempre;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Parse strings representing date ranges such as "20th century".
* The result has the form (and (< ...) (>= ...)).
*
* Currently only supports patterns like "1990's" and "1800s"
*
* @author ppasupat
*/
public class DateRangeFn extends SemanticFn {
@Override
public DerivationStream call(Example ex, Callable c) {
return new LazyDateRangeFnDerivs(ex, c);
}
public static class LazyDateRangeFnDerivs extends MultipleDerivationStream {
Example ex;
Callable c;
int index = 0;
List<Formula> formulas;
public LazyDateRangeFnDerivs(Example ex, Callable c) {
this.ex = ex;
this.c = c;
}
@Override
public Derivation createDerivation() {
if (formulas == null)
populateFormulas();
if (index >= formulas.size()) return null;
Formula formula = formulas.get(index++);
return new Derivation.Builder().withCallable(c)
.formula(formula).type(SemType.numberType).createDerivation();
}
private static final Pattern YEAR_RANGE = Pattern.compile("^(\\d+0+)\\s*'?s$");
// TODO: Handle more cases
private void populateFormulas() {
formulas = new ArrayList<>();
String query = c.childStringValue(0);
Matcher matcher = YEAR_RANGE.matcher(query);
if (!matcher.matches()) return;
int year = Integer.parseInt(matcher.group(1)), range = 10;
while (year % range == 0) {
// Put "<" before ">=" to keep the children of MergeFormula sorted
formulas.add(new MergeFormula(MergeFormula.Mode.and,
new JoinFormula(new ValueFormula<Value>(new NameValue("<")), new ValueFormula<>(new NumberValue(year + range))),
new JoinFormula(new ValueFormula<Value>(new NameValue(">=")), new ValueFormula<>(new NumberValue(year)))));
range *= 10;
}
}
}
}

View File

@ -80,6 +80,14 @@ public class DateValue extends Value {
return tree;
}
@Override public String sortString() { return "" + year + "/" + month + "/" + day; }
public String isoString() {
return "" + (year == -1 ? "xxxx" : String.format("%04d", year))
+ "-" + (month == -1 ? "xx" : String.format("%02d", month))
+ "-" + (day == -1 ? "xx" : String.format("%02d", day));
}
@Override public String pureString() { return isoString(); }
@Override public int hashCode() {
int hash = 0x7ed55d16;
hash = hash * 0xd3a2646c + year;

View File

@ -0,0 +1,161 @@
package edu.stanford.nlp.sempre;
import java.util.*;
import fig.basic.LispTree;
import fig.basic.Option;
/**
* Common pruning strategies that can be used in many semantic parsing tasks.
*
* @author ppasupat
*/
public class DefaultDerivationPruningComputer extends DerivationPruningComputer {
public static class Options {
@Option(gloss = "(for badSummarizerHead) allow count on sets of size 1")
public boolean allowCountOne = false;
}
public static Options opts = new Options();
public DefaultDerivationPruningComputer(DerivationPruner pruner) {
super(pruner);
}
public static final String atomic = "atomic";
public static final String emptyDenotation = "emptyDenotation";
public static final String nonLambdaError = "nonLambdaError";
public static final String tooManyValues = "tooManyValues";
public static final String doubleSummarizers = "doubleSummarizers";
public static final String multipleSuperlatives = "multipleSuperlatives";
public static final String sameMerge = "sameMerge";
public static final String mistypedMerge = "mistypedMerge";
public static final String unsortedMerge = "unsortedMerge";
public static final String badSummarizerHead = "badSummarizerHead";
@Override
public Collection<String> getAllStrategyNames() {
return Arrays.asList(
atomic,
emptyDenotation, nonLambdaError, tooManyValues,
doubleSummarizers, multipleSuperlatives,
sameMerge, mistypedMerge, unsortedMerge, badSummarizerHead);
}
@Override
public String isPruned(Derivation deriv) {
// atomic: Prune atomic formula at root.
// e.g., Prevent "Who was taller, Lincoln or Obama" --> fb:en.lincoln generated from lexicon without any computation
if (containsStrategy(atomic)) {
if (deriv.isRoot(ex.numTokens()) && deriv.formula instanceof ValueFormula)
return atomic;
}
// emptyDenotation: Prune if the denotation is empty
if (containsStrategy(emptyDenotation)) {
deriv.ensureExecuted(parser.executor, ex.context);
if (deriv.value instanceof ListValue && ((ListValue) deriv.value).values.isEmpty())
return emptyDenotation;
}
// nonLambdaError: Prune if the denotation is an error and the formula is not a partial formula
if (containsStrategy(nonLambdaError) && !isLambdaFormula(deriv.formula)) {
deriv.ensureExecuted(parser.executor, ex.context);
if (deriv.value instanceof ErrorValue)
return nonLambdaError;
}
// tooManyValues: Prune if the denotation has too many values (at $ROOT only)
if (containsStrategy(tooManyValues) && deriv.isRoot(ex.numTokens())) {
if (!(deriv.value instanceof ListValue) ||
((ListValue) deriv.value).values.size() > DerivationPruner.opts.maxNumValues)
return tooManyValues;
}
// doubleSummarizers: Prune when two summarizers (aggregate or superlative) are directly nested
// e.g., in (sum (avg ...)) and (min (argmax ...)), the outer operation is redundant
if (containsStrategy(doubleSummarizers)) {
Formula innerFormula = null;
if (deriv.formula instanceof SuperlativeFormula)
innerFormula = ((SuperlativeFormula) deriv.formula).head;
else if (deriv.formula instanceof AggregateFormula)
innerFormula = ((AggregateFormula) deriv.formula).child;
if (innerFormula != null &&
(innerFormula instanceof SuperlativeFormula || innerFormula instanceof AggregateFormula))
return doubleSummarizers;
}
// multipleSuperlatives: Prune when more than one superlatives are used
// (don't need to be adjacent)
if (containsStrategy(multipleSuperlatives)) {
List<LispTree> stack = new ArrayList<>();
int count = 0;
stack.add(deriv.formula.toLispTree());
while (!stack.isEmpty()) {
LispTree tree = stack.remove(stack.size() - 1);
if (tree.isLeaf()) {
if ("argmax".equals(tree.value) || "argmin".equals(tree.value)) {
count++;
if (count >= 2)
return multipleSuperlatives;
}
} else {
for (LispTree subtree : tree.children)
stack.add(subtree);
}
}
}
// sameMerge: Prune merge formulas with two identical children
if (containsStrategy(sameMerge) && deriv.formula instanceof MergeFormula) {
MergeFormula merge = (MergeFormula) deriv.formula;
if (merge.child1.equals(merge.child2))
return sameMerge;
}
// mistypedMerge: Prune merge formulas with children of different types
if (containsStrategy(mistypedMerge) && deriv.formula instanceof MergeFormula) {
MergeFormula merge = (MergeFormula) deriv.formula;
SemType type1 = TypeInference.inferType(merge.child1, true);
SemType type2 = TypeInference.inferType(merge.child2, true);
if (!type1.meet(type2).isValid())
return mistypedMerge;
}
// unsortedMerge: Prune merge formulas where the children's string forms are not lexicographically sorted.
// Will remove redundant (and Y X) when (and Y X) is already present.
if (containsStrategy(unsortedMerge) && deriv.formula instanceof MergeFormula) {
MergeFormula merge = (MergeFormula) deriv.formula;
String child1 = merge.child1.toString(), child2 = merge.child2.toString();
if (child1.compareTo(child2) >= 0)
return unsortedMerge;
}
// badSummarizerHead: Prune if the head of a superlative or a non-count aggregate
// is empty or is a single object
if (containsStrategy(badSummarizerHead)) {
Formula innerFormula = null;
boolean isCount = false;
if (deriv.formula instanceof SuperlativeFormula)
innerFormula = ((SuperlativeFormula) deriv.formula).head;
else if (deriv.formula instanceof AggregateFormula) {
innerFormula = ((AggregateFormula) deriv.formula).child;
if (((AggregateFormula) deriv.formula).mode == AggregateFormula.Mode.count)
isCount = true;
}
if (innerFormula != null) {
try {
TypeInference.inferType(innerFormula);
Value innerValue = parser.executor.execute(innerFormula, ex.context).value;
if (innerValue instanceof ListValue) {
int size = ((ListValue) innerValue).values.size();
if (size == 0 || (size == 1 && !(opts.allowCountOne && isCount)))
return badSummarizerHead;
}
} catch (Exception e) {
// TypeInference fails; probably because of free variables. No need to do anything.
}
}
}
return null;
}
// Helper function: return true if the result is clearly a binary
private boolean isLambdaFormula(Formula formula) {
if (formula instanceof LambdaFormula) return true;
if (formula instanceof ValueFormula &&
CanonicalNames.isBinary(((ValueFormula<?>) formula).value)) return true;
return false;
}
}

View File

@ -1,9 +1,9 @@
package edu.stanford.nlp.sempre;
import fig.basic.*;
import java.util.*;
import fig.basic.*;
/**
* A Derivation corresponds to the production of a (partial) logical form
* |formula| from a span of the utterance [start, end). Contains the formula and
@ -24,6 +24,14 @@ public class Derivation implements SemanticFn.Callable, HasScore {
public boolean showRules = false;
@Option(gloss = "When printing derivations, to show canonical utterance")
public boolean showUtterance = false;
@Option(gloss = "When printing derivations, show the category")
public boolean showCat = false;
@Option(gloss = "When executing, show formulae (for debugging)")
public boolean showExecutions = false;
@Option(gloss = "Pick the comparator used to sort derivations")
public String derivComparator = "ScoredDerivationComparator";
@Option(gloss = "bonus score for being all anchored")
public double anchoredBonus = 0.0;
}
public static Options opts = new Options();
@ -34,7 +42,28 @@ public class Derivation implements SemanticFn.Callable, HasScore {
public final String cat;
public final int start;
public final int end;
// Floating cell information
// TODO(yushi): make fields final
public String canonicalUtterance;
public boolean allAnchored = true;
private int[] numAnchors; // Number of times each token was anchored
/**
* Information for grammar induction.
* For each descendant derivation of the body, this class tracks where and what in the head it matches
* GrammarInfo.start, GrammarInfo.end refer to matching positions in the head, as opposed to the body
* @author sidaw
**/
public class GrammarInfo {
public boolean anchored = false;
public boolean matched = false;
public int start = -1, end = -1;
public Formula formula;
public List<Derivation> matches = new ArrayList<>();
}
public GrammarInfo grammarInfo = new GrammarInfo();
// If this derivation is composed of other derivations
public final Rule rule; // Which rule was used to produce this derivation? Set to nullRule if not.
@ -57,6 +86,15 @@ public class Derivation implements SemanticFn.Callable, HasScore {
// Information for scoring
private final FeatureVector localFeatureVector; // Features
double score = Double.NaN; // Weighted combination of features
double prob = Double.NaN; // Probability (normalized exp of score).
// Used during parsing (by FeatureExtractor, SemanticFn) to cache arbitrary
// computation across different sub-Derivations.
// Convention:
// - use the featureDomain, FeatureComputer or SemanticFn as the key.
// - the value is whatever the FeatureExtractor needs.
// This information should be set to null after parsing is done.
private Map<String, Object> tempState;
// What the formula evaluates to (optionally set later; only non-null for the root Derivation)
public Value value;
@ -64,8 +102,6 @@ public class Derivation implements SemanticFn.Callable, HasScore {
// Number in [0, 1] denoting how correct the value is.
public double compatibility = Double.NaN;
// Probability (normalized exp of score).
public double prob = Double.NaN;
// Miscellaneous statistics
int maxBeamPosition = -1; // Lowest position that this tree or any of its children is on the beam (after sorting)
@ -80,7 +116,9 @@ public class Derivation implements SemanticFn.Callable, HasScore {
// we can break ties consistently for reproducible results.
long creationIndex;
public static long numCreated = 0; // Incremented for each derivation we create.
public static final Comparator<Derivation> derivScoreComparator = new ScoredDerivationComparator();
@SuppressWarnings("unchecked")
public static final Comparator<Derivation> derivScoreComparator =
(Comparator<Derivation>)Utils.newInstanceHard(SempreUtils.resolveClassName("Derivation$" + opts.derivComparator));
public static final List<Derivation> emptyList = Collections.emptyList();
@ -138,15 +176,35 @@ public class Derivation implements SemanticFn.Callable, HasScore {
return this;
}
public Builder withAllFrom(Derivation deriv) {
this.cat = deriv.cat;
this.start = deriv.start;
this.end = deriv.end;
this.rule = deriv.rule;
this.children = deriv.children == null ? null : new ArrayList<>(deriv.children);
this.formula = deriv.formula;
this.type = deriv.type;
this.localFeatureVector = deriv.localFeatureVector;
this.score = deriv.score;
this.value = deriv.value;
this.executorStats = deriv.executorStats;
this.compatibility = deriv.compatibility;
this.prob = deriv.prob;
this.canonicalUtterance = deriv.canonicalUtterance;
return this;
}
public Derivation createDerivation() {
return new Derivation(
cat, start, end, rule, children, formula, type,
localFeatureVector, score, value, executorStats, compatibility, prob, canonicalUtterance);
localFeatureVector, score, value, executorStats, compatibility, prob,
canonicalUtterance);
}
}
Derivation(String cat, int start, int end, Rule rule, List<Derivation> children, Formula formula, SemType type,
FeatureVector localFeatureVector, double score, Value value, Evaluation executorStats, double compatibility, double prob, String canonicalUtterance) {
FeatureVector localFeatureVector, double score, Value value, Evaluation executorStats, double compatibility, double prob,
String canonicalUtterance) {
this.cat = cat;
this.start = start;
this.end = end;
@ -180,6 +238,7 @@ public class Derivation implements SemanticFn.Callable, HasScore {
public boolean containsIndex(int i) { return i < end && i >= start; }
public Rule getRule() { return rule; }
public Evaluation getExecutorStats() { return executorStats; }
public FeatureVector getLocalFeatureVector() { return localFeatureVector; }
public Derivation child(int i) { return children.get(i); }
public String childStringValue(int i) {
@ -191,6 +250,11 @@ public class Derivation implements SemanticFn.Callable, HasScore {
return cat.equals(Rule.rootCat) && ((start == 0 && end == numTokens) || (start == -1));
}
// Return whether |deriv| has root category (for floating parser)
public boolean isRootCat() {
return cat.equals(Rule.rootCat);
}
// Functions that operate on features.
public void addFeature(String domain, String name) { addFeature(domain, name, 1); }
public void addFeature(String domain, String name, double value) { this.localFeatureVector.add(domain, name, value); }
@ -202,7 +266,12 @@ public class Derivation implements SemanticFn.Callable, HasScore {
public void addFeatures(FeatureVector fv) { this.localFeatureVector.add(fv); }
public double localScore(Params params) {
return localFeatureVector.dotProduct(params);
return localFeatureVector.dotProduct(params) + (this.allAnchored()? opts.anchoredBonus : 0.0);
}
// SHOULD NOT BE USED except during test time if the memory is desperately needed.
public void clearFeatures() {
localFeatureVector.clear();
}
/**
@ -234,6 +303,8 @@ public class Derivation implements SemanticFn.Callable, HasScore {
public void ensureExecuted(Executor executor, ContextValue context) {
if (isExecuted()) return;
StopWatchSet.begin("Executor.execute");
if (opts.showExecutions)
LogInfo.logs("%s - %s", canonicalUtterance, formula);
Executor.Response response = executor.execute(formula, context);
StopWatchSet.end();
value = response.value;
@ -266,6 +337,9 @@ public class Derivation implements SemanticFn.Callable, HasScore {
if (opts.showUtterance && canonicalUtterance != null) {
tree.addChild(LispTree.proto.newList("canonicalUtterance", canonicalUtterance));
}
if (opts.showCat && cat != null) {
tree.addChild(LispTree.proto.newList("cat", cat));
}
return tree;
}
@ -304,7 +378,7 @@ public class Derivation implements SemanticFn.Callable, HasScore {
}
public String startEndString(List<String> tokens) {
return start + ":" + end + tokens.subList(start, end);
return start + ":" + end + (start == -1 ? "" : tokens.subList(start, end));
}
public String toString() { return toLispTree().toString(); }
@ -319,8 +393,13 @@ public class Derivation implements SemanticFn.Callable, HasScore {
for (Derivation child : children)
child.incrementAllFeatureVector(factor, map, updateFeatureMatcher);
}
public void incrementAllFeatureVector(double factor, FeatureVector fv) {
localFeatureVector.add(factor, fv);
for (Derivation child : children)
child.incrementAllFeatureVector(factor, fv);
}
// recursively renames all features in derivation by adding a prefix
// returns feature vector with renamed features by prefix
public FeatureVector addPrefixLocalFeatureVector(String prefix) {
return localFeatureVector.addPrefix(prefix);
}
@ -381,6 +460,25 @@ public class Derivation implements SemanticFn.Callable, HasScore {
}
}
//Used to compare derivations by score, prioritizing the fully anchored.
public static class AnchorPriorityScoreComparator implements Comparator<Derivation> {
@Override
public int compare(Derivation deriv1, Derivation deriv2) {
boolean deriv1Core = deriv1.allAnchored();
boolean deriv2Core = deriv2.allAnchored();
if (deriv1Core && !deriv2Core) return -1;
if (deriv2Core && !deriv1Core) return +1;
if (deriv1.score > deriv2.score) return -1;
if (deriv1.score < deriv2.score) return +1;
// Ensure reproducible randomness
if (deriv1.creationIndex < deriv2.creationIndex) return -1;
if (deriv1.creationIndex > deriv2.creationIndex) return +1;
return 0;
}
}
// for debugging
public void printDerivationRecursively() {
LogInfo.logs("Deriv: %s(%s,%s) %s", cat, start, end, formula);
@ -404,4 +502,78 @@ public class Derivation implements SemanticFn.Callable, HasScore {
NumUtils.expNormalize(probs);
return probs;
}
// Manipulation of temporary state used during parsing.
public Map<String, Object> getTempState() {
// Create the tempState if it doesn't exist.
if (tempState == null)
tempState = new HashMap<String, Object>();
return tempState;
}
public void clearTempState() {
tempState = null;
if (children != null)
for (Derivation child : children)
child.clearTempState();
}
/**
* Return an int array numAnchors where numAnchors[i] is
* the number of times we anchored on token i.
*
* numAnchors[>= numAnchors.length] are 0 by default.
*/
public int[] getNumAnchors() {
if (numAnchors == null) {
if (rule.isAnchored()) {
numAnchors = new int[end];
for (int i = start; i < end; i++) numAnchors[i] = 1;
} else {
numAnchors = new int[0];
for (Derivation child : children) {
int[] childNumAnchors = child.getNumAnchors();
if (numAnchors.length < childNumAnchors.length) {
int[] newNumAnchors = new int[childNumAnchors.length];
for (int i = 0; i < numAnchors.length; i++)
newNumAnchors[i] = numAnchors[i];
numAnchors = newNumAnchors;
}
for (int i = 0; i < childNumAnchors.length; i++)
numAnchors[i] += childNumAnchors[i];
}
}
}
return numAnchors;
}
/**
* Return a boolean array anchoredTokens where anchoredTokens[i]
* indicates whether we have anchored on token i.
*
* anchoredTokens[>= anchoredTokens.length] are False by default
*/
public boolean[] getAnchoredTokens() {
int[] numAnchors = getNumAnchors();
boolean[] anchoredTokens = new boolean[numAnchors.length];
for (int i = 0; i < numAnchors.length; i++)
anchoredTokens[i] = (numAnchors[i] > 0);
return anchoredTokens;
}
public Derivation betaReduction() {
Formula reduced = Formulas.betaReduction(formula);
return new Builder().withAllFrom(this).formula(reduced).createDerivation();
}
public boolean allAnchored() {
if (rule.isInduced() || !this.allAnchored) {
this.allAnchored = false;
return false;
} else {
for (Derivation child : children) {
if (child.allAnchored() == false) return false;
}
return true;
}
}
}

View File

@ -0,0 +1,111 @@
package edu.stanford.nlp.sempre;
import java.util.*;
import fig.basic.*;
/**
* Prune derivations during parsing.
*
* To add custom pruning criteria, implement a DerivationPruningComputer class,
* and put the class name in the |pruningComputers| option.
*
* @author ppasupat
*/
public class DerivationPruner {
public static class Options {
@Option(gloss = "Pruning strategies to use")
public List<String> pruningStrategies = new ArrayList<>();
@Option(gloss = "DerivationPruningComputer subclasses to look for pruning strategies")
public List<String> pruningComputers = new ArrayList<>();
@Option public int pruningVerbosity = 0;
@Option(gloss = "(for tooManyValues) maximum denotation size of the final formula")
public int maxNumValues = 10;
}
public static Options opts = new Options();
public final Parser parser;
public final Example ex;
private List<DerivationPruningComputer> pruningComputers = new ArrayList<>();
// If not null, limit the pruning strategies to this list in addition to opts.pruningStrategies.
private List<String> customAllowedPruningStrategies;
private final Set<String> allStrategyNames;
public DerivationPruner(ParserState parserState) {
this.parser = parserState.parser;
this.ex = parserState.ex;
this.pruningComputers.add(new DefaultDerivationPruningComputer(this));
for (String pruningComputer : opts.pruningComputers) {
try {
Class<?> pruningComputerClass = Class.forName(SempreUtils.resolveClassName(pruningComputer));
pruningComputers.add((DerivationPruningComputer) pruningComputerClass.getConstructor(this.getClass()).newInstance(this));
} catch (ClassNotFoundException e1) {
throw new RuntimeException("Illegal pruning computer: " + pruningComputer);
} catch (Exception e) {
e.printStackTrace();
e.getCause().printStackTrace();
throw new RuntimeException("Error while instantiating pruning computer: " + pruningComputer);
}
}
// Compile the list of all strategies
allStrategyNames = new HashSet<>();
for (DerivationPruningComputer computer : pruningComputers)
allStrategyNames.addAll(computer.getAllStrategyNames());
for (String strategy : opts.pruningStrategies) {
if (!allStrategyNames.contains(strategy))
LogInfo.fails("Pruning strategy '%s' not found!", strategy);
}
}
/**
* Set additional restrictions on the pruning strategies.
*
* If customAllowedPruningStrategies is not null, the pruning strategy must be in both
* opts.pruningStrategies and customAllowedPruningStrategies in order to be used.
*
* Useful when some pruning strategies can break the parsing mechanism.
*/
public void setCustomAllowedPruningStrategies(List<String> customAllowedPruningStrategies) {
this.customAllowedPruningStrategies = customAllowedPruningStrategies;
}
protected boolean containsStrategy(String name) {
return opts.pruningStrategies.contains(name) &&
(customAllowedPruningStrategies == null || customAllowedPruningStrategies.contains(name));
}
public List<DerivationPruningComputer> getPruningComputers() {
return new ArrayList<>(pruningComputers);
}
/**
* Return true if the derivation should be pruned. Otherwise, return false.
*/
public boolean isPruned(Derivation deriv) {
if (opts.pruningStrategies.isEmpty() && pruningComputers.isEmpty()) return false;
String matchedStrategy;
for (DerivationPruningComputer computer : pruningComputers) {
if ((matchedStrategy = computer.isPruned(deriv)) != null) {
if (opts.pruningVerbosity >= 2)
LogInfo.logs("PRUNED [%s] %s", matchedStrategy, deriv.formula);
return true;
}
}
return false;
}
/**
* Run isPruned with a (temporary) custom set of allowed pruning strategies.
* If customAllowedPruningStrategies is null, all strategies are allowed.
* If customAllowedPruningStrategies is empty, no pruning happens.
*/
public boolean isPruned(Derivation deriv, List<String> customAllowedPruningStategies) {
List<String> old = this.customAllowedPruningStrategies;
this.customAllowedPruningStrategies = customAllowedPruningStategies;
boolean answer = isPruned(deriv);
this.customAllowedPruningStrategies = old;
return answer;
}
}

View File

@ -0,0 +1,43 @@
package edu.stanford.nlp.sempre;
import java.util.Collection;
/**
* Used to prune formulas during parsing.
*
* Extend this class to add custom pruning criteria,
* then add the class name to the |pruningComputers| options of DerivationPruner.
*
* @author ppasupat
*/
public abstract class DerivationPruningComputer {
protected final DerivationPruner pruner;
protected final Parser parser;
protected final Example ex;
public DerivationPruningComputer(DerivationPruner pruner) {
this.pruner = pruner;
this.parser = pruner.parser;
this.ex = pruner.ex;
}
/**
* Return a collection of all strategy names used in this class.
*/
abstract public Collection<String> getAllStrategyNames();
// Shorthand
protected boolean containsStrategy(String name) {
return pruner.containsStrategy(name);
}
/**
* Prune the derivation.
*
* To add pruning strategies, override this method.
* Return the strategy name to prune the formula, and null otherwise.
*/
public abstract String isPruned(Derivation deriv);
}

View File

@ -10,9 +10,7 @@ import fig.basic.Evaluation;
import fig.basic.LispTree;
import fig.basic.LogInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.*;
/**
* An example corresponds roughly to an input-output pair, the basic unit which
@ -38,16 +36,20 @@ public class Example {
// What we should try to predict.
@JsonProperty public Formula targetFormula; // Logical form (e.g., database query)
@JsonProperty public Value targetValue; // Denotation (e.g., answer)
public List<Formula> alternativeFormulas; // Alternative logical form (less canonical)
@JsonProperty public Value targetValue; // Denotation (e.g., answer)
//// Information after preprocessing (e.g., tokenization, POS tagging, NER, syntactic parsing, etc.).
@JsonProperty public LanguageInfo languageInfo = null;
public LanguageInfo languageInfo = null;
//// Output of the parser.
// Predicted derivations (sorted by score).
public List<Derivation> predDerivations;
// Temporary state while parsing an Example (see Derivation.java for analogous structure).
private Map<String, Object> tempState;
// Statistics relating to processing the example.
public Evaluation evaluation;
@ -57,7 +59,6 @@ public class Example {
private ContextValue context;
private Formula targetFormula;
private Value targetValue;
private List<Derivation> predDerivations;
private LanguageInfo languageInfo;
public Builder setId(String id) { this.id = id; return this; }
@ -102,6 +103,12 @@ public class Example {
public void setContext(ContextValue context) { this.context = context; }
public void setTargetFormula(Formula targetFormula) { this.targetFormula = targetFormula; }
public void setAlternativeFormulas(List<Formula> alternativeFormulas) { this.alternativeFormulas = alternativeFormulas; }
public void addAlternativeFormula(Formula alternativeFormula) {
if (this.alternativeFormulas == null)
this.alternativeFormulas = new ArrayList<>();
this.alternativeFormulas.add(alternativeFormula);
}
public void setTargetValue(Value targetValue) { this.targetValue = targetValue; }
public String spanString(int start, int end) {
@ -133,6 +140,8 @@ public class Example {
b.setId(arg.child(1).value);
} else if ("utterance".equals(label)) {
b.setUtterance(arg.child(1).value);
} else if ("canonicalUtterance".equals(label)) {
b.setUtterance(arg.child(1).value);
} else if ("targetFormula".equals(label)) {
b.setTargetFormula(Formulas.fromLispTree(arg.child(1)));
} else if ("targetValue".equals(label) || "targetValues".equals(label)) {
@ -150,19 +159,36 @@ public class Example {
for (int i = 1; i < tree.children.size(); i++) {
LispTree arg = tree.child(i);
String label = arg.child(0).value;
if ("posTags".equals(label) || "nerTags".equals(label) || "url".equals(label)) {
// Do nothing
} else if ("tokens".equals(label)) {
int n = arg.child(1).children.size();
for (int j = 0; j < n; j++)
ex.languageInfo.tokens.add(arg.child(1).child(j).value);
if ("tokens".equals(label)) {
for (LispTree child : arg.child(1).children)
ex.languageInfo.tokens.add(child.value);
} else if ("lemmaTokens".equals(label)) {
for (LispTree child : arg.child(1).children)
ex.languageInfo.lemmaTokens.add(child.value);
} else if ("posTags".equals(label)) {
for (LispTree child : arg.child(1).children)
ex.languageInfo.posTags.add(child.value);
} else if ("nerTags".equals(label)) {
for (LispTree child : arg.child(1).children)
ex.languageInfo.nerTags.add(child.value);
} else if ("nerValues".equals(label)) {
for (LispTree child : arg.child(1).children)
ex.languageInfo.nerValues.add("null".equals(child.value) ? null : child.value);
} else if ("alternativeFormula".equals(label)) {
ex.addAlternativeFormula(Formulas.fromLispTree(arg.child(1)));
} else if ("evaluation".equals(label)) {
ex.evaluation = Evaluation.fromLispTree(arg.child(1));
} else if ("predDerivations".equals(label)) {
// Featurized
ex.predDerivations = new ArrayList<>();
for (int j = 1; j < arg.children.size(); j++)
ex.predDerivations.add(derivationFromLispTree(arg.child(j)));
} else if (!Sets.newHashSet("id", "utterance", "targetFormula", "targetValue", "targetValues", "context").contains(label)) {
} else if ("rawDerivations".equals(label) || "derivations".equals(label)) {
// Unfeaturized
ex.predDerivations = new ArrayList<>();
for (int j = 1; j < arg.children.size(); j++)
ex.predDerivations.add(rawDerivationFromLispTree(arg.child(j)));
} else if (!Sets.newHashSet("id", "utterance", "targetFormula", "targetValue", "targetValues", "context", "original").contains(label)) {
throw new RuntimeException("Invalid example argument: " + arg);
}
}
@ -170,8 +196,9 @@ public class Example {
return ex;
}
public void preprocess(LanguageAnalyzer analyzer) {
this.languageInfo = analyzer.analyze(this.utterance);
public void preprocess() {
this.languageInfo = LanguageAnalyzer.getSingleton().analyze(this.utterance);
this.targetValue = TargetValuePreprocessor.getSingleton().preprocess(this.targetValue, this);
}
public void log() {
@ -191,9 +218,19 @@ public class Example {
LogInfo.end_track();
}
// To save memory
public void clearPredDerivations() {
predDerivations.clear();
public void logWithoutContext() {
LogInfo.begin_track("Example: %s", utterance);
LogInfo.logs("Tokens: %s", getTokens());
LogInfo.logs("Lemmatized tokens: %s", getLemmaTokens());
LogInfo.logs("POS tags: %s", languageInfo.posTags);
LogInfo.logs("NER tags: %s", languageInfo.nerTags);
LogInfo.logs("NER values: %s", languageInfo.nerValues);
if (targetFormula != null)
LogInfo.logs("targetFormula: %s", targetFormula);
if (targetValue != null)
LogInfo.logs("targetValue: %s", targetValue);
LogInfo.logs("Dependency children: %s", languageInfo.dependencyChildren);
LogInfo.end_track();
}
public List<Derivation> getCorrectDerivations() {
@ -243,7 +280,14 @@ public class Example {
return tree;
}
private static Derivation derivationFromLispTree(LispTree item) {
/**
* Parse a featurized derivation.
*
* Format:
* ({compatibility} {prob} {score} {value|null} {formula} {features})
* where {features} = (({key} {value}) ({key} {value}) ...)
*/
public static Derivation derivationFromLispTree(LispTree item) {
Derivation.Builder b = new Derivation.Builder()
.cat(Rule.rootCat)
.start(-1)
@ -272,7 +316,7 @@ public class Example {
return b.createDerivation();
}
private static LispTree derivationToLispTree(Derivation deriv) {
public static LispTree derivationToLispTree(Derivation deriv) {
LispTree item = LispTree.proto.newList();
item.addChild(deriv.compatibility + "");
@ -290,4 +334,61 @@ public class Example {
return item;
}
/**
* Parse a LispTree with the format created by deriv.toLispTree().
* Due to the complexity, rules and children are not parsed.
*
* Format:
* (derivation [(formula {formula})] [(value {value})] [(type {type})]
* [(canonicalUtterance {canonicalUtterance})])
* @param item
* @return
*/
public static Derivation rawDerivationFromLispTree(LispTree item) {
Derivation.Builder b = new Derivation.Builder()
.cat(Rule.rootCat)
.start(-1).end(-1)
.rule(Rule.nullRule)
.children(new ArrayList<Derivation>());
for (int i = 1; i < item.children.size(); i++) {
LispTree arg = item.child(i);
String label = arg.child(0).value;
if ("formula".equals(label)) {
b.formula(Formulas.fromLispTree(arg.child(1)));
} else if ("value".equals(label)) {
b.value(Values.fromLispTree(arg.child(1)));
} else if ("type".equals(label)) {
b.type(SemType.fromLispTree(arg.child(1)));
} else if ("canonicalUtterance".equals(label)) {
b.canonicalUtterance(arg.child(1).value);
} else {
throw new RuntimeException("Invalid example argument: " + arg);
}
}
return b.createDerivation();
}
public static LispTree rawDerivationToLispTree(Derivation deriv) {
return deriv.toLispTree();
}
public Map<String, Object> getTempState() {
// Create the tempState if it doesn't exist.
if (tempState == null)
tempState = new HashMap<String, Object>();
return tempState;
}
public void clearTempState() {
tempState = null;
}
/**
* Clean up things to save memory
*/
public void clean() {
predDerivations.clear();
if (context.graph != null)
context.graph.clean();
}
}

View File

@ -22,6 +22,18 @@ public final class ExampleUtils {
out.close();
}
public static void writeJson(List<Example> examples, String outPath) throws IOException {
PrintWriter out = IOUtils.openOutHard(outPath);
out.println("[");
for (int i = 0; i < examples.size(); ++i) {
Example ex = examples.get(i);
out.print(ex.toJson());
out.println(i < examples.size() - 1 ? "," : "");
}
out.println("]");
out.close();
}
private static String escapeSpace(String s) {
return s.replaceAll(" ", "&nbsp;");
}
@ -38,6 +50,7 @@ public final class ExampleUtils {
PrintWriter out = IOUtils.openOutHard(outPath);
LispTree p = LispTree.proto;
out.println("# SDF version 1.1");
out.println("# " + p.L(p.L("iter", iter), p.L("group", group), p.L("numExamples", examples.size()), p.L("evaluation", evaluation.toLispTree())));
for (Example ex : examples) {
out.println("");
@ -47,11 +60,22 @@ public final class ExampleUtils {
if (outputPredDerivations) {
for (Derivation deriv : ex.predDerivations) {
StringBuilder buf = new StringBuilder();
buf.append("item " + escapeSpace(p.L(p.L("formula", deriv.formula.toLispTree()), p.L("value", deriv.value.toLispTree())).toString())); // Description
buf.append(" " + deriv.compatibility);
buf.append("item");
LispTree description = p.newList();
if (deriv.canonicalUtterance != null)
description.addChild(p.L("canonicalUtterance", deriv.canonicalUtterance));
description.addChild(p.L("formula", deriv.formula.toLispTree()));
description.addChild(p.L("value", deriv.value.toLispTree()));
buf.append("\t" + description);
buf.append("\t" + deriv.compatibility);
Map<String, Double> features = deriv.getAllFeatureVector();
buf.append("\t");
boolean first = true;
for (Map.Entry<String, Double> e : features.entrySet()) {
buf.append(" " + escapeSpace(e.getKey()) + ":" + e.getValue());
if (!first)
buf.append(' ');
first = false;
buf.append(e.getKey() + ":" + e.getValue());
}
out.println(buf.toString());
}
@ -60,4 +84,76 @@ public final class ExampleUtils {
out.close();
LogInfo.end_track();
}
public static void writeParaphraseSDF(int iter, String group, Example ex,
boolean outputPredDerivations) {
String basePath = "preds-iter" + iter + "-" + group + ".examples";
String outPath = Execution.getFile(basePath);
if (outPath == null) return;
PrintWriter out = IOUtils.openOutAppendHard(outPath);
out.println("example " + ex.id);
if (outputPredDerivations) {
int i = 0;
for (Derivation deriv : ex.predDerivations) {
if (deriv.canonicalUtterance != null)
out.println("Pred@" + i + ":\t" + ex.utterance + "\t" + deriv.canonicalUtterance + "\t" + deriv.compatibility + "\t" + deriv.formula + "\t" + deriv.prob);
i++;
}
}
out.close();
}
public static void writeEvaluationSDF(int iter, String group,
Evaluation evaluation, int numExamples) {
String basePath = "preds-iter" + iter + "-" + group + ".examples";
String outPath = Execution.getFile(basePath);
if (outPath == null) return;
PrintWriter out = IOUtils.openOutAppendHard(outPath);
LispTree p = LispTree.proto;
out.println("");
out.println("# SDF version 1.1");
out.println("# " + p.L(p.L("iter", iter), p.L("group", group), p.L("numExamples", numExamples), p.L("evaluation", evaluation.toLispTree())));
out.close();
}
public static void writePredictionTSV(int iter, String group, Example ex) {
String basePath = "preds-iter" + iter + "-" + group + ".tsv";
String outPath = Execution.getFile(basePath);
if (outPath == null) return;
PrintWriter out = IOUtils.openOutAppendHard(outPath);
List<String> fields = new ArrayList<>();
fields.add(ex.id);
if (!ex.predDerivations.isEmpty()) {
Derivation deriv = ex.predDerivations.get(0);
if (deriv.value instanceof ListValue) {
List<Value> values = ((ListValue) deriv.value).values;
for (Value v : values) {
fields.add(v.pureString().replaceAll("\\s+", " ").trim());
}
}
}
out.println(String.join("\t", fields));
out.close();
}
//read lisptree and write json
public static void main(String[] args) {
Dataset dataset = new Dataset();
Pair<String, String> pair = Pair.newPair("train", args[0]);
Dataset.opts.splitDevFromTrain = false;
dataset.readFromPathPairs(Collections.singletonList(pair));
List<Example> examples = dataset.examples("train");
try {
writeJson(examples, args[1]);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

View File

@ -1,10 +1,11 @@
package edu.stanford.nlp.sempre;
import java.util.*;
import com.google.common.base.Joiner;
import com.google.common.collect.Sets;
import fig.basic.*;
import java.util.*;
/**
* A FeatureExtractor specifies a mapping from derivations to feature vectors.
*
@ -34,6 +35,8 @@ public class FeatureExtractor {
public boolean useAllFeatures = false;
@Option(gloss = "For bigram features in paraphrased utterances, maximum distance to consider")
public int maxBigramDistance = 3;
@Option(gloss = "Whether or not paraphrasing and bigram features should be lexicalized")
public boolean lexicalBigramParaphrase = true;
}
private Executor executor;
@ -63,7 +66,6 @@ public class FeatureExtractor {
extractDependencyFeatures(ex, deriv);
extractWhTypeFeatures(ex, deriv);
conjoinLemmaAndBinary(ex, deriv);
extractParaphraseFeatures(ex, deriv);
extractBigramFeatures(ex, deriv);
for (FeatureComputer featureComputer : featureComputers)
featureComputer.extractLocal(ex, deriv);
@ -100,21 +102,24 @@ public class FeatureExtractor {
return;
}
if (deriv.value instanceof StringValue) {
if (((StringValue) deriv.value).value.equals("[]") || ((StringValue) deriv.value).value.equals("[null]"))
deriv.addFeature("denotation", "empty");
return;
}
if (deriv.value instanceof ListValue) {
ListValue list = (ListValue) deriv.value;
// TODO(pliang): this is hacky; don't depend on the logical form
if (Formulas.isCountFormula(deriv.formula)) {
if (list.values.size() != 1) {
deriv.addFeature("denotation", "size", list.values.size());
} else {
int count = getNumber(list.values.get(0));
deriv.addFeature("denotation", "count-size" + (count == 0 ? "=0" : ">0"));
}
} else {
if (list.values.size() == 1 && list.values.get(0) instanceof NumberValue) {
int count = getNumber(list.values.get(0));
deriv.addFeature("denotation", "count-size" + (count <= 1 ? "=" + count : ">1"));
}
else {
int size = list.values.size();
deriv.addFeature("denotation", "size" + (size < 3 ? "=" + size : ">=" + 3));
}
}
}
@ -137,11 +142,11 @@ public class FeatureExtractor {
String containment = deriv.containsIndex(dependency.modifier) ? "internal" : "external";
if (containsDomain("fullDependencyParse"))
addAllDependencyFeatures(dependency, direction, containment,
deriv);
deriv);
else
deriv.addFeature("dependencyParse",
"(" + dependency.label + " " + direction + " " + containment + ") --- "
+ deriv.getRule().toString());
"(" + dependency.label + " " + direction + " " + containment + ") --- "
+ deriv.getRule().toString());
}
}
}
@ -150,7 +155,7 @@ public class FeatureExtractor {
}
private void addAllDependencyFeatures(LanguageInfo.DependencyEdge dependency,
String direction, String containment, Derivation deriv) {
String direction, String containment, Derivation deriv) {
String[] types = {dependency.label, "*"};
String[] directions = {" " + direction, ""};
String[] containments = {" " + containment, ""};
@ -160,7 +165,7 @@ public class FeatureExtractor {
for (String containmentPresent : containments) {
for (String rulePresent : rules) {
deriv.addFeature("fullDependencyParse",
"(" + typePresent + directionPresent + containmentPresent + ") --- " + rulePresent);
"(" + typePresent + directionPresent + containmentPresent + ") --- " + rulePresent);
}
}
}
@ -175,8 +180,8 @@ public class FeatureExtractor {
if (ex.posTag(0).startsWith("W")) {
deriv.addFeature("whType",
"token0=" + ex.token(0) + "," +
"type=" + coarseType(deriv.type.toString()));
"token0=" + ex.token(0) + "," +
"type=" + coarseType(deriv.type.toString()));
}
}
@ -206,10 +211,12 @@ public class FeatureExtractor {
List<String> nonEntityLemmas = new LinkedList<>();
extractNonEntityLemmas(ex, deriv, nonEntityLemmas);
List<String> binaries = extractBinaries(deriv.formula);
String binariesStr = Joiner.on('_').join(binaries);
for (String nonEntityLemma : nonEntityLemmas) {
deriv.addFeature("lemmaAndBinaries", "nonEntitylemmas=" + nonEntityLemma +
",binaries=" + binariesStr);
if (!binaries.isEmpty()) {
String binariesStr = Joiner.on('_').join(binaries);
for (String nonEntityLemma : nonEntityLemmas) {
deriv.addFeature("lemmaAndBinaries", "nonEntitylemmas=" + nonEntityLemma +
",binaries=" + binariesStr);
}
}
}
@ -229,7 +236,7 @@ public class FeatureExtractor {
//Used in Berant et., EMNLP 2013, and in the agenda RL parser
//Extracts all content-word lemmas in the derivation tree not dominated by the category $Entity
private void extractNonEntityLemmas(Example ex, Derivation deriv,
List<String> nonEntityLemmas) {
List<String> nonEntityLemmas) {
if (deriv.children.size() == 0) { // base case this means it is a word that should be appended
for (int i = deriv.start; i < deriv.end; i++) {
String pos = ex.languageInfo.posTags.get(i);
@ -259,31 +266,6 @@ public class FeatureExtractor {
return res;
}
/**
* Add an indicator for each token alignment between a token in the utterance and its
* canonical form in the grammar using the ParaphraseModel, if applicable.
*/
// Compute paraphrasing features. In the future, need to store temporary
// state to make this more efficient.
void extractParaphraseFeatures(Example ex, Derivation deriv) {
if (!containsDomain("paraphrasing")) return;
if (deriv.rule == Rule.nullRule) return;
extractParaphrasePrecision(ex, deriv);
extractParaphraseRecall(ex, deriv);
// Make sure we have a valid, floating, paraphraseable rule
if (!deriv.rule.isFloating() || !deriv.rule.isRhsTerminals()) return;
String key = join(deriv.rule.rhs, " ");
ParaphraseModel model = ParaphraseModel.getSingleton();
if (!model.containsKey(key)) return;
for (String token : ex.getTokens()) {
double score = model.get(key, token);
if (score > 0.0) {
deriv.addFeature("paraphrasing", "(" + key + ", " + token + ")");
}
}
}
/**
* Add an indicator for each pair of bigrams that can be aligned from the original
* utterance and two (not necessarily contiguous) lemmas in the generated utterance
@ -294,45 +276,26 @@ public class FeatureExtractor {
LanguageInfo derivInfo = LanguageAnalyzer.getSingleton().analyze(deriv.canonicalUtterance);
List<String> derivLemmas = derivInfo.lemmaTokens;
List<String> exLemmas = ex.languageInfo.lemmaTokens;
Map<Integer, Integer> bigramCounts = new HashMap<Integer, Integer>();
for (int i = 0; i < exLemmas.size() - 1; i++) {
for (int j = 0; j < derivLemmas.size() - 1; j++) {
if (derivLemmas.get(j).equals(exLemmas.get(i))) {
// Consider bigrams separated by up to maxBigramDistance in generated utterance
for (int k = 1; j + k < derivLemmas.size() && k <= opts.maxBigramDistance; k++) {
if (derivLemmas.get(j + k).equals(exLemmas.get(i + 1))) {
deriv.addFeature("bigram",
exLemmas.get(i) + "," + exLemmas.get(i + 1) + " - " + k);
if (opts.lexicalBigramParaphrase)
deriv.addFeature("bigram",
exLemmas.get(i) + "," + exLemmas.get(i + 1) + " - " + k);
else MapUtils.incr(bigramCounts, k, 1);
}
}
}
}
}
}
private void extractParaphraseRecall(Example ex, Derivation deriv) {
if (!deriv.cat.equals(Rule.rootCat)) return;
String[] derivTokens = deriv.canonicalUtterance.split("\\s+");
int n = 0;
for (int i = 0; i < ex.languageInfo.numTokens(); ++i) {
for (int j = 0; j < derivTokens.length; ++j) {
if (derivTokens[j].equals(ex.languageInfo.tokens.get(i))) {
n++;
break;
}
}
if (!opts.lexicalBigramParaphrase) {
for (Integer dist : bigramCounts.keySet())
deriv.addFeature("bigram", "distance " + dist + " - " + bigramCounts.get(dist));
}
deriv.addFeature("paraphrasing", "deriv_recall", (double) n / ex.languageInfo.numTokens());
}
private void extractParaphrasePrecision(Example ex, Derivation deriv) {
//how many of the generated stuff is in the original utterance
int n = 0;
for (String item : deriv.rule.rhs) {
if (Rule.isCat(item)) continue;
if (ex.languageInfo.tokens.contains(item))
n++;
}
deriv.addFeature("paraphrasing", "deriv_prec", n);
}
// Joins arrayList of strings into string

View File

@ -2,6 +2,7 @@ package edu.stanford.nlp.sempre;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import fig.basic.*;
import java.util.*;
@ -17,6 +18,14 @@ import java.util.*;
* @author Jonathan Berant
*/
public class FeatureVector {
public static class Options {
@Option(gloss = "When logging, ignore features with zero weight")
public boolean ignoreZeroWeight = false;
@Option(gloss = "Log only this number of top and bottom features")
public int logFeaturesLimit = Integer.MAX_VALUE;
}
public static Options opts = new Options();
// These features map to the value 1 (most common case in NLP).
private ArrayList<String> indicatorFeatures;
// General features
@ -90,21 +99,27 @@ public class FeatureVector {
}
public void add(FeatureVector that) { add(that, AllFeatureMatcher.matcher); }
public void add(FeatureVector that, FeatureMatcher matcher) {
public void add(double scale, FeatureVector that) { add(scale, that, AllFeatureMatcher.matcher); }
public void add(FeatureVector that, FeatureMatcher matcher) { add(1, that, matcher); }
public void add(double scale, FeatureVector that, FeatureMatcher matcher) {
if (that.indicatorFeatures != null) {
for (String f : that.indicatorFeatures)
if (matcher.matches(f))
add(f);
if (matcher.matches(f)) {
if (scale == 1)
add(f);
else
add(f, scale);
}
}
if (that.generalFeatures != null) {
for (Pair<String, Double> pair : that.generalFeatures)
if (matcher.matches(pair.getFirst()))
add(pair.getFirst(), pair.getSecond());
add(pair.getFirst(), scale * pair.getSecond());
}
// dense features are always added
if (that.denseFeatures != null) {
for (int i = 0; i < denseFeatures.length; ++i)
denseFeatures[i] = that.denseFeatures[i];
denseFeatures[i] += scale * that.denseFeatures[i];
}
}
@ -229,16 +244,33 @@ public class FeatureVector {
String feature = entry.getKey();
if (entry.getValue() == 0) continue;
double value = entry.getValue() * params.getWeight(feature);
if (opts.ignoreZeroWeight && value == 0) continue;
sumValue += value;
entries.add(new java.util.AbstractMap.SimpleEntry<String, Double>(feature, value));
}
Collections.sort(entries, new ValueComparator<String, Double>(false));
LogInfo.begin_track_printAll("%s features [sum = %s] (format is feature value * weight)", prefix, Fmt.D(sumValue));
for (Map.Entry<String, Double> entry : entries) {
String feature = entry.getKey();
double value = entry.getValue();
double weight = params.getWeight(feature);
LogInfo.logs("%-50s %6s = %s * %s", "[ " + feature + " ]", Fmt.D(value), Fmt.D(MapUtils.getDouble(features, feature, 0)), Fmt.D(weight));
if (entries.size() / 2 > opts.logFeaturesLimit) {
for (Map.Entry<String, Double> entry : entries.subList(0, opts.logFeaturesLimit)) {
String feature = entry.getKey();
double value = entry.getValue();
double weight = params.getWeight(feature);
LogInfo.logs("%-50s %6s = %s * %s", "[ " + feature + " ]", Fmt.D(value), Fmt.D(MapUtils.getDouble(features, feature, 0)), Fmt.D(weight));
}
LogInfo.logs("... (%d more features) ...", entries.size() - 2 * opts.logFeaturesLimit);
for (Map.Entry<String, Double> entry : entries.subList(entries.size() - opts.logFeaturesLimit, entries.size())) {
String feature = entry.getKey();
double value = entry.getValue();
double weight = params.getWeight(feature);
LogInfo.logs("%-50s %6s = %s * %s", "[ " + feature + " ]", Fmt.D(value), Fmt.D(MapUtils.getDouble(features, feature, 0)), Fmt.D(weight));
}
} else {
for (Map.Entry<String, Double> entry : entries) {
String feature = entry.getKey();
double value = entry.getValue();
double weight = params.getWeight(feature);
LogInfo.logs("%-50s %6s = %s * %s", "[ " + feature + " ]", Fmt.D(value), Fmt.D(MapUtils.getDouble(features, feature, 0)), Fmt.D(weight));
}
}
LogInfo.end_track();
}

View File

@ -0,0 +1,52 @@
package edu.stanford.nlp.sempre;
import fig.basic.LispTree;
import java.util.ArrayList;
import java.util.List;
/**
* Given a token at a particular position, keep it is from a select set.
*
* @author ppasupat
*/
public class FilterTokenFn extends SemanticFn {
List<String> acceptableTokens = new ArrayList<>();
String mode;
public void init(LispTree tree) {
super.init(tree);
mode = tree.child(1).value;
if (!mode.equals("token") && !mode.equals("lemma"))
throw new RuntimeException("Illegal description for FilterTokenFn: " + mode);
for (int j = 2; j < tree.children.size(); j++) {
acceptableTokens.add(tree.child(j).value);
}
}
public DerivationStream call(final Example ex, final Callable c) {
return new SingleDerivationStream() {
@Override
public Derivation createDerivation() {
if (!isValid(ex, c))
return null;
else {
return new Derivation.Builder()
.withCallable(c)
.withFormulaFrom(c.child(0))
.createDerivation();
}
}
};
}
private boolean isValid(Example ex, Callable c) {
if (c.getEnd() - c.getStart() != 1) return false;
String token;
if ("token".equals(mode))
token = ex.token(c.getStart());
else
token = ex.lemmaToken(c.getStart());
return acceptableTokens.contains(token);
}
}

View File

@ -1,7 +1,9 @@
package edu.stanford.nlp.sempre;
import fig.basic.*;
import fig.exec.Execution;
import java.io.PrintWriter;
import java.util.*;
import static fig.basic.LogInfo.logs;
@ -14,42 +16,142 @@ import static fig.basic.LogInfo.logs;
* where many of the words are unaccounted for.
*
* Assume the Grammar is binarized and only has rules of the following form:
*
* $Cat => token
* $Cat => $Cat
* $Cat => token token
* $Cat => token $Cat
* $Cat => $Cat token
* $Cat => $Cat $Cat
* Each rule is either anchored or floating or both.
*
* Each rule can be either anchored or floating (or technically, both).
* For floating rules, tokens on the RHS are ignored.
*
* Chart cells are either:
* - anchored: (cat, start, end) [these are effectively at depth 0]
* - floating: (cat, depth) [depends on anchored cells as base cases]
* - anchored: (cat, start, end) [these are effectively at depth 0]
* - floating: (cat, depth or size) [depends on anchored cells as base cases]
*
* Rules:
* With rules:
* cat => cat1 cat2 [binary]
* cat => cat1 [unary]
* Combinations:
* (cat1, start, end) => (cat, start, end)
* (cat1, depth) => (cat, depth)
*
* Anchored Combinations:
* (cat1, start, end) => (cat, start, end)
* (cat1, start, mid), (cat2, mid, end) => (cat, start, end)
* (cat1, start, end), (cat2, depth) => (cat, depth + 1)
* (cat1, depth), (cat2, start, end) => (cat, depth + 1)
* (cat1, depth1), (cat2, depth2) => (cat, max(depth1, depth2)+1)
* (cat, start, end) => (cat, 0) [anchored => floating]
*
* Floating Combinations:
* [nothing] => (cat, 1) [from $Cat => token]
* (cat1, depth) => (cat, depth + 1)
* (cat1, depth1), (cat2, depth2) => (cat, max(depth1, depth2) + 1)
*
* If --useSizeInsteadOfDepth is turned on, the floating combinations become:
* [nothing] => (cat, 1) [from $Cat => token]
* (cat1, size) => (cat, size + 1)
* (cat1, size1), (cat2, size2) => (cat, size1 + size2 + 1)
*
* @author Percy Liang
*/
public class FloatingParser extends Parser {
public static class Options {
@Option public int maxDepth = 10;
@Option public boolean defaultIsFloating = true;
@Option (gloss = "Flag specifying whether anchored spans/tokens can only be used once in a derivation")
// Floating rules
@Option(gloss = "Whether rules without the (anchored 1) or (floating 1) tag should be anchored or floating")
public boolean defaultIsFloating = true;
@Option(gloss = "Limit on formula depth (or formula size when --useSizeInsteadOfDepth is true)")
public int maxDepth = 10;
@Option(gloss = "Put a limit on formula size instead of formula depth")
public boolean useSizeInsteadOfDepth = false;
@Option(gloss = "Whether floating rules are allowed to be applied consecutively")
public boolean consecutiveRules = true;
@Option(gloss = "Whether floating rule (rule $A (a)) should have depth 0 or 1")
public boolean initialFloatingHasZeroDepth = false;
@Option(gloss = "Filter child derivations using the type information from SemanticFn")
public boolean filterChildDerivations = true;
// Anchored rules
@Option(gloss = "Whether anchored spans/tokens can only be used once in a derivation")
public boolean useAnchorsOnce = false;
@Option(gloss = "Each span can be anchored this number of times (unused if useAnchorsOnce is active)")
public int useMaxAnchors = -1;
// Other options
@Option(gloss = "Whether to always execute the derivation")
public boolean executeAllDerivations = false;
@Option(gloss = "Whether to output a file with all utterances predicted")
public boolean printPredictedUtterances = false;
@Option(gloss = "Custom beam size at training time (default = Parser.beamSize)")
public int trainBeamSize = -1;
@Option(gloss = "Whether to beta reduce the formula")
public boolean betaReduce = false;
@Option(gloss = "DEBUG: Print amount of time spent on each rule")
public boolean summarizeRuleTime = false;
@Option(gloss = "Stop the parser if it has used more than this amount of time (in seconds)")
public int maxFloatingParsingTime = Integer.MAX_VALUE;
}
public static Options opts = new Options();
public FloatingParser(Spec spec) { super(spec); }
public boolean earlyStopOnConsistent = false;
public int earlyStopOnNumDerivs = -1;
public FloatingParser(Spec spec) {
super(spec);
}
/**
* Set early stopping criteria
*
* @param onConsistent
* Stop when a consistent derivation is found. (Only triggered when computeExpectedCounts = true)
* @param onNumDerivs
* Stop when the number of featurized derivations exceed this number (set to -1 to disable)
* @return
* this
*/
public FloatingParser setEarlyStopping(boolean onConsistent, int onNumDerivs) {
this.earlyStopOnConsistent = onConsistent;
this.earlyStopOnNumDerivs = onNumDerivs;
return this;
}
/**
* computeCatUnaryRules, but do not topologically sort floating rules
*/
@Override
protected void computeCatUnaryRules() {
// Handle anchored catUnaryRules
catUnaryRules = new ArrayList<>();
Map<String, List<Rule>> graph = new HashMap<>(); // Node from LHS to list of rules
for (Rule rule : grammar.rules)
if (rule.isCatUnary() && rule.isAnchored())
MapUtils.addToList(graph, rule.lhs, rule);
// Topologically sort catUnaryRules so that B->C occurs before A->B
Map<String, Boolean> done = new HashMap<>();
for (String node : graph.keySet())
traverse(catUnaryRules, node, graph, done);
// Add floating catUnaryRules
for (Rule rule : grammar.rules)
if (rule.isCatUnary() && rule.isFloating())
catUnaryRules.add(rule);
}
// Helper function for transitive closure of floating rules.
protected void traverseFloatingRules(List<Rule> orderedFloatingRules,
String node, Map<String, List<Rule>> graph, Map<String, Boolean> done) {
Boolean d = done.get(node);
if (Boolean.TRUE.equals(d)) return;
if (Boolean.FALSE.equals(d))
throw new RuntimeException("Found cycle of floating rules involving " + node);
done.put(node, false);
for (Rule rule : MapUtils.getList(graph, node)) {
for (String rhsCat : rule.rhs) {
if (Grammar.isIntermediate(rhsCat))
traverseFloatingRules(orderedFloatingRules, rhsCat, graph, done);
}
orderedFloatingRules.add(rule);
}
done.put(node, true);
}
public ParserState newParserState(Params params, Example ex, boolean computeExpectedCounts) {
return new FloatingParserState(this, params, ex, computeExpectedCounts);
@ -66,36 +168,62 @@ public class FloatingParser extends Parser {
* @author Percy Liang
*/
class FloatingParserState extends ParserState {
// cell => list of derivations, formula set
// Examples of state:
// (category, depth)
// (category, depth, set of tokens)
// cell => list of derivations
// Anchored cells: cat[start,end]
// Floating cells: cat:depth
private final Map<Object, List<Derivation>> chart = new HashMap<>();
private final DerivationPruner pruner;
private final CatSizeBound catSizeBound;
private Map<Rule, Long> ruleTime;
private boolean timeout = false;
public FloatingParserState(FloatingParser parser, Params params, Example ex, boolean computeExpectedCounts) {
super(parser, params, ex, computeExpectedCounts);
pruner = new DerivationPruner(this);
catSizeBound = new CatSizeBound(FloatingParser.opts.maxDepth, parser.grammar);
}
@Override
protected int getBeamSize() {
if (computeExpectedCounts && FloatingParser.opts.trainBeamSize > 0)
return FloatingParser.opts.trainBeamSize;
return Parser.opts.beamSize;
}
// Construct state names.
private Object floatingCell(String cat, int depth) {
return cat + ":" + depth;
return (cat + ":" + depth).intern();
}
private Object anchoredCell(String cat, int start, int end) {
return cat + "[" + start + "," + end + "]";
return (cat + "[" + start + "," + end + "]").intern();
}
private Object cell(String cat, int start, int end, int depth) {
return (start != -1) ? anchoredCell(cat, start, end) : floatingCell(cat, depth);
}
private void addToChart(Object cell, Derivation deriv) {
if (Parser.opts.verbose >= 3)
LogInfo.logs("addToChart %s: %s", cell, deriv);
if (!deriv.isFeaturizedAndScored()) // A derivation could be belong in multiple cells.
featurizeAndScoreDerivation(deriv);
if (Parser.opts.pruneErrorValues && deriv.value instanceof ErrorValue) return;
if (Parser.opts.verbose >= 4)
LogInfo.logs("addToChart %s: %s", cell, deriv);
MapUtils.addToList(chart, cell, deriv);
}
private void applyRule(Rule rule, int start, int end, int depth, Derivation child1, Derivation child2, String canonicalUtterance) {
private boolean isRootRule(Rule rule) {
return Rule.rootCat.equals(rule.lhs);
}
private boolean applyRule(Rule rule, int start, int end, int depth,
Derivation child1, Derivation child2, String canonicalUtterance) {
if (timeout && !isRootRule(rule)) return false;
applyRuleActual(rule, start, end, depth, child1, child2, canonicalUtterance);
return true;
}
private void applyRuleActual(Rule rule, int start, int end, int depth, Derivation child1, Derivation child2, String canonicalUtterance) {
if (Parser.opts.verbose >= 5) logs("applyRule %s [%s:%s] depth=%s, %s %s", rule, start, end, depth, child1, child2);
List<Derivation> children;
if (child1 == null) // 0-ary
@ -103,43 +231,55 @@ class FloatingParserState extends ParserState {
else if (child2 == null) // 1-ary
children = Collections.singletonList(child1);
else {
// Optional: ensure that each anchor is only used once per derivation.
if (FloatingParser.opts.useAnchorsOnce) {
if (FloatingRuleUtils.derivationAnchorsOverlap(child1, child2))
return;
} else if (FloatingParser.opts.useMaxAnchors >= 0) {
if (FloatingRuleUtils.maxNumAnchorOverlaps(child1, child2)
> FloatingParser.opts.useMaxAnchors)
return;
}
children = ListUtils.newList(child1, child2);
// optionally: ensure that specific anchors are only used once per final derivation
if (FloatingParser.opts.useAnchorsOnce &&
FloatingRuleUtils.derivationAnchorsOverlap(child1, child2))
return;
}
// optionally: ensure that rule being applied is not the same as one of the children's
if (!FloatingParser.opts.consecutiveRules) {
for (Derivation child : children) {
if (child.rule.equals(rule)) return;
}
}
DerivationStream results = rule.sem.call(ex,
new SemanticFn.CallInfo(rule.lhs, start, end, rule, children));
while (results.hasNext()) {
Derivation newDeriv = results.next();
if (FloatingParser.opts.betaReduce) newDeriv = newDeriv.betaReduction();
newDeriv.canonicalUtterance = canonicalUtterance;
// make sure we execute
if (FloatingParser.opts.executeAllDerivations && !(newDeriv.type instanceof FuncSemType))
newDeriv.ensureExecuted(parser.executor, ex.context);
if (pruner.isPruned(newDeriv)) continue;
// Avoid repetitive floating cells
/*
if (depth > 0) {
if (MapUtils.getSet(setChart, rule.lhs).contains(newDeriv.formula)) {
continue;
}
if (rule.lhs == Rule.rootCat)
LogInfo.logs("adding %s to root for floating", newDeriv);
MapUtils.addToSet(setChart, rule.lhs, newDeriv.formula);
}
*/
addToChart(cell(rule.lhs, start, end, depth), newDeriv);
if (depth == -1) // In addition, anchored cells become floating at level 0
addToChart(floatingCell(rule.lhs, 0), newDeriv);
}
}
private void applyAnchoredRule(Rule rule, int start, int end, Derivation child1, Derivation child2, String canonicalUtterance) {
applyRule(rule, start, end, -1, child1, child2, canonicalUtterance);
private boolean applyAnchoredRule(Rule rule, int start, int end, Derivation child1, Derivation child2, String canonicalUtterance) {
return applyRule(rule, start, end, -1, child1, child2, canonicalUtterance);
}
private void applyFloatingRule(Rule rule, int depth, Derivation child1, Derivation child2, String canonicalUtterance) {
applyRule(rule, -1, -1, depth, child1, child2, canonicalUtterance);
private boolean applyFloatingRule(Rule rule, int depth, Derivation child1, Derivation child2, String canonicalUtterance) {
return applyRule(rule, -1, -1, depth, child1, child2, canonicalUtterance);
}
/**
* Return a collection of Derivation.
*/
private List<Derivation> getDerivations(Object cell) {
List<Derivation> derivations = chart.get(cell);
// logs("getDerivations %s => %s", cell, derivations);
@ -147,6 +287,26 @@ class FloatingParserState extends ParserState {
return derivations;
}
/**
* Return a collection of DerivationGroup.
*
* The rule should be applied on all derivations (or all pairs of derivations) in each DerivationGroup.
*/
private Collection<ChildDerivationsGroup> getFilteredDerivations(Rule rule, Object cell1, Object cell2) {
List<Derivation> derivations1 = getDerivations(cell1),
derivations2 = (cell2 == null) ? null : getDerivations(cell2);
if (!FloatingParser.opts.filterChildDerivations)
return Collections.singleton(new ChildDerivationsGroup(derivations1, derivations2));
// Try to filter down the number of partial logical forms
if (rule.getSem().supportFilteringOnTypeData())
return rule.getSem().getFilteredDerivations(derivations1, derivations2);
return Collections.singleton(new ChildDerivationsGroup(derivations1, derivations2));
}
private Collection<ChildDerivationsGroup> getFilteredDerivations(Rule rule, Object cell) {
return getFilteredDerivations(rule, cell, null);
}
// Build derivations over span |start|, |end|.
private void buildAnchored(int start, int end) {
// Apply unary tokens on spans (rule $A (a))
@ -154,8 +314,10 @@ class FloatingParserState extends ParserState {
if (!rule.isAnchored()) continue;
if (rule.rhs.size() != 1 || rule.isCatUnary()) continue;
boolean match = (end - start == 1) && ex.token(start).equals(rule.rhs.get(0));
if (match)
applyAnchoredRule(rule, start, end, null, null, rule.rhs.get(0));
if (!match) continue;
StopWatch stopWatch = new StopWatch().start();
applyAnchoredRule(rule, start, end, null, null, rule.rhs.get(0));
ruleTime.put(rule, ruleTime.getOrDefault(rule, 0L) + stopWatch.stop().ms);
}
// Apply binaries on spans (rule $A ($B $C)), ...
@ -164,6 +326,7 @@ class FloatingParserState extends ParserState {
if (!rule.isAnchored()) continue;
if (rule.rhs.size() != 2) continue;
StopWatch stopWatch = new StopWatch().start();
String rhs1 = rule.rhs.get(0);
String rhs2 = rule.rhs.get(1);
boolean match1 = (mid - start == 1) && ex.token(start).equals(rhs1);
@ -191,6 +354,7 @@ class FloatingParserState extends ParserState {
for (Derivation deriv2 : derivations2)
applyAnchoredRule(rule, start, end, deriv1, deriv2, deriv1.canonicalUtterance + " " + deriv2.canonicalUtterance);
}
ruleTime.put(rule, ruleTime.getOrDefault(rule, 0L) + stopWatch.stop().ms);
}
}
@ -198,68 +362,104 @@ class FloatingParserState extends ParserState {
// Important: do this in topologically sorted order and after all the binaries are done.
for (Rule rule : parser.catUnaryRules) {
if (!rule.isAnchored()) continue;
StopWatch stopWatch = new StopWatch().start();
List<Derivation> derivations = getDerivations(anchoredCell(rule.rhs.get(0), start, end));
for (Derivation deriv : derivations) {
for (Derivation deriv : derivations)
applyAnchoredRule(rule, start, end, deriv, null, deriv.canonicalUtterance);
}
ruleTime.put(rule, ruleTime.getOrDefault(rule, 0L) + stopWatch.stop().ms);
}
}
// Build floating derivations of exactly depth |depth|.
private void buildFloating(int depth) {
// Apply unary tokens on spans (rule $A (a))
if (depth == 1) {
// Build a floating predicate from thin air
// (rule $A (a)); note that "a" is ignored
if (depth == (FloatingParser.opts.initialFloatingHasZeroDepth ? 0 : 1)) {
for (Rule rule : parser.grammar.rules) {
if (timeout && !isRootRule(rule)) continue;
if (!rule.isFloating()) continue;
if (rule.rhs.size() != 1 || rule.isCatUnary()) continue;
StopWatch stopWatch = new StopWatch().start();
applyFloatingRule(rule, depth, null, null, rule.rhs.get(0));
ruleTime.put(rule, ruleTime.getOrDefault(rule, 0L) + stopWatch.stop().ms);
}
}
// Apply binaries on spans (rule $A ($B $C)), ...
for (Rule rule : parser.grammar.rules) {
if (timeout && !isRootRule(rule)) continue;
if (!rule.isFloating()) continue;
if (rule.rhs.size() != 2) continue;
if (catSizeBound.getBound(rule.lhs) < depth) continue;
StopWatch stopWatch = new StopWatch().start();
String rhs1 = rule.rhs.get(0);
String rhs2 = rule.rhs.get(1);
if (!Rule.isCat(rhs1) && !Rule.isCat(rhs2)) { // token token
if (depth == 1)
if (depth == (FloatingParser.opts.initialFloatingHasZeroDepth ? 0 : 1)) {
applyFloatingRule(rule, depth, null, null, rhs1 + " " + rhs2);
}
} else if (!Rule.isCat(rhs1) && Rule.isCat(rhs2)) { // token $Cat
List<Derivation> derivations = getDerivations(floatingCell(rhs2, depth - 1));
for (Derivation deriv : derivations)
applyFloatingRule(rule, depth, deriv, null, rhs1 + " " + deriv.canonicalUtterance);
} else if (Rule.isCat(rhs1) && !Rule.isCat(rhs2)) { // $Cat token
List<Derivation> derivations = getDerivations(floatingCell(rhs1, depth - 1));
for (Derivation deriv : derivations)
applyFloatingRule(rule, depth, deriv, null, deriv.canonicalUtterance + " " + rhs2);
} else { // $Cat $Cat
for (int subDepth = 0; subDepth < depth; subDepth++) { // depth-1 <=depth-1
List<Derivation> derivations1 = getDerivations(floatingCell(rhs1, depth - 1));
List<Derivation> derivations2 = getDerivations(floatingCell(rhs2, subDepth));
for (Derivation deriv1 : derivations1)
for (Derivation deriv2 : derivations2)
applyFloatingRule(rule, depth, deriv1, deriv2, deriv1.canonicalUtterance + " " + deriv2.canonicalUtterance);
}
for (int subDepth = 0; subDepth < depth - 1; subDepth++) { // <depth-1 depth-1
List<Derivation> derivations1 = getDerivations(floatingCell(rhs1, subDepth));
List<Derivation> derivations2 = getDerivations(floatingCell(rhs2, depth - 1));
for (Derivation deriv1 : derivations1)
for (Derivation deriv2 : derivations2)
applyFloatingRule(rule, depth, deriv1, deriv2, deriv1.canonicalUtterance + " " + deriv2.canonicalUtterance);
if (FloatingParser.opts.useSizeInsteadOfDepth) {
derivLoop:
for (int depth1 = 0; depth1 < depth; depth1++) { // sizes must add up to depth-1 (actually size-1)
int depth2 = depth - 1 - depth1;
for (ChildDerivationsGroup group : getFilteredDerivations(rule, floatingCell(rhs1, depth1), floatingCell(rhs2, depth2)))
for (Derivation deriv1 : group.derivations1)
for (Derivation deriv2 : group.derivations2)
if (!applyFloatingRule(rule, depth, deriv1, deriv2, deriv1.canonicalUtterance + " " + deriv2.canonicalUtterance))
break derivLoop;
}
} else {
{
derivLoop:
for (int subDepth = 0; subDepth < depth; subDepth++) { // depth-1 <=depth-1
for (ChildDerivationsGroup group : getFilteredDerivations(rule, floatingCell(rhs1, depth - 1), floatingCell(rhs2, subDepth)))
for (Derivation deriv1 : group.derivations1)
for (Derivation deriv2 : group.derivations2)
if (!applyFloatingRule(rule, depth, deriv1, deriv2, deriv1.canonicalUtterance + " " + deriv2.canonicalUtterance))
break derivLoop;
}
}
{
derivLoop:
for (int subDepth = 0; subDepth < depth - 1; subDepth++) { // <depth-1 depth-1
for (ChildDerivationsGroup group : getFilteredDerivations(rule, floatingCell(rhs1, subDepth), floatingCell(rhs2, depth - 1)))
for (Derivation deriv1 : group.derivations1)
for (Derivation deriv2 : group.derivations2)
if (!applyFloatingRule(rule, depth, deriv1, deriv2, deriv1.canonicalUtterance + " " + deriv2.canonicalUtterance))
break derivLoop;
}
}
}
}
ruleTime.put(rule, ruleTime.getOrDefault(rule, 0L) + stopWatch.stop().ms);
}
// Apply unary categories on spans (rule $A ($B))
// Important: do this in topologically sorted order and after all the binaries are done.
for (Rule rule : parser.catUnaryRules) {
if (timeout && !isRootRule(rule)) continue;
if (!rule.isFloating()) continue;
List<Derivation> derivations = getDerivations(floatingCell(rule.rhs.get(0), depth - 1));
for (Derivation deriv : derivations)
applyFloatingRule(rule, depth, deriv, null, deriv.canonicalUtterance);
if (catSizeBound.getBound(rule.lhs) < depth) continue;
StopWatch stopWatch = new StopWatch().start();
derivLoop:
for (ChildDerivationsGroup group : getFilteredDerivations(rule, floatingCell(rule.rhs.get(0), depth - 1)))
for (Derivation deriv : group.derivations1)
if (!applyFloatingRule(rule, depth, deriv, null, deriv.canonicalUtterance))
break derivLoop;
ruleTime.put(rule, ruleTime.getOrDefault(rule, 0L) + stopWatch.stop().ms);
}
}
@ -269,59 +469,113 @@ class FloatingParserState extends ParserState {
derivations.addAll(myDerivations);
}
@Override public void infer() {
LogInfo.begin_track("FloatingParser.infer()");
/**
* Build derivations in a thread to allow timeout.
*/
class DerivationBuilder implements Runnable {
@Override public void run() {
// Base case ($TOKEN, $PHRASE)
for (Derivation deriv : gatherTokenAndPhraseDerivations()) {
addToChart(anchoredCell(deriv.cat, deriv.start, deriv.end), deriv);
addToChart(floatingCell(deriv.cat, 0), deriv);
}
// Base case ($TOKEN, $PHRASE)
for (Derivation deriv : gatherTokenAndPhraseDerivations()) {
addToChart(anchoredCell(deriv.cat, deriv.start, deriv.end), deriv);
addToChart(floatingCell(deriv.cat, 0), deriv);
}
Set<String> categories = new HashSet<>();
for (Rule rule : parser.grammar.rules)
categories.add(rule.lhs);
Set<String> categories = new HashSet<>();
for (Rule rule : parser.grammar.rules)
categories.add(rule.lhs);
if (Parser.opts.verbose >= 1)
LogInfo.begin_track_printAll("Anchored");
// Build up anchored derivations (like the BeamParser)
int numTokens = ex.numTokens();
for (int len = 1; len <= numTokens; len++) {
for (int i = 0; i + len <= numTokens; i++) {
buildAnchored(i, i + len);
for (String cat : categories) {
String cell = anchoredCell(cat, i, i + len).toString();
pruneCell(cell, chart.get(cell));
}
}
}
if (Parser.opts.verbose >= 1)
LogInfo.end_track();
// Build up anchored derivations (like the BeamParser)
int numTokens = ex.numTokens();
for (int len = 1; len <= numTokens; len++) {
for (int i = 0; i + len <= numTokens; i++) {
buildAnchored(i, i + len);
// Build up floating derivations
for (int depth = (FloatingParser.opts.initialFloatingHasZeroDepth ? 0 : 1); depth <= FloatingParser.opts.maxDepth; depth++) {
if (Parser.opts.verbose >= 1)
LogInfo.begin_track_printAll("%s = %d", FloatingParser.opts.useSizeInsteadOfDepth ? "SIZE" : "DEPTH", depth);
buildFloating(depth);
for (String cat : categories) {
String cell = anchoredCell(cat, i, i + len).toString();
/*if (cat.equals("$Word") || cat.equals("$Fragment")) {
LogInfo.logs("Looking at cell: %s", cell);
if (chart.get(cell) == null) LogInfo.logs("???");
else {
for (Derivation deriv : chart.get(cell))
LogInfo.logs("Found cell of interest: %s", deriv.toString());
}
}*/
String cell = floatingCell(cat, depth).toString();
pruneCell(cell, chart.get(cell));
}
if (Parser.opts.verbose >= 1)
LogInfo.end_track();
// Early stopping
if (computeExpectedCounts && ((FloatingParser) parser).earlyStopOnConsistent) {
// Consistent derivation found?
String cell = floatingCell(Rule.rootCat, depth).toString();
List<Derivation> rootDerivs = chart.get(cell);
if (rootDerivs != null) {
for (Derivation rootDeriv : rootDerivs) {
rootDeriv.ensureExecuted(parser.executor, ex.context);
if (parser.valueEvaluator.getCompatibility(ex.targetValue, rootDeriv.value) == 1) {
LogInfo.logs("Early stopped: consistent derivation found at depth = %d", depth);
return;
}
}
}
}
if (((FloatingParser) parser).earlyStopOnNumDerivs > 0) {
// Too many derivations generated?
if (numOfFeaturizedDerivs > ((FloatingParser) parser).earlyStopOnNumDerivs) {
LogInfo.logs("Early stopped: number of derivations exceeded at depth = %d", depth);
return;
}
}
}
}
}
// Build up floating derivations
for (int depth = 1; depth <= FloatingParser.opts.maxDepth; depth++) {
buildFloating(depth);
for (String cat : categories) {
String cell = floatingCell(cat, depth).toString();
/*if (cat.equals("$Word") || cat.equals("$Fragment")) {
LogInfo.logs("Looking at floating cell: %s", cell);
if (chart.get(cell) == null) LogInfo.logs("???");
else {
for (Derivation deriv : chart.get(cell))
LogInfo.logs("Found cell of interest: %s", deriv.toString());
}
}*/
pruneCell(cell, chart.get(cell));
public void buildDerivations() {
DerivationBuilder derivBuilder = new DerivationBuilder();
if (FloatingParser.opts.maxFloatingParsingTime == Integer.MAX_VALUE) {
derivBuilder.run();
} else {
Thread parsingThread = new Thread(derivBuilder);
parsingThread.start();
try {
parsingThread.join(FloatingParser.opts.maxFloatingParsingTime * 1000);
if (parsingThread.isAlive()) {
// This will only interrupt first or second passes, not the final candidate collection.
LogInfo.warnings("Parsing time exceeded %d seconds. Will now interrupt ...", FloatingParser.opts.maxFloatingParsingTime);
timeout = true;
parsingThread.interrupt();
parsingThread.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
LogInfo.fails("FloatingParser error: %s", e);
}
}
evaluation.add("timeout", timeout);
}
// ============================================================
// Main entry point
// ============================================================
@Override public void infer() {
LogInfo.begin_track_printAll("FloatingParser.infer()");
ruleTime = new HashMap<>();
buildDerivations();
if (FloatingParser.opts.summarizeRuleTime) summarizeRuleTime();
// Collect final predicted derivations
addToDerivations(anchoredCell(Rule.rootCat, 0, numTokens), predDerivations);
for (int depth = 1; depth <= FloatingParser.opts.maxDepth; depth++)
for (int depth = 0; depth <= FloatingParser.opts.maxDepth; depth++)
addToDerivations(floatingCell(Rule.rootCat, depth), predDerivations);
// Compute gradient with respect to the predicted derivations
@ -332,16 +586,37 @@ class FloatingParserState extends ParserState {
}
// Example summary
if (Parser.opts.verbose >= 1) {
LogInfo.begin_track("Summary of Example %s", ex.getUtterance());
if (Parser.opts.verbose >= 2) {
LogInfo.begin_track_printAll("Summary of Example %s", ex.getUtterance());
for (Derivation deriv : predDerivations)
LogInfo.logs("Generated: canonicalUtterance=%s, value=%s", deriv.canonicalUtterance, deriv.value);
LogInfo.end_track();
}
if (FloatingParser.opts.printPredictedUtterances) {
PrintWriter writer = IOUtils.openOutAppendEasy(Execution.getFile("canonical_utterances"));
PrintWriter fWriter = IOUtils.openOutAppendEasy(Execution.getFile("utterances_formula.tsv"));
Derivation.sortByScore(predDerivations);
for (Derivation deriv: predDerivations) {
if (deriv.score > -10) {
writer.println(String.format("%s\t%s", deriv.canonicalUtterance, deriv.score));
fWriter.println(String.format("%s\t%s", deriv.canonicalUtterance, deriv.formula.toString()));
}
}
writer.close();
fWriter.close();
}
LogInfo.end_track();
}
@Override
protected void setEvaluation() {
super.setEvaluation();
evaluation.add("numCells", chart.size());
}
@SuppressWarnings("unused")
private void visualizeAnchoredChart(Set<String> categories) {
for (String cat : categories) {
for (int len = 1; len <= numTokens; ++len) {
@ -354,4 +629,14 @@ class FloatingParserState extends ParserState {
}
}
}
private void summarizeRuleTime() {
List<Map.Entry<Rule, Long>> entries = new ArrayList<>(ruleTime.entrySet());
entries.sort(new ValueComparator<>(true));
LogInfo.begin_track_printAll("Rule time");
for (Map.Entry<Rule, Long> entry : entries) {
LogInfo.logs("%9d : %s", entry.getValue(), entry.getKey());
}
LogInfo.end_track();
}
}

View File

@ -31,14 +31,20 @@ public final class FloatingRuleUtils {
* that spans) [2, 4] then we have an overlap.
*/
public static boolean derivationAnchorsOverlap(Derivation a, Derivation b) {
List<Derivation> aRoots = getDerivationAnchors(a);
List<Derivation> bRoots = getDerivationAnchors(b);
for (Derivation aRoot : aRoots) {
for (Derivation bRoot : bRoots) {
if (aRoot.start < bRoot.end && bRoot.start < aRoot.end)
return true;
}
}
boolean[] aAnchors = a.getAnchoredTokens(), bAnchors = b.getAnchoredTokens();
for (int i = 0; i < aAnchors.length && i < bAnchors.length; i++)
if (aAnchors[i] && bAnchors[i]) return true;
return false;
}
public static int maxNumAnchorOverlaps(Derivation a, Derivation b) {
int[] aAnchors = a.getNumAnchors(), bAnchors = b.getNumAnchors();
int n = Math.max(aAnchors.length, bAnchors.length);
int maxAnchors = 0;
for (int i = 0; i < n; i++)
maxAnchors = Math.max(maxAnchors,
(i < aAnchors.length ? aAnchors[i] : 0) +
(i < bAnchors.length ? bAnchors[i] : 0));
return maxAnchors;
}
}

View File

@ -23,6 +23,10 @@ public abstract class Formula {
// Serialize as LispTree.
public abstract LispTree toLispTree();
// Recursively perform some operation on each formula.
// Apply to formulas. If |func| returns false, then recurse on children.
public abstract void forEach(Function<Formula, Boolean> func);
// Recursively perform some operation on each formula.
// Apply to formulas. If |func| returns null, then recurse on children.
public abstract Formula map(Function<Formula, Formula> func);
@ -50,6 +54,7 @@ public abstract class Formula {
public static Formula nullFormula = new PrimitiveFormula() {
public LispTree toLispTree() { return LispTree.proto.newLeaf("null"); }
@SuppressWarnings({"equalshashcode"})
@Override public boolean equals(Object o) { return this == o; }
public int computeHashCode() { return 0; }
};

View File

@ -74,6 +74,16 @@ public abstract class Formulas {
if (mode != null)
return new ArithmeticFormula(mode, fromLispTree(tree.child(1)), fromLispTree(tree.child(2)));
}
{ // ActionFormula
ActionFormula.Mode mode = ActionFormula.parseMode(func);
if (mode != null) {
List<Formula> args = Lists.newArrayList();
for (int i = 1; i < tree.children.size(); i++)
args.add(fromLispTree(tree.child(i)));
return new ActionFormula(mode, args);
}
}
// Default is join: (fb:type.object.type fb:people.person)
if (tree.children.size() != 2)
@ -85,7 +95,7 @@ public abstract class Formulas {
private static Formula parseIntToFormula(LispTree tree) {
try {
int i = Integer.parseInt(tree.value);
double d = (double) i;
double d = i;
NumberValue value = new NumberValue(d);
return new ValueFormula(value);
} catch (NumberFormatException e) {
@ -260,6 +270,27 @@ public abstract class Formulas {
return (int) getDouble(formula);
}
/**
* If the formula represents a binary (e.g., fb:a.b.c or <=),
* return the ID of the binary as a string.
* If the formula represents a reversed binary (e.g., !fb:a.b.c or (reverse fb:a.b.c)),
* return "!" + ID of the binary.
* Otherwise, return null.
*/
public static String getBinaryId(Formula formula) {
if (formula instanceof ReverseFormula) {
String childId = getBinaryId(((ReverseFormula) formula).child);
if (childId == null) return null;
return CanonicalNames.reverseProperty(childId);
} else if (formula instanceof ValueFormula) {
Value v = ((ValueFormula<?>) formula).value;
if (v instanceof NameValue) {
return ((NameValue) v).id;
}
}
return null;
}
public static ValueFormula<NameValue> newNameFormula(String id) {
return new ValueFormula<NameValue>(new NameValue(id));
}
@ -280,7 +311,7 @@ public abstract class Formulas {
// recurse
if (f instanceof AggregateFormula) {
AggregateFormula aggFormula = (AggregateFormula) f;
extractSubpartsRecursive(aggFormula, res);
extractSubpartsRecursive(aggFormula.child, res);
} else if (f instanceof CallFormula) {
CallFormula callFormula = (CallFormula) f;
extractSubpartsRecursive(callFormula.func, res);
@ -360,8 +391,19 @@ public abstract class Formulas {
// !fb:people.person.place_of_birth <=> fb:people.person.place_of_birth
private static ValueFormula<NameValue> reverseNameFormula(ValueFormula<NameValue> formula) {
String id = formula.value.id;
return new ValueFormula<>(
new NameValue(CanonicalNames.isReverseProperty(id) ? id.substring(1) : "!" + id));
return new ValueFormula<>(new NameValue(CanonicalNames.reverseProperty(id)));
}
// Try to simplify reverse subformulas within the specified formula
public static Formula simplifyReverses(Formula formula) {
return formula.map(new Function<Formula, Formula>() {
public Formula apply(Formula formula) {
if (formula instanceof ReverseFormula)
return reverseFormula(((ReverseFormula) formula).child);
return null;
}
});
}
}

View File

@ -5,7 +5,7 @@ import java.util.*;
import fig.basic.*;
/**
* Similar to LexiconFn, but list all approximate matches from a TableKnowledgeGraph.
* Similar to LexiconFn, but list all approximate matches from a FuzzyMatchable instance.
*
* @author ppasupat
*/
@ -15,7 +15,8 @@ public class FuzzyMatchFn extends SemanticFn {
}
public static Options opts = new Options();
public enum FuzzyMatchFnMode { UNARY, BINARY, ENTITY };
public enum FuzzyMatchFnMode { UNARY, BINARY, ENTITY,
ORDER_BEFORE, ORDER_AFTER, ORDER_NEXT, ORDER_PREV, ORDER_ADJACENT };
private FuzzyMatchFnMode mode;
// Generate all possible denotations regardless of the phrase
@ -29,10 +30,18 @@ public class FuzzyMatchFn extends SemanticFn {
else if ("binary".equals(value)) this.mode = FuzzyMatchFnMode.BINARY;
else if ("entity".equals(value)) this.mode = FuzzyMatchFnMode.ENTITY;
else if ("any".equals(value)) this.matchAny = true;
else if ("before".equals(value)) this.mode = FuzzyMatchFnMode.ORDER_BEFORE;
else if ("after".equals(value)) this.mode = FuzzyMatchFnMode.ORDER_AFTER;
else if ("next".equals(value)) this.mode = FuzzyMatchFnMode.ORDER_NEXT;
else if ("prev".equals(value)) this.mode = FuzzyMatchFnMode.ORDER_PREV;
else if ("adjacent".equals(value)) this.mode = FuzzyMatchFnMode.ORDER_ADJACENT;
else throw new RuntimeException("Invalid argument: " + value);
}
}
public FuzzyMatchFnMode getMode() { return mode; }
public boolean getMatchAny() { return matchAny; }
@Override
public DerivationStream call(Example ex, Callable c) {
return new LazyFuzzyMatchFnDerivs(ex, c, mode, matchAny);
@ -44,9 +53,10 @@ public class FuzzyMatchFn extends SemanticFn {
public static class LazyFuzzyMatchFnDerivs extends MultipleDerivationStream {
final Example ex;
final KnowledgeGraph graph;
final FuzzyMatchable matchable;
final Callable c;
final String query;
final List<String> sentence;
final FuzzyMatchFnMode mode;
final boolean matchAny;
@ -55,9 +65,19 @@ public class FuzzyMatchFn extends SemanticFn {
public LazyFuzzyMatchFnDerivs(Example ex, Callable c, FuzzyMatchFnMode mode, boolean matchAny) {
this.ex = ex;
this.graph = (ex.context == null) ? null : ex.context.graph;
if (ex.context != null && ex.context.graph != null && ex.context.graph instanceof FuzzyMatchable)
this.matchable = (FuzzyMatchable) ex.context.graph;
else
this.matchable = null;
this.c = c;
this.query = matchAny ? null : c.childStringValue(0);
this.query = (matchAny || c.getChildren().isEmpty()) ? null : c.childStringValue(0);
if (c.getRule().rhs.size() == 1 && Rule.phraseCat.equals(c.getRule().rhs.get(0))) {
sentence = ex.getTokens();
} else if (c.getRule().rhs.size() == 1 && Rule.lemmaPhraseCat.equals(c.getRule().rhs.get(0))) {
sentence = ex.getLemmaTokens();
} else {
sentence = null;
}
this.mode = mode;
this.matchAny = matchAny;
if (opts.verbose >= 2)
@ -67,14 +87,17 @@ public class FuzzyMatchFn extends SemanticFn {
@Override
public Derivation createDerivation() {
if (graph == null) return null;
if (matchable == null) return null;
if (query == null && !matchAny) return null;
// Compute the formulas if not computed yet
if (formulas == null) {
if (matchAny)
formulas = new ArrayList<>(graph.getAllFormulas(mode));
formulas = new ArrayList<>(matchable.getAllFormulas(mode));
else if (sentence != null)
formulas = new ArrayList<>(matchable.getFuzzyMatchedFormulas(sentence, c.getStart(), c.getEnd(), mode));
else
formulas = new ArrayList<>(graph.getFuzzyMatchedFormulas(query, mode));
formulas = new ArrayList<>(matchable.getFuzzyMatchedFormulas(query, mode));
}
// Use the next formula to create a derivation

View File

@ -0,0 +1,39 @@
package edu.stanford.nlp.sempre;
import java.util.*;
import edu.stanford.nlp.sempre.FuzzyMatchFn.FuzzyMatchFnMode;
/**
* Interface for knowledge sources that, given a phrase, can retrieve all its
* predicates that (fuzzily) match the phrase.
*
* @author ppasupat
*/
public interface FuzzyMatchable {
/**
* Return all entities / unaries / binaries that approximately match the
* string formed by joining sentence[startIndex], ..., sentence[endIndex-1]
* with spaces.
*
* This allows the algorithm to consider the context of the term being matched.
*
* One possible implementation, which ignores the context, is calling
* getFuzzyMatchedFormulas(term, mode) where
* term = String.join(" ", sentence.subList(startIndex, endIndex))
*/
public abstract Collection<Formula> getFuzzyMatchedFormulas(
List<String> sentence, int startIndex, int endIndex, FuzzyMatchFnMode mode);
/**
* Return all entities / unaries / binaries that approximately match the term
*/
public abstract Collection<Formula> getFuzzyMatchedFormulas(String term, FuzzyMatchFnMode mode);
/**
* Return all possible entities / unaries / binaries
*/
public abstract Collection<Formula> getAllFormulas(FuzzyMatchFnMode mode);
}

View File

@ -3,6 +3,7 @@ package edu.stanford.nlp.sempre;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import fig.basic.*;
import fig.exec.Execution;
@ -13,13 +14,14 @@ import java.util.*;
/**
* The grammar is a set of rules of the form:
* (rule lhsCat (rhs ... rhs) semanticFn (key value) ... (key value))
*
* Some programming-language-esque features are supported to make life easier.
* All grammar-file variables should start with '@' (both loop variables and global definitions).
*
* Includes (reads in commands from the given file):
* (include base.grammar)
* Control flow:
* (when (and tag1 (not tag2)) ...)
* (when (and tag1 (not tag2) (or tag3 tag4)) ...)
* Macro definitions:
* (def @type fb:type.object.type)
* Iteration:
@ -33,6 +35,8 @@ public class Grammar {
@Option(gloss = "Variables which are used to interpret the grammar file")
public List<String> tags = new ArrayList<>();
@Option public boolean binarizeRules = true;
@Option(gloss = "Specifiy which ApplyFn to use: defaults to JoinFn when null")
public String useApplyFn = null;
}
public static Options opts = new Options();
@ -40,10 +44,11 @@ public class Grammar {
// All the rules in the grammar. Each parser can read these and transform
// them however the parser wishes.
// This contains binarized rules
ArrayList<Rule> rules = new ArrayList<>();
protected ArrayList<Rule> rules = new ArrayList<>();
public List<Rule> getRules() { return rules; }
Map<String, LispTree> macros = new HashMap<>(); // Map from macro name to its replacement value
Set<String> validTags = new TreeSet<>(); // All tags in the grammar file
// Verbatim copy of all the lines read, so we can preserve the grammar file.
List<String> statements = new ArrayList<>();
@ -80,6 +85,15 @@ public class Grammar {
}
}
}
// Check if all tags are defined in a grammar file
LogInfo.logs("Valid tags: %s", validTags);
LogInfo.logs("Used tags: %s", new TreeSet<>(opts.tags));
for (String tag : opts.tags) {
if (!validTags.contains(tag)) {
LogInfo.warnings("Tag %s not defined in grammar", tag);
}
}
}
/**
@ -100,12 +114,24 @@ public class Grammar {
addStatement(stmt, null);
}
private static boolean isValidVar(String var) {
return var.startsWith("@");
}
private static void checkIsValidVar(String var) {
if (!isValidVar("@"))
throw new RuntimeException("Invalid variable: '" + var + "' doesn't start with '@'");
}
// Replace all leaves of LispTree with value in macros if exists
private static LispTree applyMacros(Map<String, LispTree> macros, LispTree tree) {
if (tree.isLeaf()) {
LispTree replacement = macros.get(tree.value);
if (replacement != null) return replacement;
return tree;
if (isValidVar(tree.value))
throw new RuntimeException("Undefined macro: " + tree.value);
else
return tree;
}
LispTree newTree = LispTree.proto.newList();
for (LispTree child : tree.children)
@ -126,8 +152,11 @@ public class Grammar {
statements.add(line);
Iterator<LispTree> trees = LispTree.proto.parseFromFile(path);
while (trees.hasNext())
interpret(path, trees.next(), tags);
while (trees.hasNext()) {
LispTree tree = trees.next();
interpret(path, tree, tags);
collectValidTags(tree);
}
}
public void write() {
@ -180,16 +209,28 @@ public class Grammar {
private boolean interpretBoolean(LispTree tree, Set<String> tags) {
if (tree.isLeaf())
return tags.contains(tree.value);
if ("not".equals(tree.child(0).value))
if ("not".equals(tree.child(0).value)) {
if (tree.children.size() != 2)
throw new RuntimeException("Too many arguments for not: " + tree);
return !interpretBoolean(tree.child(1), tags);
if ("and".equals(tree.child(0).value))
return interpretBoolean(tree.child(1), tags) && interpretBoolean(tree.child(2), tags);
}
if ("and".equals(tree.child(0).value)) {
for (int i = 1; i < tree.children.size(); i++)
if (!interpretBoolean(tree.child(i), tags)) return false;
return true;
}
if ("or".equals(tree.child(0).value)) {
for (int i = 1; i < tree.children.size(); i++)
if (interpretBoolean(tree.child(i), tags)) return true;
return false;
}
throw new RuntimeException("Expected a single tag, but got: " + tree);
}
public void interpretMacroDef(LispTree tree) {
if (tree.children.size() != 3 || !tree.child(1).isLeaf()) {
throw new RuntimeException("Invalid usage: (def |name| |value|)");
throw new RuntimeException("Invalid usage (def |name| |value|): " + tree);
}
String var = tree.child(1).value;
checkIsValidVar(var);
@ -198,9 +239,8 @@ public class Grammar {
public void interpretFor(String path, LispTree tree, Set<String> tags) {
if (tree.children.size() <= 3 || !tree.child(1).isLeaf()) {
throw new RuntimeException("Invalid usage: (for |var| (|value| ... |value|) |statement| ...)");
throw new RuntimeException("Invalid usage (for |var| (|value| ... |value|) |statement| ...) " + tree);
}
String var = tree.child(1).value;
checkIsValidVar(var);
List<LispTree> values = applyMacros(tree.child(2)).children;
@ -214,7 +254,13 @@ public class Grammar {
else macros.put(var, old);
}
private void interpretRule(LispTree tree) {
private static String checkCatName(String cat) {
if (isIntermediate(cat))
LogInfo.warnings("Category '%s' starts with '$Intermediate'; please avoid this unless you know what you are doing.");
return cat;
}
protected void interpretRule(LispTree tree) {
if (tree.children.size() < 4)
throw new RuntimeException("Invalid rule: " + tree);
@ -224,7 +270,7 @@ public class Grammar {
// Parse LHS
if (!tree.child(1).isLeaf())
throw new RuntimeException("Invalid LHS: " + tree.child(1));
String lhs = tree.child(1).value;
String lhs = checkCatName(tree.child(1).value);
// Parse RHS
List<String> rhs = Lists.newArrayList();
@ -236,12 +282,12 @@ public class Grammar {
LispTree child = rhsTree.child(i);
boolean isOptional = false;
if (child.isLeaf()) { // $PHRASE
rhs.add(child.value);
rhs.add(checkCatName(child.value));
} else {
// e.g., ($PHRASE optional)
// First item is the token/category; the rest of the items
// specify parameters (currently, only parameter is optional).
rhs.add(child.child(0).value);
rhs.add(checkCatName(child.child(0).value));
for (int j = 1; j < child.children.size(); j++)
if (child.child(j).value.equals("optional"))
isOptional = true;
@ -269,24 +315,61 @@ public class Grammar {
addRule(rule, isOptionals);
}
public synchronized boolean addRule(Rule rule) {
public synchronized void addRule(Rule rule) {
List<Boolean> isOptionals = new ArrayList<>();
for (String rhs : rule.rhs) isOptionals.add(false);
return addRule(rule, isOptionals);
for (int i = 0; i < rule.rhs.size(); i++) isOptionals.add(false);
addRule(rule, isOptionals);
}
// Add a rule to the grammar.
public synchronized boolean addRule(Rule rule, List<Boolean> isOptionals) {
public synchronized void addRule(Rule rule, List<Boolean> isOptionals) {
rules.addAll(binarizeRule(rule, isOptionals));
return true;
}
private void collectValidTags(LispTree tree) {
if (tree.isLeaf())
throw new RuntimeException("Expected list, got " + tree);
try {
String command = tree.child(0).value;
if ("when".equals(command)) {
collectValidTagsBoolean(tree.child(1));
for (int i = 2; i < tree.children.size(); i++)
collectValidTags(tree.child(i));
} else if ("for".equals(command)) {
for (int i = 3; i < tree.children.size(); i++)
collectValidTags(tree.child(i));
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error on " + tree + ": " + e);
}
}
private void collectValidTagsBoolean(LispTree tree) {
if (tree.isLeaf()) {
validTags.add(tree.value);
return;
}
String command = tree.child(0).value;
if ("not".equals(command))
collectValidTagsBoolean(tree.child(1));
else if ("and".equals(command) || "or".equals(command))
for (int i = 1; i < tree.children.size(); i++)
collectValidTagsBoolean(tree.child(i));
}
// Generate intermediate categories for binarization.
private int freshCatIndex = 0;
public static final String INTERMEDIATE_PREFIX = "$Intermediate";
protected int freshCatIndex = 0;
private String generateFreshCat() {
freshCatIndex++;
return "$Intermediate" + freshCatIndex;
// return "$I" + freshCatIndex + ":" + content;
return INTERMEDIATE_PREFIX + freshCatIndex;
}
public static boolean isIntermediate(String cat) {
return cat.startsWith(INTERMEDIATE_PREFIX);
}
public int getFreshCatIndex() {
return freshCatIndex;
}
// Create multiple versions of this rule if there are optional RHS.
@ -297,6 +380,14 @@ public class Grammar {
private List<Rule> binarizeRule(Rule rule, List<Boolean> isOptionals) {
List<Rule> newRules = new ArrayList<>();
// Don't binarize: do same as before
if (!opts.binarizeRules) {
if (isOptionals.contains(true))
throw new RuntimeException("Can't have optionals if don't binarize: " + rule + " " + isOptionals);
newRules.add(rule);
return newRules;
}
// Special case: JoinFn with an arg0Fn but with multiple non-optional categories.
// In this case, we need to use arg0Fn on just the first such category, and
// then use function application on the rest.
@ -334,19 +425,11 @@ public class Grammar {
}
}
// Don't binarize: do same as before
if (!opts.binarizeRules) {
if (isOptionals.contains(true))
throw new RuntimeException("Can't have optionals if don't binarize: " + rule + " " + isOptionals);
newRules.add(rule);
return newRules;
}
if (!isOptionals.contains(false))
throw new RuntimeException("Can't have all RHS items be optional: " + rule + " " + isOptionals);
// Unaries: don't need to binarize
if (rule.rhs.size() == 1) {
// Zero-aries (for floating rules) and Unaries: don't need to binarize
if (rule.rhs.size() <= 1) {
newRules.add(rule);
return newRules;
}
@ -446,13 +529,20 @@ public class Grammar {
String name = tree.child(0).value;
// Syntactic sugar: (lambda x (var x)) => (JoinFn betaReduce forward (arg0 (lambda x (var x))))
// Syntactic sugar: (lambda x (f (var x))) => (useApplyFn (lambda x (f (var x))))
// defaults to (lambda x (var x)) => (JoinFn betaReduce forward (arg0 (lambda x (var x))))
if (name.equals("lambda")) {
LispTree newTree = LispTree.proto.newList();
newTree.addChild("JoinFn");
newTree.addChild("betaReduce");
newTree.addChild("forward");
newTree.addChild(LispTree.proto.newList("arg0", tree));
if (Grammar.opts.useApplyFn == null) {
newTree.addChild("JoinFn");
newTree.addChild("betaReduce");
newTree.addChild("forward");
newTree.addChild(LispTree.proto.newList("arg0", tree));
} else {
newTree.addChild(Grammar.opts.useApplyFn);
newTree.addChild(tree);
}
tree = newTree;
name = tree.child(0).value;
}
@ -470,8 +560,4 @@ public class Grammar {
return fn;
}
private void checkIsValidVar(String var) {
if (!var.startsWith("@"))
LogInfo.errors("Invalid variable: '%s' doesn't start with '@'", var);
}
}

View File

@ -1,14 +1,17 @@
package edu.stanford.nlp.sempre;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import fig.basic.MapUtils;
import fig.basic.Option;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -19,6 +22,17 @@ import java.util.Map;
* @author Percy Liang
*/
public class JavaExecutor extends Executor {
public static class Options {
@Option(gloss = "Whether to convert NumberValue to int/double") public boolean convertNumberValues = true;
@Option(gloss = "Print stack trace on exception") public boolean printStackTrace = false;
// the actual function will be called with the current ContextValue as its last argument if marked by contextPrefix
@Option(gloss = "Formula in the grammar whose name startsWith contextPrefix is context sensitive")
public String contextPrefix = "context:";
@Option(gloss = "Reduce verbosity by automatically appending, for example, edu.stanford.nlp.sempre to java calls")
public String classPathPrefix = ""; // e.g. "edu.stanford.nlp.sempre";
}
public static Options opts = new Options();
private static JavaExecutor defaultExecutor = new JavaExecutor();
// To simplify logical forms, define some shortcuts.
@ -78,6 +92,36 @@ public class JavaExecutor extends Executor {
public static String plus(String a, String b, String c, String d, String e) {
return a + b + c + d + e;
}
public static String plus(String a, String b, String c, String d, String e, String f) {
return a + b + c + d + e + f;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g) {
return a + b + c + d + e + f + g;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g, String h) {
return a + b + c + d + e + f + g + h;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g, String h, String i) {
return a + b + c + d + e + f + g + h + i;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g, String h, String i, String j) {
return a + b + c + d + e + f + g + h + i + j;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g, String h, String i, String j, String k) {
return a + b + c + d + e + f + g + h + i + j + k;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g, String h, String i, String j, String k, String l) {
return a + b + c + d + e + f + g + h + i + j + k + l;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g, String h, String i, String j, String k, String l, String m) {
return a + b + c + d + e + f + g + h + i + j + k + l + m;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g, String h, String i, String j, String k, String l, String m, String n) {
return a + b + c + d + e + f + g + h + i + j + k + l + m + n;
}
public static String plus(String a, String b, String c, String d, String e, String f, String g, String h, String i, String j, String k, String l, String m, String n, String o) {
return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o;
}
private static String toString(Object x) {
if (x instanceof String)
return (String) x;
@ -121,13 +165,13 @@ public class JavaExecutor extends Executor {
private static Object apply(LambdaFormula func, Object x) {
// Apply the function func to x. In order to do that, need to convert x into a value.
Formula formula = Formulas.lambdaApply(func, new ValueFormula<Value>(toValue(x)));
return defaultExecutor.processFormula(formula);
return defaultExecutor.processFormula(formula, null);
}
private static Object apply(LambdaFormula func, Object x, Object y) {
// Apply the function func to x and y. In order to do that, need to convert x into a value.
Formula formula = Formulas.lambdaApply(func, new ValueFormula<Value>(toValue(x)));
formula = Formulas.lambdaApply((LambdaFormula) formula, new ValueFormula<Value>(toValue(y)));
return defaultExecutor.processFormula(formula);
return defaultExecutor.processFormula(formula, null);
}
public static List<Integer> range(int start, int end) {
@ -142,36 +186,46 @@ public class JavaExecutor extends Executor {
// We can do beta reduction here since macro substitution preserves the
// denotation (unlike for lambda DCS).
formula = Formulas.betaReduction(formula);
try {
return new Response(toValue(processFormula(formula)));
return new Response(toValue(processFormula(formula, context)));
} catch (Exception e) {
e.printStackTrace();
// Comment this out if we expect lots of innocuous type checking failures
if (opts.printStackTrace) e.printStackTrace();
return new Response(ErrorValue.badJava(e.toString()));
}
}
private Object processFormula(Formula formula) {
private Object processFormula(Formula formula, ContextValue context) {
if (formula instanceof ValueFormula) // Unpack value and convert to object (e.g., for ints)
return toObject(((ValueFormula) formula).value);
if (formula instanceof CallFormula) { // Invoke the function.
// Recurse
CallFormula call = (CallFormula) formula;
Object func = processFormula(call.func);
Object func = processFormula(call.func, context);
List<Object> args = Lists.newArrayList();
for (Formula arg : call.args) {
args.add(processFormula(arg));
args.add(processFormula(arg, context));
}
if (!(func instanceof NameValue))
throw new RuntimeException("Invalid func: " + call.func + " => " + func);
String id = ((NameValue) func).id;
if (id.indexOf(opts.contextPrefix) != -1) {
args.add(context);
id = id.replace(opts.contextPrefix, "");
}
id = MapUtils.get(shortcuts, id, id);
// classPathPrefix, like edu.stanford.nlp.sempre.interactive
if (!Strings.isNullOrEmpty(opts.classPathPrefix) && !id.startsWith(".") && !id.startsWith(opts.classPathPrefix)) {
id = opts.classPathPrefix + "." + id;
}
if (id.startsWith(".")) // Instance method
if (id.startsWith(".")) // Instance method
return invoke(id.substring(1), args.get(0), args.subList(1, args.size()).toArray(new Object[0]));
else // Static method
return invoke(id, null, args.toArray(new Object[0]));
}
@ -199,7 +253,7 @@ public class JavaExecutor extends Executor {
// Convert a Value (which are specified in the formulas) to an Object (which
// many Java functions take).
private static Object toObject(Value value) {
if (value instanceof NumberValue) {
if (value instanceof NumberValue && opts.convertNumberValues) {
// Unfortunately, NumberValues don't make a distinction between ints and
// doubles, so this is a hack.
double x = ((NumberValue) value).value;
@ -252,6 +306,7 @@ public class JavaExecutor extends Executor {
int bestCost = INVALID_TYPE_COST;
for (Method m : methods) {
if (!m.getName().equals(methodName)) continue;
m.setAccessible(true);
nameMatches.add(m);
if (isStatic != Modifier.isStatic(m.getModifiers())) continue;
int cost = typeCastCost(m.getParameterTypes(), args);

Some files were not shown because too many files have changed in this diff Show More