1.この記事で使用する論理記号
・→ 含む(A→B、A⊃B)
・⇔ 同値(A≡B、A⇔Bは、AとBがともに真、又は偽のときのみ真)
・¬ 否定(!、~)
・⋀ 論理積(&、・)
・⋁ 論理和(+)
・∀ 全ての、任意の(全称量化)
・∃ 存在する(存在量化)
・∃! 唯一存在量化(ただ1つ存在する)
・:= 定義(x := y は、x を yの別名として定義)
2.述語論理
命題論理では命題が真か偽かについてのみ考え、命題が表している対象については考えない。命題論理は最小単位である「要素命題」(真偽が問える最小の文)から成る。
「全ての人間は死ぬ」は要素命題(”全ての人間”と”死ぬ”を分けると真偽が問えない)である。
そこで次の推論を考える
(前提)全ての人間は死ぬ
(前提)ソクラテスは人間である
(結論)ソクラテスは死ぬ
この推論を命題論理で表現すると、
p:=「全ての人間は死ぬ」
q:=「ソクラテスは人間である」
r:=「ソクラテスは死ぬ」
p,q→r
となり、要素命題を記号化したことでrはp,qに無関係な記号となり、この推論式では真偽はわからない。
そこで、命題論理の拡張である述語論理を使って、要素命題を「もの」の性質やそれらの関係を表わすように拡張する。
ここで、
ソクラテス:固有名(個体定項)を記号化する(小文字a)
人間 :不特定の個体(個体変項)を記号化する(小文字x)
述語:個体の性質や関係を表わす表現を述語と呼び、大文字の記号で表わす。
「全ての人間は死ぬ」では「~は死ぬ」が述語となり、
Q(x):=「~は死ぬ」で表わす。
「ソクラテスは人間である」では「~は人間である」が述語となり、
P(x):=「~は人間である」で表わす。
述語論理では、個体変項に「すべて」や「ある」といった量を与えることを「量化する」といい、∀(全称記号で「すべての~」)と∃(存在記号で「ある~」)を使う。
従って、前記の命題論理を述語論理で表わすと、
P(ソクラテス):=「ソクラテスは人間である」
∀x(P(x)→Q(x)):=「全て人間について、人間は死ぬ」
Q(ソクラテス):=「ソクラテスは死ぬ」
となる。
3.述語論理のPrologプログラム
3.1 Prologとは
記号処理を目的につくられた非数値計算用プログラミング言語で、一階述語論理(述語論理の中でも固体の量化のみを許すもの)プログラムは複数の節と呼ばれる構造からなる。プログラムの流れは、事実や規則の集合に対して質問をし、その質問にあてはまるものを Prolog が自動で返すように動作する。
また、Prologは論理型プログラミング言語で、1982年の第五世代コンピュータ計画では述語論理を基礎にした自動推論を高速実行する並列推論マシンの開発の目標が掲げられ、並行論理プログラムの土台としてPrologが採用され10年の歳月をPrologと並行論理の研究に費やしたが一般市場での応用には至らなかったとのこと。現在では、Prolog は各教育機関で主に論理学の教材として利用されている。
Prologのプログラムは次の3つの要素から成る。
①事実: 事物とその関係についていくつかの事実を宣言すること。
述語(対象 1, 対象 2,···, 対象 n)
「”対象 1”,”対象 2”,···,”対象 n” は”述語”である」を表わす
規則: 事物とその関係についての規則を定義すること。
②帰結 :- 条件
「”条件”を満たす場合,”帰結”は正しい」という規則を表わす
P ⇒ Q(P ならばQ)という推論規則は,Q : −P と記述する
③質問: 事物とその関係について質問すること。
3.2 Prologのインストール
・動作環境
Ubuntuバージョン
$ cat /etc/os-release
VERSION=”16.04.7 LTS (Xenial Xerus)”
・swi-Prologのインストール
$ sudo apt install swi-prolog
3.3 サンプルプログラム
(例1)事実と規則を宣言
P(ソクラテス):=「ソクラテスは人間である」
∀x(P(x)→Q(x)):=「全て人間について、人間は死ぬ」
Q(ソクラテス):=「ソクラテスは死ぬ」
Prolog 処理系では,アルファベット大文字で始まる語は変数として扱われる。
test.pl
1 2 |
human(socrates). mortal(A) :- human(A). |
1 2 3 4 5 6 7 8 9 10 11 12 |
~/Prolog$ swipl test.pl Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.2.3) Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. Please visit http://www.swi-prolog.org for details. For help, use ?- help(Topic). or ?- apropos(Word). ?- mortal(socrates). true. |
(例2)事実を宣言
likes.pl
1 2 3 |
likes(taro,hanako). likes(taro,flower). likes(jiro,hanako). |
1 2 3 4 |
$ swipl likes.pl ?- likes(taro,X). X = hanako ; X = flower. |
(例2)再帰処理
nの階乗を求める
n!=n・(n−1)・(n−2)・・・2・1
0!=1
fact.pl
1 2 3 4 5 6 |
fact(0, 1). fact(N, F) :- N > 0, N1 is N - 1, fact(N1, F1), F is N * F1. |
1 2 3 4 |
$ swipl fact.pl ?- fact(3,X). X = 6 . |
・プログラムの終了
?- halt.
・トレースモード
?- trace. トレース開始
creep 1ステップずつ実行
skip 現在実行中の呼び出しのサブゴールに関する情報の表示をスキップ
help コマンドのヘルプを表示
abort トレースを途中で中止し、プロンプト
・トレースモードの停止
[trace] ?- nodebug.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
?- trace. [trace] ?- fact(3,X). Call: (7) fact(3, _G1123) ? creep Call: (8) 3>0 ? creep Exit: (8) 3>0 ? creep Call: (8) _G1201 is 3+ -1 ? creep Exit: (8) 2 is 3+ -1 ? creep Call: (8) fact(2, _G1202) ? creep Call: (9) 2>0 ? creep Exit: (9) 2>0 ? creep Call: (9) _G1204 is 2+ -1 ? creep Exit: (9) 1 is 2+ -1 ? creep Call: (9) fact(1, _G1205) ? creep Call: (10) 1>0 ? creep Exit: (10) 1>0 ? creep Call: (10) _G1207 is 1+ -1 ? creep Exit: (10) 0 is 1+ -1 ? creep Call: (10) fact(0, _G1208) ? creep Exit: (10) fact(0, 1) ? creep Call: (10) _G1210 is 1*1 ? creep Exit: (10) 1 is 1*1 ? creep Exit: (9) fact(1, 1) ? creep Call: (9) _G1213 is 2*1 ? creep Exit: (9) 2 is 2*1 ? creep Exit: (8) fact(2, 2) ? creep Call: (8) _G1123 is 3*2 ? creep Exit: (8) 6 is 3*2 ? creep Exit: (7) fact(3, 6) ? creep X = 6 [trace] ?- nodebug. ?- |
The end