Zulip Chat Archive
Stream: new members
Topic: Encoding a Raymond Smullyan Logic Puzzle Proof
Mark Fischer (Mar 01 2024 at 20:34):
I found this article where the author creates a model checker for some of Smullyan's puzzles and I thought to myself that this formalization would also work via a proof in Lean.
I'm not sure if this is the best way to encode something like this. I wasn't really sure how to create a return type that didn't give away the answer beforehand (and unless you're creating a puzzle, why would you even want to?)
The setup is that everybody is either always truthful or always a liar. Furthermore brothers are always of the same inclination, so they either both tell the truth or they both lie.
Here's the puzzle:
Now, I heard a story of two brothers, Bahman and Perviz, who were once asked if they were married. They gave the following replies:
Bahman: We are both married.
Perviz: I am not married.
“Is Bahman married or not? And what about Perviz?”
and here is my proof that (married Bahman = false) ∧ (married Perviz = true)
. The thing I'm not sure about is whether ∃a b : Bool ...
is too permissive? Actually, I'm pretty sure it is. Classically, this seems just trivially true without even looking at the hypothesis in question.
Is there a better way to encode this?
import Mathlib
opaque Object : Type
def Predicate := Object → Prop
open Classical
example
(truthful married : Predicate)
(Bahman Perviz : Object)
(h1 : truthful Bahman ↔ truthful Perviz)
(h2 : truthful Bahman ↔ married Bahman ∧ married Perviz)
(h3 : truthful Perviz ↔ ¬ married Perviz)
: ∃a b : Bool, (married Bahman = a) ∧ (married Perviz = b) := by
cases Classical.em <| truthful Bahman with
| inl h =>
have mpe := (h2.mp h).right
have nmp := h3.mp <| h1.mp h
contradiction
| inr h =>
have ntp := (iff_false_left h).mp h1
have mpe := not_not.mp <| mt h3.mpr ntp
have nmor := not_and_or.mp <| (iff_false_left h).mp h2
have nmb := nmor.resolve_right (not_not.mpr mpe)
use false, true
simp only [eq_iff_iff, iff_false, iff_true]
exact ⟨nmb, mpe⟩
Mark Fischer (Mar 01 2024 at 21:10):
Maybe this is more compelling as you need to provide actual data for each claim?
example
(truthful married : Predicate)
(Bahman Perviz : Object)
(h1 : truthful Bahman ↔ truthful Perviz)
(h2 : truthful Bahman ↔ married Bahman ∧ married Perviz)
(h3 : truthful Perviz ↔ ¬ married Perviz)
: {x : Bool × Bool // married Bahman = x.1 ∧ married Perviz = x.2} := by
use (false, true)
simp only [eq_iff_iff, iff_false, iff_true]
cases Classical.em <| truthful Bahman with
| inl h =>
have mpe := (h2.mp h).right
have nmp := h3.mp <| h1.mp h
contradiction
| inr h =>
have ntp := (iff_false_left h).mp h1
have mpe := not_not.mp <| mt h3.mpr ntp
have nmor := not_and_or.mp <| (iff_false_left h).mp h2
have nmb := nmor.resolve_right (not_not.mpr mpe)
exact ⟨nmb, mpe⟩
Notification Bot (Mar 01 2024 at 22:30):
Junyan Xu has marked this topic as resolved.
Notification Bot (Mar 01 2024 at 22:30):
Junyan Xu has marked this topic as unresolved.
Last updated: May 02 2025 at 03:31 UTC