将自然语言转换为逻辑公式

时间:2015-07-05 00:21:10

标签: logic nlp nltk lambda-calculus

我试了几天写一个NLTK语法,将简单的法语句子转换成逻辑公式。我的问题与英语句子类似。我的目标是这个语法接受几个命令(家庭自动化)并将它们转换成逻辑公式。订单的一些例子:

打开灯:

exists x.(turn_on(x) & light(x))

打开绿灯:

exists x.(turn_on(x) & light(x) & green(x))

打开厨房的灯光

exists x.(turn_on(x) & light(x) & exists y.(kitchen(y) & in(x, y)))

在这些示例中,单词 turn_on 实际上不是逻辑谓词。它将用于我的程序的下一步(当它将此公式转换为另一种表示时)。

但是,写关于占有关系的规则我有很多困难。我希望规则接受一个"无限"递归如:

  • 打开厨房的灯(灯光属于我数据库中的厨房)
  • 打开房子厨房的灯(厨房属于我数据库中的房子)
  • 打开[...](等)房子厨房的灯光。

我成功转换了第一句而不是其他的。在这里我的语法(我将法语翻译成英语以便更好地理解):

% 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'

用这个语法和顺序&#34;打开厨房的灯光#34;我得到:

exists x.(kitchen(x) & exists z1.(light(z1) & in(z1,x) & turn_on(z1)))

但是,对于订单&#34;打开房子厨房的灯光&#34;:

exists x.(house(x) & exists z5.(kitchen(z5) & exists z2.(light(z2) & in(z2,z5) & in(z2,x) & turn_on(z2))))

为了更具可读性,没有&#34;的相同公式存在&#34;:

(house(x4) & kitchen(x6) & light(x7) & in(x7,x6) & in(x7,x4) & turn_on(x7))

&#34; in&#34;存在问题。谓词。事实上,我希望厨房里有灯,厨房里有灯。然而,在这种情况下,光是在厨房和房子里(是的,它是真的,但我不想要= /)。这就是我想要的:

(house(x4) & kitchen(x6) & light(x7) & in(x7,x6) & in(x6,x4) & turn_on(x7))
                                   the difference -----^

我尝试了几种方法,但没有一种方法有效......你能帮帮我吗?我不知道我的语法是否可行。我对逻辑和lambda calcul的了解有限,我才开始对这些主题产生兴趣。

修改 这是我用于测试的python代码:

#!/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')

非常感谢,对不起我的英语。

1 个答案:

答案 0 :(得分:1)

很难说存在量词是命令句的逻辑形式。但是,你的问题在于另一个问题。

你的语法似乎很模糊。特别是当您使用x of y函数对in(x, y)进行代表时,可以想象它具有与第二个短语类似的歧义:

  

房子里厨房的灯光。

     

在院子里的孩子的球。

  1. 院子里的球。
  2. 院子里的孩子。
  3. 基于您的代码的语法为所需的句子产生了这两种解释:

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

    在第二种解释中:house(x) & exists z3.(kitchen(z3) & in(z3,x) ...是你想要的。

    <强>更新

    让我们试着避免x of y of z链中的含糊不清。

    强制x of (y of z)而不是(x of y) of z的一个非常快速的解决方案是跟踪所有名词短语中的of用法,然后强制它在OF上没有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] 的左侧:

    {{1}}