第3章 簡単な推理パズル 1.推理パズルの例題 本章では次の推理パズルを例題として取り上げる。 明、勇、正、洋の4人がある色の商品を買った。 商品は、傘、靴、紙、糸の4つであり、 その色は、赤、青、白、黒の4つである。 各人の買った商品はすべて異なり、 色もすべて異なる。 さらに次のことがわかっている。 (イ) 明は白いのを買ったが糸じゃない。 (ロ) 青い紙を買った人がいるが、勇じゃない。 (ハ) 正は靴を買ったが赤じゃない。 彼らはそれぞれ何色の何を買ったのか。 2.定式化 明の買った商品を *x とする。 青い紙を買った人を *t とする。 正が買った靴の色を *c とする。 残りの人を*s 、その人が買った商品を *y、色を *d とする。 すると、人、商品、色の組が4つできる。 (明 *x 白) (*t 紙 青) (正 靴 *c) (*s *y *d) これらの変数に対して次の制約が要請されている。 (a) (b) (c) (d) (e) (f) (g) (h) (i) *t と *s は人である。 *x と *y は商品である。 *c と *d は色である。 明、*t、正、*s はすべて異なる。 *x、紙、靴、*y はすべて異なる。 白、青、*c、*d はすべて異なる。 *x は糸ではない。 *t は勇ではない。 *c は赤ではない。 これらを記述するための述語を次のように決める。 (suiri *t *s *x *y *c *d) .... *t...*d は問題の解である (human *a) ............................ *a は人である (goods *a) .............................. *a は商品である (color *a) ............................... *a は色である (alldif *p *q *r *s) ................ *p *q *r *sはすべて異なる (ne *a *b) ............................... *aと*bは異なる すると、(a),(b),(c) は、それぞれ、 (human *t), (human *s), (goods *x), (goods *y), (color *c), (color *d), と書ける。また、(d),(e),(f) は、 (alldif 明 *t 正 *s), (alldif *x 紙 靴 *y), (alldif 白 青 *c *d), となる。最後に、(g),(h),(i) は、 (ne *x 糸), (ne *t 勇), (ne *c 赤), と書ける。 3.ルール 与えられた問題を変換するルールは、 (suiri *t *s *x *y *c *d) ==> (human *t), (human *s), (goods *x), (goods *y), (color *c), (color *d), (alldif 明 *t 正 *s), (alldif *x 紙 靴 *y), (alldif 白 青 *c *d), (ne *x 糸), (ne *t 勇), (ne *c 赤). と書ける。 4.単純なプログラム ここでは最も単純にプログラムをつくる方法を考える。 まず、人、品、色はそれぞれ4つの可能性があるので、 (human *a) ==> (= *a ==> ==> ==> 明); (= *a 勇); (= *a 正); (= *a 洋). (goods *a) ==> (= *a 傘); ==> (= *a 靴); ==> (= *a 紙); ==> (= *a 糸). (color *a) ==> (= *a 赤); ==> (= *a 青); ==> (= *a 白); ==> (= *a 黒). と処理すればよい。もちろん、 (= *x *y) ==> {(= *x *y)}. を準備しておくものとする。また alldifは、ne に還元すればよい。 (alldif *a *b *c *d) ==> (ne *a *b),(ne *a *c),(ne *a *d), (ne *b *c),(ne *b *d),(ne *c *d). 最後に neは、 (ne *a *b), {(symbol *a),(symbol *b)} ==> {(not (= *a *b))}. となる。これから得られるプログラムを実行すれば、 [D]>(suiri *t *s *x *y *c *d) -------------------------N execution -----------------------------------------------------------------------------(ans (suiri 洋 勇 傘 糸 黒 赤))<-. を得る。すなわち答えは、 *t = 洋、*s = 勇、*x = 傘、*y = 糸、*c = 黒、*d = 赤 である。明が白い傘を、洋が青い紙を、正が黒い靴を、そして勇が赤い糸を買ったことになる。 5.優先度の宣言 Nルールは、ルールのヘッドと条件部で表された適用条件が満たされると、節に適用することができる。 節のボディに複数のアトムがあり、それらのアトムの幾つかに、適用できるNルールが複数個ありうる。 したがって、計算の各時点で、その複数個のNルールの中のどれが実際に適用されるかによって、計算 (節の変換の列)はいくとおりもありうる。Nルールのプログラムはそのような計算の多様性を許してい るのである。このようなプログラムを非決定性プログラムという。 非決定性プログラムのメリットの1つは、 (1) 計算の可能性に対する不必要な限定を避けることにより、限定を表現するコストを回避する ことである。本質的でない限定をコストをかけて表現するのは好ましくないからである。 これはやや消極的な理由と言えるが、もっと積極的な理由は、 (2) 可能な計算をできるだけたくさん表現することによって、メリットを得るためである。 たとえば、 (a) 計算の自由度をコンパイラに提供することにより、より大きな最適化を追求できる。 (b) 設計変更やさらなる高速化のためのプログラムの変更がやり易い。 などのメリットが考えられる。 このようなメリットのために、一般には、非決定性を多い状態にプログラムを保つことが重要である。し かし、著しい速度低下を起こす計算の自由度が含まれてはならないので、非決定性を制御する宣言が準備 されている。 たとえば、この本章のプログラムにおいて、= アトムを処理するために、 (= *x *y) ==> {(= *x *y)}. が使われているが、計算過程で計算対象である節のボディに = アトムが生み出されても、非決定性のた めに、その = アトムがすぐさま処理されるわけではない。場合によっては、 (= 赤 白) のように、偽のアトムが生み出されたままで取り残され、他のアトムへの処理が進むこともある。これは 計算効率の低下を招く可能性がある。もし (= 赤 白) を先に処理すれば当該節は消滅するので、他のア トムへの処理はまったく無駄だからである。 これを回避する1つの方法は、ルールに優先度を付与することである。もし (= *x *y) ==> {(= *x *y)}. に高い優先度を与え、そのルールが使えるときには、他のルールを使わないことにすれば、上のような事 態は避けられる。 たとえば、= を処理するルールに eq というラベルをつける。 eq (= *x *y) ==> {(= *x *y)}. そして、 ?-(RuleClassOrder 1 2), (RuleClass eq 1), (RuleClass otherwise 2). という宣言をプログラムの先頭に書く。この宣言は、eqラベルのついたルールを優先度1で、その他の ルールを優先度2で適用することを意味する。 優先度の宣言を行い、本章のプログラムで計算時間にどの程度の短縮が見られるか調べなさい。 これによる計算時間の短縮効果は、問題が大きくなれば顕著になるだろう。 6.実行部の導入 前節では、優先度を宣言して、偽の = アトムの即時処理を達成した。しかし実はこれは最善の方法とは 言えない。実際にはもっと適切なやり方がある。それは、すべてのNルールのボディに出現する = アトム を実行部に移動することである。 たとえば、 (color *a) ==> (= *a 赤); ==> (= *a 青); ==> (= *a 白); ==> (= *a 黒). のルールを (color *a) ==> {(= *a ==> {(= ==> {(= ==> {(= 赤)}; *a 青)}; *a 白)}; *a 黒)}. に変えてしまうのである。そうすれば、= の実行はそのルール内で済んでしまうので、 eq (= *x *y) ==> {(= *x *y)}. は必要なくなり、優先度の設定も必要ない。(ただしプログラムを変える手間がかかる。) 7.秋の果物 次の推理問題をETを使って解きなさい。 「秋の果物」と題する次の問題をETを使って解いて下さい。 梨枝、桃子、杏子、美果、有果の5人が、それぞれ異なる果物を持っています。 それらの果物は、ナシ、モモ、アンズ、ビワ、レモンの5種類です。 それらを5人の間でいろいろ交換し合ったところ、 結局最初に持っていたものを交換後にも持っている人が1人だけいます。 また、交換後にも、誰もが1つだけ果物を持っています。 これに関して次の情報があります。 (1) (2) (3) (4) (5) (6) 梨枝は初めナシを持っていて、交換後にレモンを持っています。 杏子が持っていた果物は、交換後には梨枝が持っています。 交換後に美果がもっているものは、ナシでもビワでもありません。 交換後に杏子が持っているものは、桃子か自分自身が持っていたものです。 交換後に桃子が持っているのは、ビワではありません。 美果が初め持っていたものは、モモではありません。 5人はいったい、交換前と交換後に何を持っていたでしょう? 8.出典 本章の1節のパスルは、ニコリのホームページの例題です。 8節の「秋の果物」はロジックパラダイス11月増刊「パズルとクイズの本Vol.10」学習研究社 (1996.11) から採りました。
© Copyright 2024 Paperzz