Sponsored Link

トレースしてみる



それでは、今後の学習のために磯野家の家族関係を補強(?)しておきましょう。ワカメちゃんが舟さんの娘じゃない、となると大変ですからね。それに、もう一世代多いと何かと嬉しいので波平さんのお母さん、海さん(吉田の創作です)にご登場願いましょう。次の節をプログラムに追加しておいてください。
          parent(fune,wakame).
          parent(masuo,tara).
          parent(umi,namihei).

2.1カツオは男の子、ワカメは女の子

前章の演習問題で、カツオはタラちゃんの叔父さんか、ワカメは叔母さんかというのをやりました。でも、「タラちゃんの叔父さんは誰か」を知りたいときにはどうしたらいいのでしょう。parent関係で登場した人々の性別に関する情報を加えなければなりません。例えば、次のように、です。
          male(namihei).                .....list 1 
          female(fune).
          female(sazae).
          male(katuo).
          female(wakame).
          male(masuo).
          male(tara).
          female(umi).               
最初にparent関係について定義したときはparent(namihei,sazae).のように引数が2つありました。今度のmale/female関係は1つです。これらは定義の仕方次第で、2つでも3つでも構いません。その時々で一番判りやすいように定義すればいいでしょう。male/female関係も次のように引数2つで定義することができます。
          sex(namihei,male).            .....list 2
          sex(fune,female).
          sex(sazae,female).
          ........
ここでは、male/female関係(list 1)で実習を進めましょう。上のmale/female関係の定義をプログラムに追加してください。

2.2親子関係は子親関係

磯野家の人々の性別が定義されて、「タラちゃんの叔父さんは誰か」や「タラちゃんのお母さんは誰か」ができそうな雰囲気になってきました。でも、その前にルール(rule)を導入します。実は、急いては事をし損じるというほどではないですが、ルールがあると関係の拡張がずっと簡単にできるようになるからです。

先ず、parent関係の逆を考えてみましょう。いままでは「誰が誰の親である」という関係を考えていましたが、ここでは「誰が誰の子供である」という関係を考えます。parentの逆ですからchildとでもしましょう。例えば、
          child(sazae,namihei).
というように、定義していけばいいです。でも、これはちょっと面倒です。プログラムの中にparent関係は全部でいくつありますか。それと同じだけ、全く逆のchild関係を記述しなければなりません。parent関係の定義が既にあるのですから、これを利用してもっと楽にchild関係を定義しようではありませんか。 難しい言い方になりますが、child関係は と言えますね。これがルールです。Prologでは、:−を使って次のように記述します。
          child(Y,X):-parent(X,Y).
これは、また、 とも言えます。多分、こちらの方が判りやすいでしょう。どちらで考えてもいいです。自分にとって判りやすい方で考えてください。どっちだって同じなんだから。

いままで使ってきたparent関係は「事実」です。今度のchild関係は「ルール」です。事実とルールには重要な差異があります。 事実は常に無条件に真です。プログラム中に
          parent(sazae,tara).
という定義があった場合、
          ?- parent(sazae,tara).
という質問は、常に無条件に目標を充足します。内容の同じ節がプログラム中にあるのですから。一方、ルールは常に真とは限りません
          child(Y,X):-parent(X,Y).
というルールは、変数X,Yに何らかの値が設定されて、そのX,Yに対応するparent関係がプログラム中に定義されていて、はじめて真となるのです。つまり、ルールの:-の右辺はルールが充足されるための条件となっているのです。このことから、ルールの左辺を結論部、右辺を条件部と言います。また、その形式から左辺を頭部、右辺を本体とも言います。

ルールの形式
図2.1 ルールの形式



ルールが定義されていた場合に、Prologがどのように動作するかを考えましょう。次のような質問がされたとします。
          ?- child(wakame,fune).
プログラム中にはchild(wakame,fune).という節はないので、Prologは次のルールを考えます。
          child(Y,X):-parent(X,Y).
ここでPrologは、このルールでX=fune,Y=wakameと考えればいいかな、と思うわけです。そうすると、
          ?- child(wakame,fune).
を解決するためには、
          child(wakame,fune):-parent(fune,wakame).
