on(X, Y).

数値・記号処理(8)
Prolog 事始
慶應義塾大学理工学部
櫻井彰人
最も簡単なプログラム
最も簡単な Prolog プログラムは、多分、
apple.
?- apple.
ピリオドは「本当は」省略できません
でしょう。これを実習で使う B-Prolog で試してみ
よう。
通常はコマンド(ではないが)入力モード
プログラム入力モードへの切り替え
| ?- [user].
consulting....user これがプログラム
プログラム入力モードでコマンド入力
apple.
コマンド
?- apple.
Control-Z と Enter: B-Prolog の変わっている点
^Z
yes
| ?-
最も簡単なプログラム その2
次のように、user モードではプログラムの入力を
行いコマンド(より正確には、質問。意味としては
プログラムの起動)はあとで入力してもよい
| ?- [user].
consulting....user
apple.
^Z
yes
| ?- apple.
yes
| ?-
次のプログラム
| ?- [user].
consulting....user
apple.
orange.
grape.
^Z
yes
| ?- apple.
yes
| ?- orange.
yes
| ?- grape.
yes
| ?- banana.
** Error ** undefined_predicate:banana/0
| ?-
対象と関係
プログラムは、現実を計算機の中にモデルとして
表現する(モデル化)するもの
プログラム言語は、モデル化の道具。従って、標
準的なモデル化方法を提供する
Prolog は、世界は「対象(オブジェクト)」とそれら
の間になりたつ「関係(属性も含む)」とからなると
仮定する(モデル化する)
対象と関係
例えば、この世の中は、果物好きの太郎、リンゴ、みかん、
トマトからなっているとすると

like(taro, fruit).
isaFruit(apple).
isaFruit(orange).
isaVegetable(tomato).
(米国連邦最高裁1893)
計算機は言葉を知らないので、fruit と isFruit の “Fruit”
とが同じものとは思わない。そこで、

like(taro, fruit).
isa(apple, fruit).
isa(orange, fruit).
isa(tomato, vegetable).
こうした関係(like, is など)をProlog では「述語」という
で、述語を用いて書くとどうなるかというと、、、
データベースと検索
| ?- [user].
consulting....user
on(dog, donkey).
on(cat, dog).
on(rooster, cat).
^Z
yes
| ?- on(dog, X).
X = donkey?
yes
| ?- on(X, cat).
X = rooster?
yes
| ?- on(X, Y).
Y = donkey
X = dog?
yes
| ?- on(X, Y).
Y = donkey
X = dog?;
Y = dog
X = cat?;
Y = cat
X = rooster?;
no
"Photo copyright © Hyde Flippo/About.com - Used by permission"
推論規則
このデータベースは「事実」しか記載していない
Prolog のよいところは、「推論規則」が書けること
代表的な推論規則は「三段論法(syllogism)」

といっても複数個ある。因みに、三段論法とは


二つ以上の前提から結論を導き出す推論の形式
ここでは、定言三段論法(Modus Ponens)「 “ “Pならば
Q”であり、かつPである” ならばQである 」が用いられ
る。図示すれば
PQ
P
Q
推論規則の例
アルファベットの順序を定義することをかんがえよう。
a<b<c<···<y<z と言う順序である。簡単?



ord(a, b). ord(b, c). … ord(y, z) とすればよい?
ord(a, c) は?
ということは、全部で、26C2 個の定義式が必要?
推論規則の登場である。答えを言ってしまう



lt(X, Y) if and only if
ord(X, A1) and ord(A1, A2) and ··· ord(An-1, An) and ord(An, Y) と
なる A1,…,An がある
ではあるが、これは Prolog では書けない。次の方法がある(等
価である。何故か?)
lt(X,Y) if and only if
“ord(X, A) and lt(A,Y) となる A が存在するか ord(X, Y)”
Prolog では、 lt(X,Y) if ord(X, A) and lt(A,Y) に相当する
lt(X,Y) :– ord(X, A), lt(A,Y).
と lt(X,Y) if ord(X, A) に相当する
lt(X,Y) :– ord(X, Y).
推論規則の例
Prolog では、 lt(X,Y) if ord(X, A) and lt(A,Y) に
相当する
lt(X,Y) :– ord(X, A), lt(A,Y).
と lt(X,Y) if ord(X, A) に相当する
lt(X,Y) :– ord(X, Y).
をプログラムとする
では、only-if (lt(X,Y) であるための必要条件)は
どうなったか?
これは Prolog システムが(ほぼ)保証している。
試してみよう
AlphabeticalOrder.pl という
ファイルに、予め、ord(a,b)
等を入力しておく
そして右のようなことをする
と、lt( , ) があたかも、lt(a,c)
等が予め定義されていたか
のように動作する
http://www.sakurai.comp.ae.keio.ac.jp/classes/numsymbol-class/2004/AlphabeticalOrder.pl
http://www.sakurai.comp.ae.keio.ac.jp/classes/numsymbol-class/2004/NS08Programs.zip
| ?- ['AlphabeticalOrder.pl']
consulting....AlphabeticalOrder.pl
yes
| ?- [user].
consulting....user
lt(X,Y):-ord(X,Y).
lt(X,Y):-ord(X,A),lt(A,Y).
^Z
yes
| ?- lt(a,d).
yes
| ?- lt(X,d).
X = c?;
X = a?;
X = b?;
no
| ?-
例:風が吹けば桶屋が儲かる
どうも「風が吹けば箱屋が儲かる」 (世間学者気質の巻
三(明和五年、1768年))らしいので、

