Reputation: 117
I tried for days to write a NLTK grammar to convert simple French sentences into logical formulas. My problem can be similar with English sentences. My goal is that this grammar accepts several orders (home automation) and converts them into logical formulas. Some examples of orders:
Turn on the light:
exists x.(turn_on(x) & light(x))
Turn on the green light:
exists x.(turn_on(x) & light(x) & green(x))
Turn on the light of the kitchen
exists x.(turn_on(x) & light(x) & exists y.(kitchen(y) & in(x, y)))
In these examples, the word turn_on is not really a logical predicate. It will be used in the next step of my program (when it will convert this formula into another representation).
However, I have many difficulties to write the rule about possession relationship. I would like that the rule accepts an "infinite" recursion like:
I succeeded to convert the first sentence but not the others. Here my grammar (I translate French to English for a better understanding):
% start SV
SV[SEM=<?v(?sn)>] -> V[SEM=?v] SN[SEM=?sn]
SN[SEM=<?ap(?sn1, ?sn2)>] -> SN[SEM=?sn1] AP[SEM=?ap] SN[SEM=?sn2]
SN[SEM=<?ad(?n)>] -> AD[SEM=?ad] N[SEM=?n]
SN[SEM=?n] -> N[SEM=?n]
N[SEM=<?adj(?n)>] -> ADJ[SEM=?adj] N[SEM=?n]
V[SEM=<\P.P(\x.turn_on(x))>] -> 'turn' 'on'
N[SEM=<\x.light(x)>] -> 'light'
N[SEM=<\x.kitchen(x)>] -> 'kitchen'
N[SEM=<\x.house(x)>] -> 'house'
ADJ[SEM=<\P x.(P(x) & big(x))>] -> 'big'
ADJ[SEM=<\P x.(P(x) & green(x))>] -> 'green'
AD[SEM=<\P Q.exists x.(P(x) & Q(x))>] -> 'the'
AP[SEM=<\P Q R.Q(\x.P(\y.(in(y,x) & R(y))))>] -> 'of'
With this grammar and the order "turn on the light of the kitchen", I get:
exists x.(kitchen(x) & exists z1.(light(z1) & in(z1,x) & turn_on(z1)))
But, for the order "turn on the light of the kitchen of the house":
exists x.(house(x) & exists z5.(kitchen(z5) & exists z2.(light(z2) & in(z2,z5) & in(z2,x) & turn_on(z2))))
To be more readable, the same formula without the "exists":
(house(x4) & kitchen(x6) & light(x7) & in(x7,x6) & in(x7,x4) & turn_on(x7))
There is a problem with the "in" predicates. Indeed, I want that the light is in the kitchen and that the kitchen is in the house. However, in this case, the light is in the kitchen and in the house (yes, it's true, but I don't want that =/). Here's what I would like:
(house(x4) & kitchen(x6) & light(x7) & in(x7,x6) & in(x6,x4) & turn_on(x7))
the difference -----^
I tried several methods but none of them worked... Can you help me please? I don't know if it's possible with my grammar. My knowledge on logic and lambda calcul are limited, I only just beginning to get interested in these topics.
EDIT: Here is the python code that I use for my tests:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import nltk
def exec(parser, query):
try:
trees = list(parser.parse(query.split()))
except ValueError:
print('Invalid query')
return
if len(trees) == 0:
print('Invalid query')
return
print('query: %s' % query)
print('results:')
for t in trees:
sem = t.label()['SEM']
print('\t%s' % sem)
print('')
if __name__ == '__main__':
parser = nltk.load_parser('./en_grammar.fcfg')
exec(parser, 'turn on the light')
exec(parser, 'turn on the light of the kitchen')
exec(parser, 'turn on the light of the kitchen of the house')
Thanks a lot and sorry for my English.
Upvotes: 4
Views: 3685
Reputation: 4318
It is hard to say that an existential quantifier is the logical form of an imperative sentence. However, your question lies in another problem.
It seems that you have an ambiguous grammar. Specially when you intrepret the x of y
with in(x, y)
function, it is imaginable to have similar ambiguity as in second phrase:
the light of the kitchen in the house .
the ball of the kid in the yard .
Your grammar based on your code produces these two interpretations for desired sentence:
query: turn on the light of the kitchen of the house
results:
exists x.(house(x) & exists z5.(kitchen(z5) & exists z2.(light(z2) & in(z2,z5) & in(z2,x) & turn_on(z2))))
exists x.(house(x) & exists z3.(kitchen(z3) & in(z3,x) & exists z6.(light(z6) & in(z6,z3) & turn_on(z6))))
In second interpretation: house(x) & exists z3.(kitchen(z3) & in(z3,x) ...
is exact thing that you want.
UPDATE:
Let's try to avoid the ambiguity in chains of x of y of z
.
One very fast solution to force x of (y of z)
instead of (x of y) of z
is to track the of
usage in all noun phrases, and then force it to have no OF
on the left side of the of
:
SN[SEM=<?ap(?sn1, ?sn2)>, +OF] -> SN[SEM=?sn1, -OF] AP[SEM=?ap] SN[SEM=?sn2]
SN[SEM=<?ad(?n)>, -OF] -> AD[SEM=?ad] N[SEM=?n]
SN[SEM=?n, -OF] -> N[SEM=?n]
Upvotes: 1