Added tables and overnight modules

This commit is contained in:
Panupong Pasupat 2015-06-04 18:01:24 -07:00
parent b1cde3658a
commit 9178eb7322
166 changed files with 13834 additions and 527 deletions

23
.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
lib
fig
virtuoso-opensource
module-classes.txt
classes
libsempre
state
out
test-output
.project
.classpath
.settings
.idea
semparse.iml
*~
*.swp
*.bak
*.pyc
*.cache
*.DS_Store
java.hprof.txt

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.1: Semantic Parsing with Execution
## What is semantic parsing?

View File

@ -175,7 +175,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 +334,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 +375,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)

101
build.xml Normal file
View File

@ -0,0 +1,101 @@
<?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,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">
<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 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>
<!-- 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>

25
overnight/README.md Normal file
View File

@ -0,0 +1,25 @@
# Files for Building a Semantic Parser Overnight
## Setting up datasets
To generate canonical utterances, run
./pull-dependencies freebase overnight
make corenlp freebase overnight
./run @mode=genovernight-wrapper
Or, to generate each individual domain
./run @mode=genovernight @gen=1 @domain=<domain>
After turking and setting up the approprate example files, run
./run @mode=overnight @domain=<domain>
to run with all features.
To run with partial features, use the following commands:
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 - ./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

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

@ -143,6 +143,52 @@ 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', 'Data for semantic parsing with execution on tables', lambda {
pull('/u/nlp/data/semparse/wikitable/data', 'data/tables/', {:symlink => true})
pull('/u/nlp/data/semparse/wikitable/mturk-trivia-data/csv', 'data/tables/', {:symlink => true})
})
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})
})
############################################################

440
run
View File

@ -13,8 +13,21 @@ 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, '---'),
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
@ -23,7 +36,18 @@ def header(modules='core')
'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'),
@ -46,7 +70,11 @@ def figOpts; l(o('execDir', '_OUTPATH_'), o('overwriteExecDir'), o('addToView',
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])
@ -131,6 +159,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,7 +254,8 @@ 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...
@ -350,9 +380,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 +427,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,17 +436,18 @@ 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, rlwrap, '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, rlwrap, '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-freebase', 'Simple shell for using Freebase', lambda { |e| l(
@ -435,6 +477,382 @@ addMode('simple-freebase', 'Simple shell for using Freebase', lambda { |e| l(
nil) })
############################################################
# {2014-12-27} [Percy]: Overnight semantic parsing
addMode('overnight', 'Overnight semantic parsing', lambda { |e| l(
'rlwrap',
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(:domain, 'publications'),
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'),
o('OvernightDerivationPruningComputer.applyHardConstraints'),
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('PPDBModel.ppdbModelPath', lambda { |e| 'overnightData/' + e[:domain] + '-ppdb.txt' }), # codalab
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', 'lib/data/overnight/' + e[:domain] + '.word_alignments.heuristic'),
o('wordAlignmentPath', 'lib/data/overnight/' + e[:domain] + '.word_alignments.berkeley'),
#o('wordAlignmentPath', 'overnightData/' + e[:domain] + '.word_alignments.heuristic'), # codalab
#o('wordAlignmentPath', 'overnightData/' + e[:domain] + '.word_alignments.berkeley'),
nil),
o('phraseAlignmentPath', 'lib/data/overnight/' + e[:domain] + '.phrase_alignments'),
o('PPDBModel.ppdbModelPath', 'lib/data/overnight/' + e[:domain] + '-ppdb.txt'),
#o('phraseAlignmentPath', 'overnightData/' + e[:domain] + '.phrase_alignments'), # codalab
#o('PPDBModel.ppdbModelPath', 'overnightData/' + e[:domain] + '-ppdb.txt'),
o('DerivationPruner.pruningComputers', ['overnight.OvernightDerivationPruningComputer']),
o('Dataset.inPaths',
'train:lib/data/overnight/' + e[:domain] + '.paraphrases.train.examples',
'test:lib/data/overnight/' + e[:domain] + '.paraphrases.test.examples'),
#'train:overnightData/' + e[:domain] + '.paraphrases.train.examples', # codalab
#'test:overnightData/' + e[:domain] + '.paraphrases.test.examples'),
sel(:domain, {
'regex' => l(
letDefault(:data,0),
sel(:data,
l(o('Dataset.inPaths', 'train:lib/data/overnight/regex.paraphrases.train.examples')),
l(o('Dataset.inPaths', 'train:lib/data/overnight/regex.paraphrases.train.examples', 'test:lib/data/overnight/regex.examples.train.json')),
l(o('Dataset.inPaths', 'train:lib/data/overnight/regex.paraphrases.train.examples', 'test:lib/data/overnight/regex.examples.test.json')),
nil),
# selo(:debug, 'Dataset.inPaths', 'train:lib/data/overnight/regex.paraphrases.train.examples', 'train:regex/regex-debug.examples'),
o('executor', 'JavaExecutor'),
o('Builder.valueEvaluator', 'regex.RegexValueEvaluator'),
o('OvernightFeatureComputer.approxEmptyDenotation', 'true'),
# o('OvernightFeatureComputer.featureDomains', *regexFeatureDomains),
o('JavaExecutor.convertNumberValues', true),
o('Grammar.tags','generate','regex'),
o('lowerCaseTokens', false), # case sensitivity is important for correctness of regular expressions
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'),
nil),
'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'),
#o('Params.l1Reg','lazy'),
#o('Params.l1RegCoeff',0.00001),
o('OvernightDerivationPruningComputer.usePredicateDict'),
o('OvernightDerivationPruningComputer.predicateDictPath','lib/data/overnight/geo880.predicate.dict'),
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) })
def overnightFeatureDomains
[
'match',
'ppdb',
'skip-bigram',
'root',
'alignment',
'lexical',
'root_lexical',
'lf',
'simpleworld',
nil].compact
end
############################################################
# {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
rlwrap, header('core,tables,corenlp'),
# Select class
letDefault(:class, 'main'),
sel(:class, {
'main' => 'edu.stanford.nlp.sempre.Main',
'check' => 'edu.stanford.nlp.sempre.tables.test.DPParserChecker',
'align' => 'edu.stanford.nlp.sempre.tables.alignment.IBMAligner',
'dump' => 'edu.stanford.nlp.sempre.tables.serialize.SerializedDumper',
'load' => 'edu.stanford.nlp.sempre.tables.serialize.SerializedLoader',
'stats' => 'edu.stanford.nlp.sempre.tables.test.TableStatsComputer',
}),
# Fig parameters
selo(:cldir, 'execDir', '_OUTPATH_', '.'),
o('overwriteExecDir'), o('addToView', 0), o('jarFiles', 'libsempre/*'),
sel(:cldir, l(), '>/dev/null'),
# Set environment for table execution
o('executor', 'tables.lambdadcs.LambdaDCSExecutor'),
o('Builder.valueEvaluator', 'tables.TableValueEvaluator'),
o('TargetValuePreprocessor.targetValuePreprocessor', 'tables.TableValuePreprocessor'),
o('NumberFn.unitless'), o('NumberFn.alsoTestByConversion'),
o('TypeInference.typeLookup', 'tables.TableTypeLookup'),
o('JoinFn.specializedTypeCheck', false), o('JoinFn.typeInference', true),
# Parser
letDefault(:parser, 'floatsize'),
sel(:parser, {
'floatsize' => l(
o('Builder.parser', 'FloatingParser'),
o('useSizeInsteadOfDepth'),
o('FloatingParser.maxDepth', 15),
nil),
'baseline' => l(
o('Builder.parser', 'tables.baseline.TableBaselineParser'),
nil),
'dummy' => o('Builder.parser', 'tables.serialize.DummyParser'),
}),
o('FloatingParser.useAnchorsOnce', true),
letDefault(:pruning, 1),
sel(:pruning,
l(),
l(
o('DerivationPruner.pruningStrategies', *tablesPruningStrategies),
o('DerivationPruner.pruningComputers', 'tables.TableDerivationPruningComputer'),
nil),
nil),
# Grammar
tablesGrammarPaths,
# Dataset
letDefault(:data, 'none'),
letDefault(:unseen, 0),
tablesDataPaths,
# Verbosity
o('FeatureVector.ignoreZeroWeight'),
o('maxPrintedPredictions', 10), o('maxPrintedTrue', 10), o('logFeaturesLimit', 10),
letDefault(:verbose, 0),
sel(:verbose,
l(),
l(
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(),
l(
o('combineFromFloatingParser'),
sel(:unseen, unbalancedTrainDevSplit, l()),
o('maxTrainIters', 3),
o('showValues', false), o('showFirstValue'),
nil),
l(
# for dumping derivations (@class=dump)
# force unbalancedTrainDevSplit + combine from floating parser
o('combineFromFloatingParser'), o('DPParser.cheat'),
sel(:unseen, unbalancedTrainDevSplit, l()),
nil),
nil),
# Regularization
letDefault(:l1, 1),
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)),
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 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),
'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(),
'base' => l(
o('usePredicateLemma'), o('usePhraseLemmaOnly'),
nil),
'careful' => l(
o('usePredicateLemma'), o('usePhraseLemmaOnly'),
o('maxNforLexicalizeAllPairs', 2),
o('traverseWithFormulaTypes'), o('reverseNameValueConversion', 'allBang'),
o('lookUnderCellProperty'), o('useGenericCellType'),
o('computeFuzzyMatchPredicates'),
nil),
}),
nil) })
def tablesGrammarPaths
lambda { |e|
baseDir = ['tables/grammars/', 'grammars/'][e[:cldir]]
l(
letDefault(:grammar, 'combined-all'),
sel(:grammar, {
'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-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),
}),
nil)
}
end
def tablesDataPaths
lambda { |e|
baseDir = ['lib/data/tables/data/', 'WikiTableQuestions/data/'][e[:cldir]]
csvDir = ['lib/data/tables/', 'WikiTableQuestions/'][e[:cldir]]
datasets = {
'none' => l(),
# Pristine test test
'test' => l(
o('Dataset.inPaths',
"train,#{baseDir}training.examples",
"test,#{baseDir}pristine-unseen-tables.examples"),
o('Dataset.trainFrac', 1), o('Dataset.devFrac', 0),
let(:unseen, 1),
nil),
}
# 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-seed-#{x}-train.examples",
"dev,#{baseDir}random-split-seed-#{x}-test.examples",
nil),
let(:unseen, 1),
nil)
end
# That's it!
l(
o('TableKnowledgeGraph.baseCSVDir', csvDir),
sel(:data, datasets),
nil)
}
end
def tablesPruningStrategies
[
# Formula
"singleton",
"multipleSuperlatives",
"sameMerge",
"forwardBackward",
"doubleNext",
# Denotation
"emptyDenotation",
"nonLambdaError",
"tooManyValues",
"badSuperlativeHead",
"mistypedMerge",
nil].compact
end

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

@ -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

@ -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

@ -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

@ -49,6 +49,7 @@ public class AggregateFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof AggregateFormula)) return false;

View File

@ -65,6 +65,7 @@ public class ArithmeticFormula extends Formula {
}
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof ArithmeticFormula)) return false;

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

@ -56,6 +56,7 @@ public class CallFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof CallFormula)) return false;

View File

@ -13,10 +13,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,6 +31,24 @@ public final class CanonicalNames {
public static final String TYPE = "fb:type.object.type";
public static final String NAME = "fb:type.object.name";
// Unary: fb:domain.type [contains exactly one period]
// Binary: fb:domain.type.property, <, >, etc.
public static boolean isUnary(String s) {
int i = s.indexOf('.');
if (i == -1) return false;
i = s.indexOf('.', i + 1);
if (i == -1) return true;
return false;
}
public static boolean isBinary(String s) {
int i = s.indexOf('.');
if (i == -1) return false;
i = s.indexOf('.', i + 1);
if (i == -1) return false;
return true;
}
// Return whether |property| is the name of a reverse property.
// Convention: ! is the prefix for reverses.
public static boolean isReverseProperty(String property) {
@ -39,4 +59,5 @@ public final class CanonicalNames {
else return "!" + property;
}
}

View File

@ -77,6 +77,8 @@ public abstract class ChartParserState extends ParserState {
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<>());

View File

@ -33,6 +33,8 @@ 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;
@ -44,8 +46,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); }
@ -123,7 +125,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 +142,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 +175,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 +200,7 @@ public class Dataset {
allExamples.put(group, examples = new ArrayList<Example>());
readLispTreeHelper(path, maxExamples, examples);
}
splitDevFromTrain();
if (opts.splitDevFromTrain) splitDevFromTrain();
LogInfo.end_track();
}
@ -208,7 +218,7 @@ public class Dataset {
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;

View File

@ -24,6 +24,8 @@ 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 executing, show formulae (for debugging)")
public boolean showExecutions = false;
}
public static Options opts = new Options();
@ -34,7 +36,11 @@ 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;
private boolean[] anchoredTokens; // Tokens which anchored rules are defined on
// 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.
@ -58,6 +64,14 @@ public class Derivation implements SemanticFn.Callable, HasScore {
private final FeatureVector localFeatureVector; // Features
double score = Double.NaN; // Weighted combination of features
// 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;
public Evaluation executorStats;
@ -141,12 +155,14 @@ public class Derivation implements SemanticFn.Callable, HasScore {
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 +196,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 +208,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); }
@ -234,6 +256,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;
@ -304,7 +328,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 +343,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);
}
@ -404,4 +433,42 @@ 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();
}
// Compute anchoredTokens and return the result
// anchoredTokens[>= anchoredTokens.length] are False by default
public boolean[] getAnchoredTokens() {
if (anchoredTokens == null) {
if (rule.isAnchored()) {
anchoredTokens = new boolean[end];
for (int i = start; i < end; i++) anchoredTokens[i] = true;
} else {
anchoredTokens = new boolean[0];
for (Derivation child : children) {
boolean[] childAnchoredTokens = child.getAnchoredTokens();
if (anchoredTokens.length < childAnchoredTokens.length) {
boolean[] newAnchoredTokens = new boolean[childAnchoredTokens.length];
for (int i = 0; i < anchoredTokens.length; i++) newAnchoredTokens[i] = anchoredTokens[i];
anchoredTokens = newAnchoredTokens;
}
for (int i = 0; i < childAnchoredTokens.length; i++)
anchoredTokens[i] = anchoredTokens[i] || childAnchoredTokens[i];
}
}
}
return anchoredTokens.clone();
}
}

View File