imply(wind, dust).
imply(dust, eyeDisease).
imply(eyeDisease, blindIncrease).
imply(blindIncrease, shamisenSalesWell).
imply(shamisenSalesWell, catSkinNeeded).
imply(catSkinNeeded, catDecrese).
imply(catDecrease, mouseIncrease).
imply(mouseIncrease, boxDamaged).
imply(boxDamaged, boxMakerProfit).
やはり、演繹推論ないと、意味をなさない

もし imply(X,Y) かつ imply(Y,Z) ならば imply(X,Z)
変数 X, Y, Z の意味・関係を規定しておくべし


XYZ ( imply(X,Y)  imply(Y,Z)  imply(X,Z) )
imply(X,Z) :– imply(X,Y), imply(Y,Z)
参考
今日の大風で土ほこりが立ちて人の目の中へ入
れば、世間にめくらが大ぶん出来る。
そこで三味線がよふうれる。そうすると猫の皮が
たんといるによって世界中の猫が大分へる。
そふなれば鼠があばれ出すによって、おのづか
ら箱の類をかぢりおる。
爰(ここ)で箱屋をしたらば大分よかりそふなもの
じゃと思案は仕だしても、是も元手がなふては埒
(らち)明ず
「風が吹けば箱屋が儲かる」 (世間学者気質の巻三(明和五年、1768年))
再帰的述語の定義の仕方
実は、下記の定義は好ましくない。
imply(X,Z) :– imply(X,Y), imply(Y,Z)
その理由は後ほど述べることとして、今は、次の
ようにすると、記憶されたし



新たな述語名を決める( resultIn としてみよう)
2個の定義を作る。すなわち
resultIn( X, Y ) :– imply( X, Y ) .
resultIn( X, Y ) :– imply( X, A ), resultIn( A, Y ) .
これ何かに似ていませんか?

数学的帰納法に似ていませんか?
これで先ほどの on と above と同じになった
例: 風が吹けば箱屋が儲かる
だけど、これでは、風が吹
けば本当に箱屋が儲かっ
てしまう。
何が悪いのか?
現実世界では、


仮言命題が常に正しいわけ
ではない
演繹が常に正しいわけでは
ない
かなり ad hoc だが、cf
(certainty factor ) を導入し
よう
| ?- ['WhenWindBlows'].
consulting....WhenWindBlows.pl
yes
| ?- resultIn(wind, X).
X = dust?;
X = eyeDisease?;
X = blindIncrease?;
X = shamisenSalesWell?;
X = catSkinNeeded?;
X = catDecrease?;
X = mouseIncrease?;
X = boxDamaged?;
X = boxMakerProfit?;
no
http://www.sakurai.comp.ae.keio.ac.jp/classes/numsymbol-class/2004/WhenWindBlows.pl
http://www.sakurai.comp.ae.keio.ac.jp/classes/numsymbol-class/2004/WhenWindBlowsCF.pl
確からしさ
次のようにプログラムを
作ると、右のような結果に
imply(wind, dust, 1.0 ).
imply(dust, eyeDisease, 0.5 ).
imply(eyeDisease, blindIncrease, 0.1 ).
imply(blindIncrease, shamisenSalesWell, 0.9 ).
imply(shamisenSalesWell, catSkinNeeded, 0.9 ).
imply(catSkinNeeded, catDecrease, 0.9 ).
imply(catDecrease, mouseIncrease, 0.9 ).
imply(mouseIncrease, boxDamaged, 0.5 ).
imply(boxDamaged, boxMakerProfit, 0.9 ).
resultIn( X, Y, CF ) :- imply( X, Y, CF ).
resultIn( X, Y, CF ) :imply( X, A, CF1 ), resultIn( A, Y, CF2 ),
CF is CF1 * CF2 * 0.9 .
| ?- ['WhenWindBlowsCF'].
consulting....WhenWindBlowsCF.pl
yes
| ?- resultIn(wind,X,CF).
CF = 1.0
X = dust?;
CF = 0.45
X = eyeDisease?;
CF = 0.0405
X = blindIncrease?;
CF = 0.032805
X = shamisenSalesWell?;
CF = 0.02657205
X = catSkinNeeded?;
CF = 0.0215233605
X = catDecrease?;
CF = 0.017433922005
X = mouseIncrease?;
CF = 0.00784526490225
X = boxDamaged?;
CF = 0.006354664570823
X = boxMakerProfit?;
no
| ?-
関係の関係
以前の例に戻ってみよう

like(taro, fruit).
isa(apple, fruit).
isa(orange, fruit).
isa(tomato, vegetable).
まだ、isa と like の関係が示されていない。それは、
「太郎は果物が好き」かつ「リンゴは果物である」ならば
「太郎はリンゴが好き」というように表現できる。すなわち、
X ( like(taro, fruit)  is(X, fruit)  like(taro, X) )
like(taro, X) :– like(taro, fruit), is(X, fruit).
これは一般化しておいた方がよかろう
like(P, X) :– like(P, F), isa(X, F).
但し、次のようにすべし
like(P, X) :– isa(X, F), like(P, F).