について考えればいいということになります。即ち、ルールの条件部(本体)であるparent(fune,wakame).について考えればいいわけで、結局
          ?- parent(fune,wakame).
という質問があった場合と同じと言えます。ここで、
          ?- child(wakame,fune).
という目標が
          ?- parent(fune,wakame).
という目標に置き換えられたことになります。このような場合の新しい目標を副目標と言います。この新しい目標は、プログラム中に同じ内容の節がありますから真です。したがって、Prologは質問に対してyesと答えます。

2.3サザエはタラちゃんのお母さん

それでは、いよいよ母子関係について考えてみましょう。関係の名称をmotherとします。 と、考えます。これをPrologで記述すると
          mother(X,Y):-parent(X,Y),female(X).
となります。本体部の2つの目標の間のカンマはandを表し、両方の目標が充足されなくてはなりません。

次にsister関係について考えてみましょう。 と定義します。現在のところ、年齢の定義はしていないので姉と妹、兄と弟などは区別せずにsister,brotherと考えることにします。sister関係をPrologで記述すると
          sister(X,Y):-
              parent(Z,X),
              parent(Z,Y),
              female(X).
となります。

ここでプログラムの配置について注意しておきます。PrologはCと同様、プログラムの配置(カラムなど)についての制限がありません。ですから、適当にスペースを入れたり、改行したりして見易いように記述しましょう。一般には、ルールの頭部と本体とは改行し、本体は頭部より行頭を下げて(インデント)、上のsister関係のように記述します。但し、本体の目標が1つで非常に短い場合などは、このように改行・インデントを入れるとかえって見にくくなることもあります。その場合は、1行に書いてしまいましょう。いずれにしても、「見易い」ことが大切です。

さて、sister関係です。先ず、「XとYとが同じ親を持つ」ということに注意してください。ここでは、parent(Z,X),parent(Z,Y)と、「Xの親がZで、Yの親もまたZである」としました。これを、「Xの親がAで、Yの親がBで、AとBとが同一である」というようにも定義できます。しかし、これは明らかにエレガントではありません。一般に数学やプログラミングでは巧い処理のことを「エレガント」と表現します。エレガントなプログラムは見易く、判りやすく、処理も速いものです。できるだけ、そのようなプログラムを作るように心がけてください。

いまや、我々は「サザエにはワカメという妹がいるか」という質問
          ?- sister(wakame,sazae).
ができるようになりました。(ぱちぱち)上のような質問をするとPrologは期待通り、yesと答えるでしょう。(答えなければ見直すこと)「完璧!!」と思うのは早計です。次のような質問をしてみましょう。「ワカメの姉は誰か」、即ち、
          ?- sister(X,wakame).
です。Prologは複数の答えを見つけます。
          X=sazae;
          X=wakame
現在の我々のプログラムが姉と妹の区別が付かないのは仕方がないとして、ワカメの姉(妹)がワカメとは何事だ、ということです。一体全体どうなっているのでしょう。

プログラムがどのように動いているのか、判らないときはトレースします。Prologのプロンプトからtrace.と入力して、質問を入れるとPrologは1行づつ実行の過程を画面に表示しながら動きます。決して見易いものではありませんが、プログラムの動きを追うには仕方ありません。トレースすることによって、何故ワカメがワカメの姉(妹)になるのか確認しましょう。

さて、確認できたでしょうか。Prologは間違ってはいません。sister関係のルールに従うならば、ワカメはワカメの姉(妹)なのです。sister関係のルールは、
          sister(X,Y):-
              parent(Z,X),
              parent(Z,Y),
              female(X).
でした。X=wakame,Y=wakame,Z=namihei(Z=funeでもよい)とすると、ワカメはワカメの姉(妹)です。今後のためにも、XとYとが同一ではない、という関係differentを定義しておきましょう。
          different(X,Y):-X / == Y.
/ ==は等しくない、という意味です。このようにdifferent関係を定義しておけば、これを利用してsister関係を簡単に修正することができます。
          sister(X,Y):-
              parent(Z,X),
              parent(Z,Y),
              female(X),
              different(X,Y).
本章の要点をまとめておきましょう。



《演習問題》
目次に戻る目次に戻る