@ -0,0 +1,214 @@
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 public List<String> pruningStrategies = new ArrayList<>();
@Option public List<String> pruningComputers = new ArrayList<>();
@Option public int pruningVerbosity = 0;
@Option public int maxNumValues = 10;
}
public static Options opts = new Options();
public final Parser parser;
public final Example ex;
private List<DerivationPruningComputer> pruningComputers = new ArrayList<>();
private List<String> customAllowedDomains;
public DerivationPruner(ParserState parserState) {
this.parser = parserState.parser;
this.ex = parserState.ex;
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);
}
}
}
public void setCustomAllowedDomains(List<String> customAllowedDomains) {
this.customAllowedDomains = customAllowedDomains;
}
protected boolean containsStrategy(String name) {
return opts.pruningStrategies.contains(name) &&
(customAllowedDomains == null || customAllowedDomains.contains(name));
}
public boolean isPruned(Derivation deriv) {
if (opts.pruningStrategies.isEmpty() && pruningComputers.isEmpty()) return false;
if (pruneFormula(deriv)) return true;
if (pruneDenotation(deriv)) return true;
for (DerivationPruningComputer pruningComputer : pruningComputers) {
if (pruningComputer.isPruned(deriv)) return true;
}
return false;
}
// ============================================================
// Formula-based Pruning
// ============================================================
private boolean pruneFormula(Derivation deriv) {
return pruneSingleton(deriv) || pruneSuperlatives(deriv) || pruneMerges(deriv);
}
/**
* Prune singleton formula at the root.
*/
private boolean pruneSingleton(Derivation deriv) {
if (!containsStrategy("singleton")) return false;
return deriv.isRoot(ex.numTokens()) && deriv.formula instanceof ValueFormula;
}
/**
* Prune strings of multiple superlatives.
*/
private boolean pruneSuperlatives(Derivation deriv) {
if (containsStrategy("doubleSuperlatives")) {
// Prune if there is an arg{max|min} whose head has arg{max|min}
if (deriv.formula instanceof SuperlativeFormula) {
SuperlativeFormula superlative = (SuperlativeFormula) deriv.formula;
if (superlative.head instanceof SuperlativeFormula) {
if (opts.pruningVerbosity >= 2)
LogInfo.logs("PRUNED [doubleSuperlatives] %s", deriv.formula);
return true;
}
}
}
if (containsStrategy("multipleSuperlatives")) {
// Prune if there are more than arg{max|min} appearing in the formula (don't need to be adjacent)
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) {
if (opts.pruningVerbosity >= 2)
LogInfo.logs("PRUNED [multipleSuperlatives] %s", deriv.formula);
return true;
}
}
} else {
for (LispTree subtree : tree.children)
stack.add(subtree);
}
}
}
return false;
}
/**
* Prune merges.
*/
private boolean pruneMerges(Derivation deriv) {
if (!(deriv.formula instanceof MergeFormula)) return false;
MergeFormula merge = (MergeFormula) deriv.formula;
if (containsStrategy("sameMerge")) {
if (merge.child1.equals(merge.child2)) {
if (opts.pruningVerbosity >= 2)
LogInfo.logs("PRUNED [sameMerge] %s", deriv.formula);
return true;
}
}
return false;
}
// ============================================================
// Denotation-based Pruning
// ============================================================
/**
* Pruning based on denotations.
*/
private boolean pruneDenotation(Derivation deriv) {
return pruneFinalDenotation(deriv) || prunePartialDenotation(deriv);
}
private boolean pruneFinalDenotation(Derivation deriv) {
Formula formula = deriv.formula;
// Prune if the denotation is an empty list
if (containsStrategy("emptyDenotation")) {
deriv.ensureExecuted(parser.executor, ex.context);
if (deriv.value instanceof ListValue) {
if (((ListValue) deriv.value).values.isEmpty()) {
if (opts.pruningVerbosity >= 3)
LogInfo.logs("PRUNED [emptyDenotation] %s", formula);
return true;
}
}
}
// Prune if the denotation is an error and the formula is not a partial formula
if (containsStrategy("nonLambdaError") && !(deriv.formula instanceof LambdaFormula)) {
deriv.ensureExecuted(parser.executor, ex.context);
if (deriv.value instanceof ErrorValue) {
if (opts.pruningVerbosity >= 3)
LogInfo.logs("PRUNED [nonLambdaError] %s", formula);
return true;
}
}
// Prune if the denotation has too many values
if (containsStrategy("tooManyValues") && deriv.isRoot(ex.numTokens())) {
deriv.ensureExecuted(parser.executor, ex.context);
if (deriv.value instanceof ListValue) {
if (((ListValue) deriv.value).values.size() > opts.maxNumValues) {
if (opts.pruningVerbosity >= 3)
LogInfo.logs("PRUNED [tooManyValues] %s", formula);
return true;
}
}
}
return false;
}
private boolean prunePartialDenotation(Derivation deriv) {
Formula formula = deriv.formula;
if (containsStrategy("badSuperlativeHead")) {
Formula head = null;
if (formula instanceof AggregateFormula)
head = ((AggregateFormula) formula).child;
else if (formula instanceof SuperlativeFormula)
head = ((SuperlativeFormula) formula).head;
if (head != null) {
Value headValue = parser.executor.execute(head, ex.context).value;
if (headValue instanceof ListValue && ((ListValue) headValue).values.size() < 2) {
if (opts.pruningVerbosity >= 3)
LogInfo.logs("PRUNED [badSuperlativeHead] %s", formula);
return true;
}
}
}
if (containsStrategy("mistypedMerge") && formula instanceof MergeFormula) {
MergeFormula merge = (MergeFormula) formula;
SemType type1 = TypeInference.inferType(merge.child1);
SemType type2 = TypeInference.inferType(merge.child2);
if (!type1.meet(type2).isValid()) {
if (opts.pruningVerbosity >= 2)
LogInfo.logs("PRUNED [mistypedMerge] %s", deriv.formula);
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,25 @@
package edu.stanford.nlp.sempre;
/**
* 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;
public DerivationPruningComputer(DerivationPruner pruner) {
this.pruner = pruner;
}
protected boolean containsStrategy(String name) {
return pruner.containsStrategy(name);
}
public abstract boolean 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
@ -41,13 +39,16 @@ public class Example {
@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 struture).
private Map<String, Object> tempState;
// Statistics relating to processing the example.
public Evaluation evaluation;
@ -133,6 +134,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)) {
@ -162,7 +165,7 @@ public class Example {
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 (!Sets.newHashSet("id", "utterance", "targetFormula", "targetValue", "targetValues", "context", "original").contains(label)) {
throw new RuntimeException("Invalid example argument: " + arg);
}
}
@ -170,8 +173,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);
}
public void log() {
@ -191,11 +195,6 @@ public class Example {
LogInfo.end_track();
}
// To save memory
public void clearPredDerivations() {
predDerivations.clear();
}
public List<Derivation> getCorrectDerivations() {
List<Derivation> res = new ArrayList<>();
for (Derivation deriv : predDerivations) {
@ -290,4 +289,14 @@ public class Example {
return item;
}
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;
}
}

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 = edu.stanford.nlp.io.IOUtils.getPrintWriter(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,53 @@ 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();
}
//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()));
}
}
@ -229,7 +234,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 +264,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 +274,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

@ -17,6 +17,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 +98,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 +243,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;
@ -46,7 +48,18 @@ public class FloatingParser extends Parser {
@Option public boolean defaultIsFloating = true;
@Option (gloss = "Flag specifying whether anchored spans/tokens can only be used once in a derivation")
public boolean useAnchorsOnce = false;
@Option (gloss = "Flag specifying whether floating rules are allowed to be applied consecutively")
public boolean consecutiveRules = true;
@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 = "Put a limit on formula size instead of formula depth")
public boolean useSizeInsteadOfDepth = false;
@Option(gloss = "Custom beam size at training time (default = Parser.beamSize)")
public int trainBeamSize = -1;
}
public static Options opts = new Options();
public FloatingParser(Spec spec) { super(spec); }
@ -70,12 +83,25 @@ class FloatingParserState extends ParserState {
// Examples of state:
// (category, depth)
// (category, depth, set of tokens)
private final Map<Object, List<Derivation>> chart = new HashMap<>();
private final DerivationPruner pruner;
public FloatingParserState(FloatingParser parser, Params params, Example ex, boolean computeExpectedCounts) {
super(parser, params, ex, computeExpectedCounts);
pruner = new DerivationPruner(this);
}
@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;
@ -88,10 +114,11 @@ class FloatingParserState extends ParserState {
}
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);
}
@ -103,29 +130,32 @@ class FloatingParserState extends ParserState {
else if (child2 == null) // 1-ary
children = Collections.singletonList(child1);
else {
children = ListUtils.newList(child1, child2);
// optionally: ensure that specific anchors are only used once per final derivation
// Optional: ensure that each anchor is only used once per derivation.
if (FloatingParser.opts.useAnchorsOnce &&
FloatingRuleUtils.derivationAnchorsOverlap(child1, child2))
FloatingRuleUtils.derivationAnchorsOverlap(child1, child2))
return;
children = ListUtils.newList(child1, child2);
}
// 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));
new SemanticFn.CallInfo(rule.lhs, start, end, rule, children));
while (results.hasNext()) {
Derivation newDeriv = results.next();
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);
@ -236,19 +266,30 @@ class FloatingParserState extends ParserState {
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) {
for (int depth1 = 0; depth1 < depth; depth1++) {
int depth2 = depth - 1 - depth1;
List<Derivation> derivations1 = getDerivations(floatingCell(rhs1, depth1));
List<Derivation> derivations2 = getDerivations(floatingCell(rhs2, depth2));
for (Derivation deriv1 : derivations1)
for (Derivation deriv2 : derivations2)
applyFloatingRule(rule, depth, deriv1, deriv2, deriv1.canonicalUtterance + " " + deriv2.canonicalUtterance);
}
} else {
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);
}
}
}
}
@ -289,14 +330,6 @@ class FloatingParserState extends ParserState {
buildAnchored(i, i + len);
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());
}
}*/
pruneCell(cell, chart.get(cell));
}
}
@ -307,14 +340,6 @@ class FloatingParserState extends ParserState {
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));
}
}
@ -339,9 +364,29 @@ class FloatingParserState extends ParserState {
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());
}
private void visualizeAnchoredChart(Set<String> categories) {
for (String cat : categories) {
for (int len = 1; len <= numTokens; ++len) {

View File

@ -31,6 +31,7 @@ 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) {
@ -40,5 +41,10 @@ public final class FloatingRuleUtils {
}
}
return false;
*/
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;
}
}

View File

@ -50,6 +50,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

@ -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 TableKnowledgeGraph or PuzzleKnowledgeGraph.
*
* @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,6 +30,11 @@ 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);
}
}
@ -57,7 +63,7 @@ public class FuzzyMatchFn extends SemanticFn {
this.ex = ex;
this.graph = (ex.context == null) ? null : ex.context.graph;
this.c = c;
this.query = matchAny ? null : c.childStringValue(0);
this.query = (matchAny || c.getChildren().isEmpty()) ? null : c.childStringValue(0);
this.mode = mode;
this.matchAny = matchAny;
if (opts.verbose >= 2)
@ -68,6 +74,7 @@ public class FuzzyMatchFn extends SemanticFn {
@Override
public Derivation createDerivation() {
if (graph == null) return null;
if (query == null && !matchAny) return null;
// Compute the formulas if not computed yet
if (formulas == null) {

View File

@ -184,6 +184,8 @@ public class Grammar {
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 ("or".equals(tree.child(0).value))
return interpretBoolean(tree.child(1), tags) || interpretBoolean(tree.child(2), tags);
throw new RuntimeException("Expected a single tag, but got: " + tree);
}

View File

@ -3,12 +3,13 @@ package edu.stanford.nlp.sempre;
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 +20,12 @@ 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;
}
public static Options opts = new Options();
private static JavaExecutor defaultExecutor = new JavaExecutor();
// To simplify logical forms, define some shortcuts.
@ -78,6 +85,12 @@ 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;
}
private static String toString(Object x) {
if (x instanceof String)
return (String) x;
@ -146,7 +159,8 @@ public class JavaExecutor extends Executor {
try {
return new Response(toValue(processFormula(formula)));
} 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()));
}
}
@ -156,6 +170,7 @@ public class JavaExecutor extends Executor {
return toObject(((ValueFormula) formula).value);
if (formula instanceof CallFormula) { // Invoke the function.
//LogInfo.logs("formula=%s", formula);
// Recurse
CallFormula call = (CallFormula) formula;
Object func = processFormula(call.func);
@ -170,8 +185,9 @@ public class JavaExecutor extends Executor {
String id = ((NameValue) func).id;
id = MapUtils.get(shortcuts, id, 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 +215,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 +268,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);

View File

@ -24,6 +24,8 @@ public class JoinFn extends SemanticFn {
@Option(gloss = "Verbose") public int verbose = 0;
@Option public boolean showTypeCheckFailures = false;
@Option public boolean typeInference = false;
// TODO(joberant): this flag is for backward compatibility. If we don't
// need it for the new results, get rid of it.
@Option public boolean specializedTypeCheck = true;
}

View File

@ -51,6 +51,7 @@ public class JoinFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof JoinFormula)) return false;

View File

@ -25,8 +25,13 @@ public abstract class KnowledgeGraph {
String className = tree.child(1).value;
Class<?> classObject = Class.forName(SempreUtils.resolveClassName(className));
return (KnowledgeGraph) classObject.getDeclaredMethod("fromLispTree", LispTree.class).invoke(null, tree);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException | ClassNotFoundException e) {
} catch (InvocationTargetException e) {
e.getCause().printStackTrace();
LogInfo.fail(e.getCause());
throw new RuntimeException(e);
} catch (IllegalAccessException | IllegalArgumentException |
NoSuchMethodException | SecurityException | ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
} else {

View File

@ -39,6 +39,7 @@ public class LambdaFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof LambdaFormula)) return false;

View File

