130 likes | 308 Views
Prolog tutorial (1) 補足. 白井英俊(情報理工学部). 規則の練習における注意. couple(A,B) :- parent(A,C), parent(B,C), A = B. は次のようには書けない。なぜだろうか? couple(A,B) :- parent(A,C), A = B, parent(B,C). または couple(A,B) :- A = B, parent(A,C), parent(B,C). A と B に共に何らかの値が入っている場合は期待通り
E N D
Prolog tutorial (1)補足 白井英俊(情報理工学部)
規則の練習における注意 couple(A,B) :- parent(A,C), parent(B,C), A \= B. は次のようには書けない。なぜだろうか? couple(A,B) :- parent(A,C), A \= B, parent(B,C). または couple(A,B) :- A \= B, parent(A,C), parent(B,C). AとBに共に何らかの値が入っている場合は期待通り に動く。どちらかが変数の場合、 「A=B」というパタン マッチングが成功してしまうので、「必ずA\=Bは失敗」 となる
練習問題(5) 「誰が誰の親(parent)か」、「誰が男性(male)」、「誰が女性(female)」という3種類のデータがPrologのデータベースに沢山書き込まれているとする(他の情報はないとする) • 「誰が誰の息子(son)」規則を書く • 「誰が誰の夫(husband)か」規則を書く • 「誰が誰の妻(wife)か」規則を書く • 「誰が誰の孫(grandson)か」規則を書く • 他にどのような規則が書けるだろうか?
解答例(1) この場合parentとmaleの順番 はどちらが先でもよい • 「誰が誰の息子(son)」規則 解答例1 son(A,B) :- parent(B,A), male(A). 解答例2 son(A,B) :- male(A), parent(B,A). 誤答例1 (4名あり) son(A,B) :- parent(B,A). 誤答例2(各1名) son(A,B) :- person(A,B), person(C,B), A \= C, male(B). son(A,B) :- parnt(B,A), man(A). 「息子」は男(male)でないと… 問題を読んで考えましょう…
解答例(2) parent,male,femaleの 順番はどちらが先で もよい。 (2) 「誰が誰の夫(husband)か」規則 解答例1 husband(A,B) :- male(A), female(B), parent(A,C), parent(B,C), A \= B. 解答例2 husband(A,B) :- male(A), parent(A,C), parent(B,C), A \= B. 誤答例1 husband(A,B) :-male(A). female(B). 誤答例2 husband(A,B) :- person(A,B), person(C,B), A \= C, male(B). female(B)により A \= Bは不要 femaleは不要かも(gayは考慮外) 誰でも彼でも夫婦にしないで
解答例(3) parent,male,femaleの順番 はどちらが先でもよい (3) 「誰が誰の妻 (wife)か」規則 解答例1 wife(A,B) :- female(A), male(B), parent(A,C), parent(B,C), A \= B. 解答例2 wife(A,B) :- female(A), parent(A,C), parent(B,C), A \= B. 解答例3 wife(A,B) :-husband(B,A). 誤答例 wife(A,B) :-female(A). male(B). male(B)により A \= Bは不要 maleは不要かも(gayは考慮外) husbandがちゃんとできて いれば、これでもOK 誰でも彼でも夫婦にしないで
解答例(4) (4) 「誰が誰の孫(grandson)か」規則 解答例1 grandson(A,B) :- parent(C,A), parent(B,C), male(A). 誤答例 grandson(A,B) :- parent(C,A), parent(B,C). parent,maleの順番はどちらが先でもよい 「孫」と書いてあるが、講義中に述べた ように、”grandson”述語なので、「孫息子」 条件を書かないといけない
解答例(5) (5)他にどのような規則が書けるだろうか? 祖父(grandFather) 祖母(grandMother) 孫娘(grandDaughter) 娘(daughter) 先祖(ancestor) 子孫(descendant) 兄弟(brother), 姉妹(sister), sibling
規則の書き方についての注意 • 「AがBの夫(husband)」ならば、明らかに「BはAの妻(wife)」が成り立つ • だからと言って、Prologのデータベースに次のように書いてはいけない husband(A,B) :- wife(B,A). wife(B,A) :- husband(A,B). Prologでどのように事実や規則を検索するかを思い出そう
表示する… • 先の演習で、「誰が誰の息子(夫、妻、孫,…)か」、すべての組み合わせを表示させることを考える • そのために必要なのは、「出力命令」 • Prologでは、 write と nl を知っていればできる 例: ?- son(A,B), write(A), write(‘ is a son of ‘), write(B), nl. 結果=> george is a son of victoria A = george,B = victoria ? writeは文字列をそのまま 出力。 nlは改行、write(‘\nl’)と同じ
全部表示する… • 先の方法だと、「すべての息子(夫、妻、…)」を表示させるのは、一々セミコロン(;)を入力しなければならない。 • それは面倒… 「繰り返し」をさせればよい。 それには次の方法がある(何が起こるかな?): ?- son(A,B), write(A), write(‘ is a son of ‘), write(B), nl. , fail.
全部集める… • findall/3の紹介 「誰が誰の息子(夫、妻、孫,…)か」、すべての組み合わせを「求める」ことがfindallを使えば可能 一つの方法: ?- findall(s(A,B), son(A,B), L). リストの要素の形 リストを記憶する変数 するとLの値は: [s(george, victoria), s(edward,victoria), … ] これはリスト。データベースから推論できるすべての息子(son)関係にある 人の組からs( , )という形のタームが作られ、それを要素とするリストが作られる 。
いったい幾つ集まった? • リストについては次の資料で詳しく説明するが。。。 • 一言でいえば、Rubyの「配列」のようなもの • 配列と同様に、リストの要素の個数を数える述語(関数、メソッド)がある。それがlength/2 使用例: ?- findall(s(A,B), son(A,B), L), length(L,N).