Prolog による LFG [Prolog]
LFG (Lexical Functional Grammar) とは何なのかというのは以前手短に書いた [1] のでそちらを参照されたい。その記事を書いたときは LFG の素性構造を Ruby のハッシュとして表現していて、その素性構造を単一化するのに結構苦心して、バグを出したりしていた。あと破壊的な操作を導入したのでいまいちコードの正しさに確信が持てていない。
Prolog を使ったらそれが解決されるかというと別にそうでもなくて、やっぱり素性構造のような順序を問わない構造の単一化は難しい。
リストであれば例えば [X,y,Z] と [x,Y,z] を単一化したときに [x,y,z] という実体が「両方向から見える」ようになるのだけど {:a => "a", :b => "b"、:d => "d"} と {:d => "d", :c => "c", :b => "b"} を単一化したときに両方から {:a =>"a", :b => "b", :c => "c", :d => "d"} と見えるようにしないといけないというのはやっぱり破壊的に書かずにいられないのではなかろうか。(ちなみに、ひょっとしたら LiLFeS [2] っていう言語がそういうことができるものなのかもしれないのだが、これは以前試そうとしたら手元の環境でコンパイル不能だったので深追いしなかった)
それでこの問題の一番簡単な回避方法は、順序を問わない構造というのを直接表現するのをやめて普通のリストを使い、素性は名前でなくて位置から決まるようにすればいい。ここでは5要素のリストが [Subj, Pred, Num, Tense, Pers] という素性の値に対応するとみなすことにする。
この決め事に基づいて極めて簡略化された英文法を Prolog の DCG で表現すると以下のようになる。
/* f-structure: [Subj, Pred, Num, Tense, Pers] */
s([Subj|X]) --> np(Subj), vp([Subj|X]).
np(F) --> n(F).
vp(F) --> v(F).
n([_,lion,pl,_,_]) --> [lions].
v([[_,_,pl,_,3],sleep,_,pres,_]) --> [sleep].
v([[_,_,sg,_,3],sleep,_,pres,_]) --> [sleeps].
単一化を言語がサポートしているというのは本当に強力だと思う。これを以下のように使うと、文の f-structure を求めることができる。
?- s(F,[lions,sleep],[]). F = [[_G224, lion, pl, _G233, 3], sleep, _G245, pres, _G251] ; No
インスタンス化されない変数が残ってしまうのはこの実装における素性構造の扱いを先のように決めたからでしょうがない。以下のように非文を与えるときちんと失敗する。これは sg と pl が単一化に失敗するからだ。
?- s(F,[lions,sleeps],[]). No
さらに f-structure から文を求めることもできる。これは前回 Ruby で実装したものではできなかったようなことだ。
?- s([[_,lion,pl,_,3],sleep,_,pres,_],S,[]). S = [lion, sleeps] ; No
ところでついでに文のツリー構造(LFG でいう c-structure)も見れるようにした。
s(s(NP,VP),[Subj|X]) --> np(NP,Subj), vp(VP,[Subj|X]).
np(np(N),F) --> n(N,F).
vp(vp(V),F) --> v(V,F).
n(n(lions),[_,lion,pl,_,_]) --> [lions].
v(v(sleep),[[_,_,pl,_,3],sleep,_,pres,_]) --> [sleep].
v(v(sleeps),[[_,_,sg,_,3],sleep,_,pres,_]) --> [sleeps].
?- s(C,F,S,[]). C = s(np(n(lions)), vp(v(sleep))) F = [[_G251, lion, pl, _G260, 3], sleep, _G279, pres, _G285] S = [lions, sleep] ; No
[1] http://rainyday.blog.so-net.ne.jp/2007-04-09
[2] http://www-tsujii.is.s.u-tokyo.ac.jp/lilfes/index-j.html
コメント 0