/- # References 1. Avigad, Jeremy. ‘Theorem Proving in Lean’, n.d. -/ -- Exercise 1 -- -- Prove the following identities, replacing the "sorry" placeholders with -- actual proofs. namespace ex1 open or variable (p q r : Prop) -- Commutativity of ∧ and ∨ example : p ∧ q ↔ q ∧ p := Iff.intro (fun ⟨hp, hq⟩ => show q ∧ p from ⟨hq, hp⟩) (fun ⟨hq, hp⟩ => show p ∧ q from ⟨hp, hq⟩) example : p ∨ q ↔ q ∨ p := Iff.intro (fun h => h.elim Or.inr Or.inl) (fun h => h.elim Or.inr Or.inl) -- Associativity of ∧ and ∨ example : (p ∧ q) ∧ r ↔ p ∧ (q ∧ r) := Iff.intro (fun ⟨⟨hp, hq⟩, hr⟩ => ⟨hp, hq, hr⟩) (fun ⟨hp, hq, hr⟩ => ⟨⟨hp, hq⟩, hr⟩) example : (p ∨ q) ∨ r ↔ p ∨ (q ∨ r) := Iff.intro (fun h₁ => h₁.elim (fun h₂ => h₂.elim Or.inl (Or.inr ∘ Or.inl)) (Or.inr ∘ Or.inr)) (fun h₁ => h₁.elim (Or.inl ∘ Or.inl) (fun h₂ => h₂.elim (Or.inl ∘ Or.inr) Or.inr)) -- Distributivity example : p ∧ (q ∨ r) ↔ (p ∧ q) ∨ (p ∧ r) := Iff.intro (fun ⟨hp, hqr⟩ => hqr.elim (Or.inl ⟨hp, ·⟩) (Or.inr ⟨hp, ·⟩)) (fun h₁ => h₁.elim (fun ⟨hp, hq⟩ => ⟨hp, Or.inl hq⟩) (fun ⟨hp, hr⟩ => ⟨hp, Or.inr hr⟩)) example : p ∨ (q ∧ r) ↔ (p ∨ q) ∧ (p ∨ r) := Iff.intro (fun h => h.elim (fun hp => ⟨Or.inl hp, Or.inl hp⟩) (fun ⟨hq, hr⟩ => ⟨Or.inr hq, Or.inr hr⟩)) (fun ⟨h₁, h₂⟩ => h₁.elim Or.inl (fun hq => h₂.elim Or.inl (fun hr => Or.inr ⟨hq, hr⟩))) -- Other properties example : (p → (q → r)) ↔ (p ∧ q → r) := Iff.intro (fun h ⟨hp, hq⟩ => h hp hq) (fun h hp hq => h ⟨hp, hq⟩) example : ((p ∨ q) → r) ↔ (p → r) ∧ (q → r) := Iff.intro (fun h => have h₁ : p → r := h ∘ Or.inl have h₂ : q → r := h ∘ Or.inr show (p → r) ∧ (q → r) from ⟨h₁, h₂⟩) (fun ⟨h₁, h₂⟩ h => h.elim h₁ h₂) example : ¬(p ∨ q) ↔ ¬p ∧ ¬q := Iff.intro (fun h => ⟨h ∘ Or.inl, h ∘ Or.inr⟩) (fun h₁ h₂ => h₂.elim (absurd · h₁.left) (absurd · h₁.right)) example : ¬p ∨ ¬q → ¬(p ∧ q) := fun h₁ h₂ => h₁.elim (absurd h₂.left ·) (absurd h₂.right ·) example : ¬(p ∧ ¬p) := fun h => absurd h.left h.right example : p ∧ ¬q → ¬(p → q) := fun ⟨hp, nq⟩ hpq => absurd (hpq hp) nq example : ¬p → (p → q) := fun np hp => absurd hp np example : (¬p ∨ q) → (p → q) := fun npq hp => npq.elim (absurd hp ·) id example : p ∨ False ↔ p := Iff.intro (fun hpf => hpf.elim id False.elim) Or.inl example : p ∧ False ↔ False := Iff.intro (fun ⟨_, hf⟩ => hf) False.elim example : (p → q) → (¬q → ¬p) := fun hpq nq hp => absurd (hpq hp) nq end ex1 -- Example 2 -- -- Prove the following identities, replacing the “sorry” placeholders with -- actual proofs. These require classical reasoning. namespace ex2 open Classical variable (p q r s : Prop) example (hp : p) : (p → r ∨ s) → ((p → r) ∨ (p → s)) := fun h => (h hp).elim (fun hr => Or.inl (fun _ => hr)) (fun hs => Or.inr (fun _ => hs)) example : ¬(p ∧ q) → ¬p ∨ ¬q := fun npq => (em p).elim (fun hp => (em q).elim (fun hq => False.elim (npq ⟨hp, hq⟩)) Or.inr) Or.inl example : ¬(p → q) → p ∧ ¬q := fun h => have lhs : p := byContradiction fun np => h (fun (hp : p) => absurd hp np) ⟨lhs, fun hq => h (fun _ => hq)⟩ example : (p → q) → (¬p ∨ q) := fun hpq => (em p).elim (fun hp => Or.inr (hpq hp)) Or.inl example : (¬q → ¬p) → (p → q) := fun h hp => byContradiction fun nq => absurd hp (h nq) example : p ∨ ¬p := em p example : (((p → q) → p) → p) := fun h => byContradiction fun np => suffices hp : p from absurd hp np h (fun (hp : p) => absurd hp np) end ex2 -- Example 3 -- -- Prove `¬(p ↔ ¬p)` without using classical logic. namespace ex3 variable (p : Prop) example (hp : p) : ¬(p ↔ ¬p) := fun h => absurd hp (Iff.mp h hp) end ex3