(*<*) theory Blue_Eyes imports "HOL-Combinatorics.Transposition" begin (*>*)
section‹Introduction›
text‹The original problem statement cite‹xkcd› explains the puzzle well:
begin{quotation}
group of people with assorted eye colors live on an island.
are all perfect logicians -- if a conclusion can be logically deduced,
will do it instantly.
one knows the color of their eyes.
night at midnight, a ferry stops at the island.
islanders who have figured out the color of their own eyes then leave the island, and the rest stay.
can see everyone else at all times
keeps a count of the number of people they see with each eye color (excluding themselves),
they cannot otherwise communicate.
on the island knows all the rules in this paragraph.
this island there are 100 blue-eyed people,
brown-eyed people,
the Guru (she happens to have green eyes).
any given blue-eyed person can see 100 people with brown eyes and 99 people with blue eyes (and one with green),
that does not tell him his own eye color;
far as he knows the totals could be 101 brown and 99 blue.
100 brown, 99 blue, and he could have red eyes.
Guru is allowed to speak once (let's say at noon),
one day in all their endless years on the island.
before the islanders, she says the following:
`I can see someone who has blue eyes.''
leaves the island, and on what night?
end{quotation}
might seem weird that the Guru's declaration gives anyone any new information.
an informal discussion, see cite‹‹Section~1.1› in "fagin1995"›.›
section‹Modeling the world \label{sec:world}›
text‹We begin by fixing two type variables: @{typ "'color"} and @{typ "'person"}.
puzzle doesn't specify how many eye colors are possible, but four are mentioned.
, we must assume they are distinct. We specify the existence of colors other
blue and brown, even though we don't mention them later, because when blue and brown
the only possible colors, the puzzle has a different solution --- the brown-eyed logicians
leave one day after the blue-eyed ones.
refrain from specifying the exact population of the island, choosing to only assume
is finite and denote a specific person as the Guru.
could also model the Guru as an outside entity instead of a participant. This doesn't change
answer and results in a slightly simpler proof, but is less faithful to the problem statement.›
context fixes blue brown green red :: 'color assumes colors_distinct: "distinct [blue, brown, green, red]"
fixes guru :: 'person assumes"finite (UNIV :: 'person set)" begin
text‹It's slightly tricky to formalize the behavior of perfect logicians.
representation we use is centered around the type of a @{emph ‹world›},
describes the entire state of the environment. In our case, it's a function
{typ "'person => 'color"} that assigns an eye color to everyone.@{footnote ‹We would introduce
type synonym, but at the time of writing Isabelle doesn't support including type variables fixed
a locale in a type synonym.›}
only condition known to everyone and not dependent on the observer is Guru's declaration:›
definition valid :: "('person ==> 'color) ==> bool"where "valid w ⟷ (∃p. p ≠ guru ∧ w p = blue)"
text‹We then define the function @{term "possible n p w w'"}, which returns @{term True}
on day ‹n› the potential world ‹w'› is plausible from the perspective of person‹p›,
on the observations they made in the actual world ‹w›.
, @{term "leaves n p w"} is @{term True} if ‹p› is able to unambiguously deduce
color of their own eyes, i.e. if it is the same in all possible worlds. Note that if ‹p› actually
many moons ago, this function still returns @{term True}.›
fun leaves :: "nat ==> 'person ==> ('person ==> 'color) ==> bool" and possible :: "nat ==> 'person ==> ('person ==> 'color) ==> ('person ==> 'color) ==> bool" where "leaves n p w = (∀w'. possible n p w w' ⟶ w' p = w p)" | "possible n p w w' ⟷ valid w ∧ valid w' ∧ (∀p' ≠ p. w p' = w' p') ∧ (∀n' < n. ∀p'. leaves n' p' w = leaves n' p' w')"
text‹Naturally, the act of someone leaving can be observed by others, thus the two definitions
mutually recursive. As such, we need to instruct the simplifier to not unfold these definitions endlessly.› declare possible.simps[simp del] leaves.simps[simp del]
text‹A world is possible if 🪙 The Guru's declaration holds. 🪙 The eye color of everyone but the observer matches. 🪙 The same people left on each of the previous days.
, we require that the actual world ‹w› is ‹valid›, so that the relation is symmetric:›
lemma possible_sym: "possible n p w w' = possible n p w' w" by (auto simp: possible.simps)
text‹In fact, ‹possible n p› is an equivalence relation:›
lemma possible_refl: "valid w ==> possible n p w w" by (auto simp: possible.simps)
lemma possible_trans: "possible n p w1 w2 ==> possible n p w2 w3 ==> possible n p w1 w3" by (auto simp: possible.simps)
section‹Eye colors other than blue›
text‹Since there is no way to distinguish between the colors other than blue,
the blue-eyed people will ever leave. To formalize this notion, we define
function that takes a world and replaces the eye color of a specified person.
original color is specified too, so that the transformation composes nicely
the recursive hypothetical worlds of @{const possible}.›
definition try_swap :: "'person ==> 'color ==> 'color ==> ('person ==> 'color) ==>('person ==> 'color)"where "try_swap p c1 c2 w x = (if c1 = blue ∨ c2 = blue ∨ x ≠ p then w x else transpose c1 c2 (w x))"
lemma try_swap_eq[simp]: "try_swap p c1 c2 w x = try_swap p c1 c2 w' x ⟷ w x = w' x" by (auto simp add: try_swap_def transpose_eq_iff)
lemma try_swap_inv[simp]: "try_swap p c1 c2 (try_swap p c1 c2 w) = w" by (rule ext) (auto simp add: try_swap_def swap_id_eq)
lemma leaves_try_swap[simp]: assumes"valid w" shows"leaves n p (try_swap p' c1 c2 w) = leaves n p w" using assms proof (induction n arbitrary: p w rule: less_induct) case (less n) have"leaves n p w"if"leaves n p (try_swap p' c1 c2 w)"for w proof (unfold leaves.simps; rule+) fix w' assume"possible n p w w'" thenhave"possible n p (try_swap p' c1 c2 w) (try_swap p' c1 c2 w')" by (fastforce simp: possible.simps less.IH) with‹leaves n p (try_swap p' c1 c2 w)›have"try_swap p' c1 c2 w' p = try_swap p' c1 c2 w p" unfolding leaves.simps by simp thus"w' p = w p"by simp qed
with try_swap_inv show ?caseby auto qed
text‹This lets us prove that only blue-eyed people will ever leave the island.›
proposition only_blue_eyes_leave: assumes"leaves n p w"and"valid w" shows"w p = blue" proof (rule ccontr) assume"w p ≠ blue" thenobtain c where c: "w p ≠ c""c ≠ blue" using colors_distinct by (metis distinct_length_2_or_more)
let ?w' = "try_swap p (w p) c w" have"possible n p w ?w'" using‹valid w›apply (simp add: possible.simps) by (auto simp: try_swap_def) moreoverhave"?w' p ≠ w p" using c ‹w p ≠ blue›by (auto simp: try_swap_def) ultimatelyhave"¬ leaves n p w" by (auto simp: leaves.simps) with assms show False by simp qed
section"The blue-eyed logicians"
text‹We will now consider the behavior of the logicians with blue eyes. First,
simple lemmas. Reasoning about set cardinalities often requires considering infinite
separately. Usefully, all sets of people are finite by assumption.›
lemma people_finite[simp]: "finite (S::'person set)" proof (rule finite_subset) show"S ⊆ UNIV"by auto show"finite (UNIV::'person set)"by fact qed
text‹Secondly, we prove a destruction rule for @{const possible}. It is strictly weaker than
definition, but thanks to the simpler form, it's easier to guide the automation with it.› lemma possibleD_colors: assumes"possible n p w w'"and"p' ≠ p" shows"w' p' = w p'" using assms unfolding possible.simps by simp
text‹A central concept in the reasoning is the set of blue-eyed people someone can see.› definition blues_seen :: "('person ==> 'color) ==> 'person ==> 'person set"where "blues_seen w p = {p'. w p' = blue} - {p}"
lemma blues_seen_others: assumes"w p' = blue"and"p ≠ p'" shows"w p = blue ==> card (blues_seen w p) = card (blues_seen w p')" and"w p ≠ blue ==> card (blues_seen w p) = Suc (card (blues_seen w p'))" proof - assume"w p = blue" thenhave"blues_seen w p' = blues_seen w p ∪ {p} - {p'}" by (auto simp add: blues_seen_def) moreoverhave"p ∉ blues_seen w p" unfolding blues_seen_def by auto moreoverhave"p' ∈ blues_seen w p ∪ {p}" unfolding blues_seen_def using‹p ≠ p'›‹w p' = blue›by auto ultimatelyshow"card (blues_seen w p) = card (blues_seen w p')" by simp next assume"w p ≠ blue" thenhave"blues_seen w p' = blues_seen w p - {p'}" by (auto simp add: blues_seen_def) moreoverhave"p' ∈ blues_seen w p" unfolding blues_seen_def using‹p ≠ p'›‹w p' = blue›by auto ultimatelyshow"card (blues_seen w p) = Suc (card (blues_seen w p'))" by (simp only: card_Suc_Diff1 people_finite) qed
lemma blues_seen_same[simp]: assumes"possible n p w w'" shows"blues_seen w' p = blues_seen w p" using assms by (auto simp: blues_seen_def possible.simps)
lemma possible_blues_seen: assumes"possible n p w w'" assumes"w p' = blue"and"p ≠ p'" shows"w' p = blue ==> card (blues_seen w p) = card (blues_seen w' p')" and"w' p ≠ blue ==> card (blues_seen w p) = Suc (card (blues_seen w' p'))" using possibleD_colors[OF ‹possible n p w w'›] and blues_seen_others assms by (auto simp flip: blues_seen_same)
text‹Finally, the crux of the solution. We proceed by strong induction.›
lemma blue_leaves: assumes"w p = blue"and"valid w" and guru: "w guru ≠ blue" shows"leaves n p w ⟷ n ≥ card (blues_seen w p)" using assms proof (induction n arbitrary: p w rule: less_induct) case (less n) show ?case proof
― ‹First, we show that day ‹n› is sufficient to deduce that the eyes are blue.› assume"n ≥ card (blues_seen w p)" have"w' p = blue"if"possible n p w w'"for w' proof (cases "card (blues_seen w' p)") case0 moreoverfrom‹possible n p w w'›have"valid w'" by (simp add: possible.simps) ultimatelyshow"w' p = blue" unfolding valid_def blues_seen_def by auto next case (Suc k)
― ‹We consider the behavior of somebody else, who also has blue eyes.› thenhave"blues_seen w' p ≠ {}" by auto thenobtain p' where"w' p' = blue"and"p ≠ p'" unfolding blues_seen_def by auto thenhave"w p' = blue" using possibleD_colors[OF ‹possible n p w w'›] by simp
have"p ≠ guru" using‹w p = blue›and‹w guru ≠ blue›by auto hence"w' guru ≠ blue" using‹w guru ≠ blue›and possibleD_colors[OF ‹possible n p w w'›] by simp
have"valid w'" using‹possible n p w w'›unfolding possible.simps by simp
show"w' p = blue" proof (rule ccontr) assume"w' p ≠ blue"
― ‹If our eyes weren't blue, then ‹p'› would see one blue-eyed person less than us.› with possible_blues_seen[OF ‹possible n p w w'›‹w p' = blue›‹p ≠ p'›] have *: "card (blues_seen w p) = Suc (card (blues_seen w' p'))" by simp
― ‹By induction, they would've left on day ‹k = blues_seen w' p'›.› let ?k = "card (blues_seen w' p')" have"?k < n" using‹n ≥ card (blues_seen w p)›and * by simp hence"leaves ?k p' w'" using‹valid w'›‹w' p' = blue›‹w' guru ≠ blue› by (intro less.IH[THEN iffD2]; auto)
― ‹However, we know that actually, ‹p'› didn't leave that day yet.› moreoverhave"¬ leaves ?k p' w" proof assume"leaves ?k p' w" thenhave"?k ≥ card (blues_seen w p')" using‹?k < n›‹w p' = blue›‹valid w›‹w guru ≠ blue› by (intro less.IH[THEN iffD1]; auto)
have"card (blues_seen w p) = card (blues_seen w p')" by (intro blues_seen_others; fact) with * have"?k < card (blues_seen w p')" by simp with‹?k ≥ card (blues_seen w p')›show False by simp qed moreoverhave"leaves ?k p' w' = leaves ?k p' w" using‹possible n p w w'›‹?k < n› unfolding possible.simps by simp ultimatelyshow False by simp qed qed thus"leaves n p w" unfolding leaves.simps using‹w p = blue›by simp next
― ‹Then, we show that it's not possible to deduce the eye color any earlier.›
{ assume"n < card (blues_seen w p)"
― ‹Consider a hypothetical world where ‹p› has brown eyes instead. We will prove that this
world is ‹possible›.› let ?w' = "w(p := brown)" have"?w' guru ≠ blue" using‹w guru ≠ blue›‹w p = blue› by auto have"valid ?w'" proof - from‹n < card (blues_seen w p)›have"card (blues_seen w p) ≠ 0"by auto hence"blues_seen w p ≠ {}" by auto thenobtain p' where"p' ∈ blues_seen w p" by auto hence"p ≠ p'"and"w p' = blue" by (auto simp: blues_seen_def) hence"?w' p' = blue"by auto with‹?w' guru ≠ blue›show"valid ?w'" unfolding valid_def by auto qed moreoverhave"leaves n' p' w = leaves n' p' ?w'"if"n' < n"for n' p' proof - have not_leavesI: "¬leaves n' p' w'" if"valid w'""w' guru ≠ blue"and P: "w' p' = blue ==> n' < card (blues_seen w' p')"for w' proof (cases "w' p' = blue") case True thenhave"leaves n' p' w' ⟷ n' ≥ card (blues_seen w' p')" using less.IH ‹n' < n›‹valid w'›‹w' guru ≠ blue› by simp with P[OF ‹w' p' = blue›] show"¬leaves n' p' w'"by simp next case False thenshow"¬ leaves n' p' w'" using only_blue_eyes_leave ‹valid w'›by auto qed
have"¬leaves n' p' w" proof (intro not_leavesI) assume"w p' = blue" with‹w p = blue›have"card (blues_seen w p) = card (blues_seen w p')" apply (cases "p = p'", simp) by (intro blues_seen_others; auto) with‹n' < n›and‹n < card (blues_seen w p)›show"n' < card (blues_seen w p')" by simp qed fact+
moreoverhave"¬ leaves n' p' ?w'" proof (intro not_leavesI) assume"?w' p' = blue" with colors_distinct have"p ≠ p'"and"?w' p ≠ blue"by auto hence"card (blues_seen ?w' p) = Suc (card (blues_seen ?w' p'))" using‹?w' p' = blue› by (intro blues_seen_others; auto) moreoverhave"blues_seen w p = blues_seen ?w' p" unfolding blues_seen_def by auto ultimatelyshow"n' < card (blues_seen ?w' p')" using‹n' < n›and‹n < card (blues_seen w p)› by auto qed fact+
ultimatelyshow"leaves n' p' w = leaves n' p' ?w'"by simp qed ultimatelyhave"possible n p w ?w'" using‹valid w› by (auto simp: possible.simps) moreoverhave"?w' p ≠ blue" using colors_distinct by auto ultimatelyhave"¬ leaves n p w" unfolding leaves.simps using‹w p = blue›by blast
} thenshow"leaves n p w ==> n ≥ card (blues_seen w p)" by fastforce qed qed
text‹This can be combined into a theorem that describes the behavior of the logicians based
the objective count of blue-eyed people, and not the count by a specific person. The xkcd
is the instance where ‹n = 99›.›
theorem blue_eyes: assumes"card {p. w p = blue} = Suc n"and"valid w"and"w guru ≠ blue" shows"leaves k p w ⟷ w p = blue ∧ k ≥ n" proof (cases "w p = blue") case True with assms have"card (blues_seen w p) = n" unfolding blues_seen_def by simp thenshow ?thesis using‹w p = blue›‹valid w›‹w guru ≠ blue› blue_leaves by simp next case False thenshow ?thesis using only_blue_eyes_leave ‹valid w›by auto qed
end
(*<*) end (*>*)
section‹Future work›
text‹After completing this formalization, I have been made aware of epistemic logic.
@{emph ‹possible worlds›} model in \cref{sec:world} turns out to be quite similar
the usual semantics of this logic. It might be interesting to solve this puzzle within
axiom system of epistemic logic, without explicit reasoning about possible worlds.›
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.