@ -35,6 +35,9 @@ public class LanguageInfo implements MemUsage.Instrumented {
public final List<String> nerValues; // NER values (contains times, dates, etc.)
private Map<String, IntPair> lemmaSpans;
private Set<String> lowercasedSpans;
public static class DependencyEdge {
@JsonProperty
@ -291,7 +294,7 @@ public class LanguageInfo implements MemUsage.Instrumented {
public Map<String, IntPair> getLemmaSpans() {
if (lemmaSpans == null) {
lemmaSpans = new HashMap<String, IntPair>();
lemmaSpans = new HashMap<>();
for (int i = 0; i < numTokens() - 1; ++i) {
for (int j = i + 1; j < numTokens(); ++j)
lemmaSpans.put(lemmaPhrase(i, j), new IntPair(i, j));
@ -300,6 +303,17 @@ public class LanguageInfo implements MemUsage.Instrumented {
return lemmaSpans;
}
public Set<String> getLowerCasedSpans() {
if (lowercasedSpans == null) {
lowercasedSpans = new HashSet<>();
for (int i = 0; i < numTokens() - 1; ++i) {
for (int j = i + 1; j < numTokens(); ++j)
lowercasedSpans.add(phrase(i, j).toLowerCase());
}
}
return lowercasedSpans;
}
public boolean matchLemmas(List<WordInfo> wordInfos) {
for (int i = 0; i < numTokens(); ++i) {
if (matchLemmasFromIndex(wordInfos, i))
@ -324,6 +338,7 @@ public class LanguageInfo implements MemUsage.Instrumented {
*
*/
public static class LanguageUtils {
public static boolean sameProperNounClass(String noun1, String noun2) {
if ((noun1.equals("NNP") || noun1.equals("NNPS")) &&
(noun2.equals("NNP") || noun2.equals("NNPS")))
@ -335,6 +350,10 @@ public class LanguageInfo implements MemUsage.Instrumented {
return pos.startsWith("NNP");
}
public static boolean isSuperlative(String pos) { return pos.equals("RBS") || pos.equals("JJS"); }
public static boolean isComparative(String pos) { return pos.equals("RBR") || pos.equals("JJR"); }
public static boolean isEntity(LanguageInfo info, int i) {
return isProperNoun(info.posTags.get(i)) || !(info.nerTags.get(i).equals("O"));
}
@ -361,6 +380,30 @@ public class LanguageInfo implements MemUsage.Instrumented {
if (pos.startsWith("W")) return "W";
return pos;
}
// Uses a few rules to stem tokens
public static String stem(String a) {
int i = a.indexOf(' ');
if (i != -1)
return stem(a.substring(0, i)) + ' ' + stem(a.substring(i + 1));
//Maybe we should just use the Stanford stemmer
String res = a;
//hard coded words
if (a.equals("having") || a.equals("has")) res = "have";
else if (a.equals("using")) res = "use";
else if (a.equals("including")) res = "include";
else if (a.equals("beginning")) res = "begin";
else if (a.equals("utilizing")) res = "utilize";
else if (a.equals("featuring")) res = "feature";
else if (a.equals("preceding")) res = "precede";
//rules
else if (a.endsWith("ing")) res = a.substring(0, a.length() - 3);
else if (a.endsWith("s") && !a.equals("'s")) res = a.substring(0, a.length() - 1);
//don't return an empty string
if (res.length() > 0) return res;
return a;
}
}
@Override

View File

@ -59,11 +59,11 @@ public class Learner {
this.params = params;
this.dataset = dataset;
this.eventsOut = IOUtils.openOutAppendEasy(Execution.getFile("learner.events"));
if (opts.initialization != null)
if (opts.initialization != null && this.params.isEmpty())
this.params.init(opts.initialization);
// collect all semantic functions to update
semFuncsToUpdate = new ArrayList<>();
// Collect all semantic functions to update.
semFuncsToUpdate = new ArrayList<>();
for (Rule rule : parser.grammar.getRules()) {
SemanticFn currSemFn = rule.getSem();
boolean toAdd = true;
@ -125,11 +125,6 @@ public class Learner {
Utils.systemHard("ln -sf params." + iter + " " + Execution.getFile("params"));
}
// Write out examples and predictions
if (opts.outputPredDerivations)
for (String group : dataset.groups())
ExampleUtils.writeSDF(iter, group, meanEvaluations.get(group), dataset.examples(group), opts.outputPredDerivations);
LogInfo.end_track();
}
LogInfo.end_track();
@ -199,6 +194,11 @@ public class Learner {
if (opts.addFeedback && computeExpectedCounts)
addFeedback(ex);
// Write out examples and predictions
if (opts.outputPredDerivations && Builder.opts.parser.equals("FloatingParser")) {
ExampleUtils.writeParaphraseSDF(iter, group, ex, opts.outputPredDerivations);
}
// To save memory
ex.predDerivations.clear();
}
@ -212,6 +212,7 @@ public class Learner {
LogInfo.end_track();
logEvaluationStats(evaluation, prefix);
printLearnerEventsSummary(evaluation, iter, group);
ExampleUtils.writeEvaluationSDF(iter, group, evaluation, examples.size());
LogInfo.end_track();
return evaluation;
}

View File

@ -46,6 +46,7 @@ public class MarkFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof MarkFormula)) return false;

View File

@ -19,11 +19,16 @@ public class Master {
public static class Options {
@Option(gloss = "Execute these commands before starting")
public List<String> scriptPaths = Lists.newArrayList();
@Option(gloss = "Write out input lines to this path")
@Option(gloss = "Execute these commands before starting (after scriptPaths)")
public List<String> commands = Lists.newArrayList();
@Option(gloss = "Write a log of this session to this path")
public String logPath;
@Option(gloss = "Print help on startup")
public boolean printHelp = true;
@Option(gloss = "Number of exchanges to keep in the context")
public int contextMaxExchanges = 1;
public int contextMaxExchanges = 0;
@Option(gloss = "Online update weights on new examples.")
public boolean onlineLearnExamples = true;
@ -93,6 +98,8 @@ public class Master {
session = new Session(id);
for (String path : opts.scriptPaths)
processScript(session, path);
for (String command : opts.commands)
processQuery(session, command);
if (id != null)
sessions.put(id, session);
}
@ -116,13 +123,14 @@ public class Master {
LogInfo.log(" (execute |logical form|): execute the logical form (e.g., (execute (call + (number 3) (number 4))))");
LogInfo.log(" (def |key| |value|): define a macro to replace |key| with |value| in all commands (e.g., (def type fb:type.object type)))");
LogInfo.log(" (context [(user |user|) (date |date|) (exchange |exchange|) (graph |graph|)]): prints out or set the context");
LogInfo.log("Press Ctrl-D to exit.");
}
public void runInteractivePrompt() {
Session session = getSession("stdin");
printHelp();
LogInfo.log("Press Ctrl-D to exit.");
if (opts.printHelp)
printHelp();
while (true) {
LogInfo.stdout.print("> ");
@ -215,12 +223,13 @@ public class Master {
b.setContext(session.context);
Example ex = b.createExample();
ex.preprocess(LanguageAnalyzer.getSingleton());
ex.preprocess();
// Parse!
builder.parser.parse(builder.params, ex, false);
response.ex = ex;
ex.log();
if (ex.predDerivations.size() > 0) {
response.candidateIndex = 0;
printDerivation(response.getDerivation());

View File

@ -51,6 +51,7 @@ public class MergeFormula extends Formula {
return null;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof MergeFormula)) return false;

View File

@ -50,6 +50,11 @@ public class NaiveKnowledgeGraph extends KnowledgeGraph {
tree.addChild(e2.toLispTree());
return tree;
}
@Override
public String toString() {
return "<" + e1 + ", " + r + ", " + e2 + ">";
}
}
// Simplest graph representation: triples of values

View File

@ -35,6 +35,7 @@ public class NotFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof NotFormula)) return false;

View File

@ -10,6 +10,13 @@ import fig.basic.*;
* @author Percy Liang
*/
public class NumberFn extends SemanticFn {
public static class Options {
@Option(gloss = "Omit units") public boolean unitless = false;
@Option(gloss = "Also test numbers by try converting to float (instead of using NER tags)")
public boolean alsoTestByConversion = false;
}
public static Options opts = new Options();
private List<String> requests; // List of types of fields to get (e.g., NUMBER)
private boolean request(String req) {
@ -37,10 +44,10 @@ public class NumberFn extends SemanticFn {
NumberValue numberValue = new NumberValue(Double.parseDouble(value));
SemType type = numberValue.value == (int) numberValue.value ? SemType.intType : SemType.floatType;
return new Derivation.Builder()
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
} catch (NumberFormatException e) {
LogInfo.warnings("NumberFn: Cannot convert NerSpan \"%s\" to a number", value);
}
@ -52,13 +59,15 @@ public class NumberFn extends SemanticFn {
String value = ex.languageInfo.getNormalizedNerSpan("ORDINAL", c.getStart(), c.getEnd());
if (value != null) {
try {
NumberValue numberValue = new NumberValue(Double.parseDouble(value), "fb:en.ordinal_number");
NumberValue numberValue = (opts.unitless ?
new NumberValue(Double.parseDouble(value)) :
new NumberValue(Double.parseDouble(value), "fb:en.ordinal_number"));
SemType type = SemType.intType;
return new Derivation.Builder()
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
} catch (NumberFormatException e) {
LogInfo.warnings("NumberFn: Cannot convert NerSpan \"%s\" to a number", value);
}
@ -70,13 +79,15 @@ public class NumberFn extends SemanticFn {
String value = ex.languageInfo.getNormalizedNerSpan("PERCENT", c.getStart(), c.getEnd());
if (value != null) {
try {
NumberValue numberValue = new NumberValue(0.01 * Double.parseDouble(value.substring(1)));
NumberValue numberValue = (opts.unitless ?
new NumberValue(Double.parseDouble(value.substring(1))) :
new NumberValue(0.01 * Double.parseDouble(value.substring(1))));
SemType type = SemType.floatType;
return new Derivation.Builder()
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
} catch (NumberFormatException e) {
LogInfo.warnings("NumberFn: Cannot convert NerSpan \"%s\" to a number", value);
}
@ -88,19 +99,39 @@ public class NumberFn extends SemanticFn {
String value = ex.languageInfo.getNormalizedNerSpan("MONEY", c.getStart(), c.getEnd());
if (value != null) {
try {
NumberValue numberValue = new NumberValue(Double.parseDouble(value.substring(1)), "fb:en.dollar");
NumberValue numberValue = (opts.unitless ?
new NumberValue(Double.parseDouble(value.substring(1))) :
new NumberValue(Double.parseDouble(value.substring(1)), "fb:en.dollar"));
SemType type = SemType.floatType;
return new Derivation.Builder()
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
} catch (NumberFormatException e) {
LogInfo.warnings("NumberFn: Cannot convert NerSpan \"%s\" to a number", value);
}
}
}
// Test by converting string to number directly (don't look at NER)
if (opts.alsoTestByConversion && request("NUMBER") & c.getEnd() - c.getStart() == 1) {
String value = ex.languageInfo.tokens.get(c.getStart());
if (value != null) {
try {
NumberValue numberValue = new NumberValue(Double.parseDouble(value));
SemType type = numberValue.value == (int) numberValue.value ? SemType.intType : SemType.floatType;
return new Derivation.Builder()
.withCallable(c)
.formula(new ValueFormula<>(numberValue))
.type(type)
.createDerivation();
} catch (NumberFormatException e) {
// Don't issue warnings; most spans are not numbers
}
}
}
return null;
}
};

View File

@ -33,6 +33,7 @@ public class Params {
@Option(gloss = "Use dual averaging") public boolean dualAveraging = false;
@Option(gloss = "Whether to do lazy l1 reg updates") public String l1Reg = "none";
@Option(gloss = "L1 reg coefficient") public double l1RegCoeff = 0d;
@Option(gloss = "Lazy L1 full update frequency") public int lazyL1FullUpdateFreq = 5000;
}
public static Options opts = new Options();
public enum L1Reg {
@ -49,7 +50,7 @@ public class Params {
private L1Reg l1Reg = parseReg(opts.l1Reg);
// Discriminative weights
private HashMap<String, Double> weights = new HashMap<>();
private Map<String, Double> weights = new HashMap<>();
// For AdaGrad
Map<String, Double> sumSquaredGradients = new HashMap<>();
@ -110,13 +111,12 @@ public class Params {
// Update weights by adding |gradient| (modified appropriately with step size).
public synchronized void update(Map<String, Double> gradient) {
numUpdates++;
for (Map.Entry<String, Double> entry : gradient.entrySet()) {
String f = entry.getKey();
double g = entry.getValue();
if (g * g == 0) continue; // In order to not divide by zero
if (l1Reg == L1Reg.LAZY) lazyL1Update(f);
double stepSize = computeStepSize(f, g);
if (opts.dualAveraging) {
@ -132,17 +132,25 @@ public class Params {
throw new RuntimeException("Gradient absolute value is too large or too small");
}
MapUtils.incr(weights, f, stepSize * g);
if (l1Reg == L1Reg.LAZY) l1UpdateTimeMap.put(f, numUpdates);
}
}
// non lazy implementation goes over all weights
if (l1Reg == L1Reg.NONLAZY) {
Set<String> features = new HashSet<String>(weights.keySet());
for (String f :features) {
for (String f : features) {
double stepSize = computeStepSize(f, 0d); // no update for gradient here
double update = opts.l1RegCoeff * -Math.signum(MapUtils.getDouble(weights, f, opts.defaultWeight));
clipUpdate(f, stepSize * update);
}
}
numUpdates++;
if (l1Reg == L1Reg.LAZY && opts.lazyL1FullUpdateFreq > 0 && numUpdates % opts.lazyL1FullUpdateFreq == 0) {
LogInfo.begin_track("Fully apply L1 regularization.");
finalizeWeights();
System.gc();
LogInfo.end_track();
}
}
private double computeStepSize(String feature, double gradient) {
@ -174,20 +182,24 @@ public class Params {
}
private void lazyL1Update(String f) {
if (MapUtils.getDouble(weights, f, 0.0) == 0) return;
// For pre-initialized weights, which have no updates yet
if (sumSquaredGradients.get(f) == null || l1UpdateTimeMap.get(f) == null) {
l1UpdateTimeMap.put(f, numUpdates);
sumSquaredGradients.put(f, 0.0);
return;
}
int numOfIter = numUpdates - l1UpdateTimeMap.get(f);
if (numOfIter <= 0) {
l1UpdateTimeMap.put(f, numUpdates);
return;
}
int numOfIter = numUpdates - MapUtils.get(l1UpdateTimeMap, f, 0);
if (numOfIter == 0) return;
if (numOfIter < 0) throw new RuntimeException("l1UpdateTimeMap is out of sync.");
double stepSize = (numOfIter * opts.initStepSize) / (Math.sqrt(sumSquaredGradients.get(f) + 1));
double update = -opts.l1RegCoeff * Math.signum(MapUtils.getDouble(weights, f, 0.0));
clipUpdate(f, stepSize * update);
l1UpdateTimeMap.put(f, numUpdates);
if (weights.containsKey(f))
l1UpdateTimeMap.put(f, numUpdates);
else
l1UpdateTimeMap.remove(f);
}
public synchronized double getWeight(String f) {
@ -200,7 +212,7 @@ public class Params {
}
}
public synchronized Map<String, Double> getWeights() { return weights; }
public synchronized Map<String, Double> getWeights() { finalizeWeights(); return weights; }
public void write(PrintWriter out) { write(null, out); }

View File

@ -1,75 +0,0 @@
package edu.stanford.nlp.sempre;
import java.util.HashMap;
import java.util.Map;
import fig.basic.IOUtils;
import fig.basic.Option;
import fig.basic.MapUtils;
import fig.basic.LogInfo;
/**
* ParaphraseModel extracts and scores paraphrasing featues from derivations.
* This model is intended to be used with FloatingParser
*
* @author Yushi Wang
*/
public final class ParaphraseModel {
public static class Options {
@Option(gloss = "Path to file with alignment table")
public String paraphraseModelPath = "regex/regex-alignments.txt";
}
public static Options opts = new Options();
public static ParaphraseModel model;
Map<String, Map<String, Double>> table;
// We should only have one paraphrase model
public static ParaphraseModel getSingleton() {
if (model == null) {
model = new ParaphraseModel();
}
return model;
}
private ParaphraseModel() {
table = loadParaphraseModel(opts.paraphraseModelPath);
}
/**
* Loading paraphrase model from file
*/
private Map<String, Map<String, Double>> loadParaphraseModel(String path) {
LogInfo.begin_track("Loading paraphrase model");
Map<String, Map<String, Double>> res = new HashMap<String, Map<String, Double>>();
for (String line: IOUtils.readLinesHard(path)) {
String[] tokens = line.split("\t");
// double count = Double.parseDouble(tokens[2]);
MapUtils.putIfAbsent(res, tokens[0], new HashMap<String, Double>());
for (String token : tokens)
LogInfo.logs("%s", token);
res.get(tokens[0]).put(tokens[1], 1.0);
/* Alignment stats don't matter right now
if(count>=threshold) {
AlignmentStats aStats = new AlignmentStats(count, Double.parseDouble(tokens[3]), Double.parseDouble(tokens[4]));
res.get(tokens[0]).put(tokens[1], aStats);
}
*/
}
LogInfo.logs("ParaphraseUtils.loadPhraseTable: number of entries=%s", res.size());
LogInfo.end_track();
return res;
}
public boolean containsKey(String key) {
return table.containsKey(key);
}
public Double get(String key, String token) {
if (!table.containsKey(key) || !table.get(key).containsKey(token)) return 0.0;
return table.get(key).get(token);
}
}

View File

@ -21,6 +21,8 @@ public abstract class Parser {
@Option(gloss = "Maximal number of predictions to print")
public int maxPrintedPredictions = Integer.MAX_VALUE;
@Option(gloss = "Maximal number of correct predictions to print")
public int maxPrintedTrue = Integer.MAX_VALUE;
@Option(gloss = "Use a coarse pass to prune the chart before full parsing")
public boolean coarsePrune = false;
@ -42,6 +44,18 @@ public abstract class Parser {
@Option(gloss = "Whether to unroll derivation streams (applies to lazy parsers)")
public boolean unrollStream = false;
@Option(gloss = "Inject random noise into the score (to mix things up a bit)")
public double derivationScoreNoise = 0;
@Option(gloss = "Source of random noise")
public Random derivationScoreRandom = new Random(1);
@Option (gloss = "Prune away error denotations")
public boolean pruneErrorValues = false;
@Option(gloss = "Dump all features (for debugging)")
public boolean dumpAllFeatures = false;
}
public static final Options opts = new Options();
@ -155,6 +169,11 @@ public abstract class Parser {
ex.evaluation = new Evaluation();
addToEvaluation(state, ex.evaluation);
// Clean up temporary state used during parsing
ex.clearTempState();
for (Derivation deriv : ex.predDerivations)
deriv.clearTempState();
return state;
}
@ -214,7 +233,6 @@ public abstract class Parser {
double topMass = 0;
if (ex.targetValue != null) {
while (numTop < numCandidates &&
compatibilities[numTop] > 0.0d &&
Math.abs(predDerivations.get(numTop).score - predDerivations.get(0).score) < 1e-10) {
topMass += probs[numTop];
numTop++;
@ -248,21 +266,33 @@ public abstract class Parser {
}
// Fully correct
int numPrintedSoFar = 0;
for (int i = 0; i < predDerivations.size(); i++) {
Derivation deriv = predDerivations.get(i);
if (compatibilities != null && compatibilities[i] == 1) {
LogInfo.logs(
"True@%04d: %s [score=%s, prob=%s%s]", i, deriv.toString(),
Fmt.D(deriv.score), Fmt.D(probs[i]), compatibilities != null ? ", comp=" + Fmt.D(compatibilities[i]) : "");
boolean print = printAllPredictions || (numPrintedSoFar < opts.maxPrintedTrue);
if (print) {
LogInfo.logs(
"True@%04d: %s [score=%s, prob=%s%s]", i, deriv.toString(),
Fmt.D(deriv.score), Fmt.D(probs[i]), compatibilities != null ? ", comp=" + Fmt.D(compatibilities[i]) : "");
numPrintedSoFar++;
if (opts.dumpAllFeatures) FeatureVector.logFeatureWeights("Features", deriv.getAllFeatureVector(), state.params);
}
}
}
// Partially correct
numPrintedSoFar = 0;
for (int i = 0; i < predDerivations.size(); i++) {
Derivation deriv = predDerivations.get(i);
if (compatibilities != null && compatibilities[i] > 0 && compatibilities[i] < 1) {
LogInfo.logs(
"Part@%04d: %s [score=%s, prob=%s%s]", i, deriv.toString(),
Fmt.D(deriv.score), Fmt.D(probs[i]), compatibilities != null ? ", comp=" + Fmt.D(compatibilities[i]) : "");
boolean print = printAllPredictions || (numPrintedSoFar < opts.maxPrintedTrue);
if (print) {
LogInfo.logs(
"Part@%04d: %s [score=%s, prob=%s%s]", i, deriv.toString(),
Fmt.D(deriv.score), Fmt.D(probs[i]), compatibilities != null ? ", comp=" + Fmt.D(compatibilities[i]) : "");
numPrintedSoFar++;
if (opts.dumpAllFeatures) FeatureVector.logFeatureWeights("Features", deriv.getAllFeatureVector(), state.params);
}
}
}
// Anything that's predicted.
@ -276,6 +306,7 @@ public abstract class Parser {
"Pred@%04d: %s [score=%s, prob=%s%s]", i, deriv.toString(),
Fmt.D(deriv.score), Fmt.D(probs[i]), compatibilities != null ? ", comp=" + Fmt.D(compatibilities[i]) : "");
// LogInfo.logs("Derivation tree: %s", deriv.toRecursiveString());
if (opts.dumpAllFeatures) FeatureVector.logFeatureWeights("Features", deriv.getAllFeatureVector(), state.params);
}
}

View File

@ -4,6 +4,7 @@ import fig.basic.Fmt;
import fig.basic.LogInfo;
import fig.basic.NumUtils;
import fig.basic.Evaluation;
import fig.basic.Option;
import java.util.ArrayList;
import java.util.List;
@ -16,6 +17,14 @@ import java.util.Map;
* @author Percy Liang
*/
public abstract class ParserState {
public static class Options {
@Option(gloss = "Use a custom distribution for computing expected counts")
public CustomExpectedCount customExpectedCounts = CustomExpectedCount.NONE;
}
public static Options opts = new Options();
public enum CustomExpectedCount { NONE, UNIFORM, TOP, RANDOM, }
//// Input: specification of how to parse
public final Parser parser;
@ -41,8 +50,6 @@ public abstract class ParserState {
public int totalGeneratedDerivs; // Total number of derivations produced
public int numOfFeaturizedDerivs = 0; // Number of derivations featured
@SuppressWarnings({ "unchecked" })
public ParserState(Parser parser, Params params, Example ex, boolean computeExpectedCounts) {
this.parser = parser;
this.params = params;
@ -70,7 +77,7 @@ public abstract class ParserState {
if (parser.verbose(5)) {
LogInfo.logs("featurizeAndScoreDerivation(score=%s) %s %s: %s [rule: %s]",
Fmt.D(deriv.score), deriv.cat, ex.spanString(deriv.start, deriv.end), deriv, deriv.rule);
Fmt.D(deriv.score), deriv.cat, ex.spanString(deriv.start, deriv.end), deriv, deriv.rule);
}
numOfFeaturizedDerivs++;
}
@ -113,8 +120,26 @@ public abstract class ParserState {
i++;
}
// Inject noise into the noise (to simulate sampling); ideally would add Gumbel noise
if (Parser.opts.derivationScoreNoise > 0) {
for (Derivation deriv : derivations)
deriv.score += Parser.opts.derivationScoreRandom.nextDouble() * Parser.opts.derivationScoreNoise;
}
Derivation.sortByScore(derivations);
// Print out information
if (parser.opts.verbose >= 3) {
LogInfo.begin_track("ParserState.pruneCell(%s): %d derivations", cellDescription, derivations.size());
for (Derivation deriv : derivations) {
LogInfo.logs("%s(%s,%s): %s %s, [score=%s]", deriv.cat, deriv.start, deriv.end, deriv.formula,
deriv.canonicalUtterance, deriv.score);
}
LogInfo.end_track();
}
// Max beam position (after sorting)
i = 0;
for (Derivation deriv : derivations) {
@ -142,46 +167,46 @@ public abstract class ParserState {
// All tokens (length 1)
for (int i = 0; i < numTokens; i++) {
derivs.add(
new Derivation.Builder()
.cat(Rule.tokenCat).start(i).end(i + 1)
.rule(Rule.nullRule)
.children(Derivation.emptyList)
.withStringFormulaFrom(ex.token(i))
.canonicalUtterance(ex.token(i))
.createDerivation());
new Derivation.Builder()
.cat(Rule.tokenCat).start(i).end(i + 1)
.rule(Rule.nullRule)
.children(Derivation.emptyList)
.withStringFormulaFrom(ex.token(i))
.canonicalUtterance(ex.token(i))
.createDerivation());
// Lemmatized version
derivs.add(
new Derivation.Builder()
.cat(Rule.lemmaTokenCat).start(i).end(i + 1)
.rule(Rule.nullRule)
.children(Derivation.emptyList)
.withStringFormulaFrom(ex.lemmaToken(i))
.canonicalUtterance(ex.token(i))
.createDerivation());
new Derivation.Builder()
.cat(Rule.lemmaTokenCat).start(i).end(i + 1)
.rule(Rule.nullRule)
.children(Derivation.emptyList)
.withStringFormulaFrom(ex.lemmaToken(i))
.canonicalUtterance(ex.token(i))
.createDerivation());
}
// All phrases (any length)
for (int i = 0; i < numTokens; i++) {
for (int j = i + 1; j <= numTokens; j++) {
derivs.add(
new Derivation.Builder()
.cat(Rule.phraseCat).start(i).end(j)
.rule(Rule.nullRule)
.children(Derivation.emptyList)
.withStringFormulaFrom(ex.phrase(i, j))
.canonicalUtterance(ex.phrase(i, j))
.createDerivation());
new Derivation.Builder()
.cat(Rule.phraseCat).start(i).end(j)
.rule(Rule.nullRule)
.children(Derivation.emptyList)
.withStringFormulaFrom(ex.phrase(i, j))
.canonicalUtterance(ex.phrase(i, j))
.createDerivation());
// Lemmatized version
derivs.add(
new Derivation.Builder()
.cat(Rule.lemmaPhraseCat).start(i).end(j)
.rule(Rule.nullRule)
.children(Derivation.emptyList)
.withStringFormulaFrom(ex.lemmaPhrase(i, j))
.canonicalUtterance(ex.phrase(i, j))
.createDerivation());
new Derivation.Builder()
.cat(Rule.lemmaPhraseCat).start(i).end(j)
.rule(Rule.nullRule)
.children(Derivation.emptyList)
.withStringFormulaFrom(ex.lemmaPhrase(i, j))
.canonicalUtterance(ex.phrase(i, j))
.createDerivation());
}
}
return derivs;
@ -231,12 +256,36 @@ public abstract class ParserState {
trueScores = new double[n];
predScores = new double[n];
// For update schemas that choose one good and one bad candidate to update
int[] goodAndBad = null;
if (opts.customExpectedCounts == CustomExpectedCount.TOP) {
goodAndBad = getTopDerivations(derivations);
if (goodAndBad == null) return;
} else if (opts.customExpectedCounts == CustomExpectedCount.RANDOM) {
goodAndBad = getRandomDerivations(derivations);
if (goodAndBad == null) return;
}
for (int i = 0; i < n; i++) {
Derivation deriv = derivations.get(i);
double logReward = Math.log(compatibilityToReward(deriv.compatibility));
trueScores[i] = deriv.score + logReward;
predScores[i] = deriv.score;
switch (opts.customExpectedCounts) {
case NONE:
trueScores[i] = deriv.score + logReward;
predScores[i] = deriv.score;
break;
case UNIFORM:
trueScores[i] = logReward;
predScores[i] = 0;
break;
case TOP: case RANDOM:
trueScores[i] = (i == goodAndBad[0]) ? 0 : Double.NEGATIVE_INFINITY;
predScores[i] = (i == goodAndBad[1]) ? 0 : Double.NEGATIVE_INFINITY;
break;
default:
throw new RuntimeException("Unknown customExpectedCounts: " + opts.customExpectedCounts);
}
}
// Usually this happens when there are no derivations.
@ -247,7 +296,45 @@ public abstract class ParserState {
for (int i = 0; i < n; i++) {
Derivation deriv = derivations.get(i);
double incr = trueScores[i] - predScores[i];
if (incr == 0) continue;
deriv.incrementAllFeatureVector(incr, counts);
}
}
private static int[] getTopDerivations(List<Derivation> derivations) {
int chosenGood = -1, chosenBad = -1;
double chosenGoodScore = Double.NEGATIVE_INFINITY, chosenBadScore = Double.NEGATIVE_INFINITY;
for (int i = 0; i < derivations.size(); i++) {
Derivation deriv = derivations.get(i);
if (deriv.compatibility == 1) { // good
if (deriv.score > chosenGoodScore) {
chosenGood = i; chosenGoodScore = deriv.score;
}
} else { // bad
if (deriv.score > chosenBadScore) {
chosenBad = i; chosenBadScore = deriv.score;
}
}
}
return (chosenGood == -1 || chosenBad == -1) ? null : new int[] {chosenGood, chosenBad};
}
private static int[] getRandomDerivations(List<Derivation> derivations) {
int chosenGood = -1, chosenBad = -1, numGoodSoFar = 0, numBadSoFar = 0;
for (int i = 0; i < derivations.size(); i++) {
Derivation deriv = derivations.get(i);
if (deriv.compatibility == 1) {
numGoodSoFar++;
if (Math.random() <= 1.0 / numGoodSoFar) {
chosenGood = i;
}
} else { // bad
numBadSoFar++;
if (Math.random() <= 1.0 / numBadSoFar) {
chosenBad = i;
}
}
}
return (chosenGood == -1 || chosenBad == -1) ? null : new int[] {chosenGood, chosenBad};
}
}

View File

@ -412,7 +412,7 @@ final class ReinforcementParserState extends AbstractReinforcementParserState {
updateBackpointers(pds.derivStream, nextDeriv);
DerivationStream derivStream = SingleDerivationStream.constant(nextDeriv);
if (parser.verbose(3)) {
if (parser.verbose(3) && derivStream.hasNext()) {
Derivation deriv = derivStream.peek();
LogInfo.logs("unrollHighProbStreams(): add deriv=%s(%s,%s) [%s] score=%s, |stream|=%s",
deriv.cat, deriv.start, deriv.end, deriv.formula, deriv.score, pds.derivStream.estimatedSize());
@ -820,7 +820,7 @@ final class ReinforcementParserState extends AbstractReinforcementParserState {
modified = true;
Derivation nextDeriv = pds.derivStream.next();
DerivationStream newDerivStream = SingleDerivationStream.constant(nextDeriv);
if (parser.verbose(3)) {
if (parser.verbose(3) && newDerivStream.hasNext()) {
Derivation deriv = newDerivStream.peek();
LogInfo.logs("MultiplicativeSampler.unroll(): add necessary deriv=%s(%s,%s) [%s] score=%s, |stream|=%s, creationIndex=%s",
deriv.cat, deriv.start, deriv.end, deriv.formula, deriv.score, pds.derivStream.estimatedSize(), deriv.creationIndex);

View File

@ -39,6 +39,7 @@ public class ReverseFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof ReverseFormula)) return false;

View File

@ -75,6 +75,16 @@ public class Rule {
return true;
}
// Return the number of categories on the RHS
public int numRhsCats() {
int ret = 0;
for (int i = 0; i < rhs.size(); ++i) {
if (isCat(rhs.get(i)))
ret++;
}
return ret;
}
public LispTree toLispTree() {
LispTree tree = LispTree.proto.newList();
tree.addChild("rule");

View File

@ -102,6 +102,7 @@ public abstract class SemType {
public static final SemType intType = new AtomicSemType(CanonicalNames.INT);
public static final SemType floatType = new AtomicSemType(CanonicalNames.FLOAT);
public static final SemType dateType = new AtomicSemType(CanonicalNames.DATE);
public static final SemType timeType = new AtomicSemType(CanonicalNames.TIME);
public static final SemType numberType = new AtomicSemType(CanonicalNames.NUMBER);
public static final SemType numberOrDateType = new UnionSemType(numberType, dateType);
public static final SemType entityType = new AtomicSemType(CanonicalNames.ENTITY);

View File

@ -38,18 +38,36 @@ public class SimpleAnalyzer extends LanguageAnalyzer {
utterance = breakHyphens(utterance);
// Default analysis - create tokens crudely
utterance = utterance.replaceAll(",", " ,");
utterance = utterance.replaceAll("\\.", " .");
utterance = utterance.replaceAll("\\?", " ?");
utterance = utterance.replaceAll("'", " '");
utterance = utterance.replaceAll("\\[", " [ ");
utterance = utterance.replaceAll("\\]", " ] ");
utterance = utterance.trim();
StringBuilder buf = new StringBuilder();
for (int i = 0; i < utterance.length(); i++) {
char c = utterance.charAt(i);
// Put whitespace around certain characters.
// TODO(pliang): handle contractions such as "can't" properly.
boolean boundaryBefore = !(i - 1 >= 0) || utterance.charAt(i - 1) == ' ';
boolean boundaryAfter = !(i + 1 < utterance.length()) || utterance.charAt(i + 1) == ' ';
boolean separate;
if (c == '.') // Break off period if already space around it (to preserve numbers like 3.5)
separate = boundaryBefore || boundaryAfter;
else
separate = (",?'\"[]".indexOf(c) != -1);
if (separate) buf.append(' ');
// Convert quotes
if (c == '"')
buf.append(boundaryBefore ? "``" : "''");
else if (c == '\'')
buf.append(boundaryBefore ? "`" : "'");
else
buf.append(c);
if (separate) buf.append(' ');
}
utterance = buf.toString().trim();
if (!utterance.equals("")) {
for (String token : utterance.split("\\s+")) {
String[] tokens = utterance.split("\\s+");
for (String token : tokens) {
languageInfo.tokens.add(LanguageAnalyzer.opts.lowerCaseTokens ? token.toLowerCase() : token);
String lemma = token;
if (token.endsWith("s"))
if (token.endsWith("s") && token.length() > 1)
lemma = token.substring(0, token.length() - 1);
languageInfo.lemmaTokens.add(LanguageAnalyzer.opts.lowerCaseTokens ? lemma.toLowerCase() : lemma);
@ -65,15 +83,14 @@ public class SimpleAnalyzer extends LanguageAnalyzer {
try {
Double.parseDouble(token);
languageInfo.posTags.add("CD");
if (token.length() == 4)
languageInfo.nerTags.add("DATE");
else
languageInfo.nerTags.add("NUMBER");
languageInfo.nerTags.add("NUMBER");
languageInfo.nerValues.add(token);
} catch (NumberFormatException e) {
// Guess that capitalized nouns are proper
if (Character.isUpperCase(token.charAt(0)))
languageInfo.posTags.add("NNP");
else if (token.equals("'") || token.equals("\"") || token.equals("''") || token.equals("``"))
languageInfo.posTags.add("''");
else
languageInfo.posTags.add("UNK");
languageInfo.nerTags.add("UNK");

View File

@ -61,6 +61,7 @@ public class SuperlativeFormula extends Formula {
return res;
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof SuperlativeFormula)) return false;

View File

@ -0,0 +1,36 @@
package edu.stanford.nlp.sempre;
import fig.basic.*;
/**
* Preprocess the targetValue of an example.
*
* @author ppasupat
*/
public abstract class TargetValuePreprocessor {
public static class Options {
@Option public String targetValuePreprocessor = null;
}
public static Options opts = new Options();
private static TargetValuePreprocessor singleton;
public static TargetValuePreprocessor getSingleton() {
if (singleton == null) {
if (opts.targetValuePreprocessor == null || opts.targetValuePreprocessor.isEmpty())
singleton = new IdentityTargetValuePreprocessor();
else
singleton = (TargetValuePreprocessor) Utils.newInstanceHard(
SempreUtils.resolveClassName(opts.targetValuePreprocessor));
}
return singleton;
}
public static void setSingleton(TargetValuePreprocessor processor) { singleton = processor; }
public abstract Value preprocess(Value value);
}
class IdentityTargetValuePreprocessor extends TargetValuePreprocessor {
public Value preprocess(Value value) { return value; }
}

View File

@ -0,0 +1,51 @@
package edu.stanford.nlp.sempre;
import fig.basic.LispTree;
/**
* Created by joberant on 1/23/15.
* Value for representing time
*/
public class TimeValue extends Value {
public final int hour;
public final int minute;
public TimeValue(int hour, int minute) {
if (hour > 23 || hour < 0) throw new RuntimeException("Illegal hour: " + hour);
if (minute > 59 || minute < 0) throw new RuntimeException("Illegal minute: " + minute);
this.hour = hour;
this.minute = minute;
}
public TimeValue(LispTree tree) {
this.hour = Integer.valueOf(tree.child(1).value);
this.minute = Integer.valueOf(tree.child(2).value);
}
@Override
public LispTree toLispTree() {
LispTree tree = LispTree.proto.newList();
tree.addChild("time");
tree.addChild(String.valueOf(hour));
tree.addChild(String.valueOf(minute));
return tree;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TimeValue timeValue = (TimeValue) o;
if (hour != timeValue.hour) return false;
if (minute != timeValue.minute) return false;
return true;
}
@Override
public int hashCode() {
int result = hour;
result = 31 * result + minute;
return result;
}
}

View File

@ -1,6 +1,7 @@
package edu.stanford.nlp.sempre;
import fig.basic.*;
import java.util.*;
/**
@ -56,6 +57,13 @@ public final class TypeInference {
}
private static final ValueFormula typeFormula = new ValueFormula(new NameValue(CanonicalNames.TYPE));
private static final Set<Formula> comparisonFormulas = new HashSet<>(Arrays.asList(
new ValueFormula(new NameValue("<")),
new ValueFormula(new NameValue(">")),
new ValueFormula(new NameValue("<=")),
new ValueFormula(new NameValue(">="))));
private static class TypeException extends Exception { }
private static class Env {
@ -109,16 +117,6 @@ public final class TypeInference {
return type;
}
// Unary: fb:domain.type [contains exactly one period]
// Binary: fb:domain.type.property, <, >, etc.
private static boolean isUnary(String s) {
int i = s.indexOf('.');
if (i == -1) return false;
i = s.indexOf('.', i + 1);
if (i == -1) return true;
return false;
}
private static SemType check(SemType type) throws TypeException {
if (!type.isValid()) throw new TypeException();
return type;
@ -137,10 +135,11 @@ public final class TypeInference {
if (value instanceof NumberValue) return check(type.meet(SemType.numberType));
else if (value instanceof StringValue) return check(type.meet(SemType.stringType));
else if (value instanceof DateValue) return check(type.meet(SemType.dateType));
else if (value instanceof TimeValue) return check(type.meet(SemType.timeType));
else if (value instanceof NameValue) {
String id = ((NameValue) value).id;
if (isUnary(id)) { // Unary
if (CanonicalNames.isUnary(id)) { // Unary
SemType unaryType = env.typeLookup.getEntityType(id);
if (unaryType == null)
unaryType = SemType.entityType;
@ -170,6 +169,10 @@ public final class TypeInference {
if (typeFormula.equals(join.relation) && join.child instanceof ValueFormula)
return check(type.meet(SemType.newAtomicSemType(Formulas.getString(join.child))));
// Special case: (<= (number 5)) => same type as (number 5)
if (comparisonFormulas.contains(join.relation))
return check(type.meet(inferType(join.child, env, SemType.numberOrDateType)));
SemType relationType = inferType(join.relation, env, new FuncSemType(SemType.topType, type)); // Relation
SemType childType = inferType(join.child, env, relationType.getArgType()); // Child
relationType = inferType(join.relation, env, new FuncSemType(childType, type)); // Relation again

View File

@ -5,6 +5,8 @@ import com.fasterxml.jackson.annotation.JsonValue;
import fig.basic.LispTree;
import fig.basic.LogInfo;
import java.util.Comparator;
/**
* Values represent denotations (or partial denotations).
*
@ -26,4 +28,11 @@ public abstract class Value {
@Override public abstract boolean equals(Object o);
@Override public abstract int hashCode();
public static class ValueComparator implements Comparator<Value> {
@Override
public int compare(Value o1, Value o2) {
return o1.toString().compareTo(o2.toString());
}
}
}

View File

@ -17,6 +17,7 @@ public class ValueFormula<T extends Value> extends PrimitiveFormula {
return value.toLispTree();
}
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@ -27,6 +27,7 @@ public final class Values {
if ("context".equals(type)) return new ContextValue(tree);
if ("date".equals(type)) return new DateValue(tree);
if ("error".equals(type)) return new ErrorValue(tree);
if ("time".equals(type)) return new TimeValue(tree);
return null;
}

View File

@ -12,6 +12,7 @@ public class VariableFormula extends PrimitiveFormula {
public VariableFormula(String name) { this.name = name; }
public LispTree toLispTree() { return LispTree.proto.newList("var", name); }
@SuppressWarnings({"equalshashcode"})
@Override
public boolean equals(Object thatObj) {
if (!(thatObj instanceof VariableFormula)) return false;

View File

@ -1,17 +0,0 @@
<project>
<target name="compile">
<property name="module_name" value="core"/>
<property name="root" location="../../../../../"/>
<!--<property name="classes" location="${root}/classes/${module_name}"/>-->
<property name="classes" location="${root}/classes"/>
<mkdir dir="${classes}"/>
<mkdir dir="${root}/libsempre"/>
<path id="lib.path"><fileset dir="${root}/lib"/><fileset dir="${root}/libsempre"/></path>
<javac srcdir="${root}/src" destdir="${classes}" classpathref="lib.path" debug="true" includeantruntime="false">
<include name="edu/stanford/nlp/sempre/*.java"/>
<include name="edu/stanford/nlp/sempre/test/"/>
</javac>
<jar destfile="${root}/libsempre/sempre-${module_name}.jar" basedir="${classes}" includes="edu/**">
</jar>
</target>
</project>

View File

@ -1,14 +0,0 @@
<project>
<target name="compile">
<property name="module_name" value="cache"/>
<property name="root" location="../../../../../../"/>
<property name="classes" location="${root}/classes/${module_name}"/>
<mkdir dir="${classes}"/>
<mkdir dir="${root}/libsempre"/>
<path id="lib.path"><fileset dir="${root}/lib"/><fileset dir="${root}/libsempre"/></path>
<javac srcdir="${root}/src" destdir="${classes}" classpathref="lib.path" debug="true" includeantruntime="false">
<include name="edu/stanford/nlp/sempre/cache/"/>
</javac>
<jar destfile="${root}/libsempre/sempre-${module_name}.jar" basedir="${classes}"/>
</target>
</project>

View File

@ -2,7 +2,6 @@ package edu.stanford.nlp.sempre.corenlp;
import edu.stanford.nlp.sempre.*;
import edu.stanford.nlp.sempre.LanguageInfo.DependencyEdge;
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.ling.IndexedWord;
import edu.stanford.nlp.ling.CoreAnnotations.*;
@ -13,9 +12,13 @@ import edu.stanford.nlp.semgraph.SemanticGraph;
import edu.stanford.nlp.semgraph.SemanticGraphCoreAnnotations;
import edu.stanford.nlp.semgraph.SemanticGraphEdge;
import edu.stanford.nlp.util.CoreMap;
import com.google.common.collect.Lists;
import com.google.common.base.Joiner;
import fig.basic.*;
import java.io.*;
import java.util.*;
/**
@ -113,6 +116,7 @@ public class CoreNLPAnalyzer extends LanguageAnalyzer {
// Fills in a stanford dependency graph for constructing a feature
for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) {
SemanticGraph ccDeps = sentence.get(SemanticGraphCoreAnnotations.CollapsedCCProcessedDependenciesAnnotation.class);
if (ccDeps == null) continue;
int sentenceBegin = sentence.get(CoreAnnotations.TokenBeginAnnotation.class);
// Iterate over all tokens and their dependencies
@ -133,4 +137,27 @@ public class CoreNLPAnalyzer extends LanguageAnalyzer {
}
return languageInfo;
}
// Test on example sentence.
public static void main(String[] args) {
CoreNLPAnalyzer analyzer = new CoreNLPAnalyzer();
while (true) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter some text:");
String text = reader.readLine();
LanguageInfo langInfo = analyzer.analyze(text);
LogInfo.begin_track("Analyzing \"%s\"", text);
LogInfo.logs("tokens: %s", langInfo.tokens);
LogInfo.logs("lemmaTokens: %s", langInfo.lemmaTokens);
LogInfo.logs("posTags: %s", langInfo.posTags);
LogInfo.logs("nerTags: %s", langInfo.nerTags);
LogInfo.logs("nerValues: %s", langInfo.nerValues);
LogInfo.logs("dependencyChildren: %s", langInfo.dependencyChildren);
LogInfo.end_track();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@ -1,14 +0,0 @@
<project>
<target name="compile">
<property name="module_name" value="corenlp"/>
<property name="root" location="../../../../../../"/>
<property name="classes" location="${root}/classes/${module_name}"/>
<mkdir dir="${classes}"/>
<mkdir dir="${root}/libsempre"/>
<path id="lib.path"><fileset dir="${root}/lib"/><fileset dir="${root}/libsempre"/></path>
<javac srcdir="${root}/src" destdir="${classes}" classpathref="lib.path" debug="true" includeantruntime="false">
<include name="edu/stanford/nlp/sempre/corenlp/"/>
</javac>
<jar destfile="${root}/libsempre/sempre-${module_name}.jar" basedir="${classes}"/>
</target>
</project>

View File

@ -87,7 +87,7 @@ public class Free917Converter implements Runnable {
questionWriter.println("(lambda $0 /common/topic (exists $1 (exists $2 (/film/film/estimated_budget&/measurement_unit/dated_money_value@valid_date@amount@currency:t /en/transformers:/film/film $-1 $1 $0 $2))))");
else if (line.equals("(lambda $0 /location/location (exists $1 (exists $2 (exists $3 (exists $4 (exists $5 (/library/public_library/address&/location/mailing_address@street_address@street_address_2@citytown@postal_code@state_province_region@country:t /m/02ncllz:/library/public_library $1 $2 $0 $3 $4 $5)))))))"))
questionWriter.println("(lambda $0 /location/location (exists $1 (exists $2 (exists $3 (exists $4 (exists $5 (/library/public_library/address&/location/mailing_address@street_address@street_address_2@citytown@postal_code@state_province_region@country:t /m/02ncllz:/library/public_library $-1 $1 $2 $0 $3 $4 $5)))))))");
else if (line.equals("who won aliââ¬â€œfrazier ii"))
else if (line.matches("who won ali.*frazier ii"))
questionWriter.println("who won muhammad ali vs. joe frazier ii");
else if (line.equals("(lambda $0 /people/person (exists $1 (exists $2 (exists $3 (/base/boxing/match_boxer_relationship@match@boxer@winner_won@points:t $1 $0 $2 $3)))))")) {
if (i++ == 0)
@ -341,7 +341,7 @@ public class Free917Converter implements Runnable {
npWriter.println("film domain :- NP : /m/010s:/freebase/domain_profile");
else if (line.equals("newscaster :- NP : /en/newscaster:/tv/non_character_role"))
npWriter.println("newscaster :- NP : /en/news_presenter:/tv/non_character_role");
else if (line.equals("ali<EFBFBD>frazier ii :- NP : /en/ali-frazier_ii:/base/boxing/boxing_match")) {
else if (line.matches("ali.*frazier ii :- NP : /en/ali-frazier_ii:/base/boxing/boxing_match")) {
} else
npWriter.println(line);
}

View File

@ -1,10 +1,13 @@
package edu.stanford.nlp.sempre.freebase;
import java.io.*;
import java.util.*;
import edu.stanford.nlp.sempre.*;
import fig.basic.*;
import fig.exec.Execution;
import edu.stanford.nlp.sempre.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
/**
* Converts Luke Zettlemoyer's lambda calculus data format into our example files.
@ -15,25 +18,25 @@ import edu.stanford.nlp.sempre.*;
public class LambdaCalculusConverter implements Runnable {
public static class Options {
@Option(gloss = "Input path (lambda calculus)")
public String inPath = "freebase/data/geo/geosents600-typed.ccg.dev";
public String inPath = "overnight/geo/geosents280-typed.ccg.test.new";
@Option(gloss = "Specification of translations")
public String specPath = "freebase/data/geo/geo.spec";
public String specPath = "overnight/geo/geo.spec";
@Option(gloss = "Specification of variable names")
public String varPath = "freebase/data/geo/geo.vars";
public String varPath = "overnight/geo/geo.vars";
@Option(gloss = "Specification of primitive types")
public String primPath = "freebase/data/geo/geo.primitives";
public String primPath = "overnight/geo/geo.primitives";
@Option(gloss = "Specification of formula replacements")
public String replacePath = "freebase/data/geo/geo.replace";
public String replacePath = "overnight/geo/geo.replace";
@Option(gloss = "Specification of manual conversions")
public String manualConversionsPath = "freebase/data/geo/geo.manual_conversions";
@Option(gloss = "Input path (examples)")
public String outPath = "freebase/data/geo/geo.out.json";
public String manualConversionsPath = "overnight/geo/geo.manual_conversions";
@Option(gloss = "Output path (examples)")
public String outPath = "overnight/geo/geo.out.json";
@Option(gloss = "Specific example to parse and run")
public int runInd = -1;
public int runInd = -1;
@Option(gloss = "Output path for lexicon grammar")
public String lexiconPath = "freebase/data/geo/geo.out.grammar";
public String lexiconPath = "overnight/geo/geo.out.grammar";
@Option(gloss = "Verbose output (for debugging)")
public boolean verbose = false; // TODO Currently unused
public boolean verbose = false; // TODO Currently unused
}
public static Options opts = new Options();
@ -72,11 +75,13 @@ public class LambdaCalculusConverter implements Runnable {
}
public void readPrereqs() {
LogInfo.begin_track("Reading prereq");
readSpec();
readPrimitives();
readVars();
readStringMap(opts.replacePath, replaceMap);
readStringMap(opts.manualConversionsPath, manualConversionsMap);
LogInfo.end_track();
}
void readSpec() {
@ -248,7 +253,7 @@ public class LambdaCalculusConverter implements Runnable {
if (primitive == null)
return null;
// if (primitive.equals("string"))
// parts[0] = capitalizeWords(parts[0]);
// parts[0] = capitalizeWords(parts[0]);
// return Formula.fromString(String.format("(%s %s)", primitive, parts[0]));
if (primitive.equals("string"))
return Formula.fromString(String.format("(!fb:type.object.name fb:en.%s)", parts[0]));
@ -257,41 +262,41 @@ public class LambdaCalculusConverter implements Runnable {
}
Formula handleExists(LispTree tree, String headVar, List<String> existsVars) {
// (exists $1 (and (river:t $1) (loc:t $1 $0)))
String eVar = tree.child(1).value;
existsVars.add(eVar);
// FIXME Currently assuming format where exists contains and statement with
// n clauses where first n - 1 clauses describe exists var and last clause
// relates exists var to the head var
List<LispTree> andTreeList = tree.child(2).children;
// FIXME Don't assume and tree
LispTree newAndTree = LispTree.proto.newList();
// (exists $1 (and (river:t $1) (loc:t $1 $0)))
String eVar = tree.child(1).value;
existsVars.add(eVar);
// FIXME Currently assuming format where exists contains and statement with
// n clauses where first n - 1 clauses describe exists var and last clause
// relates exists var to the head var
List<LispTree> andTreeList = tree.child(2).children;
// FIXME Don't assume and tree
LispTree newAndTree = LispTree.proto.newList();
int predTreeInd = -1;
int numPredTrees = 0;
for (int k = 0; k < andTreeList.size(); k++) {
String childStr = andTreeList.get(k).toString();
if (childStr.contains(headVar)) {
predTreeInd = k;
numPredTrees++;
}
int predTreeInd = -1;
int numPredTrees = 0;
for (int k = 0; k < andTreeList.size(); k++) {
String childStr = andTreeList.get(k).toString();
if (childStr.contains(headVar)) {
predTreeInd = k;
numPredTrees++;
}
}
String func = tree.child(2).child(0).value;
if (numPredTrees == 0 || func.equals("exists")) {
return toLambda(eVar, toFormula(tree.child(2), eVar, existsVars));
}
String func = tree.child(2).child(0).value;
if (numPredTrees == 0 || func.equals("exists")) {
return toLambda(eVar, toFormula(tree.child(2), eVar, existsVars));
}
newAndTree.children = new ArrayList<LispTree>(andTreeList.subList(0, andTreeList.size()));
LispTree predTree = newAndTree.children.remove(predTreeInd);
if (newAndTree.children.size() == 2)
newAndTree = newAndTree.child(1);
newAndTree.children = new ArrayList<LispTree>(andTreeList.subList(0, andTreeList.size()));
LispTree predTree = newAndTree.children.remove(predTreeInd);
if (newAndTree.children.size() == 2)
newAndTree = newAndTree.child(1);
LispTree newPredTree = LispTree.proto.parseFromString(predTree.toString().replace(eVar, newAndTree.toString()));
LispTree newPredTree = LispTree.proto.parseFromString(predTree.toString().replace(eVar, newAndTree.toString()));
Formula form = toFormula(newPredTree, eVar, existsVars);
existsVars.remove(eVar);
return form;
Formula form = toFormula(newPredTree, eVar, existsVars);
existsVars.remove(eVar);
return form;
}
// hit: ignore these clauses in (and ...) constructions
@ -323,7 +328,7 @@ public class LambdaCalculusConverter implements Runnable {
// (sum $0 (and (state:t $0) (next_to:t $0 texas:s)) (population:i $0))
String numFunc = tree.child(3).child(0).value;
return new AggregateFormula(AggregateFormula.Mode.sum,
toJoin(numFunc, toFormula(tree.child(2), tree.child(1).value, existsVars)));
toJoin(numFunc, toFormula(tree.child(2), tree.child(1).value, existsVars)));
} else if (func.equals("argmax") || func.equals("argmin")) {
// (argmax $0 (state:t $0) (density:i $0))
// (argmin $1 (river:t $1) (len:i $1))
@ -379,7 +384,7 @@ public class LambdaCalculusConverter implements Runnable {
else // secondIsHead
return toJoin("!" + func, form1);
// else
// return toJoin(func, form1);
// return toJoin(func, form1);
} else {
throw new RuntimeException("Bad arity: " + tree);
}
@ -458,8 +463,10 @@ public class LambdaCalculusConverter implements Runnable {
ArrayList<String> existsVars = new ArrayList<String>();
if (manualConversionsMap.containsKey(line)) {
LogInfo.logs("MANUAL CONVERSION=%s", line);
ex.setTargetFormula(Formula.fromString(manualConversionsMap.get(line)));
} else {
LogInfo.log("AUTOMATIC CONVERSION");
ex.setTargetFormula(toFormula(tree, null, existsVars));
}
LogInfo.logs(color.colorize("OUT [%d]: %s", "yellow"), newId, ex.createExample().targetFormula.toLispTree());
@ -476,8 +483,9 @@ public class LambdaCalculusConverter implements Runnable {
void executeExamples() {
int runInd = opts.runInd;
// FIXME Should be passed in
SparqlExecutor.opts.endpointUrl = "http://localhost:3093/sparql";
SparqlExecutor.opts.endpointUrl = "http://localhost:3094/sparql";
SparqlExecutor.opts.cachePath = "SparqlExecutor.cache";
SparqlExecutor.opts.lambdaAllowDiagonals = false; //jonathan
SparqlExecutor executor = new SparqlExecutor();
int exInd = 1;
@ -506,12 +514,12 @@ public class LambdaCalculusConverter implements Runnable {
void writeExamples() {
// Sort validExampleIds by the length of the utterance of the example
Collections.sort(validExampleIds, new Comparator<Integer>() {
public int compare(Integer left, Integer right) {
return Integer.compare(validExampleLengths.get(validExampleIds.indexOf(left)),
validExampleLengths.get(validExampleIds.indexOf(right)));
}
});
// Collections.sort(validExampleIds, new Comparator<Integer>() {
// public int compare(Integer left, Integer right) {
// return Integer.compare(validExampleLengths.get(validExampleIds.indexOf(left)),
// validExampleLengths.get(validExampleIds.indexOf(right)));
// }
// });
PrintWriter out = IOUtils.openOutHard(opts.outPath);
out.println("["); // Print out as a list

View File

@ -1,14 +0,0 @@
<project>
<target name="compile">
<property name="module_name" value="freebase"/>
<property name="root" location="../../../../../../"/>
<property name="classes" location="${root}/classes/${module_name}"/>
<mkdir dir="${classes}"/>
<mkdir dir="${root}/libsempre"/>
<path id="lib.path"><fileset dir="${root}/lib"/><fileset dir="${root}/libsempre"/></path>
<javac srcdir="${root}/src" destdir="${classes}" classpathref="lib.path" debug="true" includeantruntime="false">
<include name="edu/stanford/nlp/sempre/freebase/"/>
</javac>
<jar destfile="${root}/libsempre/sempre-${module_name}.jar" basedir="${classes}"/>
</target>
</project>

View File

@ -69,8 +69,10 @@ public class SparqlExecutorTest {
SparqlExecutor executor = new SparqlExecutor();
public SparqlExecutorTest() {
SparqlExecutor.opts.endpointUrl = System.getProperty("sparqlserver");
// Hard-coding not ideal.
SparqlExecutor.opts.endpointUrl = "http://localhost:3093/sparql";
if (SparqlExecutor.opts.endpointUrl == null)
SparqlExecutor.opts.endpointUrl = "http://freebase.cloudapp.net:3093/sparql";
SparqlExecutor.opts.verbose = 3;
}

View File

@ -1,12 +1,18 @@
package edu.stanford.nlp.sempre.freebase.utils;
import com.google.common.base.Joiner;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import edu.stanford.nlp.io.IOUtils;
import edu.stanford.nlp.objectbank.ObjectBank;
import edu.stanford.nlp.sempre.DateValue;
import edu.stanford.nlp.sempre.DescriptionValue;
import edu.stanford.nlp.sempre.Json;
import edu.stanford.nlp.sempre.NameValue;
import edu.stanford.nlp.stats.ClassicCounter;
import edu.stanford.nlp.stats.Counter;
import edu.stanford.nlp.util.StringUtils;
import fig.basic.LispTree;
import fig.basic.LogInfo;
import java.io.BufferedReader;
@ -202,4 +208,54 @@ public final class FileUtils {
}
return sb.toString();
}
//input: tab separated file with |utterance| |gold| |predicted|
//output: prediction file for codalab
public static void generatePredictionFile(String inFile, String outFile) throws IOException {
PrintWriter writer = IOUtils.getPrintWriter(outFile);
for (String line : IOUtils.readLines(inFile)) {
String[] tokens = line.split("\\t");
if (tokens.length == 0)
continue;
if (tokens.length < 2)
throw new RuntimeException("Illegal line: " + line);
String utterance = tokens[0];
// get gold
List<String> goldDescriptions = new ArrayList<>();
LispTree goldTree = LispTree.proto.parseFromString(tokens[1]);
for (int i = 1; i < goldTree.children.size(); ++i) {
DescriptionValue dValue = (DescriptionValue) DescriptionValue.fromString(goldTree.child(i).toString());
goldDescriptions.add(dValue.value);
}
// get predicted
List<String> predictedDescriptions = new ArrayList<>();
if (tokens.length > 2) {
LispTree predictedTree = LispTree.proto.parseFromString(tokens[2]);
for (int i = 1; i < predictedTree.children.size(); ++i) {
if (predictedTree.child(i).child(0).value.equals("name")) {
NameValue nValue = (NameValue) NameValue.fromString(predictedTree.child(i).toString());
predictedDescriptions.add(nValue.description);
} else if (predictedTree.child(i).child(0).value.equals("date")) {
DateValue dateValue = (DateValue) DateValue.fromString(predictedTree.child(i).toString());
predictedDescriptions.add(dateValue.toString());
} else
throw new RuntimeException("Can not support this value: " + line);
}
}
writer.println(Joiner.on('\t').join(utterance,
Json.writeValueAsStringHard(goldDescriptions),
Json.writeValueAsStringHard(predictedDescriptions)));
}
writer.close();
}
public static void main(String[] args) {
try {
generatePredictionFile(args[0], args[1]);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,146 @@
package edu.stanford.nlp.sempre.overnight;
import com.google.common.base.Joiner;
import edu.stanford.nlp.io.IOUtils;
import edu.stanford.nlp.stats.ClassicCounter;
import edu.stanford.nlp.stats.Counter;
import edu.stanford.nlp.stats.Counters;
import fig.basic.LispTree;
import fig.basic.MapUtils;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Word-aligns original utterances with their paraphrases
* Created by joberant on 2/20/15.
*/
public class Aligner {
private Map<String, Counter<String>> model = new HashMap<>();
public double getCondProb(String target, String source) {
if (model.containsKey(source)) {
if (model.get(source).containsKey(target))
return model.get(source).getCount(target);
}
return 0d;
}
public int size() { return model.size(); }
//takes an example file and creates a model
public void heuristicAlign(String exampleFile, int threshold) {
model.clear();
Iterator<LispTree> iter = LispTree.proto.parseFromFile(exampleFile);
while (iter.hasNext()) {
LispTree tree = iter.next();
LispTree utteranceTree = tree.child(1);
LispTree originalTree = tree.child(2);
String utterance = preprocessUtterance(utteranceTree.child(1).value);
String original = preprocessUtterance(originalTree.child(1).value);
String[] utteranceTokens = utterance.split("\\s+");
String[] originalTokens = original.split("\\s+");
align(utteranceTokens, originalTokens);
}
normalize(threshold);
}
public void saveModel(String out) throws IOException {
PrintWriter writer = IOUtils.getPrintWriter(out);
for (String source: model.keySet()) {
Counter<String> counts = model.get(source);
for (String target: counts.keySet()) {
writer.println(Joiner.on('\t').join(source, target, counts.getCount(target)));
}
}
}
//normalize all the counts to get conditional probabilities
private void normalize(int threshold) {
for (String source: model.keySet()) {
Counter<String> counts = model.get(source);
Counters.removeKeys(counts, Counters.keysBelow(counts, threshold));
Counters.normalize(counts);
}
}
//count every co-occurrence
private void align(String[] utteranceTokens, String[] originalTokens) {
for (String utteranceToken: utteranceTokens) {
for (String originalToken: originalTokens) {
MapUtils.putIfAbsent(model, utteranceToken.toLowerCase(), new ClassicCounter<>());
MapUtils.putIfAbsent(model, originalToken.toLowerCase(), new ClassicCounter<>());
model.get(utteranceToken.toLowerCase()).incrementCount(originalToken.toLowerCase());
model.get(originalToken.toLowerCase()).incrementCount(utteranceToken.toLowerCase());
}
}
}
//remove '?' and '.'
public String preprocessUtterance(String utterance) {
if (utterance.endsWith("?"))
return utterance.substring(0, utterance.length() - 1);
if (utterance.endsWith("."))
return utterance.substring(0, utterance.length() - 1);
return utterance;
}
//read from serialized file
public static Aligner read(String path) {
Aligner res = new Aligner();
for (String line: edu.stanford.nlp.io.IOUtils.readLines(path)) {
String[] tokens = line.split("\t");
MapUtils.putIfAbsent(res.model, tokens[0], new ClassicCounter<>());
res.model.get(tokens[0]).incrementCount(tokens[1], Double.parseDouble(tokens[2]));
}
return res;
}
private void berkeleyAlign(String file, int threshold) {
for (String line: IOUtils.readLines(file)) {
String[] tokens = line.split("\t");
String[] sourceTokens = tokens[0].split("\\s+");
String[] targetTokens = tokens[1].split("\\s+");
String[] alignmentTokens = tokens[2].split("\\s+");
for (String alignmentToken: alignmentTokens) {
String[] alignment = alignmentToken.split("-");
Integer source = Integer.parseInt(alignment[0]);
Integer target = Integer.parseInt(alignment[1]);
MapUtils.putIfAbsent(model, sourceTokens[source], new ClassicCounter<>());
MapUtils.putIfAbsent(model, targetTokens[target], new ClassicCounter<>());
model.get(sourceTokens[source]).incrementCount(targetTokens[target]);
model.get(targetTokens[target]).incrementCount(sourceTokens[source]);
}
}
normalize(threshold);
}
//args[0] - example file with utterance and original
//args[1] - output file
//args[2] - heuristic or berkeley
//args[3] - threshold
public static void main(String[] args) {
Aligner aligner = new Aligner();
int threshold = Integer.parseInt(args[3]);
if (args[2].equals("heuristic"))
aligner.heuristicAlign(args[0], threshold);
else if (args[2].equals("berkeley"))
aligner.berkeleyAlign(args[0], threshold);
else throw new RuntimeException("bad alignment mode: " + args[2]);
try {
aligner.saveModel(args[1]);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,59 @@
package edu.stanford.nlp.sempre.overnight;
import edu.stanford.nlp.io.IOUtils;
import edu.stanford.nlp.sempre.StringValue;
import fig.basic.LispTree;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Created by joberant on 2/24/15.
* This converts
* (targetValue (list (name fb:en.place.walton_county)))
* to
* (targetValue (string [(name fb:en.place.walton_county)]))
* This has nothing to do with 'paraphrase', it's just here for no reason
*/
public final class ConvertTargetValueFromListToString {
private ConvertTargetValueFromListToString() { }
public static void main(String[] args) {
try {
PrintWriter writer = IOUtils.getPrintWriter(args[1]);
Iterator<LispTree> trees = LispTree.proto.parseFromFile(args[0]);
while (trees.hasNext()) {
LispTree tree = trees.next();
LispTree outTree = LispTree.proto.newList();
outTree.addChild("example");
outTree.addChild(tree.child(1));
List<String> output = new ArrayList<>();
LispTree targetValue = tree.child(3);
if (!targetValue.child(0).value.equals("targetValue"))
throw new RuntimeException("Expected a target value as second child: " + targetValue);
LispTree list = targetValue.child(1);
if (!list.child(0).value.equals("list"))
throw new RuntimeException("Expected a list as first child: " + list);
for (int i = 1; i < list.children.size(); ++i)
output.add(list.child(i).toString());
StringValue newTargetValue = new StringValue(output.toString());
LispTree newTargetValueTree = LispTree.proto.newList();
newTargetValueTree.addChild("targetValue");
newTargetValueTree.addChild(newTargetValue.toLispTree());
outTree.addChild(newTargetValueTree);
outTree.print(120, 120, writer);
writer.println();
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,53 @@
package edu.stanford.nlp.sempre.overnight;
import edu.stanford.nlp.io.IOUtils;
import fig.basic.LispTree;
import fig.basic.LogInfo;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
/**
* Created by joberant on 2/22/15.
* Takes a file with lisp trees of original and canonical utterances
* and creates the input for the berkley aligner
*/
public final class CreateBerkeleyAlignerInputFromLispTree {
private CreateBerkeleyAlignerInputFromLispTree() { }
//args[0]: lisp tree file
//args[1] output directory
public static void main(String[] args) {
Iterator<LispTree> trees = LispTree.proto.parseFromFile(args[0]);
try {
PrintWriter writerOriginal = IOUtils.getPrintWriter(args[1] + ".e");
PrintWriter writerUtterance = IOUtils.getPrintWriter(args[1] + ".f");
LogInfo.logs("output directory=%s", args[1]);
int i = 0;
while (trees.hasNext()) {
i++;
LispTree tree = trees.next();
LispTree utteranceTree = tree.child(1);
LispTree originalTree = tree.child(2);
if (!utteranceTree.child(0).value.equals("utterance"))
throw new RuntimeException("First child is not an utterance " + utteranceTree);
if (!originalTree.child(0).value.equals("original"))
throw new RuntimeException("second child is not the original " + originalTree);
String uttearnce = utteranceTree.child(1).value;
if (uttearnce.endsWith("?") || uttearnce.endsWith("."))
uttearnce = uttearnce.substring(0, uttearnce.length() - 1);
String original = originalTree.child(1).value;
writerOriginal.println(original);
writerUtterance.println(uttearnce);
}
LogInfo.logs("Numebr of trees=%s", i);
writerOriginal.close();
writerUtterance.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,50 @@
package edu.stanford.nlp.sempre.overnight;
import fig.basic.Option;
import fig.exec.Execution;
import edu.stanford.nlp.sempre.*;
/**
* Created by joberant on 1/27/15.
* Generating canonical utterances from grammar with various depths
*/
public class GenerationMain implements Runnable {
@Option
public boolean interactive = false;
@Option
public boolean varyMaxDepth = false;
@Override
public void run() {
Builder builder = new Builder();
builder.build();
Dataset dataset = new Dataset();
dataset.read();
int currDepth = varyMaxDepth ? 1 : FloatingParser.opts.maxDepth;
int maxDepth = FloatingParser.opts.maxDepth;
for (; currDepth < maxDepth + 1; currDepth++) {
FloatingParser.opts.maxDepth = currDepth;
//LogInfo.logs("Curr depth=%s", currDepth);
//LogInfo.logs("file = %s", FloatingParser.opts.predictedUtterancesFile);
//PrintWriter writer = IOUtils.openOutAppendEasy(Execution.getFile(FloatingParser.opts.predictedUtterancesFile));
//writer.println(String.format("Depth=%s", currDepth));
//writer.println(String.format("--------", currDepth));
//writer.close();
Learner learner = new Learner(builder.parser, builder.params, dataset);
learner.learn();
}
if (interactive) {
Master master = new Master(builder);
master.runInteractivePrompt();
}
}
public static void main(String[] args) {
Execution.run(args, "GenerationMain", new GenerationMain(), Master.getOptionsParser());
}
}

View File

@ -0,0 +1,57 @@
package edu.stanford.nlp.sempre.overnight;
import java.util.*;
import java.util.regex.Pattern;
import edu.stanford.nlp.sempre.*;
import fig.basic.Option;
import fig.basic.MapUtils;
/**
* Hard-coded hacks for pruning derivations in floating parser for overnight domains.
*
*/
public class OvernightDerivationPruningComputer extends DerivationPruningComputer {
public static class Options {
@Option (gloss = "Whether filter derivations using hard constraints")
public boolean applyHardConstraints = false;
}
public static Options opts = new Options();
public OvernightDerivationPruningComputer(DerivationPruner pruner) {
super(pruner);
}
@Override
public boolean isPruned(Derivation deriv) {
if (opts.applyHardConstraints && violateHardConstraints(deriv)) return true;
return false;
}
// Check a few hard constraints on each derivation
private static boolean violateHardConstraints(Derivation deriv) {
if (deriv.value != null) {
if (deriv.value instanceof ErrorValue) return true;
if (deriv.value instanceof StringValue) { //empty denotation
if (((StringValue) deriv.value).value.equals("[]")) return true;
}
if (deriv.value instanceof ListValue) {
List<Value> values = ((ListValue) deriv.value).values;
// empty lists
if (values.size() == 0) return true;
// NaN
if (values.size() == 1 && values.get(0) instanceof NumberValue) {
if (Double.isNaN(((NumberValue) values.get(0)).value)) return true;
}
// If we are supposed to get a number but we get a string (some sparql weirdness)
if (deriv.type.equals(SemType.numberType) &&
values.size() == 1 &&
!(values.get(0) instanceof NumberValue)) return true;
}
}
return false;
}
}

View File

@ -0,0 +1,609 @@
package edu.stanford.nlp.sempre.overnight;
import com.google.common.base.Joiner;
import com.google.common.collect.Sets;
import edu.stanford.nlp.io.IOUtils;
import fig.basic.BipartiteMatcher;
import fig.basic.LogInfo;
import fig.basic.MapUtils;
import fig.basic.Option;
import edu.stanford.nlp.sempre.*;
import java.util.*;
/**
* Define features on the input utterance and a partial canonical utterance.
*
* Feature computation recipe:
* - For both the input and (partial) canonical utterance, extract a list of tokens
* (perhaps with POS tags).
* - Given a list of tokens, extract a set of items, where an item is a (tag,
* data) pair, where the tag specifies the "type" of the data, and is used
* to determine features. Example: ("bigram", "not contains"), ("unigram",
* "not"), ("unigram-RB", "not")
* - Given the input and canonical items, define recall features (how much of
* the input items is the canononical covering).
* This recipe allows us to decouple the extraction of items on one utterance
* from the computation of actual precision/recall features.
*
* @author Percy Liang
* @author Yushi Wang
*/
public class OvernightFeatureComputer implements FeatureComputer {
public static class Options {
@Option(gloss = "Set of paraphrasing feature domains to include")
public Set<String> featureDomains = new HashSet<>();
@Option(gloss = "Whether or not to count intermediate categories for size feature")
public boolean countIntermediate = true;
@Option(gloss = "Whether or not to do match/ppdb analysis")
public boolean itemAnalysis = true;
@Option(gloss = "Whether or not to learn paraphrases")
public boolean learnParaphrase = true;
@Option(gloss = "Verbose flag")
public int verbose = 0;
@Option(gloss = "Path to alignment file")
public String wordAlignmentPath;
@Option(gloss = "Path to phrase alignment file")
public String phraseAlignmentPath;
@Option(gloss = "Threshold for phrase table co-occurrence")
public int phraseTableThreshold = 3;
}
public static Options opts = new Options();
private static Aligner aligner;
private static Map<String, Map<String, Double>> phraseTable;
public final SimpleLexicon simpleLexicon = SimpleLexicon.getSingleton();
@Override public void extractLocal(Example ex, Derivation deriv) {
if (deriv.rule.rhs == null) return;
// Optimization: feature vector same as child, so don't do anything.
if (deriv.rule.isCatUnary()) {
if (deriv.isRootCat()) {
extractValueInFormulaFeature(deriv);
extractRootFeatures(ex, deriv);
return;
}
}
// Important! We want to define the global feature vector for this
// derivation, but we can only specify the local feature vector. So to
// make things cancel out, we subtract out the unwanted feature vectors of
// descendents.
subtractDescendentsFeatures(deriv, deriv);
deriv.addFeature("paraphrase", "size", derivationSize(deriv));
extractRootFeatures(ex, deriv);
extractLexicalFeatures(ex, deriv);
extractPhraseAlignmentFeatures(ex, deriv);
extractLogicalFormFeatures(ex, deriv);
if (!opts.itemAnalysis) return;
List<Item> inputItems = computeInputItems(ex);
List<Item> candidateItems = computeCandidateItems(ex, deriv);
for (Item input : inputItems) {
double match = 0;
double ppdb = 0;
double skipBigram = 0;
double skipPpdb = 0;
for (Item candidate : candidateItems) {
if (!input.tag.equals(candidate.tag)) continue;
if (input.tag.equals("skip-bigram")) {
skipBigram = Math.max(skipBigram, computeMatch(input.data, candidate.data));
skipPpdb = Math.max(skipPpdb, computeParaphrase(input.data, candidate.data));
} else {
match = Math.max(match, computeMatch(input.data, candidate.data));
ppdb = Math.max(ppdb, computeParaphrase(input.data, candidate.data));
}
}
if (match > 0 && opts.featureDomains.contains("match")) deriv.addFeature("paraphrase", "match");
if (ppdb > 0 && opts.featureDomains.contains("ppdb")) deriv.addFeature("paraphrase", "ppdb");
if (skipBigram > 0 && opts.featureDomains.contains("skip-bigram")) deriv.addFeature("paraphrase", "skip-bigram");
if (skipPpdb > 0 && opts.featureDomains.contains("skip-ppdb")) deriv.addFeature("paraphrase", "skip-ppdb");
}
HashMap<String, Double> features = new LinkedHashMap<>();
deriv.incrementAllFeatureVector(+1, features);
if (opts.verbose >= 1) {
LogInfo.logs("category %s, %s %s", deriv.cat, inputItems, candidateItems);
FeatureVector.logFeatures(features);
}
}
private void extractValueInFormulaFeature(Derivation deriv) {
if (!opts.featureDomains.contains("denotation")) return;
if (deriv.value instanceof StringValue) {
//get strings from value
List<String> valueList = new ArrayList<>();
String value = ((StringValue) deriv.value).value;
if (value.charAt(0) == '[')
value = value.substring(1, value.length() - 1); //strip "[]"
String[] tokens = value.split(",");
for (String token : tokens) {
token = token.trim(); //strip spaces
if (token.length() > 0)
valueList.add(token);
}
//get strings from formula
List<Formula> formulaList = deriv.formula.mapToList(formula -> {
List<Formula> res = new ArrayList<>();
if (formula instanceof ValueFormula) {
res.add(formula);
}
return res;
}, true);
for (Formula f : formulaList) {
Value formulaValue = ((ValueFormula) f).value;
String valueStr = (formulaValue instanceof StringValue) ? ((StringValue) formulaValue).value : formulaValue.toString();
if (valueList.contains(valueStr))
deriv.addFeature("denotation", "value_in_formula");
}
}
}
private void extractRootFeatures(Example ex, Derivation deriv) {
if (!deriv.isRootCat()) return;
if (!opts.featureDomains.contains("root") && !opts.featureDomains.contains("root_lexical")) return;
List<String> derivTokens = Arrays.asList(deriv.canonicalUtterance.split("\\s+"));
List<String> inputTokens = ex.getTokens();
//alignment features
BipartiteMatcher bMatcher = new BipartiteMatcher();
List<String> filteredInputTokens = filterStopWords(inputTokens);
List<String> filteredDerivTokens = filterStopWords(derivTokens);
int[] assignment = bMatcher.findMaxWeightAssignment(buildAlignmentMatrix(filteredInputTokens, filteredDerivTokens));
if (opts.featureDomains.contains("root")) {
//number of unmathced words based on exact match and ppdb
int matches = 0;
for (int i = 0; i < filteredInputTokens.size(); ++i) {
if (assignment[i] != i) {
matches++;
}
}
deriv.addFeature("root", "unmatched_input", filteredInputTokens.size() - matches);
deriv.addFeature("root", "unmatched_deriv", filteredDerivTokens.size() - matches);
if (deriv.value != null) {
if (deriv.value instanceof ListValue) {
ListValue list = (ListValue) deriv.value;
deriv.addFeature("root", String.format("pos0=%s&returnType=%s", ex.posTag(0), list.values.get(0).getClass()));
}
}
}
if (opts.featureDomains.contains("root_lexical")) {
for (int i = 0; i < assignment.length; ++i) {
if (assignment[i] == i) {
if (i < filteredInputTokens.size()) {
String inputToken = filteredInputTokens.get(i).toLowerCase();
deriv.addFeature("root_lexical", "deleted_token=" + inputToken);
if (!simpleLexicon.lookup(inputToken).isEmpty()) {
deriv.addFeature("root_lexical", "deleted_entity");
}
}
else {
String derivToken = filteredDerivTokens.get(i - filteredInputTokens.size());
deriv.addFeature("root_lexical", "deleted_token=" + derivToken);
if (!simpleLexicon.lookup(derivToken).isEmpty()) {
deriv.addFeature("root_lexical", "deleted_entity");
}
}
}
}
}
}
private List<Formula> getCallFormulas(Derivation deriv) {
return deriv.formula.mapToList(formula -> {
List<Formula> res = new ArrayList<>();
if (formula instanceof CallFormula) {
res.add(((CallFormula) formula).func);
}
return res;
}, true);
}
private void extractLogicalFormFeatures(Example ex, Derivation deriv) {
if (!opts.featureDomains.contains("lf")) return;
for (int i = 0; i < ex.numTokens(); ++i) {
List<Formula> callFormulas = getCallFormulas(deriv);
if (ex.posTag(i).equals("JJS")) {
if (ex.token(i).equals("least") || ex.token(i).equals("most")) //at least and at most are not what we want
continue;
for (Formula callFormula: callFormulas) {
String callFormulaDesc = callFormula.toString();
//LogInfo.logs("SUPER: utterance=%s, formula=%s", ex.utterance, deriv.formula);
deriv.addFeature("lf", callFormulaDesc + "& superlative");
}
}
}
if (!opts.featureDomains.contains("simpleworld")) return;
//specific handling of simple world methods
if (deriv.formula instanceof CallFormula) {
CallFormula callFormula = (CallFormula) deriv.formula;
String desc = callFormula.func.toString();
switch (desc) {
case "edu.stanford.nlp.sempre.overnight.SimpleWorld.filter":
deriv.addFeature("simpleworld", "filter&" + callFormula.args.get(1));
break;
case "edu.stanford.nlp.sempre.overnight.SimpleWorld.getProperty":
deriv.addFeature("simpleworld", "getProperty&" + callFormula.args.get(1));
break;
case "edu.stanford.nlp.sempre.overnight.SimpleWorld.superlative":
deriv.addFeature("simpleworld", "superlative&" + callFormula.args.get(1) + "&" + callFormula.args.get(2));
break;
case "edu.stanford.nlp.sempre.overnight.SimpleWorld.countSuperlative":
deriv.addFeature("simpleworld", "countSuperlative&" + callFormula.args.get(1) + "&" + callFormula.args.get(2));
break;
case "edu.stanford.nlp.sempre.overnight.SimpleWorld.countComparative":
deriv.addFeature("simpleworld", "countComparative&" + callFormula.args.get(2) + "&" + callFormula.args.get(1));
break;
case "edu.stanford.nlp.sempre.overnight.SimpleWorld.aggregate":
deriv.addFeature("simpleworld", "countComparative&" + callFormula.args.get(0));
break;
default: break;
}
}
}
private void extractPhraseAlignmentFeatures(Example ex, Derivation deriv) {
if (!opts.featureDomains.contains("alignment")) return;
if (phraseTable == null) phraseTable = loadPhraseTable();
//get the tokens
List<String> derivTokens = Arrays.asList(deriv.canonicalUtterance.split("\\s+"));
Set<String> inputSubspans = ex.languageInfo.getLowerCasedSpans();
for (int i = 0; i < derivTokens.size(); ++i) {
for (int j = i + 1; j <= derivTokens.size() && j <= i + 4; ++j) {
String lhs = Joiner.on(' ').join(derivTokens.subList(i, j));
if (entities.contains(lhs)) continue; //optimization
if (phraseTable.containsKey(lhs)) {
Map<String, Double> rhsCandidates = phraseTable.get(lhs);
Set<String> intersection = Sets.intersection(rhsCandidates.keySet(), inputSubspans);
for (String rhs: intersection) {
addAndFilterLexicalFeature(deriv, "alignment", rhs, lhs);
}
}
}
}
}
private Map<String, Map<String, Double>> loadPhraseTable() {
Map<String, Map<String, Double>> res = new HashMap<>();
int num = 0;
for (String line : IOUtils.readLines(opts.phraseAlignmentPath)) {
String[] tokens = line.split("\t");
if (tokens.length != 3) throw new RuntimeException("Bad alignment line: " + line);
MapUtils.putIfAbsent(res, tokens[0], new HashMap<>());
double value = Double.parseDouble(tokens[2]);
if (value >= opts.phraseTableThreshold) {
res.get(tokens[0]).put(tokens[1], value);
num++;
}
}
LogInfo.logs("Number of entries=%s", num);
return res;
}
private void addAndFilterLexicalFeature(Derivation deriv, String domain, String str1, String str2) {
String[] str1Tokens = str1.split("\\s+");
String[] str2Tokens = str2.split("\\s+");
for (String str1Token: str1Tokens)
if (entities.contains(str1Token)) return;
for (String str2Token: str2Tokens)
if (entities.contains(str2Token)) return;
if (stopWords.contains(str1) || stopWords.contains(str2)) return;
deriv.addFeature(domain, str1 + "--" + str2);
}
private void extractLexicalFeatures(Example ex, Derivation deriv) {
if (!opts.featureDomains.contains("lexical")) return;
List<String> derivTokens = Arrays.asList(deriv.canonicalUtterance.split("\\s+"));
List<String> inputTokens = ex.getTokens();
//alignment features
BipartiteMatcher bMatcher = new BipartiteMatcher();
List<String> filteredInputTokens = filterStopWords(inputTokens);
List<String> filteredDerivTokens = filterStopWords(derivTokens);
double[][] alignmentMatrix = buildLexicalAlignmentMatrix(filteredInputTokens, filteredDerivTokens);
int[] assignment = bMatcher.findMaxWeightAssignment(alignmentMatrix);
for (int i = 0; i < filteredInputTokens.size(); ++i) {
if (assignment[i] != i) {
int derivIndex = assignment[i] - filteredInputTokens.size();
String inputToken = filteredInputTokens.get(i).toLowerCase();
if (entities.contains(inputToken)) continue; //optimization - stop here
String derivToken = filteredDerivTokens.get(derivIndex).toLowerCase();
if (!inputToken.equals(derivToken)) {
addAndFilterLexicalFeature(deriv, "lexical", inputToken, derivToken);
extractStringSimilarityFeatures(deriv, inputToken, derivToken);
//2:2 features
if (i < filteredInputTokens.size() - 1) {
if (assignment[i + 1] == assignment[i] + 1) {
String inputBigram = Joiner.on(' ').join(inputToken, filteredInputTokens.get(i + 1)).toLowerCase();
String derivBigram = Joiner.on(' ').join(derivToken, filteredDerivTokens.get(derivIndex + 1)).toLowerCase();
if (!inputBigram.equals(derivBigram)) {
addAndFilterLexicalFeature(deriv, "lexical", inputBigram, derivBigram);
}
}
}
//1:2 features
if (derivIndex > 0) {
addAndFilterLexicalFeature(deriv, "lexical", inputToken,
Joiner.on(' ').join(filteredDerivTokens.get(derivIndex - 1), filteredDerivTokens.get(derivIndex)));
}
if (derivIndex < filteredDerivTokens.size() - 1) {
addAndFilterLexicalFeature(deriv, "lexical", inputToken,
Joiner.on(' ').join(filteredDerivTokens.get(derivIndex), filteredDerivTokens.get(derivIndex + 1)));
}
}
}
}
}
private void extractStringSimilarityFeatures(Derivation deriv, String inputToken, String derivToken) {
if (inputToken.startsWith(derivToken) || derivToken.startsWith(inputToken))
deriv.addFeature("lexical", "starts_with");
else if (inputToken.length() > 4 && derivToken.length() > 4) {
if (inputToken.substring(0, 4).equals(derivToken.substring(0, 4)))
deriv.addFeature("lexical", "common_prefix");
}
}
//return a list without wtop words
private List<String> filterStopWords(List<String> tokens) {
List<String> res = new ArrayList<>();
for (String token : tokens) {
if (!stopWords.contains(token))
res.add(token);
}
return res;
}
private double[][] buildAlignmentMatrix(List<String> inputTokens, List<String> derivTokens) {
double[][] res = new double[inputTokens.size() + derivTokens.size()][inputTokens.size() + derivTokens.size()];
for (int i = 0; i < inputTokens.size(); ++i) {
for (int j = 0; j < derivTokens.size(); ++j) {
String inputToken = inputTokens.get(i);
String derivToken = derivTokens.get(j);
if (computeMatch(inputToken, derivToken) > 0d) {
res[i][inputTokens.size() + j] = 1d;
res[inputTokens.size() + j][i] = 1d;
}
else if (computeParaphrase(inputToken, derivToken) > 0d) {
res[i][inputTokens.size() + j] = 0.5d;
res[inputTokens.size() + j][i] = 0.5d;
}
}
}
for (int i = 0; i < res.length - 1; i++) {
for (int j = i + 1; j < res.length; j++) {
if (i != j && res[i][j] < 1) {
res[i][j] = Double.NEGATIVE_INFINITY;
res[j][i] = Double.NEGATIVE_INFINITY;
}
}
}
return res;
}
private double[][] buildLexicalAlignmentMatrix(List<String> inputTokens, List<String> derivTokens) {
if (aligner == null) {
aligner = Aligner.read(opts.wordAlignmentPath);
}
double[][] res = new double[inputTokens.size() + derivTokens.size()][inputTokens.size() + derivTokens.size()];
//init with -infnty and low score on the diagonal
for (int i = 0; i < res.length - 1; i++) {
for (int j = i; j < res.length; j++) {
if (i == j) {
res[i][j] = 0d;
res[j][i] = 0d;
}
else {
res[i][j] = -1000d;
res[j][i] = -1000d;
}
}
}
for (int i = 0; i < inputTokens.size(); ++i) {
for (int j = 0; j < derivTokens.size(); ++j) {
String inputToken = inputTokens.get(i).toLowerCase();
String derivToken = derivTokens.get(j).toLowerCase();
if (computeMatch(inputToken, derivToken) > 0) {
res[i][inputTokens.size() + j] = 1d;
res[inputTokens.size() + j][i] = 1d;
} else if (computeParaphrase(inputToken, derivToken) > 0) {
res[i][inputTokens.size() + j] = 0.5d;
res[inputTokens.size() + j][i] = 0.5d;
}
else if (aligner.getCondProb(inputToken, derivToken) > 0d &&
aligner.getCondProb(derivToken, inputToken) > 0d) {
double product = aligner.getCondProb(inputToken, derivToken) * aligner.getCondProb(derivToken, inputToken);
res[i][inputTokens.size() + j] = product;
res[inputTokens.size() + j][i] = product;
}
}
}
return res;
}
// Represents a local pattern on an utterance.
private static class Item {
public final String tag;
public final String data;
public Item(String tag, String data) {
this.tag = tag;
this.data = data;
}
@Override public String toString() {
return tag + ":" + data;
}
}
// Fetch items from the temporary state.
// If it doesn't exist, create one.
private static List<Item> getItems(Map<String, Object> tempState) {
List<Item> items = (List<Item>) tempState.get("items");
if (items == null)
tempState.put("items", items = new ArrayList<>());
return items;
}
private static void setItems(Map<String, Object> tempState, List<Item> items) {
tempState.put("items", items);
}
// TODO(yushi): make this less hacky
private static final List<String> stopWords = Arrays.asList("\' \" `` ` \'\' a an the that which . what ? is are am be of".split(" "));
private static final Set<String> entities =
new HashSet<>(Arrays.asList("alice", "bob", "greenberg", "greenberg cafe", "central office",
"sacramento", "austin", "california", "texas", "colorado", "colorado river", "red river", "lake tahoe", "tahoe", "lake huron", "huron", "mount whitney", "whitney", "mount rainier", "rainier", "death valley", "pacific ocean", "pacific",
"sesame", "mission ave", "mission", "chelsea",
"multivariate data analysis", "multivariate data", "data analysis", "multivariate", "data", "efron", "lakoff", "annals of statistics", "annals", "annals of", "of statistics", "statistics", "computational linguistics", "computational", "linguistics",
"thai cafe", "pizzeria juno",
"new york", "york", "beijing", "brown university", "ucla", "mckinsey", "google"));
private static boolean isStopWord(String token) {
return stopWords.contains(token);
}
private static void populateItems(List<String> tokens, List<Item> items) {
List<String> prunedTokens = new ArrayList<>();
// Populate items with unpruned tokens
for (int i = 0; i < tokens.size(); i++) {
items.add(new Item("unigram", tokens.get(i)));
if (i - 1 >= 0) {
items.add(new Item("bigram", tokens.get(i - 1) + " " + tokens.get(i)));
}
if (!isStopWord(tokens.get(i)) || (i > 0 && (tokens.get(i - 1).equals('`') || tokens.get(i - 1).equals("``"))))
prunedTokens.add(tokens.get(i));
}
// Populate items with skip words removed
for (int i = 1; i < prunedTokens.size(); i++) {
items.add(new Item("skip-bigram", prunedTokens.get(i - i) + " " + prunedTokens.get(i)));
}
}
// Compute the items for the input utterance.
private static List<Item> computeInputItems(Example ex) {
List<Item> items = getItems(ex.getTempState());
if (items.size() != 0) return items;
List<String> tokens = new ArrayList<>(ex.getTokens());
populateItems(tokens, items);
LogInfo.logs("input %s, items %s", ex, items);
return items;
}
// Return the set of tokens (partial canonical utterance) produced by the
// derivation.
public static List<String> extractTokens(Example ex, Derivation deriv, List<String> tokens) {
int childIndex = 0;
if (deriv.rule.rhs != null) {
for (String p : deriv.rule.rhs)
if (Rule.isCat(p))
extractTokens(ex, deriv.children.get(childIndex++), tokens);
else
tokens.add(p);
} else if (deriv.start != -1 && deriv.end != -1) {
for (int i = deriv.start; i < deriv.end; i++)
tokens.add(ex.token(i));
}
return tokens;
}
// Compute the items for a partial canonical utterance.
private static List<Item> computeCandidateItems(Example ex, Derivation deriv) {
// Get tokens
List<String> tokens = new ArrayList<>();
extractTokens(ex, deriv, tokens);
// Compute items
List<Item> items = new ArrayList<>();
populateItems(tokens, items);
return items;
}
private static void subtractDescendentsFeatures(Derivation deriv, Derivation subderiv) {
if (subderiv.children != null) {
for (Derivation child : subderiv.children) {
deriv.getLocalFeatureVector().add(-1, child.getLocalFeatureVector());
subtractDescendentsFeatures(deriv, child);
}
}
}
// Return the "complexity" of the given derivation.
private static int derivationSize(Derivation deriv) {
int sum = 0;
if (opts.countIntermediate || !(deriv.rule.lhs.contains("Intermediate"))) sum++;
if (deriv.children != null) {
for (Derivation child : deriv.children)
sum += derivationSize(child);
}
return sum;
}
private static double computeMatch(String a, String b) {
if (a.equals(b)) return 1;
if (LanguageInfo.LanguageUtils.stem(a).equals(LanguageInfo.LanguageUtils.stem(b))) return 1;
return 0;
}
private static double computeParaphrase(String a, String b) {
if (computeMatch(a, b) > 0) return 0;
String[] aGrams = a.split(" ");
String[] bGrams = b.split(" ");
if (aGrams.length != bGrams.length) return 0;
PPDBModel model = PPDBModel.getSingleton();
int numPpdb = 0;
int numMisses = 0;
for (int i = 0; i < aGrams.length; i++) {
if (computeMatch(aGrams[i], bGrams[i]) == 0d) {
if (model.get(aGrams[i], bGrams[i]) > 0d ||
model.get(LanguageInfo.LanguageUtils.stem(aGrams[i]),
LanguageInfo.LanguageUtils.stem(bGrams[i])) > 0d) {
numPpdb++;
}
else {
numMisses++;
}
}
}
return (numMisses == 0 && numPpdb <= 1 ? 1d : 0d);
}
}

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