1

我有一个句子及其语法,在哪里可以找到谓词序言,让我可以用逻辑语言编写句子?

存在或你们中的任何人都可以帮助我创建一个谓词

将以下字符串作为输入

(S (NP (NNP John))
    (VP (VBP see)
      (NP (NNP Mary))))

并返回这个

see(John,Mary)
4

2 回答 2

1

如果我理解,您希望将 LISP 结构解析为 Prolog。那么Markus Triska 的LisProlog可能是合适的工具。使用那个和这个片段

test :- parse("(S (NP (NNP John))
        (VP (VBP see)
         (NP (NNP Mary))))",
          R),
    maplist(sexp_write(""), R).

sexp_write(Indent, E) :-
    is_list(E),
    format('~s~w~n', [Indent, E]),
    maplist(sexp_write([0' |Indent]), E).
sexp_write(Indent, E) :-
    format('~s~w~n', [Indent, E]).

我明白了

?- test.
[s(S),[s(NP),[s(NNP),s(John)]],[s(VP),[s(VBP),s(see)],[s(NP),[s(NNP),s(Mary)]]]]
 s(S)
 [s(NP),[s(NNP),s(John)]]
  s(NP)
  [s(NNP),s(John)]
   s(NNP)
   s(John)
 [s(VP),[s(VBP),s(see)],[s(NP),[s(NNP),s(Mary)]]]
  s(VP)
  [s(VBP),s(see)]
   s(VBP)
   s(see)
  [s(NP),[s(NNP),s(Mary)]]
   s(NP)
   [s(NNP),s(Mary)]
    s(NNP)
    s(Mary)
true .

现在您应该决定将逻辑形式翻译成 Prolog 术语。

一般来说,这是一个困难的主题,因为你需要对量化做一些选择。对于您的简单陈述,您可以从一个非常简单的模式匹配开始,完全忽略上述问题。

sexp_to_term(S_exp, T_exp) :-
    parse(S_exp, [R]),
    termize(R, T),
    pattern(T, T_exp).

pattern(T, T_exp) :-
    T = 'S'('NP'('NNP'(Subj)),'VP'('VBP'(Verb),'NP'('NNP'(Obj)))),
    T_exp =.. [Verb, Subj, Obj].

termize(s(Tag), Tag).
termize([s(Tag)|Args], Term) :-
    maplist(termize, Args, ArgsT),
    Term =.. [Tag|ArgsT].

测试:

?- gtrace,sexp_to_term("(S (NP (NNP John)) (VP (VBP see) (NP (NNP Mary))))", T).
T = see('John', 'Mary').
于 2013-02-19T13:08:06.880 回答
1

我认为@CapelliC 的答案更好(+1),但我想尝试一下,看看我想出了什么。你可以在没有 LisProlog 的情况下解决这个问题,但你可以肯定 LisProlog 会比我现成的 DCG 废话做得更好

首先,为了方便起见,我想将您的例句粘贴到代码中,这样我就不必继续重新输入它了:

sent("(S (NP (NNP John))
         (VP (VBP see)
             (NP (NNP Mary))))").

现在一些辅助 DCG 规则:

whitespace --> [X], { char_type(X, white) ; char_type(X, space) }, whitespace.
whitespace --> [].

char(C) --> [C], { char_type(C, graph), \+ memberchk(C, "()") }.

我需要memberchk在那里以确保我不会将括号放入原子中。

chars([C|Rest]) --> char(C), chars(Rest).
chars([C]) --> char(C).

term(T) --> chars(C), { atom_chars(T, C) }.
term(L) --> list(L).

list(T) --> "(", terms(T), ")".

terms([]) --> [].
terms([T|Terms]) --> term(T), whitespace, !, terms(Terms).

术语和列表之间存在相互递归,但这正是我们想要的,因为我们希望列表能够嵌套在任何地方。让我们测试一下解析:

?- sent(X), phrase(list(Y), X).
X = [40, 83, 32, 40, 78, 80, 32, 40, 78|...],
Y = ['S', ['NP', ['NNP', 'John']], ['VP', ['VBP', see], ['NP', ['NNP'|...]]]] ;

到目前为止,这看起来不错。模式匹配看起来与@CapelliC 的非常相似:

simplify(['S', ['NP', ['NNP', Subject]], 
               ['VP', ['VBP', Verb], 
                      ['NP', ['NNP', Object]]]], 
         Result) :-
    Result =.. [Verb, Subject, Object].

不幸的是,使用大写的原子会掩盖这里的意图,这实际上是很自然的。如果我们可以使用小写字母,则模式看起来更像这样:

simplify([s, [np, [nnp, Subject]], 
             [vp, [vbp, Verb], 
                  [np, [nnp, Object]]]], 
         Result) :-
    Result =.. [Verb, Subject, Object].

我们在这里使用强大的“univ”运算符 ( =..) 从列表中生成 Prolog 术语。您可以将此运算符视为 Lisp 翻译器,因为它本质上就是这样做的:

?- s(this, that) =.. X.
X = [s, this, that].

?- X =.. [s, this, that].
X = s(this, that).

所以应该清楚模式匹配是如何工作的。让我们看看整个事情是如何组合在一起的:

?- sent(X), phrase(list(Y), X), simplify(Y, Z).
X = [40, 83, 32, 40, 78, 80, 32, 40, 78|...],
Y = ['S', ['NP', ['NNP', 'John']], ['VP', ['VBP', see], ['NP', ['NNP'|...]]]],
Z = see('John', 'Mary') .

对于它的价值,将自然语言句子翻译成逻辑命题是一个大问题。通常不会这么容易,但是有一些书讨论了如何解决这个问题。我建议查看自然语言的表示和推理,以获取有关这个大问题的更多信息。

所以你有它。像这样手工完成的好处是,您可以从 Lisp 的语法中精确控制要采用的内容,并且易于扩展或修改。缺点是您必须调试语法——我很确定这个语法存在我没有注意到或花时间发现的问题(我远非 DCG 专家!)。如果没有更好的要求,我肯定会接受@CapelliC 的回答,但我认为看看如何从头开始解决这个问题可能会有所帮助。

于 2013-02-19T18:29:48.860 回答