文とその構文がありますが、論理言語で文を書くことができる述語プロローグはどこにありますか?
存在するか、あなたの誰かが私がその述語を作成するのを手伝ってくれる
次の文字列を入力として受け取ります
(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)
@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).
term と list の間には相互再帰がありますが、リストをどこにでも入れ子にできるようにしたいので、これが必要です。解析をテストしましょう:
?- 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') .
なんといっても、自然言語の文を論理的な命題に翻訳することは大きな問題です。通常はこれほど簡単ではありませんが、問題へのアプローチ方法を説明している本があります。この大きな問題の詳細については、Representation and Inference for Natural Languageを確認することをお勧めします。
それで、あなたはそれを持っています。このように手動で行うことの利点は、Lisp の文法から正確に何を取得したいかを制御できることと、拡張または変更が容易であることです。欠点は、文法をデバッグする必要があることです。これには、私が気付かなかったり、見つけるのに時間がかかったりしていない問題があることは間違いありません (私は DCG の専門家ではありません!)。より良い要件がなければ、@ CapelliCの答えを間違いなく受け入れますが、これを最初からどのようにアプローチできるかを確認すると役立つと思いました。
私が理解できれば、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').