Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Up to the 7th calibration now works

- This tool is capable of some pretty cool stuff, now.
- Check out the EXAMPLE.md for relative quantity comparison, special
  case comparators with contexts, subordinate conjunctions as filtering
  context containers.
- You can also correct the parser if/when it gets confused, and now all
  words are given a change to be accounted for. To mimic older
  functionality, simply say "1" for all questions of "what role does
  this fill". 1 being the "this is noise" option.
  • Loading branch information...
commit bc65ebb2ed03788912ff4a510af15389b0080784 1 parent cc41c42
Eric Garside authored
View
147 EXAMPLE.md
@@ -1,3 +1,11 @@
+
+how many asking
+balloons unit
+does q_start
+Jane context
+have q_stop
+('now', None) subordinate
+? punctuation
# Zoidberg Solution
## The problem
@@ -38,13 +46,22 @@ The answer is the unknown value of balloons owned by Jane at the end of the prob
## Data extraction
### Sentence 1
-balloons owend by Jane = 14
+balloons owned by Jane = 14
### Sentence 2
-balloons owend by Jane + 6
+balloons owned by Jane + 6
## Correct response
20 balloons
+how many asking
+bananas unit
+did q_start
+Mrs. Jones context
+buy q_stop
+in conjunction
+the noise
+('beginning', 'in') subordinate
+? punctuation
# Zoidberg Solution
## The problem
@@ -74,7 +91,7 @@ I think this problem is about Mrs. Jones, her family, and her friends exchanging
context operator constant unit punctuation
Mrs. Jones gave the remaining 4 bananas to her friends .
- context operator noise solution_zero constant unit unknown context punctuation
+ context operator noise solution_zero constant unit noise context punctuation
How many bananas did Mrs. Jones buy in the beginning ?
asking unit q_start context q_stop conjunction noise subordinate punctuation
@@ -91,18 +108,25 @@ The answer is the unknown value of bananas owned by Mrs. Jones at the beginning
## Data extraction
### Sentence 1
-bananas owend by Mrs. Jones = 0
-bananas owend by Mrs. Jones + x
+bananas owned by Mrs. Jones = 0
+bananas owned by Mrs. Jones + x
### Sentence 2
-bananas owend by Mrs. Jones - 5
+bananas owned by Mrs. Jones - 5
### Sentence 3
-bananas owend by Mrs. Jones - 4
-bananas owend by Mrs. Jones == 0
+bananas owned by Mrs. Jones - 4
+bananas owned by Mrs. Jones == 0
## Correct response
9 bananas
+how many asking
+jars unit
+does q_start
+Tony context
+have q_stop
+('now', None) subordinate
+? punctuation
# Zoidberg Solution
## The problem
@@ -126,7 +150,7 @@ I think this problem is about Tony and his sister exchanging jars and asks a sin
context operator constant unit punctuation
Tony gives 16 jars to his sister .
- context operator constant unit unknown context punctuation
+ context operator constant unit noise context punctuation
How many jars does Tony have now ?
asking unit q_start context q_stop subordinate punctuation
@@ -143,13 +167,19 @@ The answer is the unknown value of jars owned by Tony at the end of the problem.
## Data extraction
### Sentence 1
-jars owend by Tony = 19
+jars owned by Tony = 19
### Sentence 2
-jars owend by Tony - 16
+jars owned by Tony - 16
## Correct response
3 jars
+how many asking
+dolls unit
+does q_start
+Ethelle context
+have q_stop
+? punctuation
# Zoidberg Solution
## The problem
@@ -190,14 +220,23 @@ The answer is the unknown value of dolls owned by Ethelle.
## Data extraction
### Sentence 1
-dolls owend by Lucy = 8
+dolls owned by Lucy = 8
### Sentence 2
-dolls owend by Ethelle = 8
-dolls owend by Ethelle + 4
+dolls owned by Ethelle = 8
+dolls owned by Ethelle + 4
## Correct response
12 dolls
+how many asking
+fewer rel_less
+toy cars unit
+does q_start
+Chandler context
+have q_stop
+than conjunction
+('Joey', (u'singular', u'masculine')) comparator_context
+? punctuation
# Zoidberg Solution
## The problem
@@ -238,13 +277,20 @@ The answer is the difference in value of toy cars owned by Chandler with respect
## Data extraction
### Sentence 1
-toy cars owend by Joey = 13
+toy cars owned by Joey = 13
### Sentence 2
-toy cars owend by Chandler = 6
+toy cars owned by Chandler = 6
## Correct response
7 fewer toy cars
+how many asking
+apples unit
+does q_start
+Marc context
+have q_stop
+('now', None) subordinate
+? punctuation
# Zoidberg Solution
## The problem
@@ -281,10 +327,10 @@ I think this problem is about Marc, Jim, and Julia exchanging apples and asks a
context operator constant unit noise punctuation
Marc gives 2 apples to Jim .
- context operator constant unit unknown context punctuation
+ context operator constant unit noise context punctuation
Marc gives 3 apples to Julia .
- context operator constant unit unknown context punctuation
+ context operator constant unit noise context punctuation
How many apples does Marc have now ?
asking unit q_start context q_stop subordinate punctuation
@@ -301,16 +347,73 @@ The answer is the unknown value of apples owned by Marc at the end of the proble
## Data extraction
### Sentence 1
-apples owend by Marc = 10
+apples owned by Marc = 10
### Sentence 2
-apples owend by Marc - 2
+apples owned by Marc - 2
### Sentence 3
-apples owend by Marc - 2
+apples owned by Marc - 2
### Sentence 4
-apples owend by Marc - 3
+apples owned by Marc - 3
## Correct response
3 apples
+how many asking
+fish context
+are pre_ind_plu
+swimming acting
+in conjunction
+the noise
+('pond', 'in') subordinate
+('now', None) subordinate
+? punctuation
+# Zoidberg Solution
+
+## The problem
+8 fish are swimming in a pond. 4 more fish join them.
+How many fish are swimming in the pond now?
+
+## Digested problem
+ 8 fish are swimming in a pond .
+ CD JJ NN VBG IN DT NN .
+
+ 4 more fish join them .
+ LS JJR JJ NN PRP .
+
+ How many fish are swimming in the pond now ?
+ WRB JJ JJ VBP VBG IN DT NN RB .
+
+## Problem inference
+I think this problem is about an increasing number of swimming fish in a pond and asks a single question.
+
+## Parsed problem
+ 8 fish are swimming in a pond .
+ constant context pre_ind_plu acting conjunction constant subordinate punctuation
+
+ 4 more fish join fish .
+ constant rel_more context operator context punctuation
+
+ How many fish are swimming in the pond now ?
+ asking context pre_ind_plu acting conjunction noise subordinate subordinate punctuation
+
+
+## Question 1
+
+### Question text
+How many fish are swimming in the pond now?
+
+### Answer interpretation
+The answer is the unknown value of fish swimming fish in a pond at the end of the problem.
+
+## Data extraction
+
+### Sentence 1
+swimming fish in a pond = 8
+
+### Sentence 2
+swimming fish in a pond + 4
+
+## Correct response
+12 fish
View
8 TODO
@@ -1 +1,7 @@
-* Calibration 5 needs work; other calibrations appear to work
+* Calibrations greater than 7 are broken
+* There's a bug right now where on the first run through a problem where you
+ specify a correct pre_ind_plu using the unknown setter, the brain farts
+ and it answers incorrectly, but if rerun answers just fine.
+ Repro steps:
+ * Remove brain
+ * Answer calibration 7
View
2  calibrations/07.txt
@@ -0,0 +1,2 @@
+8 fish are swimming in a pond. 4 more fish join them.
+How many fish are swimming in the pond now?
View
1  calibrations/08.txt
@@ -0,0 +1 @@
+Michael had 8 pieces of pizza. He ate 2 pieces of pizza. How many pieces were left?
View
2  calibrations/09.txt
@@ -0,0 +1,2 @@
+Pigpen had some rocks. He kept 3 rocks for himself and gave the remaining 8 rocks to his friends.
+How many rocks did he have in the beginning?
View
1  calibrations/10.txt
@@ -0,0 +1 @@
+Mr. Lupis needs 4 eggs to bake 13 muffins. He has only 2 eggs. How many more eggs does he need to bake the muffins?
View
1  calibrations/11.txt
@@ -0,0 +1 @@
+Mitch has 3 cobs. Lisa has 2 cobs. How many cobs do they have altogether?
View
3  calibrations/12.txt
@@ -0,0 +1,3 @@
+Mickey has a dozen apples.
+Eric takes away half of the apples.
+How many apples does Mickey have now?
View
2  example.brain.json
@@ -1 +1 @@
-{"operator_verbs": {"has": "eq", "bought": "ad", "ate": "su", "buys": "ad", "gave": "su", "gives": "su"}, "inclusive": {"her family": "inclusive", "friends": "exclusive", "her friends": "exclusive", "family": "inclusive"}, "subordinates": {"now": "time_ending", "beginning": "time_starting"}, "retagged": {"ate": "operator_verbs"}, "relative": {"more": "rel_more"}, "answer_syntax": {"how many": "expression"}, "plurality": {"Jones": "singular", "sister": "singular", "ate": null, "her": "singular", "family": "plural", "friends": "plural", "bananas": "plural", "Lucy": "singular", "Mrs.": "singular", "Jane": "singular", "his": "singular", "she": "singular", "Tony": "singular", "jars": "plural", "dolls": "plural", "balloons": "plural", "Ethelle": "singular", "he": "singular"}, "determiners": {"the": "noise", "some": "variable", "another": "noise"}, "gender": {"Jones": "ambiguous", "sister": "feminine", "his": "masculine", "her": "feminine", "family": "mixed", "friends": "mixed", "bananas": "neutral", "Lucy": "feminine", "Mrs.": "feminine", "Jane": "feminine", "she": "feminine", "Tony": "masculine", "jars": "neutral", "dolls": "neutral", "balloons": "neutral", "Ethelle": "feminine", "he": "masculine"}, "gerunds": {"remaining": "solution_zero"}, "comparison_adj": {}}
+{"operator_verbs": {"gives": "su", "ate": "su", "join": "ad", "buys": "ad", "gave": "su", "has": "eq", "throws": "su", "bought": "ad"}, "subordinates": {"pond": "place_noun", "away": "False", "now": "time_ending", "beginning": "time_starting"}, "inclusive": {"her family": "inclusive", "friends": "exclusive", "her friends": "exclusive", "family": "inclusive"}, "unknown": {"('to', 'TO', None)": "False", "('fish', 'JJ', None)": null, "('4', 'LS', None)": null}, "retagged": {"ate": "operator_verbs", "join": "operator_verbs", "fish": "nounlike", "to": "noise", "are": "pre_ind_plu", "away": "noise", "4": "numbers"}, "relative": {"fewer": "rel_less", "more": "rel_more"}, "answer_syntax": {"How many": "expression", "how many": "expression"}, "plurality": {"bananas": "plural", "family": "plural", "Marc": "singular", "fish": "regular", "Jim": "singular", "are": null, "apples": "plural", "Jane": "singular", "pond": "singular", "Chandler": "singular", "toy": "singular", "her": "singular", "jars": "plural", "Joey": "singular", "balloons": "plural", "dolls": "plural", "Jones": "singular", "them": "plural", "his": "singular", "cars": "plural", "Lucy": "singular", "Mrs.": "singular", "Ethelle": "singular", "friends": "plural", "he": "singular", "sister": "singular", "ate": null, "join": null, "Julia": "singular", "she": "singular", "Tony": "singular"}, "determiners": {"a": "constant", "away": "noise", "some": "variable", "to": "noise", "another": "noise", "the": "noise"}, "gender": {"bananas": "neutral", "family": "mixed", "Marc": "masculine", "fish": "mixed", "Jim": "masculine", "apples": "neutral", "Jane": "feminine", "pond": "neutral", "Chandler": "masculine", "toy": "neutral", "her": "feminine", "jars": "neutral", "he": "masculine", "balloons": "neutral", "dolls": "neutral", "Jones": "ambiguous", "them": "mixed", "his": "masculine", "cars": "neutral", "Lucy": "feminine", "Mrs.": "feminine", "Tony": "masculine", "friends": "mixed", "Joey": "masculine", "sister": "feminine", "Julia": "feminine", "she": "feminine", "Ethelle": "feminine"}, "gerunds": {"remaining": "solution_zero", "swimming": "acting"}, "comparison_adj": {}, "numbers": {"4": "4"}}
View
15 run_example.sh
@@ -1,8 +1,9 @@
-sudo ./setup.py install
clear
-cat calibrations/01.txt | zoidberg > EXAMPLE.md
-cat calibrations/02.txt | zoidberg >> EXAMPLE.md
-cat calibrations/03.txt | zoidberg >> EXAMPLE.md
-cat calibrations/04.txt | zoidberg >> EXAMPLE.md
-cat calibrations/05.txt | zoidberg >> EXAMPLE.md
-cat calibrations/06.txt | zoidberg >> EXAMPLE.md
+echo "" > EXAMPLE.md
+cat calibrations/01.txt | zoidberg | tee -a EXAMPLE.md
+cat calibrations/02.txt | zoidberg | tee -a EXAMPLE.md
+cat calibrations/03.txt | zoidberg | tee -a EXAMPLE.md
+cat calibrations/04.txt | zoidberg | tee -a EXAMPLE.md
+cat calibrations/05.txt | zoidberg | tee -a EXAMPLE.md
+cat calibrations/06.txt | zoidberg | tee -a EXAMPLE.md
+cat calibrations/07.txt | zoidberg | tee -a EXAMPLE.md
View
47 zoidberg/answer.py
@@ -28,17 +28,23 @@ def __init__(self, query):
self.relative = False
self.rel_mode = None
self.comparator = None
- self.subordinate = None
+ self.subordinates = []
self.relative_value = False
self.value = None
self.unit = None
self.context = None
+ self.last_unrefined_context = None
+
+ self.actor = None
+ self.action = None
+
self.execute()
def execute(self):
p = self.query.problem
+ i = p.inference
# The asking process determines what type of answer we want
asking = False
@@ -51,6 +57,7 @@ def execute(self):
for v_part in self.query:
val, part, subtype = v_part
+ print val, part
if part == "asking":
self.syntax = p.brain.answer_syntax(val, str(self.query))
@@ -66,6 +73,19 @@ def execute(self):
self.relative = True
self.rel_mode = "ad"
+ if part == "pre_ind_plu":
+ if asking and self.last_unrefined_context:
+ self.actor = self.last_unrefined_context
+ self.last_unrefined_context = None
+
+ # Specifying the acting is tantamount to ending the question
+ if part == "acting":
+ if asking:
+ self.action = val
+ asking = False
+ refining = True
+ specifying = True
+
# assume unit appearing during asking for answer
if part == "unit" and asking:
self.unit = val
@@ -78,23 +98,24 @@ def execute(self):
asking = False
refining = True
- # The qstart ends asking and begins specifying
+ # The qstop ends asking and begins specifying
if part == "q_stop":
refining = True
specifying = True
# assume context during refining is owner
- if part == "context" and refining:
- self.context = val
+ if part == "context":
+ if refining:
+ self.context = val
+ else:
+ self.last_unrefined_context = val
# Assume subordinate during specifying is answer condition
if part == "subordinate" and specifying:
subs = self.query.subordinates
self.subordinate = [s for s in subs if s[0] == val[0]]
if len(self.subordinate) > 0:
- self.subordinate = self.subordinate[0][1]
- else:
- self.subordinate = None
+ self.subordinates += self.subordinate
def __str__(self):
o = []
@@ -128,6 +149,9 @@ def __str__(self):
mode = "unknown"
i.append("the {0} {1} of".format(mode, syntax))
+ if self.actor:
+ i.append("{0} {1}".format(self.actor, self.action))
+
if self.value:
if self.relative_value:
i.append("the")
@@ -142,8 +166,13 @@ def __str__(self):
if self.relative:
i.append("with respect to {0}".format(self.comparator))
- if self.subordinate:
- i.append(ANSWER_SUBORDINATE[self.subordinate])
+ if len(self.subordinates) > 0:
+ for sub in self.subordinates:
+ w, s = sub
+ if s == "place_noun":
+ i.append(self.query.problem.inference.subordinate_strings[w])
+ else:
+ i.append(ANSWER_SUBORDINATE[s])
o.append(" ".join(i) + ".")
View
102 zoidberg/brain.py
@@ -15,7 +15,8 @@
"determiners": {},
"inclusive": {},
"relative": {},
- "gerunds": {}
+ "gerunds": {},
+ "numbers": {}
}
# Various mathematical operators we know of
@@ -30,7 +31,8 @@
# Various types of supported subordinace
SUBORDINATES = [
("time_starting", "Time: Beginning"),
- ("time_ending", "Time: Ending")
+ ("time_ending", "Time: Ending"),
+ ("place_noun", "Place (pond, mall, home, work)")
]
RELATIVE = [
@@ -52,7 +54,8 @@
GERUNDS = [
("noise", "This has no numeric connotations. (walking)"),
- ("solution_zero", "Connotes the ending value is zero (remaining)")
+ ("solution_zero", "Connotes the ending value is zero (remaining)"),
+ ("acting", "Is some action being performed (dancing, swimming)")
]
COMPARISONS = [
@@ -71,14 +74,15 @@
PLURALITY = [
("singular", "Refers to a single (balloon, she)"),
- ("plural", "Refers to a plural (balloons, they)")
+ ("plural", "Refers to a plural (balloons, they)"),
+ ("regular", "Refers to a regular plural (fish, sheep)")
]
GENDERS = [
("masculine", "Refers to a male gender"),
("feminine", "Refers to a female gender"),
("neutral", "Refers to a non-gendered entity"),
- ("mixed", "Refers to a mixture of genders (a group of people)"),
+ ("mixed", "Refers to a mixture of/ambiguous genders (a group of )"),
("ambiguous", "Refers to a man or woman but is not clear enough to know")
]
@@ -88,24 +92,20 @@
("subordinates", "This indicates a point in time"),
("comparison_adj", "This indicates a comparison between things"),
("answer_syntax", "This frames the answer to the question"),
- ("nounlike", "This is a noun or pronoun")
+ ("nounlike", "This is a noun or pronoun"),
+ ("numbers", "This is a cardinal number"),
+ ("pre_ind_plu", "This is present indicitive plural (someone ->is<-, they ->are<-)")
]
INPUT_STR = "What {0} does {1}'{2}' indicate in the sentence: '{3}'"
-def get_input(data, prompt, x, ref, brain):
- i = 0
+def get_input(data, prompt, x, ref, brain, force_retag=False):
msg = "\t{0}. {1}"
- print "\t0. This word has been misidentified."
- for k in data:
- i += 1
- print msg.format(i, k[1])
-
sys.stdin = open('/dev/tty')
- r = int(raw_input(prompt))
def retag():
- print "Okay, how should '{0}' be treated?".format(x)
+ if not force_retag:
+ print "Okay, how should '{0}' be treated?".format(x)
i = 0
for k in RETAGS:
i += 1
@@ -128,6 +128,8 @@ def retag():
brain.answer_syntax(x, ref)
elif item == "nounlike":
brain.noun_like(x, ref)
+ elif item == "numbers":
+ brain.number(x, ref)
elif item == "noise":
brain.add("determiners", x, "noise")
# A false in the indicator means it's noise and can be ignored
@@ -137,6 +139,17 @@ def retag():
# This is for the original add
return None
+ if force_retag:
+ return retag()
+
+ i = 0
+ print "\t0. This word has been misidentified."
+ for k in data:
+ i += 1
+ print msg.format(i, k[1])
+
+ r = int(raw_input(prompt))
+
if r == 0:
return retag()
@@ -148,6 +161,11 @@ def input_operator_type(x, ref, brain):
print INPUT_STR.format("operation", "the verb ", x, ref)
return get_input(OPERATORS, "'{0}' indicates: ".format(x), x, ref, brain)
+def input_unknown(pack, ref, brain):
+ x, tag, subtype = pack
+ print INPUT_STR.format("concept", "", x, ref)
+ return get_input([], "'{0}' is: ".format(x), x, ref, brain, True)
+
def input_subordinate_type(x, ref, brain):
print INPUT_STR.format("subordinate", "", x, ref)
return get_input(SUBORDINATES, "'{0}' indicates: ".format(x), x, ref,
@@ -185,6 +203,19 @@ def input_inclusive(x, ref, brain):
print "Is the group '{0}' inclusive of {1}?".format(x, ref)
return get_input(INCLUSIVE, "'{0}' is: ".format(x), x, ref, brain)
+def input_number(x, ref, brain):
+ print INPUT_STR.format("numeric quantity", "", x, ref)
+ prompt = "Please input the actual numerical value of '{0}': ".format(x)
+ sys.stdin = open('/dev/tty')
+ r = raw_input(prompt)
+ try:
+ if r == "":
+ r = x
+ r = float(r) if "." in r else int(r)
+ return r
+ except ValueError:
+ return input_number(x, ref, brain)
+
class Brain(object):
def __init__(self, path=None):
if path is None:
@@ -198,6 +229,11 @@ def __init__(self, path=None):
self.raw = DEFAULT_BRAIN
def add(self, key, val, value):
+ key = str(key)
+ val = str(val)
+ if value is not None:
+ value = str(value)
+
if not key in self.raw:
self.raw[key] = {}
if not val in self.raw[key]:
@@ -211,22 +247,27 @@ def retag(self, val, tag):
if val in self.raw["retagged"]:
item = self.raw["retagged"][val]
if item == "subordinates":
- return "SUB"
+ tag = "SUB"
elif item == "operator_verbs":
- return "VBX"
+ tag = "VBX"
elif item == "comparison_adj":
# @TODO No comparisons yet!
- return "COMP"
+ tag = "COMP"
elif item == "answer_syntax":
- return "ANSYX"
+ tag = "ANSYX"
elif item == "nounlike":
- return "NN"
+ tag = "NN"
elif item == "noise":
- return "DT"
+ tag = "DT"
+ elif item == "numbers":
+ tag = "CD"
+ val = str(self.raw["numbers"][val])
+ elif item == "pre_ind_plu":
+ tag = "PIP"
else:
print item
- return "!!!"
- return tag
+ tag = "!!!"
+ return (val, tag)
def proc(self, key, val, fn, ref):
value = None
@@ -235,20 +276,23 @@ def proc(self, key, val, fn, ref):
return self.add(key, val, value)
def subordinate(self, sub, ref):
- return self.proc("subordinates", sub, input_subordinate_type, ref)
+ subtype = self.proc("subordinates", sub, input_subordinate_type, ref)
+ if subtype == "place_noun":
+ self.noun_like(sub, ref)
+ return subtype
def operator(self, verb, ref):
return self.proc("operator_verbs", verb, input_operator_type, ref)
def comparison(self, comp, ref):
- return self.proc("comparison_adj", verb, input_comparison_type, ref)
+ return self.proc("comparison_adj", comp, input_comparison_type, ref)
def answer_syntax(self, query, ref):
return self.proc("answer_syntax", query, input_answer_syntax, ref)
def noun_like(self, n, ref):
plurality = self.proc("plurality", n, input_plurality, ref)
- if not plurality:
+ if plurality is None:
gender = None
else:
gender = self.proc("gender", n, input_gender, ref)
@@ -271,6 +315,12 @@ def is_inclusive(self, n):
def relative(self, n, ref):
return self.proc("relative", n, input_relative, ref)
+ def unknown(self, n, tag, subtype, ref):
+ return self.proc("unknown", (n, tag, subtype), input_unknown, ref)
+
+ def number(self, n, ref):
+ return self.proc("numbers", n, input_number, ref)
+
def dump(self):
set_json(self.path, self.raw)
View
56 zoidberg/inference.py
@@ -23,6 +23,13 @@
"mu": "increased",
"su": "decreased",
"di": "decreased"
+ },
+ "context_actions_nounit": {
+ "eq": "the number of",
+ "ad": "an increasing number of",
+ "mu": "an increasing number of",
+ "su": "a decreasing number of",
+ "di": "a decreasing number of"
}
}
@@ -36,6 +43,7 @@ def __init__(self, problem):
self.queries = []
# Collection of verbs which describe data manipulations
+ self.preops = []
self.operators = []
# Contexts are the way to define the "Joe" of "Joe's apples"
@@ -44,10 +52,16 @@ def __init__(self, problem):
# Units are the way to define the "apple" of "Joe's apples"
self.units = []
+ # Actions are a way to subsect contexts
+ self.actions = []
+
# Subordinate conjunctions; time/place/cause and effect which can
# identify the time period
self.subordinates = []
+ # Display strings for subordinates
+ self.subordinate_strings = {}
+
# Store a reference to the problem
self.problem = problem
@@ -66,7 +80,7 @@ def track_longer(self, l):
def execute(self):
p = self.problem
- raw_operators = []
+ raw_actions, raw_operators, raw_subordinates = [], [], []
index = 0
for s_tags in p.sentence_tags:
@@ -75,9 +89,16 @@ def execute(self):
self.track_longer(s.longest_phrase)
raw_operators += s.operators
+ raw_actions += s.actions
+ raw_subordinates += s.subordinates
+
self.contexts += s.contexts
self.units += s.units
- self.subordinates += s.subordinates
+ if len(s.subordinate_strings) > 0:
+ sd = dict(s.subordinate_strings)
+ if len(self.subordinate_strings) > 0:
+ sd.update(self.subordinate_strings)
+ self.subordinate_strings = sd
if s.question:
self.queries.append(index)
@@ -86,10 +107,13 @@ def execute(self):
# Ensure uniqueness in our data
raw_operators = uniq(raw_operators)
+ raw_actions = uniq(raw_actions)
+ raw_subordinates = uniq(raw_subordinates)
+
self.contexts = uniq(self.contexts)
self.units = uniq(self.units)
- self.subordinates = uniq(self.subordinates)
+ # Set our phrasings based on the contexts in play
if len(self.contexts) > 1:
op_key = OPERATOR_STR["multiple_contexts"]
elif len(self.contexts) > 0:
@@ -97,19 +121,41 @@ def execute(self):
else:
op_key = OPERATOR_STR["no_context"]
- # Resolve the verbs to actual operators using the brain
+ for sub in raw_subordinates:
+ word, subtype = sub
+ if subtype is not None and subtype[0:4] != "time":
+ self.subordinates.append(self.subordinate_strings[word])
+ self.subordinates = uniq(self.subordinates)
+
+ format_operators = True
+ for act in raw_actions:
+ self.actions.append(act)
+ self.actions = uniq(self.actions)
+
+ pre_ops = False
+ if len(self.units) == 0 and len(self.actions) > 0:
+ pre_ops = True
+ # We have special phrasing which is mucked up by the operators
+ # if we're only dealing with
+ op_key = OPERATOR_STR["context_actions_nounit"]
+
for op in raw_operators:
if op != "eq" or len(raw_operators) == 1:
self.operators.append(op_key[op])
self.operators = uniq(self.operators)
+ if pre_ops:
+ self.preops = self.operators
+ self.operators = []
+
def __str__(self):
o = []
i = ["I think this problem is about"]
thought_any = False
multiple_contexts = len(self.contexts) > 1
- for x in [self.contexts, self.operators, self.units]:
+ for x in [self.preops, self.actions, self.contexts, self.operators,
+ self.units, self.subordinates]:
f = list_format(x)
if f is not None:
thought_any = True
View
2  zoidberg/problem.py
@@ -20,12 +20,14 @@ def __init__(self, text, brain_path=None):
self.all_tags = None
self.all_words = None
self.longest_word = None
+ self.units_acting_as_context = {}
# Mrs. Jones
self.last_contexts = {
"plurality": {
"singular": None,
"plural": None,
+ "regular": None
},
"gender": {
"masculine": None,
View
341 zoidberg/sentence_parser.py
@@ -4,6 +4,30 @@
class SentenceParser(object):
def __init__(self, sentence, problem, text):
+ self.index = 0
+ self.acting = False
+ self.last_operator = None
+ self.last_operator_type = None
+ self.last_word = None
+ self.last_tag = None
+ self.last_unit = None
+ self.last_unit_tag = None
+ self.last_unit_index = None
+ self.last_verb_tag = None
+ self.last_verb = -1
+ self.last_noun_tag = None
+ self.last_subtype = None
+ self.last_conjunction = None
+ self.conjunction_parts = []
+ self.phrasing_question = False
+ self.subtype = None
+ self.is_relative_quantity = False
+ self.partial_context = None
+ self.last_partial_context = None
+ self.partial_subtype = None
+ self.comparator_context = None
+ self.main_context = None
+ self.last_context = None
self.sentence = sentence
self.problem = problem
self.sentence_text = text
@@ -24,10 +48,18 @@ def __init__(self, sentence, problem, text):
# Units are the way to define the "apple" of "Joe's apples"
self.units = []
+ # Actions are like a joint structure of contexts and units
+ # in that a context can "own" an action the same way it can
+ # own a unit. The action also acts as a "subcontext" as the
+ # context owner (in this case, actor) can be "performing" an
+ # action which differentiates it from the larger context.
+ self.actions = []
+
# Subordinate conjunctions; time/place/cause and effect which can
# identify the time period
self.conjunctions = []
self.subordinates = []
+ self.subordinate_strings = {}
self.execute()
@@ -107,80 +139,68 @@ def get_subtype(self, word, tag):
def execute(self):
p = self.problem
- index = 0
-
- last_word = None
- last_tag = None
- last_verb_tag = None
- last_verb = -1
- last_noun_tag = None
- last_subtype = None
- last_conjunction = None
- phrasing_question = False
- subtype = None
- is_relative_quantity = False
- partial_context = None
- last_partial_context = None
- partial_subtype = None
- comparator_context = None
- main_context = None
- for s_tag in self.sentence:
- word, tag = s_tag
+ def process(word, tag):
did_something = False
- subtype = None
- if index == 0 and tag not in ["NNP", "NNPS"]:
+ self.subtype = None
+ if self.index == 0 and tag not in ["NNP", "NNPS"]:
# Fix capitalization for non proper nouns
word = word.lower()
- tag = p.brain.retag(word, tag)
+ word, tag = p.brain.retag(word, tag)
if tag == "!!!":
print "Missing retag converter in the brain"
exit(1)
+ if self.last_conjunction is not None:
+ self.conjunction_parts.append(word)
+
# Fix the parser as we go on brain retags
- def do_track(subtype):
+ def do_track(subtype, tag):
if subtype[0] is None and subtype[1] is None:
subtype = None
tag = p.brain.retag(word, tag)
- return False
- return True
+ return (False, subtype, tag)
+ return (True, subtype, tag)
if tag in ["NN", "NNS"]:
- if last_tag in ["PRP$"]:
+ if self.last_tag in ["PRP$"]:
# Detects Jane's friends; probably context
- context = " ".join([partial_context, word])
+ context = " ".join([self.partial_context, word])
self.parsed.pop()
+ self.last_context = context
self.contexts.append(context)
did_something = True
- subtype = self.get_subtype(word, tag)
+ self.subtype = self.get_subtype(word, tag)
+
+ self.partial_context = None
+ self.last_partial_context = None
+ self.partial_subtype = None
- partial_context = None
- last_partial_context = None
- partial_subtype = None
+ track, self.subtype, tag = do_track(self.subtype, tag)
- if do_track(subtype):
- if subtype[0] == "plural" and subtype[1] == "mixed":
+ if track:
+ if self.subtype[0] == "plural" and self.subtype[1] == "mixed":
# PRP$ will always have a noun like last_subtype
- last_plural, last_gender = last_subtype
+ last_plural, last_gender = self.last_subtype
# Last Plural Context
lpc = p.last_contexts["plurality"][last_plural]
# Last Gender Context
lgc = p.last_contexts["gender"][last_gender]
- last_context = None
+ self.last_context = None
if lgc == lpc:
- last_context = lgc
+ self.last_context = lgc
elif lgc is not None:
- last_context = lgc
+ self.last_context = lgc
elif lpc is not None:
- last_context = lpc
+ self.last_context = lpc
- if last_context is not None:
+ if self.last_context is not None:
# Last context string
inc = p.brain.inclusive(word,
- "'{0}' ({1}) in '{2}'".format(last_word,
- last_context[0],
+ "'{0}' ({1}) in '{2}'".format(self.last_word,
+ self.last_context[0],
context))
# Add the context by the word for easier lookup
# this will capture 'her friends' and define
@@ -190,179 +210,252 @@ def do_track(subtype):
p.brain.add("inclusive", context, inc)
# Assume the first context after a comparison is the
# comparator context
- if is_relative_quantity and not comparator_context and main_context:
- comparator_context = context
- self.track(context, "comparator_context", subtype, conv=True)
+ if self.is_relative_quantity and not self.comparator_context and self.main_context:
+ self.comparator_context = context
+ self.track(context, "comparator_context", self.subtype, conv=True)
else:
- main_context = context
- self.track(context, "context", subtype)
+ self.main_context = context
+ self.track(context, "context", self.subtype)
else:
- if last_conjunction is not None:
- conjunction = (word, last_conjunction)
+ if self.last_conjunction is not None:
+ conjunction = (word, self.last_conjunction)
+ self.last_conjunction = None
+ self.subordinate_strings[word] = " ".join(self.conjunction_parts)
+ self.conjunction_parts = []
self.conjunctions.append(conjunction)
did_something = True
- self.track(conjunction, "subordinate", subtype)
+ self.track(conjunction, "subordinate", self.subtype)
else:
- subtype = self.get_subtype(word, tag)
- if do_track(subtype):
+ self.subtype = self.get_subtype(word, tag)
+ track, self.subtype, tag = do_track(self.subtype, tag)
+ did_something = True
+ if track:
unit = word
- if tag == "NNS" and last_tag == "NN":
- unit = " ".join([last_word, word])
+ if tag == "NNS" and self.last_tag == "NN":
+ unit = " ".join([self.last_word, word])
self.units.pop()
self.parsed.pop()
- self.units.append(unit)
- did_something = True
- self.track(unit, "unit", subtype)
- if not did_something and subtype == None:
- subtype = self.get_subtype(word, tag)
+ if not unit in p.units_acting_as_context or not p.units_acting_as_context[unit]:
+ self.last_unit = unit
+ self.last_unit_tag = tag
+ self.last_unit_index = len(self.parsed)
+ self.units.append(unit)
+ self.track(unit, "unit", self.subtype)
+ else:
+ context = unit
+ # @TODO: This needs to be a subroutine or something
+ self.last_context = context
+ self.contexts.append(context)
+ if self.is_relative_quantity and not self.comparator_context and self.main_context:
+ self.comparator_context = context
+ self.track(context, "comparator_context", self.subtype)
+ else:
+ self.main_context = context
+ self.track(context, "context", self.subtype)
+
+ if not did_something and self.subtype == None:
+ self.subtype = self.get_subtype(word, tag)
if tag == "SUB":
did_something = True
- self.track(word, "subordinate", subtype)
+ self.track(word, "subordinate", self.subtype)
if tag == "PRP":
- c = self.resolve_context(subtype)
+ c = self.resolve_context(self.subtype)
if c is not None:
+ # If we're setting a relative quantity and the contexts are
+ # the same we're not actually setting a relative quantity
+ # we are simply indicating a mathematical operand
+ if self.is_relative_quantity and c[0] == self.last_context:
+ self.is_relative_quantity = False
did_something = True
- if is_relative_quantity and not comparator_context and main_context:
- comparator_context = c[0]
- self.track(c[0], "comparator_context", subtype, conv=True)
+ if self.is_relative_quantity and not self.comparator_context and self.main_context:
+ self.comparator_context = c[0]
+ self.track(c[0], "comparator_context", self.subtype, conv=True)
else:
- main_context = c[0]
- self.track(c[0], "context", subtype)
+ self.main_context = c[0]
+ self.track(c[0], "context", self.subtype)
if tag == "PRP$":
- if last_conjunction is not None:
- if is_relative_quantity and not comparator_context and main_context:
+ if self.last_conjunction is not None:
+ if self.is_relative_quantity and not self.comparator_context and self.main_context:
did_something = True
- comparator_context = word
- self.track(word, "comparator_context", subtype, conv=True)
- last_conjunction = None
+ self.comparator_context = word
+ self.track(word, "comparator_context", self.subtype, conv=True)
+ self.last_conjunction = None
+ self.conjunction_parts = []
if not did_something:
did_something = True
- partial_context = word
- partial_subtype = subtype
- last_partial_context = self.track(word, "partial_context",
- subtype)
+ self.partial_context = word
+ self.partial_subtype = self.subtype
+ self.last_partial_context = self.track(word, "partial_context",
+ self.subtype)
if tag in ["NNP", "NNPS"]:
- if last_tag in ["NNP", "NNPS"]:
+ if self.last_tag in ["NNP", "NNPS"]:
# Last was partial context; the "Mrs." in "Mrs. Jones"
+ self.last_context = None
lc = self.contexts.pop()
self.parsed.pop()
- context = " ".join([last_word, word])
- if is_relative_quantity and comparator_context == lc:
- comparator_context = context
- if subtype is not None and subtype[1] == "ambiguous":
- old = self.get_subtype(last_word, last_tag)
- subtype = (subtype[0], old[1])
+ context = " ".join([self.last_word, word])
+ if self.is_relative_quantity and self.comparator_context == lc:
+ self.comparator_context = context
+ if self.subtype is not None and self.subtype[1] == "ambiguous":
+ old = self.get_subtype(self.last_word, self.last_tag)
+ self.subtype = (self.subtype[0], old[1])
else:
context = word
+ self.last_context = context
self.contexts.append(context)
did_something = True
- if is_relative_quantity and not comparator_context and main_context:
- comparator_context = context
- self.track(context, "comparator_context", subtype)
+ if self.is_relative_quantity and not self.comparator_context and self.main_context:
+ self.comparator_context = context
+ self.track(context, "comparator_context", self.subtype)
else:
- main_context = context
- self.track(context, "context", subtype)
+ self.main_context = context
+ self.track(context, "context", self.subtype)
if tag[:2] == "VB":
if tag == "VB":
- if last_verb_tag is not None:
+ if self.last_verb_tag is not None:
# VB*...VB indicates a question not an operation
+ self.last_operator = None
q_start = self.raw_operators.pop()
- self.track(q_start, "q_start", subtype, last_verb)
+ self.track(q_start, "q_start", self.subtype, self.last_verb)
did_something = True
- self.track(word, "q_stop", subtype)
+ self.track(word, "q_stop", self.subtype)
elif tag != "VBG":
- last_verb_tag = tag
- last_verb = len(self.parsed)
+ self.last_verb_tag = tag
+ self.last_verb = len(self.parsed)
+ self.last_operator = word
self.raw_operators.append(word)
did_something = True
- subtype = self.get_subtype(word, tag)
- self.track(word, "operator", subtype)
+ self.subtype = self.get_subtype(word, tag)
+ self.track(word, "operator", self.subtype)
else:
did_something = True
gtype = p.brain.gerund(word, self.sentence_text)
- self.track(word, gtype, subtype)
+ if gtype == "acting":
+ self.acting = False
+ self.actions.append(word)
+ self.track(word, gtype, self.subtype)
if tag == "JJR":
did_something = True
adj = p.brain.relative(word, self.sentence_text)
- is_relative_quantity = adj != "noise"
- self.track(word, adj, subtype)
+ self.is_relative_quantity = adj != "noise"
+ self.track(word, adj, self.subtype)
if tag == "IN":
- last_conjunction = word
+ self.last_conjunction = word
+ self.conjunction_parts.append(word)
did_something = True
- self.track(word, "conjunction", subtype)
+ self.track(word, "conjunction", self.subtype)
if tag == ".":
did_something = True
- self.track(word, "punctuation", subtype)
+ self.track(word, "punctuation", self.subtype)
if tag == "CD": # A cardinal number
did_something = True
- self.track(word, "constant", subtype)
+ self.track(word, "constant", self.subtype)
if tag == "DT": # A determiner (the)
did_something = True
dtype = p.brain.determiner(word, self.sentence_text)
- self.track(word, dtype, subtype)
+ self.track(word, dtype, self.subtype)
if tag == "RB": # An adverb, probably a subordinate?
- if last_conjunction is not None:
- conjunction = (word, last_conjunction)
+ if self.last_conjunction is not None:
+ conjunction = (word, self.last_conjunction)
+ self.last_conjunction = None
+ self.subordinate_strings[word] = " ".join(self.conjunction_parts)
+ self.conjunction_parts = []
else:
conjunction = (word, None)
+ self.subordinate_strings[word] = word
self.conjunctions.append(conjunction)
did_something = True
- self.track(conjunction, "subordinate", subtype)
+ self.track(conjunction, "subordinate", self.subtype)
# Anything about phrasing must come before the wh-determiner block
if tag == "JJ": # Adjective
- if phrasing_question:
+ if self.phrasing_question:
self.parsed.pop()
did_something = True
- self.track(" ".join([last_word, word]), "asking", subtype)
+ self.track(" ".join([self.last_word, word]), "asking", self.subtype)
+
+ if tag == "PIP":
+ did_something = True
+ self.track(word, "pre_ind_plu", self.subtype)
+ self.acting = True
+ if self.last_unit is not None and self.last_context is None:
+ # If we have a present indicitive plural with no context
+ # it is likely that we're dealing with a context which has
+ # been misinterpreted as a unit, so switch that
+ # mistake here.
+ p.units_acting_as_context[self.last_unit] = True
+
+ # Remove the last unit and make it a context
+ context = self.units.pop()
+ self.last_context = context
+ self.contexts.append(context)
+ if self.is_relative_quantity and not self.comparator_context and self.main_context:
+ self.comparator_context = context
+ self.track(context, "comparator_context", self.subtype, self.last_unit_index)
+ else:
+ self.main_context = context
+ self.track(context, "context", self.subtype, self.last_unit_index)
+
+ # @TODO: This needs a much better tracking system
+ self.last_unit = None
+ self.last_unit_tag = None
+ self.last_unit_index = -1
if tag in ["WRB", "WDT", "WP", "WP$"]: # Wh- determiner
self.question = True
- phrasing_question = True
+ self.phrasing_question = True
+ did_something = True
+ self.track(word, "asking", self.subtype)
+ elif self.phrasing_question:
+ self.phrasing_question = False
+
+ if self.subtype is not None:
did_something = True
- self.track(word, "asking", subtype)
- elif phrasing_question:
- phrasing_question = False
if not did_something:
- self.track((word, tag), "unknown", subtype)
+ p.brain.unknown(word, tag, self.subtype, self.sentence_text)
+ process(word, tag)
+
+ self.last_word = word
+ self.last_tag = tag
+ self.last_subtype = self.subtype
- last_word = word
- last_tag = tag
- last_subtype = subtype
- index += 1
+ for s_tag in self.sentence:
+ process(*s_tag)
+ self.index += 1
- if partial_context:
- context = partial_context
- idx = last_partial_context
- stype = partial_subtype
+ if self.partial_context:
+ context = self.partial_context
+ idx = self.last_partial_context
+ stype = self.partial_subtype
- partial_context = None
- last_partial_context = None
- partial_subtype = None
+ self.partial_context = None
+ self.last_partial_context = None
+ self.partial_subtype = None
- if is_relative_quantity and not comparator_context and main_context:
- comparator_context = context
+ if self.is_relative_quantity and not self.comparator_context and self.main_context:
+ self.comparator_context = context
self.track(context, "comparator_context", stype, idx, True)
# Make all the inferred items unique
self.raw_operators = uniq(self.raw_operators)
self.contexts = uniq(self.contexts)
self.units = uniq(self.units)
+ self.actions = uniq(self.actions)
# Resolve the verbs to actual operators using the brain
for o in self.raw_operators:
View
419 zoidberg/solution.py
@@ -15,13 +15,20 @@
}
def number(s):
- return float(s) if '.' in s else int(s)
+ try:
+ return float(s) if '.' in s else int(s)
+ except ValueError:
+ return -1
class Solution(object):
def __init__(self, problem):
self.problem = problem
self.last_index = 0
+ self.last_container = None
+ self.last_action = None
+ self.last_actor = None
+
self.context = None
self.operator = None
self.constant = None
@@ -32,6 +39,7 @@ def __init__(self, problem):
self.sentence_data = []
self.data = None
+ self.actor_data = None
letters = [chr(x) for x in xrange(ord("a"), ord("z")+1)]
self.varpool = letters[-3:] + letters[:-3]
@@ -43,6 +51,11 @@ def __init__(self, problem):
self.symbols = {}
self.correct_responses = []
+ self.container = None
+ self.containers = None
+ self.actor = None
+ self.action = None
+
self.execute()
def store_var(self, idx, var):
@@ -53,8 +66,15 @@ def store_var(self, idx, var):
else:
self.middle_vars.append(var)
- def get_symbol(self, context, unit, idx=-1, operator=None, constant=None):
- sym = " ".join([context, unit])
+ def get_symbol(self, context, unit, container, idx=-1, operator=None, constant=None):
+ if context is None or unit is None:
+ return (False, Symbol("BROKEN"), "BROKEN")
+
+ s = [context, unit]
+ if container is not None and container != "_unknown_":
+ s.append(container)
+
+ sym = " ".join(s)
first_time = sym not in self.symbols
hindsight_inference = False
if first_time:
@@ -94,6 +114,18 @@ def get_symbol(self, context, unit, idx=-1, operator=None, constant=None):
return (hindsight_inference, symbol, var)
def reset_extractor(self):
+ if self.action is not None:
+ self.last_action = self.action
+
+ if self.actor is not None:
+ self.last_actor = self.actor
+
+ if self.container is not None:
+ self.last_container = self.container
+
+ self.container = None
+ self.actor = None
+ self.action = None
self.context = None
self.operator = None
self.constant = None
@@ -105,11 +137,17 @@ def reset_extractor(self):
def generate_expression(self, zeroes_out=False):
if self.data is None:
self.data = {}
+ if self.actor_data is None:
+ self.actor_data = {}
+ actor = "@{0}".format(self.actor)
+ action = self.action
context = self.context
operator = self.operator
constant = self.constant
+ container = self.container
unit = self.unit
+ data = None
if context is None:
context = "_unknown_"
@@ -117,21 +155,83 @@ def generate_expression(self, zeroes_out=False):
if unit is None:
unit = "_unknown_"
- if context not in self.data:
- self.data[context] = {}
+ k1, k2 = None, None
+ if actor and action:
+ if actor not in self.actor_data:
+ self.actor_data[actor] = {}
- if unit not in self.data[context]:
- self.data[context][unit] = []
+ if action not in self.actor_data[actor]:
+ self.actor_data[actor][action] = []
- if self.relative and self.comparator_context:
- sym = " ".join([self.comparator_context, unit])
- if operator == "eq":
- operator = self.rel_mode
- self.data[context][unit].append(("eq", sym))
+ # Assume an equality in this case
+ if operator is None and constant is not None:
+ operator = "eq"
+
+ data = self.actor_data[actor][action]
+ k1 = actor
+ k2 = action
+ else:
+ if self.last_action is not None and context == self.last_actor:
+ actor = "@{0}".format(self.last_actor)
+ action = self.last_action
+
+ if not actor in self.actor_data:
+ self.actor_data[actor] = {}
+
+ if not action in self.actor_data[actor]:
+ self.actor_data[actor][action] = []
+
+ if container is None and self.last_container is not None:
+ container = self.last_container
+
+ # Only one action for the actor, so it's likely this
+ data = self.actor_data[actor][action]
+
+ k1 = actor
+ k2 = action
+ else:
+ if context not in self.data:
+ self.data[context] = {}
+
+ if unit not in self.data[context]:
+ self.data[context][unit] = []
+
+ data = self.data[context][unit]
+ k1 = context
+ k2 = unit
+
+ if data is not None:
+ if self.relative and self.comparator_context:
+ sym = " ".join([self.comparator_context, unit])
+ if operator == "eq":
+ operator = self.rel_mode
+ data.append(("eq", sym))
+
+ data.append((operator, constant))
+ if zeroes_out:
+ data.append(("ans", "0"))
+
+ # If nothing was done there's nothing to do
+ if len(data) == 0:
+ self.data = None
+ self.actor_data = None
+ self.containers = None
+
+ if container is None:
+ container = "_unknown_"
+
+ if container is not None:
+ if self.containers is None:
+ self.containers = {}
+
+ if not container in self.containers:
+ self.containers[container] = {}
+
+ if not k1 in self.containers[container]:
+ self.containers[container][k1] = {}
+
+ self.containers[container][k1][k2] = data
- self.data[context][unit].append((operator, constant))
- if zeroes_out:
- self.data[context][unit].append(("ans", "0"))
self.reset_extractor()
def has_any(self):
@@ -156,6 +256,7 @@ def execute(self):
# we only want to change the context to the primary one
did_set_context = False
zeroes_out = False
+ last_context = None
for v_part in parser.parsed:
val, part, subtype = v_part
@@ -163,11 +264,12 @@ def execute(self):
if not did_set_context:
did_set_context = True
self.context = val
+ last_context = val
- if part == "operator":
+ if part == "operator" and not self.operator:
self.operator = parser.operator[val]
- if part == "constant":
+ if part == "constant" and not self.constant:
self.constant = val
if part == "unit":
@@ -187,6 +289,20 @@ def execute(self):
if part == "comparator_context":
self.comparator_context = val[0]
+ if part == "pre_ind_plu":
+ if last_context and not self.actor:
+ self.actor = last_context
+ last_context = None
+
+ if part == "acting":
+ if self.actor:
+ self.action = val
+
+ if part == "subordinate":
+ if val[1] is not None:
+ # If we have a conjunction we have an container
+ self.container = val[0]
+
if self.has_all():
self.generate_expression(zeroes_out)
@@ -201,9 +317,11 @@ def execute(self):
else:
self.reset_extractor()
- if self.data is not None:
- self.sentence_data.append(self.data)
+ if self.containers is not None:
+ self.sentence_data.append(self.containers)
self.data = None
+ self.actor_data = None
+ self.containers = None
def newvar(self):
sym = self.varpool.pop(0)
@@ -217,53 +335,59 @@ def compute(self):
last_context = None
switch_context = False
new_sentence_data = []
- for data in self.sentence_data:
- new_data = {}
- for context in data:
- units = data[context]
-
- # Use the last context for inclusive context
- if p.brain.is_inclusive(context):
- if last_context is not None:
- context = last_context
- switch_context = True
+ for sd in self.sentence_data:
+ new_container = {}
+ for container in sd:
+ data = sd[container]
+ new_data = {}
+ for context in data:
+ units = data[context]
+
+ # use the last context for inclusive context
+ if p.brain.is_inclusive(context):
+ if last_context is not None:
+ context = last_context
+ switch_context = True
+ else:
+ # @todo: this state should probably never happen?
+ # a context that is inclusive should have one context
+ # that preceeds it
+ print "Well this is a fine mess"
+ exit(1)
else:
- # @TODO: This state should probably never happen?
- # A context that is inclusive should have one context
- # that preceeds it
- print "Well this is a fine mess"
- exit(1)
- else:
- switch_context = False
-
- new_units = {}
- for unit in units:
- # We increment at the start because of the bail-out nature
- data_index = -1
-
- new_values = []
- for values in units[unit]:
- data_index += 1
- operator, constant = values
-
- if constant in self.symbols:
- constant = self.symbols[constant]
- elif constant is not None:
- # Convert and type the constant properly
- constant = number(constant)
-
- # Apply the operation to the symbol
- if operator is not None:
- inf, symbol, con = self.get_symbol(context, unit,
- index, operator, constant)
- if inf:
- new_values.append(("eq", "0"))
- new_values.append((operator, con))
- new_units[unit] = new_values
- new_data[context] = new_units
- last_context = context
+ switch_context = False
+
+ new_units = {}
+ for unit in units:
+ # We increment at the start because of the bail-out nature
+ data_index = -1
+
+ new_values = []
+ for values in units[unit]:
+ data_index += 1
+ operator, constant = values
+
+ if constant in self.symbols:
+ constant = self.symbols[constant]
+ elif constant is not None:
+ # Convert and type the constant properly
+ constant = number(constant)
+
+ # Apply the operation to the symbol
+ if operator is not None:
+ inf, symbol, con = self.get_symbol(context,
+ unit, container, index, operator, constant)
+ if inf:
+ new_values.append(("eq", "0"))
+ else:
+ con = constant
+ new_values.append((operator, con))
+ new_units[unit] = new_values
+ new_data[context] = new_units
+ last_context = context
+ new_container[container] = new_data
index += 1
- new_sentence_data.append(new_data)
+ new_sentence_data.append(new_container)
self.sentence_data = new_sentence_data
def compute_correct(self):
@@ -273,12 +397,12 @@ def compute_correct(self):
i = p.inference
q = p.question
- def add_response(val, unit):
+ def add_response(val, unit, idx):
for v in val:
i = [str(v)]
if unit is not None:
i.append(unit)
- self.correct_responses.append(" ".join(i))
+ self.correct_responses.insert(idx, " ".join(i))
def simple_solve(sym):
for c in [Symbol, Function, Pow, Derivative]:
@@ -286,33 +410,49 @@ def simple_solve(sym):
return solve(sym, sym)
return [sym]
+ index = 0
for answer in q.answers:
- inf, equ, con = self.get_symbol(answer.context, answer.unit)
- if answer.subordinate is not None:
- if answer.subordinate == "time_ending":
- l = len(self.ending_vars)
-
- if l == 1:
- symbol = self.symbols[self.ending_vars[0]]
- add_response(solve(equ, symbol), answer.unit)
- elif l == 0:
- add_response(simple_solve(equ), answer.unit)
- else:
- self.correct_responses.append(
- "Not sure; too many ending variables!")
- elif answer.subordinate == "time_starting":
- if len(self.beginning_vars) == 1:
- symbol = self.symbols[self.beginning_vars[0]]
- add_response(solve(equ, symbol), answer.unit)
- elif l == 0:
- add_response(simple_solve(equ))
+ if answer.actor and answer.action:
+ # The answer in actor/action questions is the actor normally?
+ answer.unit = answer.actor
+ inf, equ, con = self.get_symbol("@" + answer.actor, answer.action, None, index)
+ else:
+ inf, equ, con = self.get_symbol(answer.context, answer.unit, None, index)
+
+ if len(answer.subordinates) > 0:
+ working_answer = None
+ for s in answer.subordinates:
+ word, sub = s
+ if sub == "time_ending":
+ l = len(self.ending_vars)
+
+ if l == 1:
+ symbol = self.symbols[self.ending_vars[0]]
+ add_response(solve(equ, symbol), answer.unit, index)
+ elif l == 0:
+ add_response(simple_solve(equ), answer.unit, index)
+ else:
+ self.correct_responses.append(
+ "Not sure; too many ending variables!")
+ elif sub == "time_starting":
+ l = len(self.beginning_vars)
+ if l == 1:
+ symbol = self.symbols[self.beginning_vars[0]]
+ add_response(solve(equ, symbol), answer.unit, index)
+ elif l == 0:
+ add_response(simple_solve(equ), answer.unit, index)
+ else:
+ self.correct_responses.append(
+ "Not sure; too many starting variables!")
+ elif sub == "place_noun":
+ if answer.actor and answer.action:
+ inf, equ, con = self.get_symbol("@" + answer.actor, answer.action, word, index)
+ else:
+ inf, equ, con = self.get_symbol(answer.context, answer.unit, word, index)
else:
- self.correct_responses.append(
- "Not sure; too many starting variables!")
- else:
- self.correct_responses.append("No sure; no subordinates!")
+ self.correct_responses.append("No sure; unknown subordinate type {0} ({1})".format(sub, word))
elif answer.relative:
- coinf, comp, conc= self.get_symbol(answer.comparator, answer.unit)
+ coinf, comp, conc = self.get_symbol(answer.comparator, answer.unit, None)
v = self.newvar()
v = 0
@@ -329,44 +469,81 @@ def simple_solve(sym):
if answer.unit:
unt.append(answer.unit)
- add_response(simple_solve(v), " ".join(unt))
+ add_response(simple_solve(v), " ".join(unt), index)
else:
- add_response(simple_solve(equ), answer.unit)
+ add_response(simple_solve(equ), answer.unit, index)
+ index += 1
def __str__(self):
o = []
o.append("\n## Data extraction")
index = 1
- for data in self.sentence_data:
- s = []
- for context in data:
- for unit in data[context]:
- for values in data[context][unit]:
- operator, constant = values
- i = []
-
- display_constant = constant
- if display_constant is None:
- display_constant = "<an unknown number>"
-
- if operator is None:
- continue # Probably the question
-
- if context != "_unknown_" and unit != "_unknown_":
- i.append(unit)
- i.append("owend by")
- i.append(context)
- i.append(OP_DISPLAY[operator])
- i.append(display_constant)
- else:
- i.append("I don't know how to format this state!")
-
- s.append(" ".join(i))
-
- if len(s) > 0:
- o.append("\n### Sentence {0}".format(index))
- o.append("\n".join(s))
+ for sd in self.sentence_data:
+ for container in sd:
+ data = sd[container]
+ s = []
+ for context in data:
+ for unit in data[context]:
+ for values in data[context][unit]:
+ operator, constant = values
+ i = []
+
+ actor = None
+ action = None
+
+ if context[0:1] == "@":
+ actor = context[1:]
+ action = unit
+ unit = None
+ context = None
+
+ if context == "_unknown_":
+ context = None
+
+ if unit == "_unknown_":
+ unit = None
+
+ if container is None or container == "_unknown_":
+ container = None
+ else:
+ container = self.problem.inference.subordinate_strings[container]
+
+ display_constant = constant
+ if display_constant is None:
+ display_constant = "<an unknown number>"
+
+ if operator is None:
+ continue # Probably the question
+
+ if actor is not None and action is not None:
+ i.append(action)
+ i.append(actor)
+
+ if container is not None:
+ i.append(container)
+
+ i.append(OP_DISPLAY[operator])
+ i.append(display_constant)
+ elif context is not None and unit is not None:
+ i.append(unit)
+ i.append("owned by")
+ i.append(context)
+
+ if container is not None:
+ i.append(container)
+
+ i.append(OP_DISPLAY[operator])
+ i.append(display_constant)
+ else:
+ did_something = False
+ i.append("I don't know how to format this!")
+
+ s.append(" ".join(i))
+
+ if len(s) > 0:
+ o.append("\n### Sentence {0}".format(index))
+ o.append("\n".join(s))
index += 1
if len(self.correct_responses) > 0:
Please sign in to comment.
Something went wrong with that request. Please try again.