手順を書かずに答えを探す
Prolog(プロログ)は、事実を並べて質問すると、答えを探してくれる論理型プログラミング言語です。手順ではなく「何が成り立つか」を書くので、探し方は Prolog にまかせられます。
履修名簿から「この科目を取っている人は誰か」を探す場面を考えます。Python なら探す手順を書きます。Prolog では名簿を事実として並べ、「誰が取っているか」と質問するだけです。
このレッスンのゴール
メモ
Prolog の事実を読み、質問して、その答えを読むことができる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| 事実 | 成り立つと宣言した、1行の文 | parent(tom, ann). |
| 質問 | Prolog に答えを探させる問い | |
| アトム | 小文字で始まる、決まった名前 | tom |
| 変数 | 大文字で始まる、答えの入る場所 | X |
| 単一化 | 2つの形が同じになるよう変数を決めること |
学生が入力するセルは、このプレビューでは空白です。
事実は「成り立つこと」を1行で書く
事実は、成り立つと宣言する1行で、最後に点を打ちます。ラボの facts.pl には parent(tom, ann). のような行があります。これは「tom は ann の親である」と読みます。
tom や ann のように小文字で始まる名前をアトムと呼びます。Prolog は、書かれた事実だけを知っています。書かれていないことは知りません。
例: 事実の並び
% 例です。% から後ろはコメントです。
parent(tom, ann).
parent(tom, ben).
parent(ann, cat).
colour(red).
colour(green).ラボの端末で事実を読む
この次のコマンドは、ラボの端末に打ちこむ1行です。docker exec prolog は、prolog の容器の中でコマンドを動かします。ファイルの中のコメントと、Prolog が出す文字は、すべて英語です。
ファイルを書きかえていなければ、facts.pl には parent が5行、colour が3行あります。
facts.pl を表示する
docker exec prolog cat facts.plここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
質問は事実と照らし合わせて答える
質問を出すと、Prolog は事実を上から順に調べます。質問と同じ事実が見つかれば成功、見つからなければ失敗です。
次の2つは「tom は ann の親か」「ann は dan の親か」を質問します。-> と ; で、成功なら yes、失敗なら no と書かせています。-g は動かす質問、-t halt は終わったら止める指定です。
成り立つ質問
docker exec prolog swipl -q -g "(parent(tom, ann) -> writeln(yes) ; writeln(no))" -t halt facts.plここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
成り立たない質問
docker exec prolog swipl -q -g "(parent(ann, dan) -> writeln(yes) ; writeln(no))" -t halt facts.plここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
「no と出たら、現実でもちがう」と考える人が多くいます。no は「書いた事実から確かめられない」という意味です。事実を1行足せば、同じ質問が yes になることがあります。
大文字の変数で「誰?」と聞く
質問に変数を入れると、Prolog が当てはまる答えを探します。変数は大文字で始めます。たとえば parent(tom, X) は「tom の子の X は誰か」です。
Prolog は事実を上から順に試し、形が合うものを見つけると X を決めます。これが単一化です。答えは、事実が書かれた順に出ます。
例: parent(tom, X) の探し方
| 試す事実 | 形は合うか | X の値 |
|---|---|---|
| parent(tom, ann) | 合う | ann |
| parent(tom, ben) | 合う | ben |
| parent(ann, cat) | 合わない(ann は tom と別) | 決まらない |
| parent(ben, dan) | 合わない | 決まらない |
学生が入力するセルは、このプレビューでは空白です。
ben の子を全部出す
docker exec prolog swipl -q -g "forall(parent(ben, X), writeln(X))" -t halt facts.plここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
親子の組を全部出す
docker exec prolog swipl -q -g "forall(parent(X, Y), (write(X-Y), nl))" -t halt facts.plここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。