我有一个句子及其语法,在哪里可以找到谓词序言,让我可以用逻辑语言编写句子?
存在或你们中的任何人都可以帮助我创建一个谓词
将以下字符串作为输入
(S (NP (NNP John))
(VP (VBP see)
(NP (NNP Mary))))
并返回这个
see(John,Mary)
我有一个句子及其语法,在哪里可以找到谓词序言,让我可以用逻辑语言编写句子?
存在或你们中的任何人都可以帮助我创建一个谓词
将以下字符串作为输入
(S (NP (NNP John))
(VP (VBP see)
(NP (NNP Mary))))
并返回这个
see(John,Mary)
如果我理解,您希望将 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').
我认为@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 的回答,但我认为看看如何从头开始解决这个问题可能会有所帮助。