Zulip Chat Archive
Stream: new members
Topic: help with relations in a logic puzzle
Lucas Bazante (Jun 01 2024 at 15:37):
I'm formalizing a logic puzzle described in Leanprover 3 - A Logic Puzzle for a lecture. The book is from Lean 3, but I'm using Lean 4. I've already solved it (at least i think i did), but i think the code is very messy.
I've defined an inductive type for the persons in the puzzle, and propositions/relations about them. This part of the code looks like this
inductive Person : Type where
| Alice
| Husband
| Brother
| Son
| Daughter
deriving Repr
open Person
-- relations
def inBar : Person -> Prop := λ_ => True
def inBeach : Person -> Prop := λ_ => True
def isAlone : Person -> Prop := λ_ => True
def isVictim : Person -> Prop := λ_ => True
def isKiller : Person -> Prop := λ_ => True
def hasTwin : Person → Prop := λ_ => True
def isOlder : Person → Person → Prop := λ_ _ => True
I've done it so it works with the rest of my code, and it works as it should, i can use them as long as i have a proof of them.
But I'm really new to Lean, and this looks very odd to me. Is there a better way of defining a proposition like this?
Luigi Massacci (Jun 01 2024 at 19:26):
Well you could move the Person
term to the left of the colon, but that seems reasonable
Luigi Massacci (Jun 01 2024 at 19:27):
and presumably you have some kind of match
statement in the body of the definitions
Lucas Bazante (Jun 02 2024 at 11:48):
OK! After this topic, i've changed the def
s for axiom
s, so i don't have to define a body for a predicate/relation that really doesn't have one. I hope it isn't weird and hacky still.
Mark Fischer (Jun 03 2024 at 15:42):
I think this is a great place for opaque
. The compiler will create a term that inhabits the type (from the Inhabited
type class) if it can, but you don't have access to the proof term. This acts a bit like Axiom, but there's no risk that you've introduced an inconsistency.
-- relations
opaque inBar : Person -> Prop
opaque inBeach : Person -> Prop
opaque isAlone : Person -> Prop
opaque isVictim : Person -> Prop
opaque isKiller : Person -> Prop
opaque hasTwin : Person → Prop
opaque isOlder : Person → Person → Prop
I'd be interested too see the rest of formalization :)
Mark Fischer (Jun 03 2024 at 19:06):
This is my natural language style interpretation of the puzzle, I'm not sure if it's correct. Feels like this might not be the best approach.
The idea was to get each h1 through h6 to read more or less directly like the puzzle clues. e1 through e18 are meant to be facts about the world that the puzzle author might reasonably grant the solver.
Seems like you really need to lean on the fact that there are exactly 5 roles, which is one role per person. I dunno, I gave it a quick try but it felt a bit tedious as it seemed like quite often the only way to solve certain goals was to list every possibility and eliminate all but one. I'm sure that there are tactics I'm not too familiar with that would help it along.
inductive Person : Type where
| Alice
| Husband
| Brother
| Son
| Daughter
open Person
opaque man : Person → Prop
opaque woman : Person → Prop
opaque inBar : Person → Prop
opaque victim : Person → Prop
opaque killer : Person → Prop
opaque atBeach : Person → Prop
opaque alone : Person → Prop
opaque together : Person → Person → Prop
opaque twin : Person → Person → Prop
opaque younger : Person → Person → Prop
theorem summers
-- Some extralogical assumptions
-- -- man/woman
(e₁ : ∀x, woman x ∨ man x)
(e₂ : woman x ↔ ¬man x)
(e₃ : woman Alice)
(e₄ : man Husband)
(e₅ : man Brother)
(e₆ : man Son)
(e₇ : woman Daughter)
-- -- age
(e₈ : younger Son Alice)
(e₉: younger Son Husband)
(e₁₀: younger Daughter Alice)
(e₁₁: younger Daughter Husband)
-- -- twins
(e₁₂: ∀x y, younger x y → ¬twin x y)
-- -- location
(e₁₃: ∀x y, alone x → ¬together x y)
(e₁₄: ∀x, inBar x ∨ atBeach x ∨ alone x)
(e₁₅: ∀x y, inBar x ∧ inBar y → together x y)
(e₁₆: ∀x y, atBeach x ∧ atBeach y → together x y)
-- -- murder
(e₁₇: ∃!x, killer x)
(e₁₈: ∃!x, victim x)
-- Translated Clues
(h₁ : ∃x y, man x ∧ woman y ∧ inBar x ∧ inBar y)
(h₂ : ∀x y, killer x ∧ victim y → together x y ∧ atBeach x ∧ atBeach y)
(h₃ : alone Son ∨ alone Daughter)
(h₄ : ¬together Alice Husband )
(h₅ : ∀x y, twin x y ∧ victim x → ¬killer y)
(h₆ : ∀x y, killer x ∧ victim y → younger y x)
: victim Brother ∧ killer Husband := sorry
I'm not really sure what the best way to say something like "2/5 people are in the bar, 2/5 people are at the beach, and the last person is alone." It's a very easy step informally, but I'm not sure how to translate that idea in a way that cashes out later in the poof.
Ah well! :)
Andrew Yang (Jun 03 2024 at 20:49):
Here is my implementation (and I have a proof to make sure this formalization is correct)
I do not like the fact that
- I cannot logically conclude that Alice is a woman. (edit: not assumed)
-
I cannot logically conclude that the two kids are younger than the husband
(fun fact: My paternal grandmother is younger than some of my paternal grandfather's sons;
but maybe "their" means "Alice and Husband's" and not just Alice's and "their son" means "their biological son", which solves 1 and 2) -
The worst one of all: (5) actually means "The victim has a twin among the four other people who is not the killer" (and that the only permissible pair of twins are (Alice, Brother) and (Son, Daughter))
All these make me feel that this is more of a riddle than a logical puzzle. Or maybe I'm just not familiar enough with logical puzzles to know the hidden assumptions.
inductive Person : Type where
| Alice
| Husband
| Brother
| Son
| Daughter
deriving Inhabited
open Person
inductive Location : Type where
| Bar
| Beach
| SomewhereElse
deriving Inhabited
opaque Person.location : Person → Location
def Together (x y : Person) : Prop :=
x.location = .Bar ∧ y.location = .Bar ∨ x.location = .Beach ∨ x.location = .Beach
inductive Gender : Type where
| Male
| Female
| Unknown
deriving Inhabited
opaque Person.gender : Person → Gender
inductive mightBeTwins : Person → Person → Prop where
| aliceBrother : mightBeTwins Alice Brother
| brotherAlice : mightBeTwins Brother Alice
| sonDaughter : mightBeTwins Son Daughter
| daughterSon : mightBeTwins Daughter Son
opaque younger : Person → Person → Prop
opaque isTwin : Person → Person → Prop
def summers
(killer : Person)
(victim : Person)
(h₀ : killer ≠ victim)
(h₁ : ∀ p₁ p₂, younger p₁ p₂ → ¬ younger p₂ p₁)
(h₃ : ∀ p₁ p₂, isTwin p₁ p₂ → mightBeTwins p₁ p₂)
(h₅ : younger Son Husband) -- Maybe?
(h₇ : younger Daughter Husband) -- Maybe?
-- Gender Clues
(gH : Husband.gender = .Male)
(gS : Son.gender = .Male)
(gD : Daughter.gender = .Female)
(gB : Brother.gender = .Male)
-- Translated Clues
(H₁ : ∃ x y : Person, x.gender = .Male ∧ y.gender = .Female ∧ x.location = .Bar ∧ y.location = .Bar)
(H₂ : killer.location = .Beach ∧ victim.location = .Beach)
(H₃ : (∀ x, Together x Son → x = Son) ∨ (∀ x, Together x Daughter → x = Daughter))
(H₄ : ¬ Together Alice Husband)
(H₅ : ∃ x, isTwin victim x ∧ killer ≠ x)
(H₆ : younger killer victim) :
victim = Brother := by sorry
Mark Fischer (Jun 03 2024 at 21:11):
Yeah, I can see how including inductive types for Location and Gender makes sense. Though this means that nobody is alone at the beach as a matter of definition which doesn't seem right. The fact that people are together at the beach emerges from the clues.
I also think mightBeTwins
should be derived from information about their ages (as per your second point).
Yeah, choosing how to formalize such puzzles isn't always easy. There's often room for ambiguity since the Author of the puzzle just used plain English. I think that assuming Alice is female makes sense in context, especially since assuming otherwise forces the daughter to be at the bar, which forces the son to be alone, and causes a contradiction.
This definitely has many improvements over what I did :)
Andrew Yang (Jun 03 2024 at 21:18):
Though this means that nobody is alone at the beach as a matter of definition which doesn't seem right.
I think renaming Alone
to AloneAndNotAtTheBeachNorAtTheBar
solves this.
Andrew Yang (Jun 03 2024 at 21:23):
No. H₃
need some tweaks in that case.
Andrew Yang (Jun 03 2024 at 21:40):
Okay I improved it a bit (edited the code above)
Last updated: May 02 2025 at 03:31 UTC