'Quoting' in Predicates With Events
One of the trickier things I had to deal with is demonstrated by the preposition “on” represented by the _on_p_loc
ERG predicate. That predicate, with the same argument types, is used in two very different ways:
- “Get the book on the table”
- Logic:
_the_q__xhh(x8, _the_q__xhh(x15, _table_n_1__x(x15), and(_book_n_of__xi(x8, i13), _on_p_loc__exx(e14, x8, x15))), pronoun_q__xhh(x3, pron__x(x3), _get_v_1__exx(e2, x3, x8)))
- In this case, the
_on_p_loc__exx
predicate is being asked to filterx8
(which at that point contains all books) to just those that are on whatever is inx15
(which at that point contains one table which is “the table”). This is a query about the current state of the world, which I call the “default world”. The implementation of the predicate should look at the current state of the world and filter down to just books on the table.
- Logic:
- “Put the book on the table”
- Logic:
pronoun_q__xhh(x3, pron__x(x3), _the_q__xhh(x17, _table_n_1__x(x17), _the_q__xhh(x8, _book_n_of__xi(x8, i14), _put_v_1__exxh(e2, x3, x8, _on_p_loc__exx(e16, x8, x17)))))
- This is a statement about something the speaker wants to be true but is presumably not yet:
_on_p_loc__exx
would return “false” if it were simply evaluating whether it is true in the default world. Moreover, the_put_v_1__exxh
predicate wants “where to put the book” passed as its final argument so it can go and put it there. So, in this case,_on_p_loc__exx
needs to package up the description of “book on the table” as data and somehow deliver it to_put_v_1__exxh
so it can “put it”.
- Logic:
Clearly the implementation of _on_p_loc__exx
needs to do something very different in each case. The problem is, if you look at the two predicates, they are identical except for variable names (which doesn’t matter for execution): _on_p_loc__exx(e14, x8, x15)
and _on_p_loc__exx(e16, x8, x17)
. How will they know when to act how?
My answer is that something more is needed in the representation to indicate which mode to operate in: an extra argument that I call “Quote” (stealing from the LISP programming language):
Quote == create
means: package yourself up as dataQuote == eval
means: see if this is true in the default world
One more thing is missing here: where should _on_p_loc__exx
actually store the data if Quote == create
? It turns out that its first argument is an e
variable or “Event Variable”. For our purposes now, imagine it as a variable that acts as a “bag of information”. The bag can get passed between predicates for scenarios where one predicate is saying, for example, “where” (as in this case) or “how” (in the case of adverbs) another term should do its job. It is there to address this scenario. Think of it as a place to hang a bunch of extra arguments or settings to a predicate.
With this addition the logic looks like this:
- Logic:
_the_q__xhh(x8, _the_q__xhh(x15, _table_n_1__x(x15), and(_book_n_of__xi(x8, i13), _on_p_loc__exx(e14, x8, x15, quote1))), pronoun_q__xhh(x3, pron__x(x3), _get_v_1__exx(e2, x3, x8)))
- Logic:
pronoun_q__xhh(x3, pron__x(x3), _the_q__xhh(x17, _table_n_1__x(x17), _the_q__xhh(x8, _book_n_of__xi(x8, i14), _put_v_1__exxh(e2, x3, x8, _on_p_loc__exx(e16, x8, x17, quote1)))))
The only change is that predicates with events are now getting an extra quote
argument.
[The problem of how _put_v_1__exxh actually gets ahold of the event from _put_v_1__exxh
in Prolog is described here]
Deciding When To Quote
The next problem is: how does the value of quote get set to create
or eval
? Since there is nothing about the predicate itself that says which way to set quoting, it has to be something outside the predicate.
There are three cases here:
Case 1: The caller of the predicate sets quoting for predicates it calls
When a predicate like _on_p_loc__exx
can operate in either mode, the only code that really knows which way to set its quoting is the code that is calling the predicate. Recall from the post on how to build predicates that Prolog only automatically executes the top level predicates. I.e. the ones that outside all parenthesis. So, in “Get the book on the table”, Prolog only executes the first _the_q__xhh
predicate since all the rest are recursively inside of it as arguments. All the rest of the predicates are executed by whatever predicate they are an argument of:
_the_q__xhh(x8, _the_q__xhh(x15, _table_n_1__x(x15), and(_book_n_of__xi(x8, i13), _on_p_loc__exx(e14, x8, x15, quote1))), pronoun_q__xhh(x3, pron__x(x3), _get_v_1__exx(e2, x3, x8)))
So, in that case, _on_p_loc__exx
is evaluated by the predicate _the_q__xhh(x15...
and it is responsible for setting the quoting value of everything it executes. Because “the” does not need things quoted, it sets quoted = eval.
In the case of “Put the book on the table”, the predicate _put_v_1__exxh
is the one evaluating _on_p_loc__exx
, and _put_v_1__exxh
knows that it needs its argument quoted, so it sets the value to that in its implementation – you won’t see it represented in the Prolog here:
pronoun_q__xhh(x3,
pron__x(x3),
_the_q__xhh(x17,
_table_n_1__x(x17),
_the_q__xhh(x8,
_book_n_of__xi(x8, i14),
_put_v_1__exxh(e2, x3, x8,
_on_p_loc__exx(e16, x8, x17, quote1)))))
Case 2: Predicates that always quote
Some words, like adverbs or words like “very”, are there for the sole purpose of modifying other words. That is all they do and so they always operate quoted no matter what they are passed. Because they don’t have any indicator that this is their behavior, they still are passed a quote argument, they just ignore it and always quote.
Almost all the cases I have seen, if a predicate takes an event as a non-ARG0 argument it indicates it should always quote. That’s because the whole point of passing an event in is to allow it to do something with it. For example, look at _loud_a_1__ee
in the following:
"Go to the green cave loudly"
┌pron__x:x3
pronoun_q__xhh:x3,h5,h6┤
│ ┌_green_a_2__ex:e14,x9
│ ┌and┤
│ │ └_cave_n_1__x:x9
└_the_q__xhh:x9,h11,h12┤
│ ┌_to_p_dir__eex:e8,e2,x9
└and┤
├_go_v_1__ex:e2,x3
└_loud_a_1__ee:e15,e2
Logic: pronoun_q__xhh(x3, pron__x(x3), _the_q__xhh(x9, and(_green_a_2__ex(e14, x9), _cave_n_1__x(x9)), and(_to_p_dir__eex(e8, e2, x9), _loud_a_1__ee(e15, e2), _go_v_1__ex(e2, x3))))
The sole purpose of _loud_a_1__ee
is to put data on e2
that gets picked up by _go_v_1__ex
and tells it how to go.
Case 3: The “Index” of a phrase
Verbs are an example of predicates that can operate in either mode. For example, in “Get the diamond that shines”, get
is a command asking for the world to be changed but shines
is a query helping indicate which diamond in the default word the speaker is indicating. And, obviously, they could each by in sentences working in the other mode (e.g. “shine the flashlight”). So, just like on
they need to be told which mode to be in for a particular phrase.
"Get the diamond that shines"
┌pron__x:x3
pronoun_q__xhh:x3,h5,h6┤
│ ┌_get_v_1__exx:e2,x3,x8
└_the_q__xhh:x8,h10,h11┤
│ ┌_diamond_n_1__x:x8
└and┤
└_shine_v_1__ex:e13,x8
Logic: pronoun_q__xhh(x3, pron__x(x3), _the_q__xhh(x8, and(_diamond_n_1__x(x8), _shine_v_1__ex(e13, x8)), _get_v_1__exx(e2, x3, x8)))
Using the rules described so far, both _shine_v_1__ex
(correctly) and _get_v_1__exx
(incorrectly) would be evaluated. get
shouldn’t be evaluated since the speaker intent is to change the world, not query its current state. But quoting it isn’t quite right either: there isn’t a predicate that needs the “data” that it would generate by quoting, right?
Actually, there is. It just hasn’t been shown yet because it isn’t generated by the ERG, it needs to be added by our engine afterwards. This is described in the section on executing the Prolog since it is added at the very end. The short story is that verbs which are the “index” or “the main verb of the sentence” can actually change the state of the world (e.g. “put the diamond on the table”) and need to be executed in a different way since they use a special planner subsystem to do it.
So, the index verb is always quoted and a special term is added to the Prolog which does the work of actually changing the world using the data that the verb attaches about itself to its event. How the verb does that is described here.
What Predicates Get a Quote Argument?
Two cases require adding a Quote argument to a predicate:
- Predicates that introduce an Event: Because (as the example shows) one key reason for having the event argument in the first pace is to allow the predicate to “add itself as data” to it for other predicates to use
- Predicates with a scopal argument: Quantifiers like
_the_q__xhh
don’t introduce an event, but they do have scopal arguments (arguments that are themselves predicates, i.e.h
arguments) and thus they are responsible for calling their scopal arguments and setting their quote variables. Because quantifiers can themselves be arguments to other predicates, and those predicates may want the whole branch quoted, they need to be able to “pass through” the value. Thus quantifiers (and anything else that has scopal arguments) also have a quote parameter so they can pass it through.