2008-02-04 [長年日記]
λ. Alloyで知識論理を使って論理パズルを解く
bonotakeさんの日記で時々取り上げられているAlloy、パズルを解くのに便利とのことなので、ちょっと週末に遊んでみた。 対象とするのは、以前にSPASSで知識の論理を使って論理パズルを解く?でも取りあげた「赤いぼうし」の問題で、これは以下のような問題。
AさんとBさんがいて、少なくとも一人は赤い帽子を被っていて、赤い帽子を被っていない人は白い帽子を被っている。ただし、二人とも他人の帽子の色は分かるが、自分の被っている帽子の色は分からない。そして、Aさんが「自分の帽子の色が分からない」と発言した。このとき、Bさんの被っている帽子の色は何か? そして、Bさんは自分の被っている帽子の色が分かるか?
この前提となる状況をAlloyでは以下のようにモデル化することが出来る。
-- 世界
sig W {
K_a: set W, -- 「Aさんが知っている」という様相の到達可能性関係
K_b: set W, -- 「Bさんが知っている」という様相の到達可能性関係
}
-- 命題: 世界の集合を外延として持つ。
abstract sig Prop { ext: set W }
-- Aさんが赤い帽子を被っているという命題
one sig A_wears_a_redhat extends Prop { }
-- Bさんが赤い帽子を被っているという命題
one sig B_wears_a_redhat extends Prop { }
-- 公理
fact {
-- K_aは同値関係(K_aはS5様相)
all w1 : W | all w2 : W {
(w2 in w1.*K_a or w1 in w2.K_a) implies w2 in w1.K_a
}
-- K_bは同値関係(K_bはS5様相)
all w1 : W | all w2 : W {
(w2 in w1.*K_b or w1 in w2.K_b) implies w2 in w1.K_b
}
all w : W {
-- どちらかの帽子は赤である
(w in A_wears_a_redhat.ext or w in B_wears_a_redhat.ext)
-- AさんはBさんの帽子の色を知っている
(all w1 : w.K_a | w1 in B_wears_a_redhat.ext) or
(all w1 : w.K_a | not (w1 in B_wears_a_redhat.ext))
-- BさんはAさんの帽子の色を知っている
(all w1 : w.K_b | w1 in A_wears_a_redhat.ext) or
(all w1 : w.K_b | not (w1 in A_wears_a_redhat.ext))
-- Aさんは自分の帽子の色が分からない
not (all w1 : w.K_a | w1 in A_wears_a_redhat.ext)
not (all w1 : w.K_a | not (w1 in A_wears_a_redhat.ext))
}
-- 世界は一つ以上存在
#W > 0
}
で、まずモデルが存在すること(無矛盾であること)を Alloy Analyzer でチェックする。
pred show() { }
run show for 10 W
これを実行すると以下のような結果とモデルが得られる。
Executing "Run show for 10 W" Solver=sat4j Bitwidth=4 MaxSeq=4 Symmetry=20 11845 vars. 230 primary vars. 21671 clauses. 133ms. Instance found. Predicate is consistent. 29ms.
B_wears_a_redhatが成り立っている世界があるので、Bさんの帽子がちゃんと決まるとしたら、それは赤の帽子。 なので、assertとcheckを使って反例がないかをチェックする。
assert test1 {
all w : W | w in B_wears_a_redhat.ext
}
check test1 for 10
Executing "Check test1 for 10"
Solver=sat4j Bitwidth=4 MaxSeq=7 Symmetry=20
11935 vars. 240 primary vars. 21825 clauses. 150ms.
No counterexample found. Assertion may be valid. 19ms.
結果、反例は見つからなかった。 もちろん、より大きなモデルに反例がある可能性はあるけど、まあこの場合には多分大丈夫だろう。
次に、Bさんが「自分は赤い帽子を被っている」ことを知っているかもチェック。
assert test2 {
all w : W | all w1 : w.K_b | w1 in B_wears_a_redhat.ext
}
check test2 for 10
Executing "Check test2 for 10"
Solver=sat4j Bitwidth=4 MaxSeq=7 Symmetry=20
12123 vars. 250 primary vars. 22166 clauses. 133ms.
No counterexample found. Assertion may be valid. 30ms.
やはり反例は見つからない。
というわけで、どうやらBさんの被っているのは赤い帽子で、しかもBさんもそのことを知っているようです。
参考
λ. 最終発表会打ち上げ
萩野・服部研の最終発表会後の打ち上げに参加。 OB比率高いよ……
[ツッコミを入れる]
![[得られたモデル]](./images/s20080204_0.jpg)
![[某所の冬景色]](./images/s20080204_1.jpg)
