Конвертировать естественный язык в логическую формулу

Я несколько дней пытался написать грамматику 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'

С этой грамматикой и приказом "включить свет на кухне" я получаю:

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

Но для заказа "включи свет на кухне дома":

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

Чтобы быть более читабельным, та же формула без "существует":

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

Существует проблема с предикатами in. Действительно, я хочу, чтобы свет был на кухне, а кухня - в доме. Однако в этом случае свет есть на кухне и в доме (да, это правда, но я этого не хочу =/). Вот что я хотел бы:

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

Я попробовал несколько методов, но ни один из них не сработал... Не могли бы вы помочь мне, пожалуйста? Я не знаю, возможно ли это с моей грамматикой. Мои знания по логике и лямбда-исчислению ограничены, я только начинаю интересоваться этими темами.

РЕДАКТИРОВАТЬ: Вот код 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 ответ

Решение

Трудно сказать, что экзистенциальный квантор является логической формой императивного предложения. Тем не менее, ваш вопрос заключается в другой проблеме.

Кажется, у вас есть неоднозначная грамматика. Особенно, когда вы представляете x of y с in(x, y) функция, это возможно, чтобы иметь такую ​​же неопределенность, как во второй фразе:

свет кухни в доме.

мячик малыша во дворе.

  1. Мяч, который находится во дворе.
  2. Малыш, который во дворе.

Ваша грамматика, основанная на вашем коде, дает следующие две интерпретации для желаемого предложения:

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]
Другие вопросы по тегам