bookshelf/exercises/theorem-proving-in-lean/exercises-3.lean

160 lines
4.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/- Exercises 3
-
- 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