「とはなんですか」疑問文: prolog二分木

知識に基づいて、「とはなんですか」という疑問文を生成するprolog文を作った。例えば、「アトムはロボットです」という部分知識があったときに、これを回答にするような問いを考えるということである。プログラムは次のようになる。細かい調整はしていないので、色々バグもあると思う。

単純疑問文の場合と発想を変えてプログラム化した。シンプルだ。単純疑問文の場合も、この発想で書き直せば、もっといい感じになると思う。

%% ----- なんですか 疑問文 -----
nandesuka(T,Out) :- not(functor(T,node,3)),Out=T.
nandesuka(node(N,L,R),Out) :-
        (
            'です'=N,
            not(functor(L,node,3))
        ->  N1='ですか',
            L1='なん',
            R1=R
        ;   (
                'は'=N
            ->  N1='とは'
            ;   N1=N,
                true
            ),
            %% 左右の葉を再帰的に処理する
            nandesuka(L,L1),
            nandesuka(R,R1),
            true
        ),
        Out = node(N1,L1,R1).

変な感じではあるが、元々に知識的ツリーを入れると、それを答えとするような疑問文を生成するということである。

if文を使っている。if文の中にif文を使って、ネストしている。ある意味、if文は、Cやjavaなどの逐次処理言語の得意芸であり、あまりprolog的にはなじまないのかもしれないが、prolog的には、cut(!)を使った単純な構造である。if文の最後にtrueが付いているのは、if文の条件節が成立しなくても、カッコの次を実行するためである。そうしないと、成立しないときに、バックトラックに入って、その後を実行しなくなる。

最初のif文は、node値が「です」の部分木に出会ったら、それを「ですか」に変えて、その左葉の値がツリーでない限り、「なん」という疑問詞に変えるということである。この時の左葉が部分ツリーになる場合は、うまくいかないが、そういう状況は、想像できない。ないと思う。

さらに、「は」とう格助詞がnode値の時は、それを「とは」に変える処理もする。

「です」nodeに出会った時は、それ以上の再帰的処理はしないが(文の最後であるはずだから)、そうでない限り、各葉の再帰的処理に入り、各葉がnodeでないときは、そのまま値を返すという再帰的処理の終端処理が、最初のprolog文である。

実行結果は次のようになる。

?- ['quetion.swi'].
true.

?- nandesuka(node(は,[アトム, 'S:普/C:自然物/D:科学・技術'],node(です,[ロボット, 'S:普/C:人工物-その他/D:科学・技術'],[ ])),Out).

Out = node(とは, [アトム, 'S:普/C:自然物/D:科学・技術'], node(ですか, なん, [])).

知識文は「アトムはロボットです」をjavaのprolog二分木作成システムで作った二分木である。フォーマット改変の記事で、それぞれの記号的意味は解説している。