如何使用prolog翻译逻辑语言中的句子?

如何使用prolog翻译逻辑语言中的句子?,prolog,Prolog,我有一个句子和它的语法,我在哪里可以找到谓词prolog,它允许我用逻辑语言写这个句子 存在,或者您可以帮助我创建一个谓词 将以下字符串作为输入 (S (NP (NNP John)) (VP (VBP see) (NP (NNP Mary)))) 还这个 see(John,Mary) 如果我理解,您希望将LISP结构解析为Prolog。然后,由马库斯·特里斯卡(Markus Triska)设计,可能是合适的工具。使用那个和这个片段 test :- parse("(S (N

我有一个句子和它的语法,我在哪里可以找到谓词prolog,它允许我用逻辑语言写这个句子

存在,或者您可以帮助我创建一个谓词

将以下字符串作为输入

(S (NP (NNP John))
    (VP (VBP see)
      (NP (NNP Mary))))
还这个

see(John,Mary)

如果我理解,您希望将LISP结构解析为Prolog。然后,由马库斯·特里斯卡(Markus Triska)设计,可能是合适的工具。使用那个和这个片段

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]).
我明白了

现在,您应该决定将逻辑形式转换为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].
测试:


我认为@capelical的答案更好(+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'|...]]]] ;
到目前为止,这个看起来不错。模式匹配看起来与@capelical非常相似:

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专家!)。如果没有更好的要求,我肯定会接受@capelical的答案,但我认为看看如何从头开始可能会有所帮助。

谢谢,这似乎很理想,但我不工作,我创建了一个prolog文件,其中包含您告诉我的代码lisprolog和子句,但这是一条语句:——Gtrace,sexp_to_term((S(NP(NNP-John))(VP(VBP-see)(NP(NNP-Mary))))”,T.——那个----?-测试回答“否”。使用yap,不使用gtrace,太糟糕了,它不适用于所有句法形式,只适用于主谓补语,谢谢你,你愿意给我上私人课吗?显然是付费的?我可以(意大利语:)。给我发邮件,看看我们是否能达成协议(请参阅我的个人资料以获取电子邮件)。再见,我给你发了一封电子邮件,请帮我转达一下。gabriele@gmail.com实际上,DCG的输出比LisProlog的输出更可读。可能LisProlog公式由于需要进一步求值而变得杂乱无章。这显然与真正的Lisp解析器相去甚远,因此它可能受益于简单性。但我很看重正确性,我怀疑我15分钟的DCG练习是否比公布的代码更正确。我认为LisProlog很棒。解析器也非常紧凑。大约25年前,我在Autolisp(简单的Autocad 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') .