Add documentation throughout modules.

finite-set-exercises
Joshua Potter 2023-05-04 16:37:54 -06:00
parent cab7aa82a3
commit 4b32563cee
28 changed files with 754 additions and 718 deletions

View File

@ -1,5 +1,20 @@
/-! # Bookshelf.Combinator.Aviary
A collection of combinator birds representable in Lean. Certain duplicators,
e.g. mockingbirds, are not directly expressible since they would require
encoding a signature in which an argument has types `α` *and* `αα`.
Duplicators that are included, e.g. the warbler, are not exactly correct
considering they still have the same limitation described above during actual
use. Their inclusion here serves more as pseudo-documentation than anything.
[^1]: Smullyan, Raymond M. To Mock a Mockingbird: And Other Logic Puzzles
Including an Amazing Adventure in Combinatory Logic. Oxford: Oxford
university press, 2000.
-/
/-- /--
Bald Eagle #### Bald Eagle
`E'xy₁y₂y₃z₁z₂z₃ = x(y₁y₂y₃)(z₁z₂z₃)` `E'xy₁y₂y₃z₁z₂z₃ = x(y₁y₂y₃)(z₁z₂z₃)`
-/ -/
@ -8,35 +23,35 @@ def E' (x : α → β → γ)
(z₁ : ζ → η → β) (z₂ : ζ) (z₃ : η) := x (y₁ y₂ y₃) (z₁ z₂ z₃) (z₁ : ζ → η → β) (z₂ : ζ) (z₃ : η) := x (y₁ y₂ y₃) (z₁ z₂ z₃)
/-- /--
Becard #### Becard
`B₃xyzw = x(y(zw))` `B₃xyzw = x(y(zw))`
-/ -/
def B₃ (x : α → ε) (y : β → α) (z : γ → β) (w : γ) := x (y (z w)) def B₃ (x : α → ε) (y : β → α) (z : γ → β) (w : γ) := x (y (z w))
/-- /--
Blackbird #### Blackbird
`B₁xyzw = x(yzw)` `B₁xyzw = x(yzw)`
-/ -/
def B₁ (x : α → ε) (y : β → γα) (z : β) (w : γ) := x (y z w) def B₁ (x : α → ε) (y : β → γα) (z : β) (w : γ) := x (y z w)
/-- /--
Bluebird #### Bluebird
`Bxyz = x(yz)` `Bxyz = x(yz)`
-/ -/
def B (x : αγ) (y : β → α) (z : β) := x (y z) def B (x : αγ) (y : β → α) (z : β) := x (y z)
/-- /--
Bunting #### Bunting
`B₂xyzwv = x(yzwv)` `B₂xyzwv = x(yzwv)`
-/ -/
def B₂ (x : α → ζ) (y : β → γ → ε → α) (z : β) (w : γ) (v : ε) := x (y z w v) def B₂ (x : α → ζ) (y : β → γ → ε → α) (z : β) (w : γ) (v : ε) := x (y z w v)
/-- /--
Cardinal Once Removed #### Cardinal Once Removed
`C*xyzw = xywz` `C*xyzw = xywz`
-/ -/
@ -45,49 +60,49 @@ def C_star (x : α → β → γ → δ) (y : α) (z : γ) (w : β) := x y w z
notation "C*" => C_star notation "C*" => C_star
/-- /--
Cardinal #### Cardinal
`Cxyz = xzy` `Cxyz = xzy`
-/ -/
def C (x : α → β → δ) (y : β) (z : α) := x z y def C (x : α → β → δ) (y : β) (z : α) := x z y
/-- /--
Converse Warbler #### Converse Warbler
`W'xy = yxx` `W'xy = yxx`
-/ -/
def W' (x : α) (y : αα → β) := y x x def W' (x : α) (y : αα → β) := y x x
/-- /--
Dickcissel #### Dickcissel
`D₁xyzwv = xyz(wv)` `D₁xyzwv = xyz(wv)`
-/ -/
def D₁ (x : α → β → δ → ε) (y : α) (z : β) (w : γ → δ) (v : γ) := x y z (w v) def D₁ (x : α → β → δ → ε) (y : α) (z : β) (w : γ → δ) (v : γ) := x y z (w v)
/-- /--
Dove #### Dove
`Dxyzw = xy(zw)` `Dxyzw = xy(zw)`
-/ -/
def D (x : αγ → δ) (y : α) (z : β → γ) (w : β) := x y (z w) def D (x : αγ → δ) (y : α) (z : β → γ) (w : β) := x y (z w)
/-- /--
Dovekie #### Dovekie
`D₂xyzwv = x(yz)(wv)` `D₂xyzwv = x(yz)(wv)`
-/ -/
def D₂ (x : α → δ → ε) (y : β → α) (z : β) (w : γ → δ) (v : γ) := x (y z) (w v) def D₂ (x : α → δ → ε) (y : β → α) (z : β) (w : γ → δ) (v : γ) := x (y z) (w v)
/-- /--
Eagle #### Eagle
`Exyzwv = xy(zwv)` `Exyzwv = xy(zwv)`
-/ -/
def E (x : α → δ → ε) (y : α) (z : β → γ → δ) (w : β) (v : γ) := x y (z w v) def E (x : α → δ → ε) (y : α) (z : β → γ → δ) (w : β) (v : γ) := x y (z w v)
/-- /--
Finch Once Removed #### Finch Once Removed
`F*xyzw = xwzy` `F*xyzw = xwzy`
-/ -/
@ -96,98 +111,98 @@ def F_star (x : α → β → γ → δ) (y : γ) (z : β) (w : α) := x w z y
notation "F*" => F_star notation "F*" => F_star
/-- /--
Finch #### Finch
`Fxyz = zyx` `Fxyz = zyx`
-/ -/
def F (x : α) (y : β) (z : β → αγ) := z y x def F (x : α) (y : β) (z : β → αγ) := z y x
/-- /--
Goldfinch #### Goldfinch
`Gxyzw = xw(yz)` `Gxyzw = xw(yz)`
-/ -/
def G (x : αγ → δ) (y : β → γ) (z : β) (w : α) := x w (y z) def G (x : αγ → δ) (y : β → γ) (z : β) (w : α) := x w (y z)
/-- /--
Hummingbird #### Hummingbird
`Hxyz = xyzy` `Hxyz = xyzy`
-/ -/
def H (x : α → β → αγ) (y : α) (z : β) := x y z y def H (x : α → β → αγ) (y : α) (z : β) := x y z y
/-- /--
Identity Bird #### Identity Bird
`Ix = x` `Ix = x`
-/ -/
def I (x : α) : α := x def I (x : α) : α := x
/-- /--
Kestrel #### Kestrel
`Kxy = x` `Kxy = x`
-/ -/
def K (x : α) (_ : β) := x def K (x : α) (_ : β) := x
/-- /--
Owl #### Owl
`Oxy = y(xy)` `Oxy = y(xy)`
-/ -/
def O (x : (α → β) → α) (y : α → β) := y (x y) def O (x : (α → β) → α) (y : α → β) := y (x y)
/-- /--
Phoenix #### Phoenix
`Φxyzw = x(yw)(zw)` `Φxyzw = x(yw)(zw)`
-/ -/
def Φ (x : β → γ → δ) (y : α → β) (z : αγ) (w : α) := x (y w) (z w) def Φ (x : β → γ → δ) (y : α → β) (z : αγ) (w : α) := x (y w) (z w)
/-- /--
Psi Bird #### Psi Bird
`Ψxyzw = x(yz)(yw)` `Ψxyzw = x(yz)(yw)`
-/ -/
def Ψ (x : ααγ) (y : β → α) (z : β) (w : β) := x (y z) (y w) def Ψ (x : ααγ) (y : β → α) (z : β) (w : β) := x (y z) (y w)
/-- /--
Quacky Bird #### Quacky Bird
`Q₄xyz = z(yx)` `Q₄xyz = z(yx)`
-/ -/
def Q₄ (x : α) (y : α → β) (z : β → γ) := z (y x) def Q₄ (x : α) (y : α → β) (z : β → γ) := z (y x)
/-- /--
Queer Bird #### Queer Bird
`Qxyz = y(xz)` `Qxyz = y(xz)`
-/ -/
def Q (x : α → β) (y : β → γ) (z : α) := y (x z) def Q (x : α → β) (y : β → γ) (z : α) := y (x z)
/-- /--
Quirky Bird #### Quirky Bird
`Q₃xyz = z(xy)` `Q₃xyz = z(xy)`
-/ -/
def Q₃ (x : α → β) (y : α) (z : β → γ) := z (x y) def Q₃ (x : α → β) (y : α) (z : β → γ) := z (x y)
/-- /--
Quixotic Bird #### Quixotic Bird
`Q₁xyz = x(zy)` `Q₁xyz = x(zy)`
-/ -/
def Q₁ (x : αγ) (y : β) (z : β → α) := x (z y) def Q₁ (x : αγ) (y : β) (z : β → α) := x (z y)
/-- /--
Quizzical Bird #### Quizzical Bird
`Q₂xyz = y(zx)` `Q₂xyz = y(zx)`
-/ -/
def Q₂ (x : α) (y : β → γ) (z : α → β) := y (z x) def Q₂ (x : α) (y : β → γ) (z : α → β) := y (z x)
/-- /--
Robin Once Removed #### Robin Once Removed
`R*xyzw = xzwy` `R*xyzw = xzwy`
-/ -/
@ -196,35 +211,35 @@ def R_star (x : α → β → γ → δ) (y : γ) (z : α) (w : β) := x z w y
notation "R*" => R_star notation "R*" => R_star
/-- /--
Robin #### Robin
`Rxyz = yzx` `Rxyz = yzx`
-/ -/
def R (x : α) (y : β → αγ) (z : β) := y z x def R (x : α) (y : β → αγ) (z : β) := y z x
/-- /--
Sage Bird #### Sage Bird
`Θx = x(Θx)` `Θx = x(Θx)`
-/ -/
partial def Θ [Inhabited α] (x : αα) := x (Θ x) partial def Θ [Inhabited α] (x : αα) := x (Θ x)
/-- /--
Starling #### Starling
`Sxyz = xz(yz)` `Sxyz = xz(yz)`
-/ -/
def S (x : α → β → γ) (y : α → β) (z : α) := x z (y z) def S (x : α → β → γ) (y : α → β) (z : α) := x z (y z)
/-- /--
Thrush #### Thrush
`Txy = yx` `Txy = yx`
-/ -/
def T (x : α) (y : α → β) := y x def T (x : α) (y : α → β) := y x
/-- /--
Vireo Once Removed #### Vireo Once Removed
`V*xyzw = xwyz` `V*xyzw = xwyz`
-/ -/
@ -233,14 +248,14 @@ def V_star (x : α → β → γ → δ) (y : β) (z : γ) (w : α) := x w y z
notation "V*" => V_star notation "V*" => V_star
/-- /--
Vireo #### Vireo
`Vxyz = zxy` `Vxyz = zxy`
-/ -/
def V (x : α) (y : β) (z : α → β → γ) := z x y def V (x : α) (y : β) (z : α → β → γ) := z x y
/-- /--
Warbler #### Warbler
`Wxy = xyy` `Wxy = xyy`
-/ -/

View File

@ -1,21 +1,34 @@
import Mathlib.Tactic.Ring import Mathlib.Tactic.Ring
/-! # Bookshelf.LTuple.Basic
The following is a representation of a (possibly empty) left-biased tuple. A
left-biased `n`-tuple is defined recursively as follows:
```
⟨x₁, ..., xₙ⟩ = ⟨⟨x₁, ..., xₙ₋₁⟩, xₙ⟩
```
Note a `Tuple` exists in Lean already. This implementation differs in two
notable ways:
1. It is left-associative. The built-in `Tuple` instance evaluates e.g.
`(x₁, x₂, x₃)` as `(x₁, (x₂, x₃))` instead of `((x₁, x₂), x₃)`.
2. Internally, the built-in `Tuple` instance is syntactic sugar for nested
`Prod` instances. Unlike this implementation, an `LTuple` is a homogeneous
collection.
In general, prefer using `Prod` over `LTuple`. This exists primarily to solve
certain theorems outlined in [^1].
[^1]: Enderton, Herbert B. A Mathematical Introduction to Logic. 2nd ed. San
Diego: Harcourt/Academic Press, 2001.
-/
/-- /--
A representation of a possibly empty left-biased tuple. `n`-tuples are defined #### LTuple
recursively as follows:
`⟨x₁, ..., xₙ⟩ = ⟨⟨x₁, ..., xₙ₋₁⟩, xₙ⟩` A left-biased, possibly empty, homogeneous `Tuple`-like structure..
Keep in mind a tuple in Lean already exists but it differs in two ways:
1. It is right associative. That is, `(x₁, x₂, x₃)` evaluates to
`(x₁, (x₂, x₃))` instead of `((x₁, x₂), x₃)`.
2. Internally a tuple is syntactic sugar for nested `Prod` instances. Inputs
types of `Prod` are not required to be the same meaning non-homogeneous
collections are allowed.
In general, prefer using `Prod` over this `Tuple` definition. This exists solely
for proving theorems outlined in Enderton's book.
-/ -/
inductive LTuple : (α : Type u) → (size : Nat) → Type u where inductive LTuple : (α : Type u) → (size : Nat) → Type u where
| nil : LTuple α 0 | nil : LTuple α 0
@ -23,9 +36,7 @@ inductive LTuple : (α : Type u) → (size : Nat) → Type u where
namespace LTuple namespace LTuple
-- ======================================== /-! ## Coercions -/
-- Coercions
-- ========================================
scoped instance : CoeOut (LTuple α (min (m + n) m)) (LTuple α m) where scoped instance : CoeOut (LTuple α (min (m + n) m)) (LTuple α m) where
coe := cast (by simp) coe := cast (by simp)
@ -48,17 +59,19 @@ scoped instance : Coe (LTuple α (min m n + 1)) (LTuple α (min (m + 1) (n + 1))
scoped instance : Coe (LTuple α m) (LTuple α (min (m + n) m)) where scoped instance : Coe (LTuple α m) (LTuple α (min (m + n) m)) where
coe := cast (by simp) coe := cast (by simp)
-- ======================================== /-! ### Equality -/
-- Equality
-- ========================================
theorem eq_nil : @LTuple.nil α = nil := rfl
/--
Two values `a` and `b` are equal **iff** `[a] = [b]`.
-/
theorem eq_iff_singleton : (a = b) ↔ (snoc a nil = snoc b nil) := by theorem eq_iff_singleton : (a = b) ↔ (snoc a nil = snoc b nil) := by
apply Iff.intro apply Iff.intro
· intro h; rw [h] · intro h; rw [h]
· intro h; injection h · intro h; injection h
/--
Two lists are equal **iff** their heads and tails are equal.
-/
theorem eq_iff_snoc {t₁ t₂ : LTuple α n} theorem eq_iff_snoc {t₁ t₂ : LTuple α n}
: (a = b ∧ t₁ = t₂) ↔ (snoc t₁ a = snoc t₂ b) := by : (a = b ∧ t₁ = t₂) ↔ (snoc t₁ a = snoc t₂ b) := by
apply Iff.intro apply Iff.intro
@ -74,7 +87,7 @@ equality.
protected def hasDecEq [DecidableEq α] (t₁ t₂ : LTuple α n) protected def hasDecEq [DecidableEq α] (t₁ t₂ : LTuple α n)
: Decidable (Eq t₁ t₂) := : Decidable (Eq t₁ t₂) :=
match t₁, t₂ with match t₁, t₂ with
| nil, nil => isTrue eq_nil | nil, nil => isTrue rfl
| snoc as a, snoc bs b => | snoc as a, snoc bs b =>
match LTuple.hasDecEq as bs with match LTuple.hasDecEq as bs with
| isFalse np => isFalse (fun h => absurd (eq_iff_snoc.mpr h).right np) | isFalse np => isFalse (fun h => absurd (eq_iff_snoc.mpr h).right np)
@ -86,47 +99,43 @@ protected def hasDecEq [DecidableEq α] (t₁ t₂ : LTuple α n)
instance [DecidableEq α] : DecidableEq (LTuple α n) := LTuple.hasDecEq instance [DecidableEq α] : DecidableEq (LTuple α n) := LTuple.hasDecEq
-- ======================================== /-! ## Basic API -/
-- Basic API
-- ========================================
/-- /--
Returns the number of entries of the `Tuple`. Returns the number of entries in an `LTuple`.
-/ -/
def size (_ : LTuple α n) : Nat := n def size (_ : LTuple α n) : Nat := n
/-- /--
Returns all but the last entry of the `Tuple`. Returns all but the last entry of an `LTuple`.
-/ -/
def init : (t : LTuple α (n + 1)) → LTuple α n def init : (t : LTuple α (n + 1)) → LTuple α n
| snoc vs _ => vs | snoc vs _ => vs
/-- /--
Returns the last entry of the `Tuple`. Returns the last entry of an `LTuple`.
-/ -/
def last : LTuple α (n + 1) → α def last : LTuple α (n + 1) → α
| snoc _ v => v | snoc _ v => v
/-- /--
Prepends an entry to the start of the `Tuple`. Prepends an entry to an `LTuple`.
-/ -/
def cons : LTuple α n → α → LTuple α (n + 1) def cons : LTuple α n → α → LTuple α (n + 1)
| nil, a => snoc nil a | nil, a => snoc nil a
| snoc ts t, a => snoc (cons ts a) t | snoc ts t, a => snoc (cons ts a) t
-- ======================================== /-! ## Concatenation -/
-- Concatenation
-- ========================================
/-- /--
Join two `Tuple`s together end to end. Joins two `LTuple`s together end to end.
-/ -/
def concat : LTuple α m → LTuple α n → LTuple α (m + n) def concat : LTuple α m → LTuple α n → LTuple α (m + n)
| is, nil => is | is, nil => is
| is, snoc ts t => snoc (concat is ts) t | is, snoc ts t => snoc (concat is ts) t
/-- /--
Concatenating a `Tuple` with `nil` yields the original `Tuple`. Concatenating an `LTuple` with `nil` yields the original `LTuple`.
-/ -/
theorem self_concat_nil_eq_self (t : LTuple α m) : concat t nil = t := theorem self_concat_nil_eq_self (t : LTuple α m) : concat t nil = t :=
match t with match t with
@ -134,7 +143,7 @@ theorem self_concat_nil_eq_self (t : LTuple α m) : concat t nil = t :=
| snoc _ _ => rfl | snoc _ _ => rfl
/-- /--
Concatenating `nil` with a `Tuple` yields the `Tuple`. Concatenating `nil` with an `LTuple` yields the original `LTuple`.
-/ -/
theorem nil_concat_self_eq_self (t : LTuple α m) : concat nil t = t := by theorem nil_concat_self_eq_self (t : LTuple α m) : concat nil t = t := by
induction t with induction t with
@ -158,15 +167,16 @@ theorem nil_concat_self_eq_self (t : LTuple α m) : concat nil t = t := by
h₁ h₁
/-- /--
Concatenating a `Tuple` to a nonempty `Tuple` moves `concat` calls closer to Concatenating an `LTuple` to a nonempty `LTuple` moves `concat` calls closer to
expression leaves. the expression leaves.
-/ -/
theorem concat_snoc_snoc_concat {bs : LTuple α n} theorem concat_snoc_snoc_concat {bs : LTuple α n}
: concat as (snoc bs b) = snoc (concat as bs) b := : concat as (snoc bs b) = snoc (concat as bs) b :=
rfl rfl
/-- /--
`snoc` is equivalent to concatenating the `init` and `last` element together. `snoc` is equivalent to concatenating the `init` and `last` elements of an
`LTuple` together.
-/ -/
theorem snoc_eq_init_concat_last (as : LTuple α m) theorem snoc_eq_init_concat_last (as : LTuple α m)
: snoc as a = concat as (snoc nil a) := by : snoc as a = concat as (snoc nil a) := by
@ -174,13 +184,11 @@ theorem snoc_eq_init_concat_last (as : LTuple α m)
| nil => rfl | nil => rfl
| snoc _ _ => simp; unfold concat concat; rfl | snoc _ _ => simp; unfold concat concat; rfl
-- ======================================== /-! ## Initial Sequences -/
-- Initial sequences
-- ========================================
/-- /--
Take the first `k` entries from the `Tuple` to form a new `Tuple`, or the entire Takes the first `k` entries from an `LTuple` to form a new `LTuple`, or the
`Tuple` if `k` exceeds the number of entries. entire `LTuple` if `k` exceeds the size.
-/ -/
def take (t : LTuple α n) (k : Nat) : LTuple α (min n k) := def take (t : LTuple α n) (k : Nat) : LTuple α (min n k) :=
if h : n ≤ k then if h : n ≤ k then
@ -196,7 +204,7 @@ def take (t : LTuple α n) (k : Nat) : LTuple α (min n k) :=
rw [min_eq_right h', min_eq_right (Nat.le_trans h' (Nat.le_succ m))] rw [min_eq_right h', min_eq_right (Nat.le_trans h' (Nat.le_succ m))]
/-- /--
Taking no entries from any `Tuple` should yield an empty one. Taking no entries from any `LTuple` should yield an empty `LTuple`.
-/ -/
theorem self_take_zero_eq_nil (t : LTuple α n) : take t 0 = @nil α := by theorem self_take_zero_eq_nil (t : LTuple α n) : take t 0 = @nil α := by
induction t with induction t with
@ -204,13 +212,14 @@ theorem self_take_zero_eq_nil (t : LTuple α n) : take t 0 = @nil α := by
| snoc as a ih => unfold take; simp; rw [ih]; simp | snoc as a ih => unfold take; simp; rw [ih]; simp
/-- /--
Taking any number of entries from an empty `Tuple` should yield an empty one. Taking any number of entries from an empty `LTuple` should yield an empty
`LTuple`.
-/ -/
theorem nil_take_zero_eq_nil (k : Nat) : (take (@nil α) k) = @nil α := by theorem nil_take_zero_eq_nil (k : Nat) : (take (@nil α) k) = @nil α := by
cases k <;> (unfold take; simp) cases k <;> (unfold take; simp)
/-- /--
Taking `n` entries from a `Tuple` of size `n` should yield the same `Tuple`. Taking `n` entries from an `LTuple` of size `n` should yield the same `LTuple`.
-/ -/
theorem self_take_size_eq_self (t : LTuple α n) : take t n = t := by theorem self_take_size_eq_self (t : LTuple α n) : take t n = t := by
cases t with cases t with
@ -218,8 +227,8 @@ theorem self_take_size_eq_self (t : LTuple α n) : take t n = t := by
| snoc as a => unfold take; simp | snoc as a => unfold take; simp
/-- /--
Taking all but the last entry of a `Tuple` is the same result, regardless of the Taking `n - 1` elements from an `LTuple` of size `n` yields the same result,
value of the last entry. regardless of the last entry's value.
-/ -/
theorem take_subst_last {as : LTuple α n} (a₁ a₂ : α) theorem take_subst_last {as : LTuple α n} (a₁ a₂ : α)
: take (snoc as a₁) n = take (snoc as a₂) n := by : take (snoc as a₁) n = take (snoc as a₂) n := by
@ -227,7 +236,8 @@ theorem take_subst_last {as : LTuple α n} (a₁ a₂ : α)
simp simp
/-- /--
Taking `n` elements from a tuple of size `n + 1` is the same as invoking `init`. Taking `n` elements from an `LTuple` of size `n + 1` is the same as invoking
`init`.
-/ -/
theorem init_eq_take_pred (t : LTuple α (n + 1)) : take t n = init t := by theorem init_eq_take_pred (t : LTuple α (n + 1)) : take t n = init t := by
cases t with cases t with
@ -238,8 +248,8 @@ theorem init_eq_take_pred (t : LTuple α (n + 1)) : take t n = init t := by
simp simp
/-- /--
If two `Tuple`s are equal, then any initial sequences of those two `Tuple`s are If two `LTuple`s are equal, then any initial sequences of these two `LTuple`s
also equal. are also equal.
-/ -/
theorem eq_tuple_eq_take {t₁ t₂ : LTuple α n} theorem eq_tuple_eq_take {t₁ t₂ : LTuple α n}
: (t₁ = t₂) → (t₁.take k = t₂.take k) := by : (t₁ = t₂) → (t₁.take k = t₂.take k) := by
@ -247,8 +257,8 @@ theorem eq_tuple_eq_take {t₁ t₂ : LTuple α n}
rw [h] rw [h]
/-- /--
Given a `Tuple` of size `k`, concatenating an arbitrary `Tuple` and taking `k` Given an `LTuple` of size `k`, concatenating an arbitrary `LTuple` and taking
elements yields the original `Tuple`. `k` elements yields the original `LTuple`.
-/ -/
theorem eq_take_concat {t₁ : LTuple α m} {t₂ : LTuple α n} theorem eq_take_concat {t₁ : LTuple α m} {t₂ : LTuple α n}
: take (concat t₁ t₂) m = t₁ := by : take (concat t₁ t₂) m = t₁ := by
@ -264,4 +274,4 @@ theorem eq_take_concat {t₁ : LTuple α m} {t₂ : LTuple α n}
rw [ih] rw [ih]
simp simp
end LTuple end LTuple

View File

@ -1,27 +1,28 @@
import Mathlib.Data.Fintype.Basic import Mathlib.Data.Fintype.Basic
import Mathlib.Tactic.NormNum import Mathlib.Tactic.NormNum
/-! # Bookshelf.List.Basic
Additional theorems and definitions useful in the context of `List`s.
-/
namespace List namespace List
-- ======================================== /-! ## Indexing -/
-- Indexing
-- ========================================
/-- /--
Getting an element `i` from a list is equivalent to `get`ting an element `i + 1` Getting the `(i + 1)`st entry of a `List` is equivalent to getting the `i`th
from that list as a tail. entry of the `List`'s tail.
-/ -/
theorem get_cons_succ_self_eq_get_tail_self theorem get_cons_succ_self_eq_get_tail_self
: get (x :: xs) (Fin.succ i) = get xs i := by : get (x :: xs) (Fin.succ i) = get xs i := by
conv => lhs; unfold get; simp only conv => lhs; unfold get; simp only
-- ======================================== /-! ### Length -/
-- Length
-- ========================================
/-- /--
A list is nonempty if and only if it can be written as a head concatenated with A `List` is nonempty **iff** it can be written as some head concatenated with
a tail. some tail.
-/ -/
theorem self_neq_nil_imp_exists_mem : xs ≠ [] ↔ (∃ a as, xs = a :: as) := by theorem self_neq_nil_imp_exists_mem : xs ≠ [] ↔ (∃ a as, xs = a :: as) := by
apply Iff.intro apply Iff.intro
@ -34,7 +35,7 @@ theorem self_neq_nil_imp_exists_mem : xs ≠ [] ↔ (∃ a as, xs = a :: as) :=
simp simp
/-- /--
Only the empty list has length zero. A `List` is empty **iff** it has length zero.
-/ -/
theorem eq_nil_iff_length_zero : xs = [] ↔ length xs = 0 := by theorem eq_nil_iff_length_zero : xs = [] ↔ length xs = 0 := by
apply Iff.intro apply Iff.intro
@ -47,7 +48,7 @@ theorem eq_nil_iff_length_zero : xs = [] ↔ length xs = 0 := by
| cons a as => simp at h | cons a as => simp at h
/-- /--
If the length of a list is greater than zero, it cannot be `List.nil`. A `List` is nonempty **iff** it has length greater than zero.
-/ -/
theorem neq_nil_iff_length_gt_zero : xs ≠ [] ↔ xs.length > 0 := by theorem neq_nil_iff_length_gt_zero : xs ≠ [] ↔ xs.length > 0 := by
have : ¬xs = [] ↔ ¬length xs = 0 := Iff.not eq_nil_iff_length_zero have : ¬xs = [] ↔ ¬length xs = 0 := Iff.not eq_nil_iff_length_zero
@ -57,12 +58,10 @@ theorem neq_nil_iff_length_gt_zero : xs ≠ [] ↔ xs.length > 0 := by
← zero_lt_iff ← zero_lt_iff
] at this ] at this
-- ======================================== /-! ### Membership -/
-- Membership
-- ========================================
/-- /--
If there exists a member of a list, the list must be nonempty. There exists a member of a `List` **iff** the `List` is nonempty.
-/ -/
theorem exists_mem_iff_neq_nil : (∃ x, x ∈ xs) ↔ xs ≠ [] := by theorem exists_mem_iff_neq_nil : (∃ x, x ∈ xs) ↔ xs ≠ [] := by
apply Iff.intro apply Iff.intro
@ -74,18 +73,18 @@ theorem exists_mem_iff_neq_nil : (∃ x, x ∈ xs) ↔ xs ≠ [] := by
| cons a as => exact ⟨a, by simp⟩ | cons a as => exact ⟨a, by simp⟩
/-- /--
Any value that can be retrieved via `get` must be a member of the list argument. If `i` is a valid index of `List` `xs`, then `xs[i]` is a member of `xs`.
-/ -/
theorem get_mem_self {xs : List α} {i : Fin xs.length} : get xs i ∈ xs := by theorem get_mem_self {xs : List α} {i : Fin xs.length} : get xs i ∈ xs := by
induction xs with induction xs with
| nil => have ⟨_, hj⟩ := i; simp at hj | nil => have ⟨_, hj⟩ := i; simp at hj
| cons a as ih => | cons a as ih =>
by_cases hk : i = ⟨0, by simp⟩ by_cases hk : i = ⟨0, by simp⟩
· -- If `i = 0`, we are `get`ting the head of our list. This element is · -- If `i = 0`, we are `get`ting the head of our list. This entry is
-- trivially a member of `xs`. -- trivially a member of `xs`.
conv => lhs; unfold get; rw [hk]; simp only conv => lhs; unfold get; rw [hk]; simp only
simp simp
· -- Otherwise we are `get`ting an element in the tail. Our induction · -- Otherwise we are `get`ting an entry in the tail. Our induction
-- hypothesis closes this case. -- hypothesis closes this case.
have ⟨k', hk'⟩ : ∃ k', i = Fin.succ k' := by have ⟨k', hk'⟩ : ∃ k', i = Fin.succ k' := by
have ni : ↑i ≠ (0 : ) := fun hi => hk (Fin.ext hi) have ni : ↑i ≠ (0 : ) := fun hi => hk (Fin.ext hi)
@ -98,8 +97,8 @@ theorem get_mem_self {xs : List α} {i : Fin xs.length} : get xs i ∈ xs := by
exact mem_append_of_mem_right [a] ih exact mem_append_of_mem_right [a] ih
/-- /--
`x` is a member of list `xs` if and only if there exists some index of `xs` that A value `x` is a member of `List` `xs` **iff** there exists some index `i` such
`x` corresponds to. that `x = xs[i]`.
-/ -/
theorem mem_iff_exists_get {xs : List α} theorem mem_iff_exists_get {xs : List α}
: x ∈ xs ↔ ∃ i : Fin xs.length, xs.get i = x := by : x ∈ xs ↔ ∃ i : Fin xs.length, xs.get i = x := by
@ -117,12 +116,10 @@ theorem mem_iff_exists_get {xs : List α}
| nil => have nh := i.2; simp at nh | nil => have nh := i.2; simp at nh
| cons a bs => rw [← hi]; exact get_mem_self | cons a bs => rw [← hi]; exact get_mem_self
-- ======================================== /-! ## Sublists -/
-- Sublists
-- ========================================
/-- /--
Given nonempty list `xs`, `head` is equivalent to `get`ting the `0`th index. The first entry of a nonempty `List` has index `0`.
-/ -/
theorem head_eq_get_zero {xs : List α} (h : xs ≠ []) theorem head_eq_get_zero {xs : List α} (h : xs ≠ [])
: head xs h = get xs ⟨0, neq_nil_iff_length_gt_zero.mp h⟩ := by : head xs h = get xs ⟨0, neq_nil_iff_length_gt_zero.mp h⟩ := by
@ -131,8 +128,7 @@ theorem head_eq_get_zero {xs : List α} (h : xs ≠ [])
simp simp
/-- /--
Given nonempty list `xs`, `getLast xs` is equivalent to `get`ting the The last entry of a nonempty `List` has index `1` less than its length.
`length - 1`th index.
-/ -/
theorem getLast_eq_get_length_sub_one {xs : List α} (h : xs ≠ []) theorem getLast_eq_get_length_sub_one {xs : List α} (h : xs ≠ [])
: getLast xs h = get xs ⟨xs.length - 1, by : getLast xs h = get xs ⟨xs.length - 1, by
@ -155,12 +151,11 @@ theorem some_tail?_imp_cons (h : tail? xs = some ys) : ∃ x, xs = x :: ys := by
| nil => simp at h | nil => simp at h
| cons r rs => exact ⟨r, by simp at h; rw [h]⟩ | cons r rs => exact ⟨r, by simp at h; rw [h]⟩
-- ======================================== /-! ### Zips -/
-- Zips
-- ========================================
/-- /--
The length of a list zipped with its tail is the length of the tail. The length of a zip consisting of a `List` and its tail is the length of the
`List`'s tail.
-/ -/
theorem length_zipWith_self_tail_eq_length_sub_one theorem length_zipWith_self_tail_eq_length_sub_one
: length (zipWith f (a :: as) as) = length as := by : length (zipWith f (a :: as) as) = length as := by
@ -170,7 +165,7 @@ theorem length_zipWith_self_tail_eq_length_sub_one
simp only [le_add_iff_nonneg_right] simp only [le_add_iff_nonneg_right]
/-- /--
The result of a `zipWith` is nonempty if and only if both arguments are The output `List` of a `zipWith` is nonempty **iff** both of its inputs are
nonempty. nonempty.
-/ -/
theorem zipWith_nonempty_iff_args_nonempty theorem zipWith_nonempty_iff_args_nonempty
@ -190,7 +185,7 @@ theorem zipWith_nonempty_iff_args_nonempty
simp simp
/-- /--
An index less than the length of a `zip` is less than the length of the left An index less than the length of a `zipWith` is less than the length of the left
operand. operand.
-/ -/
theorem fin_zipWith_imp_val_lt_length_left {i : Fin (zipWith f xs ys).length} theorem fin_zipWith_imp_val_lt_length_left {i : Fin (zipWith f xs ys).length}
@ -200,7 +195,7 @@ theorem fin_zipWith_imp_val_lt_length_left {i : Fin (zipWith f xs ys).length}
exact hi.left exact hi.left
/-- /--
An index less than the length of a `zip` is less than the length of the left An index less than the length of a `zipWith` is less than the length of the left
operand. operand.
-/ -/
theorem fin_zipWith_imp_val_lt_length_right {i : Fin (zipWith f xs ys).length} theorem fin_zipWith_imp_val_lt_length_right {i : Fin (zipWith f xs ys).length}
@ -209,13 +204,11 @@ theorem fin_zipWith_imp_val_lt_length_right {i : Fin (zipWith f xs ys).length}
simp only [length_zipWith, ge_iff_le, lt_min_iff] at hi simp only [length_zipWith, ge_iff_le, lt_min_iff] at hi
exact hi.right exact hi.right
-- ======================================== /-! ### Pairwise -/
-- Pairwise
-- ========================================
/-- /--
Given a list `xs` of length `k`, produces a list of length `k - 1` where the Given a `List` `xs` of length `k`, this function produces a `List` of length
`i`th member of the resulting list is `f xs[i] xs[i + 1]`. `k - 1` where the `i`th member of the resulting `List` is `f xs[i] xs[i + 1]`.
-/ -/
def pairwise (xs : List α) (f : αα → β) : List β := def pairwise (xs : List α) (f : αα → β) : List β :=
match xs.tail? with match xs.tail? with
@ -223,8 +216,8 @@ def pairwise (xs : List α) (f : αα → β) : List β :=
| some ys => zipWith f xs ys | some ys => zipWith f xs ys
/-- /--
If list `xs` is empty, then any `pairwise` operation on `xs` yields an empty If `List` `xs` is empty, then any `pairwise` operation on `xs` yields an empty
list. `List`.
-/ -/
theorem len_pairwise_len_nil_eq_zero {xs : List α} (h : xs = []) theorem len_pairwise_len_nil_eq_zero {xs : List α} (h : xs = [])
: (xs.pairwise f).length = 0 := by : (xs.pairwise f).length = 0 := by
@ -248,8 +241,8 @@ theorem len_pairwise_len_cons_sub_one {xs : List α} (h : xs.length > 0)
conv => lhs; unfold length conv => lhs; unfold length
/-- /--
If the `pairwise` list isn't empty, then the original list must have at least If a `pairwise`'d `List` isn't empty, then the input `List` must have at least
two elements. two entries.
-/ -/
theorem mem_pairwise_imp_length_self_ge_2 {xs : List α} (h : xs.pairwise f ≠ []) theorem mem_pairwise_imp_length_self_ge_2 {xs : List α} (h : xs.pairwise f ≠ [])
: xs.length ≥ 2 := by : xs.length ≥ 2 := by
@ -263,8 +256,8 @@ theorem mem_pairwise_imp_length_self_ge_2 {xs : List α} (h : xs.pairwise f ≠
| cons a' bs' => unfold length length; rw [add_assoc]; norm_num | cons a' bs' => unfold length length; rw [add_assoc]; norm_num
/-- /--
If `x` is a member of the pairwise'd list, there must exist two (adjacent) If `x` is a member of a `pairwise`'d list, there must exist two (adjacent)
elements of the list, say `x₁` and `x₂`, such that `x = f x₁ x₂`. entries of the list, say `x₁` and `x₂`, such that `x = f x₁ x₂`.
-/ -/
theorem mem_pairwise_imp_exists_adjacent {xs : List α} (h : x ∈ xs.pairwise f) theorem mem_pairwise_imp_exists_adjacent {xs : List α} (h : x ∈ xs.pairwise f)
: ∃ i : Fin (xs.length - 1), ∃ x₁ x₂, : ∃ i : Fin (xs.length - 1), ∃ x₁ x₂,

View File

@ -1,14 +1,30 @@
import Mathlib.Data.Real.Basic import Mathlib.Data.Real.Basic
/-! # Bookshelf.Real.Basic
A collection of basic notational conveniences.
-/
/--
An abbreviation of `ℝ²` as the Cartesian product ` × `.
-/
notation "ℝ²" => × notation "ℝ²" => ×
namespace Real namespace Real
/-- /--
The area of a unit circle. Definitionally, the area of a unit circle.
###### PORT
As of now, this remains an `axiom`, but it should be replaced by the definition
in `Mathlib` once ported to Lean 4.
-/ -/
axiom pi : axiom pi :
/--
An abbreviation of `pi` as symbol `π`.
-/
notation "π" => pi notation "π" => pi
end Real end Real

View File

@ -1,6 +1,11 @@
import Bookshelf.Real.Basic import Bookshelf.Real.Basic
import Bookshelf.Real.Set.Partition import Bookshelf.Real.Set.Partition
/-! # Bookshelf.Real.Function.Step
A characterization of step functions.
-/
namespace Real.Function namespace Real.Function
open Partition open Partition

View File

@ -1,6 +1,15 @@
import Bookshelf.Real.Function.Step import Bookshelf.Real.Function.Step
import Bookshelf.Real.Geometry.Rectangle import Bookshelf.Real.Geometry.Rectangle
/-! # Bookshelf.Real.Geometry.Area
An axiomatic foundation for the concept of *area*. These axioms are those
outlined in [^1].
[^1]: Apostol, Tom M. Calculus, Vol. 1: One-Variable Calculus, with an
Introduction to Linear Algebra. 2nd ed. Vol. 1. 2 vols. Wiley, 1991.
-/
namespace Real.Geometry.Area namespace Real.Geometry.Area
/-- /--

View File

@ -1,6 +1,10 @@
import Bookshelf.Real.Basic
import Mathlib.Data.Real.Sqrt import Mathlib.Data.Real.Sqrt
import Bookshelf.Real.Basic /-! # Bookshelf.Real.Geometry.Basic
A collection of useful definitions and theorems around geometry.
-/
namespace Real namespace Real
@ -8,7 +12,10 @@ namespace Real
The undirected angle at `p₂` between the line segments to `p₁` and `p₃`. If The undirected angle at `p₂` between the line segments to `p₁` and `p₃`. If
either of those points equals `p₂`, this is `π / 2`. either of those points equals `p₂`, this is `π / 2`.
PORT: `geometry.euclidean.angle` ###### PORT
This should be replaced with the original Mathlib `geometry.euclidean.angle`
definition once ported.
-/ -/
axiom angle (p₁ p₂ p₃ : ℝ²) : axiom angle (p₁ p₂ p₃ : ℝ²) :
@ -24,10 +31,10 @@ noncomputable def dist (x y : ℝ²) :=
Real.sqrt ((abs (y.1 - x.1)) ^ 2 + (abs (y.2 - x.2)) ^ 2) Real.sqrt ((abs (y.1 - x.1)) ^ 2 + (abs (y.2 - x.2)) ^ 2)
/-- /--
Two sets `S` and `T` are `similar` iff there exists a one-to-one correspondence Two sets `S` and `T` are `similar` **iff** there exists a one-to-one
between `S` and `T` such that the distance between any two points `P, Q ∈ S` and correspondence between `S` and `T` such that the distance between any two points
corresponding points `P', Q' ∈ T` differ by some constant `α`. In other words, `P, Q ∈ S` and corresponding points `P', Q' ∈ T` differ by some constant `α`. In
`α|PQ| = |P'Q'|`. other words, `α|PQ| = |P'Q'|`.
-/ -/
def similar (S T : Set ℝ²) : Prop := def similar (S T : Set ℝ²) : Prop :=
∃ f : ℝ² → ℝ², Function.Bijective f ∧ ∃ f : ℝ² → ℝ², Function.Bijective f ∧
@ -43,7 +50,7 @@ def congruent (S T : Set ( × )) : Prop :=
dist x y = dist (f x) (f y) dist x y = dist (f x) (f y)
/-- /--
Any two congruent sets must be similar to one another. Any two `congruent` sets must be similar to one another.
-/ -/
theorem congruent_similar {S T : Set ℝ²} : congruent S T → similar S T := by theorem congruent_similar {S T : Set ℝ²} : congruent S T → similar S T := by
intro hc intro hc

View File

@ -1,5 +1,15 @@
import Bookshelf.Real.Geometry.Basic import Bookshelf.Real.Geometry.Basic
/-! # Bookshelf.Real.Geometry.Rectangle
A characterization of a rectangle. This follows the definition as outlined in
[^1]. Note that a `Point` and a `LineSegment` are both considered rectangles,
with one or both dimensions equal to `0` respectively.
[^1]: Apostol, Tom M. Calculus, Vol. 1: One-Variable Calculus, with an
Introduction to Linear Algebra. 2nd ed. Vol. 1. 2 vols. Wiley, 1991.
-/
namespace Real namespace Real
/-- /--
@ -29,11 +39,17 @@ A `Rectangle` is the locus of points bounded by its edges.
def set_def (r : Rectangle) : Set ℝ² := def set_def (r : Rectangle) : Set ℝ² :=
sorry sorry
/--
A `Rectangle`'s top side is equal in length to its bottom side.
-/
theorem dist_top_eq_dist_bottom (r : Rectangle) theorem dist_top_eq_dist_bottom (r : Rectangle)
: dist r.top_left r.top_right = dist r.bottom_left r.bottom_right := by : dist r.top_left r.top_right = dist r.bottom_left r.bottom_right := by
unfold top_right dist unfold top_right dist
repeat rw [add_comm, sub_right_comm, add_sub_cancel'] repeat rw [add_comm, sub_right_comm, add_sub_cancel']
/--
A `Rectangle`'s left side is equal in length to its right side.
-/
theorem dist_left_eq_dist_right (r : Rectangle) theorem dist_left_eq_dist_right (r : Rectangle)
: dist r.top_left r.bottom_left = dist r.top_right r.bottom_right := by : dist r.top_left r.bottom_left = dist r.top_right r.bottom_right := by
unfold top_right dist unfold top_right dist

View File

@ -1,5 +1,12 @@
import Bookshelf.Real.Basic import Bookshelf.Real.Basic
/-! # Bookshelf.Real.Rational
Additional theorems and definitions useful in the context of rational numbers.
Most of these will likely be deleted once the corresponding functions in
`Mathlib` are ported to Lean 4.
-/
/-- /--
Assert that a real number is irrational. Assert that a real number is irrational.
-/ -/
@ -7,8 +14,5 @@ def irrational (x : ) := x ∉ Set.range RatCast.ratCast
/-- /--
Assert that a real number is rational. Assert that a real number is rational.
Note this does *not* require the found rational to be in reduced form. Members
of `` expect this (by proving the numerator and denominator are co-prime).
-/ -/
def rational (x : ) := ¬ irrational x def rational (x : ) := ¬ irrational x

View File

@ -1,5 +1,11 @@
import Mathlib.Data.Real.Basic import Mathlib.Data.Real.Basic
/-! # Bookshelf.Real.Sequence.Arithmetic
A characterization of an arithmetic sequence, i.e. a sequence with a common
difference between each term.
-/
namespace Real namespace Real
/-- /--

View File

@ -1,5 +1,11 @@
import Mathlib.Data.Real.Basic import Mathlib.Data.Real.Basic
/-! # Bookshelf.Real.Sequence.Geometric
A characterization of a geometric sequence, i.e. a sequence with a common ratio
between each term.
-/
namespace Real namespace Real
/-- /--

View File

@ -1,5 +1,10 @@
import Mathlib.Data.Real.Basic import Mathlib.Data.Real.Basic
/-! # Bookshelf.Real.Set.Basic
A collection of useful definitions and theorems regarding sets.
-/
namespace Real namespace Real
/-- /--
@ -10,7 +15,7 @@ def minkowski_sum (s t : Set ) :=
{ x | ∃ a ∈ s, ∃ b ∈ t, x = a + b } { x | ∃ a ∈ s, ∃ b ∈ t, x = a + b }
/-- /--
The sum of two sets is nonempty if and only if the summands are nonempty. The sum of two sets is nonempty **iff** the summands are nonempty.
-/ -/
def nonempty_minkowski_sum_iff_nonempty_add_nonempty {s t : Set } def nonempty_minkowski_sum_iff_nonempty_add_nonempty {s t : Set }
: (minkowski_sum s t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := by : (minkowski_sum s t).Nonempty ↔ s.Nonempty ∧ t.Nonempty := by

View File

@ -1,5 +1,11 @@
import Mathlib.Data.Real.Basic import Mathlib.Data.Real.Basic
/-! # Bookshelf.Real.Set.Interval
A syntactic description of the various types of continuous intervals permitted
on the real number line.
-/
/-- /--
Representation of a closed interval. Representation of a closed interval.
-/ -/

View File

@ -1,7 +1,15 @@
import Mathlib.Data.List.Sort
import Bookshelf.List.Basic import Bookshelf.List.Basic
import Bookshelf.Real.Set.Interval import Bookshelf.Real.Set.Interval
import Mathlib.Data.List.Sort
/-! # Bookshelf.Real.Set.Partition
A description of a partition as defined in the context of stepwise functions.
Refer to [^1] for more information.
[^1]: Apostol, Tom M. Calculus, Vol. 1: One-Variable Calculus, with an
Introduction to Linear Algebra. 2nd ed. Vol. 1. 2 vols. Wiley, 1991.
-/
namespace Real namespace Real

View File

@ -1,4 +1 @@
-- Apostol, Tom M. Calculus, Vol. 1: One-Variable Calculus, with an Introduction
-- to Linear Algebra. 2nd ed. Vol. 1. 2 vols. Wiley, 1991.
import Exercises.Apostol.Chapter_I_3 import Exercises.Apostol.Chapter_I_3
import Exercises.Apostol.Exercises_I_3_12

View File

@ -1,22 +1,22 @@
/- import Bookshelf.Real.Set
Chapter I 3
/-! # Exercises.Apostol.Chapter_I_3
A Set of Axioms for the Real-Number System A Set of Axioms for the Real-Number System
-/ -/
import Bookshelf.Real.Set
namespace Exercises.Apostol.Chapter_I_3
#check Archimedean #check Archimedean
#check Real.exists_isLUB #check Real.exists_isLUB
namespace Real namespace Real
-- ======================================== /-! ## The least-upper-bound axiom (completeness axiom) -/
-- The least-upper-bound axiom (completeness axiom)
-- ========================================
/-- /--
A property holds for the negation of elements in set `S` if and only if it also A property holds for the negation of elements in set `S` **iff** it also holds
holds for the elements of the negation of `S`. for the elements of the negation of `S`.
-/ -/
lemma set_neg_prop_iff_neg_set_prop (S : Set ) (p : → Prop) lemma set_neg_prop_iff_neg_set_prop (S : Set ) (p : → Prop)
: (∀ y, y ∈ S → p (-y)) ↔ (∀ y, y ∈ -S → p y) := by : (∀ y, y ∈ S → p (-y)) ↔ (∀ y, y ∈ -S → p y) := by
@ -79,8 +79,8 @@ lemma neg_upper_bounds_eq_lower_bounds_neg (S : Set )
exact hx exact hx
/-- /--
An element `x` is the least element of the negation of a set if and only if `-x` An element `x` is the least element of the negation of a set **iff** `-x` is the
if the greatest element of the set. greatest element of the set.
-/ -/
lemma is_least_neg_set_eq_is_greatest_set_neq (S : Set ) lemma is_least_neg_set_eq_is_greatest_set_neq (S : Set )
: IsLeast (-S) x = IsGreatest S (-x) := by : IsLeast (-S) x = IsGreatest S (-x) := by
@ -89,8 +89,8 @@ lemma is_least_neg_set_eq_is_greatest_set_neq (S : Set )
rfl rfl
/-- /--
At least with respect to ``, `x` is the least upper bound of set `-S` if and At least with respect to ``, `x` is the least upper bound of set `-S` **iff**
only if `-x` is the greatest lower bound of `S`. `-x` is the greatest lower bound of `S`.
-/ -/
theorem is_lub_neg_set_iff_is_glb_set_neg (S : Set ) theorem is_lub_neg_set_iff_is_glb_set_neg (S : Set )
: IsLUB (-S) x = IsGLB S (-x) := : IsLUB (-S) x = IsGLB S (-x) :=
@ -100,8 +100,7 @@ theorem is_lub_neg_set_iff_is_glb_set_neg (S : Set )
_ = IsGreatest (lowerBounds S) (-x) := by rw [is_least_neg_set_eq_is_greatest_set_neq] _ = IsGreatest (lowerBounds S) (-x) := by rw [is_least_neg_set_eq_is_greatest_set_neq]
_ = IsGLB S (-x) := rfl _ = IsGLB S (-x) := rfl
/-- /-- #### Theorem I.27
Theorem I.27
Every nonempty set `S` that is bounded below has a greatest lower bound; that Every nonempty set `S` that is bounded below has a greatest lower bound; that
is, there is a real number `L` such that `L = inf S`. is, there is a real number `L` such that `L = inf S`.
@ -122,7 +121,7 @@ theorem exists_isGLB (S : Set ) (hne : S.Nonempty) (hbdd : BddBelow S)
rw [←bddAbove_def] at hbdd' rw [←bddAbove_def] at hbdd'
-- Once we have found a supremum for `-S`, we argue the negation of this value -- Once we have found a supremum for `-S`, we argue the negation of this value
-- is the same as the infimum of `S`. -- is the same as the infimum of `S`.
let ⟨ub, ubp⟩ := exists_isLUB (-S) hne' hbdd' let ⟨ub, ubp⟩ := Real.exists_isLUB (-S) hne' hbdd'
exact ⟨-ub, (is_lub_neg_set_iff_is_glb_set_neg S).mp ubp⟩ exact ⟨-ub, (is_lub_neg_set_iff_is_glb_set_neg S).mp ubp⟩
/-- /--
@ -146,12 +145,9 @@ lemma leq_nat_abs_ceil_self (x : ) : x ≤ Int.natAbs ⌈x⌉ := by
_ ≤ 0 := le_of_lt (lt_of_not_le h) _ ≤ 0 := le_of_lt (lt_of_not_le h)
_ ≤ ↑(Int.natAbs ⌈x⌉) := GE.ge.le h' _ ≤ ↑(Int.natAbs ⌈x⌉) := GE.ge.le h'
-- ======================================== /-! ## The Archimedean property of the real-number system -/
-- The Archimedean property of the real-number system
-- ========================================
/-- /-- #### Theorem I.29
Theorem I.29
For every real `x` there exists a positive integer `n` such that `n > x`. For every real `x` there exists a positive integer `n` such that `n > x`.
-/ -/
@ -163,8 +159,7 @@ theorem exists_pnat_geq_self (x : ) : ∃ n : +, ↑n > x := by
_ = x' := rfl _ = x' := rfl
exact ⟨x', h⟩ exact ⟨x', h⟩
/-- /-- #### Theorem I.30
Theorem I.30
If `x > 0` and if `y` is an arbitrary real number, there exists a positive If `x > 0` and if `y` is an arbitrary real number, there exists a positive
integer `n` such that `nx > y`. integer `n` such that `nx > y`.
@ -179,8 +174,7 @@ theorem exists_pnat_mul_self_geq_of_pos {x y : }
rw [div_mul, div_self (show x ≠ 0 from LT.lt.ne' hx), div_one] at p' rw [div_mul, div_self (show x ≠ 0 from LT.lt.ne' hx), div_one] at p'
exact ⟨n, p'⟩ exact ⟨n, p'⟩
/-- /-- #### Theorem I.31
Theorem I.31
If three real numbers `a`, `x`, and `y` satisfy the inequalities If three real numbers `a`, `x`, and `y` satisfy the inequalities
`a ≤ x ≤ a + y / n` for every integer `n ≥ 1`, then `x = a`. `a ≤ x ≤ a + y / n` for every integer `n ≥ 1`, then `x = a`.
@ -245,9 +239,7 @@ theorem forall_pnat_frac_leq_self_leq_imp_eq {x y a : }
have z : x < x := lt_of_le_of_lt (h 1).right r have z : x < x := lt_of_le_of_lt (h 1).right r
simp at z simp at z
-- ======================================== /-! ## Fundamental properties of the supremum and infimum -/
-- Fundamental properties of the supremum and infimum
-- ========================================
/-- /--
Every member of a set `S` is less than or equal to some value `ub` if and only Every member of a set `S` is less than or equal to some value `ub` if and only
@ -278,8 +270,7 @@ lemma mem_imp_ge_lub {x : } (h : IsLUB S s) : x ∈ upperBounds S → x ≥ s
intro hx intro hx
exact h.right hx exact h.right hx
/-- /-- #### Theorem I.32a
Theorem I.32a
Let `h` be a given positive number and let `S` be a set of real numbers. If `S` Let `h` be a given positive number and let `S` be a set of real numbers. If `S`
has a supremum, then for some `x` in `S` we have `x > sup S - h`. has a supremum, then for some `x` in `S` we have `x > sup S - h`.
@ -330,8 +321,7 @@ lemma mem_imp_le_glb {x : } (h : IsGLB S s) : x ∈ lowerBounds S → x ≤ s
intro hx intro hx
exact h.right hx exact h.right hx
/-- /-- #### Theorem I.32b
Theorem I.32b
Let `h` be a given positive number and let `S` be a set of real numbers. If `S` Let `h` be a given positive number and let `S` be a set of real numbers. If `S`
has an infimum, then for some `x` in `S` we have `x < inf S + h`. has an infimum, then for some `x` in `S` we have `x < inf S + h`.
@ -353,8 +343,7 @@ theorem inf_imp_exists_lt_inf_add_delta {S : Set } {s h : } (hp : h > 0)
exact le_of_not_gt (not_and.mp (nb x) hx) exact le_of_not_gt (not_and.mp (nb x) hx)
rwa [← mem_lower_bounds_iff_forall_ge] at nb' rwa [← mem_lower_bounds_iff_forall_ge] at nb'
/-- /-- #### Theorem I.33a (Additive Property)
Theorem I.33a (Additive Property)
Given nonempty subsets `A` and `B` of ``, let `C` denote the set Given nonempty subsets `A` and `B` of ``, let `C` denote the set
`C = {a + b : a ∈ A, b ∈ B}`. If each of `A` and `B` has a supremum, then `C` `C = {a + b : a ∈ A, b ∈ B}`. If each of `A` and `B` has a supremum, then `C`
@ -377,7 +366,7 @@ theorem sup_minkowski_sum_eq_sup_add_sup (A B : Set ) (a b : )
_ ≤ a + b := add_le_add hs₁ hs₂ _ ≤ a + b := add_le_add hs₁ hs₂
-- Now we show `a + b` is the *least* upper bound of `C`. We know a least -- Now we show `a + b` is the *least* upper bound of `C`. We know a least
-- upper bound `c` exists; show that `c = a + b`. -- upper bound `c` exists; show that `c = a + b`.
have ⟨c, hc⟩ := exists_isLUB C have ⟨c, hc⟩ := Real.exists_isLUB C
(Real.nonempty_minkowski_sum_iff_nonempty_add_nonempty.mpr ⟨hA, hB⟩) (Real.nonempty_minkowski_sum_iff_nonempty_add_nonempty.mpr ⟨hA, hB⟩)
⟨a + b, hub⟩ ⟨a + b, hub⟩
suffices (∀ n : +, c ≤ a + b ∧ a + b ≤ c + (1 / n)) by suffices (∀ n : +, c ≤ a + b ∧ a + b ≤ c + (1 / n)) by
@ -404,8 +393,7 @@ theorem sup_minkowski_sum_eq_sup_add_sup (A B : Set ) (a b : )
_ ≤ a' + b' + 1 / n := le_of_lt hab' _ ≤ a' + b' + 1 / n := le_of_lt hab'
_ ≤ c + 1 / n := add_le_add_right hc' (1 / n) _ ≤ c + 1 / n := add_le_add_right hc' (1 / n)
/-- /-- #### Theorem I.33b (Additive Property)
Theorem I.33b (Additive Property)
Given nonempty subsets `A` and `B` of ``, let `C` denote the set Given nonempty subsets `A` and `B` of ``, let `C` denote the set
`C = {a + b : a ∈ A, b ∈ B}`. If each of `A` and `B` has an infimum, then `C` `C = {a + b : a ∈ A, b ∈ B}`. If each of `A` and `B` has an infimum, then `C`
@ -455,8 +443,7 @@ theorem inf_minkowski_sum_eq_inf_add_inf (A B : Set )
_ ≤ a + b := le_of_lt hab' _ ≤ a + b := le_of_lt hab'
· exact hc.right hlb · exact hc.right hlb
/-- /-- #### Theorem I.34
Theorem I.34
Given two nonempty subsets `S` and `T` of `` such that `s ≤ t` for every `s` in Given two nonempty subsets `S` and `T` of `` such that `s ≤ t` for every `s` in
`S` and every `t` in `T`. Then `S` has a supremum, and `T` has an infimum, and `S` and every `t` in `T`. Then `S` has a supremum, and `T` has an infimum, and
@ -503,3 +490,158 @@ theorem forall_mem_le_forall_mem_imp_sup_le_inf (S T : Set )
simp at this simp at this
end Real end Real
/-! ## Exercises -/
/-- #### Exercise 1
If `x` and `y` are arbitrary real numbers with `x < y`, prove that there is at
least one real `z` satisfying `x < z < y`.
-/
theorem exercise1 (x y : ) (h : x < y) : ∃ z, x < z ∧ z < y := by
have ⟨z, hz⟩ := exists_pos_add_of_lt' h
refine ⟨x + z / 2, ⟨?_, ?_⟩⟩
· have hz' : z / 2 > 0 := by
have hr := div_lt_div_of_lt (show (0 : ) < 2 by simp) hz.left
rwa [zero_div] at hr
exact (lt_add_iff_pos_right x).mpr hz'
· have hz' : z / 2 < z := div_lt_self hz.left (show 1 < 2 by norm_num)
calc x + z / 2
_ < x + z := (add_lt_add_iff_left x).mpr hz'
_ = y := hz.right
/-- #### Exercise 2
If `x` is an arbitrary real number, prove that there are integers `m` and `n`
such that `m < x < n`.
-/
theorem exercise2 (x : ) : ∃ m n : , m < x ∧ x < n := by
refine ⟨x - 1, ⟨x + 1, ⟨?_, ?_⟩⟩⟩ <;> norm_num
/-- #### Exercise 3
If `x > 0`, prove that there is a positive integer `n` such that `1 / n < x`.
-/
theorem exercise3 (x : ) (h : x > 0) : ∃ n : +, 1 / n < x := by
have ⟨n, hn⟩ := @Real.exists_pnat_mul_self_geq_of_pos x 1 h
refine ⟨n, ?_⟩
have hr := mul_lt_mul_of_pos_right hn (show 0 < 1 / ↑↑n by norm_num)
conv at hr => arg 2; rw [mul_comm, ← mul_assoc]; simp
rwa [one_mul] at hr
/-- #### Exercise 4
If `x` is an arbitrary real number, prove that there is exactly one integer `n`
which satisfies the inequalities `n ≤ x < n + 1`. This `n` is called the
greatest integer in `x` and is denoted by `⌊x⌋`. For example, `⌊5⌋ = 5`,
`⌊5 / 2⌋ = 2`, `⌊-8/3⌋ = -3`.
-/
theorem exercise4 (x : ) : ∃! n : , n ≤ x ∧ x < n + 1 := by
let n := Int.floor x
refine ⟨n, ⟨?_, ?_⟩⟩
· exact ⟨Int.floor_le x, Int.lt_floor_add_one x⟩
· intro y hy
rw [← Int.floor_eq_iff] at hy
exact Eq.symm hy
/-- #### Exercise 5
If `x` is an arbitrary real number, prove that there is exactly one integer `n`
which satisfies `x ≤ n < x + 1`.
-/
theorem exercise5 (x : ) : ∃! n : , x ≤ n ∧ n < x + 1 := by
let n := Int.ceil x
refine ⟨n, ⟨?_, ?_⟩⟩
· exact ⟨Int.le_ceil x, Int.ceil_lt_add_one x⟩
· simp only
intro y hy
suffices y - 1 < x ∧ x ≤ y by
rw [← Int.ceil_eq_iff] at this
exact Eq.symm this
apply And.intro
· have := (sub_lt_sub_iff_right 1).mpr hy.right
rwa [add_sub_cancel] at this
· exact hy.left
/-! #### Exercise 6
If `x` and `y` are arbitrary real numbers, `x < y`, prove that there exists at
least one rational number `r` satisfying `x < r < y`, and hence infinitely many.
This property is often described by saying that the rational numbers are *dense*
in the real-number system.
###### TODO
-/
/-! #### Exercise 7
If `x` is rational, `x ≠ 0`, and `y` irrational, prove that `x + y`, `x - y`,
`xy`, `x / y`, and `y / x` are all irrational.
###### TODO
-/
/-! #### Exercise 8
Is the sum or product of two irrational numbers always irrational?
###### TODO
-/
/-! #### Exercise 9
If `x` and `y` are arbitrary real numbers, `x < y`, prove that there exists at
least one irrational number `z` satisfying `x < z < y`, and hence infinitely
many.
###### TODO
-/
/-! #### Exercise 10
An integer `n` is called *even* if `n = 2m` for some integer `m`, and *odd* if
`n + 1` is even. Prove the following statements:
(a) An integer cannot be both even and odd.
(b) Every integer is either even or odd.
(c) The sum or product of two even integers is even. What can you say about the
sum or product of two odd integers?
(d) If `n²` is even, so is `n`. If `a² = 2b²`, where `a` and `b` are integers,
then both `a` and `b` are even.
(e) Every rational number can be expressed in the form `a / b`, where `a` and
`b` are integers, at least one of which is odd.
###### TODO
-/
def is_even (n : ) := ∃ m : , n = 2 * m
def is_odd (n : ) := is_even (n + 1)
/-! #### Exercise 11
Prove that there is no rational number whose square is `2`.
[Hint: Argue by contradiction. Assume `(a / b)² = 2`, where `a` and `b` are
integers, at least one of which is odd. Use parts of Exercise 10 to deduce a
contradiction.]
###### TODO
-/
/-! #### Exercise 12
The Archimedean property of the real-number system was deduced as a consequence
of the least-upper-bound axiom. Prove that the set of rational numbers satisfies
the Archimedean property but not the least-upper-bound property. This shows that
the Archimedean property does not imply the least-upper-bound axiom.
###### TODO
-/
end Exercises.Apostol.Chapter_I_3

View File

@ -1,195 +0,0 @@
/-
Exercises I 3.12
A Set of Axioms for the Real-Number System
-/
import Mathlib.Algebra.Order.Floor
import Mathlib.Data.PNat.Basic
import Mathlib.Data.Real.Basic
import Mathlib.Data.Real.Sqrt
import Mathlib.Tactic.LibrarySearch
import Bookshelf.Real.Rational
import Exercises.Apostol.Chapter_I_3
-- ========================================
-- Exercise 1
--
-- If `x` and `y` are arbitrary real numbers with `x < y`, prove that there is
-- at least one real `z` satisfying `x < z < y`.
-- ========================================
theorem exercise1 (x y : ) (h : x < y) : ∃ z, x < z ∧ z < y := by
have ⟨z, hz⟩ := exists_pos_add_of_lt' h
refine ⟨x + z / 2, ⟨?_, ?_⟩⟩
· have hz' : z / 2 > 0 := by
have hr := div_lt_div_of_lt (show (0 : ) < 2 by simp) hz.left
rwa [zero_div] at hr
exact (lt_add_iff_pos_right x).mpr hz'
· have hz' : z / 2 < z := div_lt_self hz.left (show 1 < 2 by norm_num)
calc x + z / 2
_ < x + z := (add_lt_add_iff_left x).mpr hz'
_ = y := hz.right
-- ========================================
-- Exercise 2
--
-- If `x` is an arbitrary real number, prove that there are integers `m` and `n`
-- such that `m < x < n`.
-- ========================================
theorem exercise2 (x : ) : ∃ m n : , m < x ∧ x < n := by
refine ⟨x - 1, ⟨x + 1, ⟨?_, ?_⟩⟩⟩ <;> norm_num
-- ========================================
-- Exercise 3
--
-- If `x > 0`, prove that there is a positive integer `n` such that `1 / n < x`.
-- ========================================
theorem exercise3 (x : ) (h : x > 0) : ∃ n : +, 1 / n < x := by
have ⟨n, hn⟩ := @Real.exists_pnat_mul_self_geq_of_pos x 1 h
refine ⟨n, ?_⟩
have hr := mul_lt_mul_of_pos_right hn (show 0 < 1 / ↑↑n by norm_num)
conv at hr => arg 2; rw [mul_comm, ← mul_assoc]; simp
rwa [one_mul] at hr
-- ========================================
-- Exercise 4
--
-- If `x` is an arbitrary real number, prove that there is exactly one integer
-- `n` which satisfies the inequalities `n ≤ x < n + 1`. This `n` is called the
-- greatest integer in `x` and is denoted by `⌊x⌋`. For example, `⌊5⌋ = 5`,
-- `⌊5 / 2⌋ = 2`, `⌊-8/3⌋ = -3`.
-- ========================================
theorem exercise4 (x : ) : ∃! n : , n ≤ x ∧ x < n + 1 := by
let n := Int.floor x
refine ⟨n, ⟨?_, ?_⟩⟩
· exact ⟨Int.floor_le x, Int.lt_floor_add_one x⟩
· intro y hy
rw [← Int.floor_eq_iff] at hy
exact Eq.symm hy
-- ========================================
-- Exercise 5
--
-- If `x` is an arbitrary real number, prove that there is exactly one integer
-- `n` which satisfies `x ≤ n < x + 1`.
-- ========================================
theorem exercise5 (x : ) : ∃! n : , x ≤ n ∧ n < x + 1 := by
let n := Int.ceil x
refine ⟨n, ⟨?_, ?_⟩⟩
· exact ⟨Int.le_ceil x, Int.ceil_lt_add_one x⟩
· simp only
intro y hy
suffices y - 1 < x ∧ x ≤ y by
rw [← Int.ceil_eq_iff] at this
exact Eq.symm this
apply And.intro
· have := (sub_lt_sub_iff_right 1).mpr hy.right
rwa [add_sub_cancel] at this
· exact hy.left
-- ========================================
-- Exercise 6
--
-- If `x` and `y` are arbitrary real numbers, `x < y`, prove that there exists
-- at least one rational number `r` satisfying `x < r < y`, and hence infinitely
-- many. This property is often described by saying that the rational numbers
-- are *dense* in the real-number system.
-- ========================================
-- # TODO
-- ========================================
-- Exercise 7
--
-- If `x` is rational, `x ≠ 0`, and `y` irrational, prove that `x + y`, `x - y`,
-- `xy`, `x / y`, and `y / x` are all irrational.
-- ========================================
-- # TODO
-- ========================================
-- Exercise 8
--
-- Is the sum or product of two irrational numbers always irrational?
-- ========================================
-- # TODO
-- ========================================
-- Exercise 9
--
-- If `x` and `y` are arbitrary real numbers, `x < y`, prove that there exists
-- at least one irrational number `z` satisfying `x < z < y`, and hence
-- infinitely many.
-- ========================================
-- # TODO
-- ========================================
-- Exercise 10
--
-- An integer `n` is called *even* if `n = 2m` for some integer `m`, and *odd*
-- if `n + 1` is even. Prove the following statements:
--
-- (e) Every rational number can be expressed in the form `a / b`, where `a` and
-- `b` are integers, at least one of which is odd.
-- ========================================
def is_even (n : ) := ∃ m : , n = 2 * m
def is_odd (n : ) := is_even (n + 1)
-- ----------------------------------------
-- (a) An integer cannot be both even and odd.
-- ----------------------------------------
-- # TODO
-- ----------------------------------------
-- (b) Every integer is either even or odd.
-- ----------------------------------------
-- # TODO
-- ----------------------------------------
-- (c) The sum or product of two even integers is even. What can you say about
-- the sum or product of two odd integers?
-- ----------------------------------------
-- # TODO
-- ----------------------------------------
-- (d) If `n²` is even, so is `n`. If `a² = 2b²`, where `a` and `b` are
-- integers, then both `a` and `b` are even.
-- ----------------------------------------
-- # TODO
-- ========================================
-- Exercise 11
--
-- Prove that there is no rational number whose square is `2`.
--
-- [Hint: Argue by contradiction. Assume `(a / b)² = 2`, where `a` and `b` are
-- integers, at least one of which is odd. Use parts of Exercise 10 to deduce a
-- contradiction.]
-- ========================================
-- # TODO
-- ========================================
-- Exercise 12
--
-- The Archimedean property of the real-number system was deduced as a
-- consequence of the least-upper-bound axiom. Prove that the set of rational
-- numbers satisfies the Archimedean property but not the least-upper-bound
-- property. This shows that the Archimedean property does not imply the
-- least-upper-bound axiom.
-- ========================================
-- # TODO

View File

@ -1,4 +1,3 @@
-- Avigad, Jeremy. Theorem Proving in Lean, n.d.
import Exercises.Avigad.Chapter2 import Exercises.Avigad.Chapter2
import Exercises.Avigad.Chapter3 import Exercises.Avigad.Chapter3
import Exercises.Avigad.Chapter4 import Exercises.Avigad.Chapter4

View File

@ -1,14 +1,14 @@
/- /-! # Exercises.Avigad.Chapter2
Chapter 2
Dependent Type Theory Dependent Type Theory
-/ -/
-- ======================================== /-! #### Exercise 1
-- Exercise 1
-- Define the function `Do_Twice`, as described in Section 2.4.
-- Define the function `Do_Twice`, as described in Section 2.4. -/
-- ========================================
namespace Exercises.Avigad.Chapter2
namespace ex1 namespace ex1
@ -20,11 +20,10 @@ def doTwiceTwice (f : (Nat → Nat) → (Nat → Nat)) (x : Nat → Nat) := f (f
end ex1 end ex1
-- ======================================== /-! #### Exercise 2
-- Exercise 2
-- Define the functions `curry` and `uncurry`, as described in Section 2.4.
-- Define the functions `curry` and `uncurry`, as described in Section 2.4. -/
-- ========================================
namespace ex2 namespace ex2
@ -36,17 +35,15 @@ def uncurry (f : α → β → γ) : (α × β → γ) :=
end ex2 end ex2
-- ======================================== /-! #### Exercise 3
-- Exercise 3
-- Above, we used the example `vec α n` for vectors of elements of type `α` of
-- Above, we used the example `vec α n` for vectors of elements of type `α` of length `n`. Declare a constant `vec_add` that could represent a function that
-- length `n`. Declare a constant `vec_add` that could represent a function that adds two vectors of natural numbers of the same length, and a constant
-- adds two vectors of natural numbers of the same length, and a constant `vec_reverse` that can represent a function that reverses its argument. Use
-- `vec_reverse` that can represent a function that reverses its argument. Use implicit arguments for parameters that can be inferred. Declare some variables
-- implicit arguments for parameters that can be inferred. Declare some nd check some expressions involving the constants that you have declared.
-- variables and check some expressions involving the constants that you have -/
-- declared.
-- ========================================
namespace ex3 namespace ex3
@ -73,16 +70,14 @@ variable (c d : vec Prop 2)
end ex3 end ex3
-- ======================================== /-! #### Exercise 4
-- Exercise 4
-- Similarly, declare a constant `matrix` so that `matrix α m n` could represent
-- Similarly, declare a constant `matrix` so that `matrix α m n` could represent the type of `m` by `n` matrices. Declare some constants to represent functions
-- the type of `m` by `n` matrices. Declare some constants to represent on this type, such as matrix addition and multiplication, and (using vec)
-- functions on this type, such as matrix addition and multiplication, and multiplication of a matrix by a vector. Once again, declare some variables and
-- (using vec) multiplication of a matrix by a vector. Once again, declare some check some expressions involving the constants that you have declared.
-- variables and check some expressions involving the constants that you have -/
-- declared.
-- ========================================
namespace ex4 namespace ex4
@ -110,3 +105,5 @@ variable (d : ex3.vec Prop 3)
#check matrix.app c d #check matrix.app c d
end ex4 end ex4
end Exercises.Avigad.Chapter2

View File

@ -1,14 +1,14 @@
/- /-! # Exercises.Avigad.Chapter3
Chapter 3
Propositions and Proofs Propositions and Proofs
-/ -/
-- ======================================== /-! #### Exercise 1
-- Exercise 1
-- Prove the following identities.
-- Prove the following identities. -/
-- ========================================
namespace Exercises.Avigad.Chapter3
namespace ex1 namespace ex1
@ -17,23 +17,23 @@ open or
variable (p q r : Prop) variable (p q r : Prop)
-- Commutativity of ∧ and -- Commutativity of ∧ and
example : p ∧ q ↔ q ∧ p := theorem and_comm' : p ∧ q ↔ q ∧ p :=
Iff.intro Iff.intro
(fun ⟨hp, hq⟩ => show q ∧ p from ⟨hq, hp⟩) (fun ⟨hp, hq⟩ => show q ∧ p from ⟨hq, hp⟩)
(fun ⟨hq, hp⟩ => show p ∧ q from ⟨hp, hq⟩) (fun ⟨hq, hp⟩ => show p ∧ q from ⟨hp, hq⟩)
example : p q ↔ q p := theorem or_comm' : p q ↔ q p :=
Iff.intro Iff.intro
(fun h => h.elim Or.inr Or.inl) (fun h => h.elim Or.inr Or.inl)
(fun h => h.elim Or.inr Or.inl) (fun h => h.elim Or.inr Or.inl)
-- Associativity of ∧ and -- Associativity of ∧ and
example : (p ∧ q) ∧ r ↔ p ∧ (q ∧ r) := theorem and_assoc : (p ∧ q) ∧ r ↔ p ∧ (q ∧ r) :=
Iff.intro Iff.intro
(fun ⟨⟨hp, hq⟩, hr⟩ => ⟨hp, hq, hr⟩) (fun ⟨⟨hp, hq⟩, hr⟩ => ⟨hp, hq, hr⟩)
(fun ⟨hp, hq, hr⟩ => ⟨⟨hp, hq⟩, hr⟩) (fun ⟨hp, hq, hr⟩ => ⟨⟨hp, hq⟩, hr⟩)
example : (p q) r ↔ p (q r) := theorem or_assoc' : (p q) r ↔ p (q r) :=
Iff.intro Iff.intro
(fun h₁ => h₁.elim (fun h₁ => h₁.elim
(fun h₂ => h₂.elim Or.inl (Or.inr ∘ Or.inl)) (fun h₂ => h₂.elim Or.inl (Or.inr ∘ Or.inl))
@ -43,14 +43,14 @@ example : (p q) r ↔ p (q r) :=
(fun h₂ => h₂.elim (Or.inl ∘ Or.inr) Or.inr)) (fun h₂ => h₂.elim (Or.inl ∘ Or.inr) Or.inr))
-- Distributivity -- Distributivity
example : p ∧ (q r) ↔ (p ∧ q) (p ∧ r) := theorem and_or_left : p ∧ (q r) ↔ (p ∧ q) (p ∧ r) :=
Iff.intro Iff.intro
(fun ⟨hp, hqr⟩ => hqr.elim (Or.inl ⟨hp, ·⟩) (Or.inr ⟨hp, ·⟩)) (fun ⟨hp, hqr⟩ => hqr.elim (Or.inl ⟨hp, ·⟩) (Or.inr ⟨hp, ·⟩))
(fun h₁ => h₁.elim (fun h₁ => h₁.elim
(fun ⟨hp, hq⟩ => ⟨hp, Or.inl hq⟩) (fun ⟨hp, hq⟩ => ⟨hp, Or.inl hq⟩)
(fun ⟨hp, hr⟩ => ⟨hp, Or.inr hr⟩)) (fun ⟨hp, hr⟩ => ⟨hp, Or.inr hr⟩))
example : p (q ∧ r) ↔ (p q) ∧ (p r) := theorem or_and_left : p (q ∧ r) ↔ (p q) ∧ (p r) :=
Iff.intro Iff.intro
(fun h => h.elim (fun h => h.elim
(fun hp => ⟨Or.inl hp, Or.inl hp⟩) (fun hp => ⟨Or.inl hp, Or.inl hp⟩)
@ -60,12 +60,12 @@ example : p (q ∧ r) ↔ (p q) ∧ (p r) :=
(fun hq => h₂.elim Or.inl (fun hr => Or.inr ⟨hq, hr⟩))) (fun hq => h₂.elim Or.inl (fun hr => Or.inr ⟨hq, hr⟩)))
-- Other properties -- Other properties
example : (p → (q → r)) ↔ (p ∧ q → r) := theorem imp_imp_iff_and_imp : (p → (q → r)) ↔ (p ∧ q → r) :=
Iff.intro Iff.intro
(fun h ⟨hp, hq⟩ => h hp hq) (fun h ⟨hp, hq⟩ => h hp hq)
(fun h hp hq => h ⟨hp, hq⟩) (fun h hp hq => h ⟨hp, hq⟩)
example : ((p q) → r) ↔ (p → r) ∧ (q → r) := theorem or_imp : ((p q) → r) ↔ (p → r) ∧ (q → r) :=
Iff.intro Iff.intro
(fun h => (fun h =>
have h₁ : p → r := h ∘ Or.inl have h₁ : p → r := h ∘ Or.inl
@ -73,42 +73,41 @@ example : ((p q) → r) ↔ (p → r) ∧ (q → r) :=
show (p → r) ∧ (q → r) from ⟨h₁, h₂⟩) show (p → r) ∧ (q → r) from ⟨h₁, h₂⟩)
(fun ⟨h₁, h₂⟩ h => h.elim h₁ h₂) (fun ⟨h₁, h₂⟩ h => h.elim h₁ h₂)
example : ¬(p q) ↔ ¬p ∧ ¬q := theorem nor_or : ¬(p q) ↔ ¬p ∧ ¬q :=
Iff.intro Iff.intro
(fun h => ⟨h ∘ Or.inl, h ∘ Or.inr⟩) (fun h => ⟨h ∘ Or.inl, h ∘ Or.inr⟩)
(fun h₁ h₂ => h₂.elim (absurd · h₁.left) (absurd · h₁.right)) (fun h₁ h₂ => h₂.elim (absurd · h₁.left) (absurd · h₁.right))
example : ¬p ¬q → ¬(p ∧ q) := theorem not_and_or_mpr : ¬p ¬q → ¬(p ∧ q) :=
fun h₁ h₂ => h₁.elim (absurd h₂.left ·) (absurd h₂.right ·) fun h₁ h₂ => h₁.elim (absurd h₂.left ·) (absurd h₂.right ·)
example : ¬(p ∧ ¬p) := theorem and_not_self : ¬(p ∧ ¬p) :=
fun h => absurd h.left h.right fun h => absurd h.left h.right
example : p ∧ ¬q → ¬(p → q) := theorem not_imp_o_and_not : p ∧ ¬q → ¬(p → q) :=
fun ⟨hp, nq⟩ hpq => absurd (hpq hp) nq fun ⟨hp, nq⟩ hpq => absurd (hpq hp) nq
example : ¬p → (p → q) := theorem false_elim_self : ¬p → (p → q) :=
fun np hp => absurd hp np fun np hp => absurd hp np
example : (¬p q) → (p → q) := theorem not_or_imp_imp : (¬p q) → (p → q) :=
fun npq hp => npq.elim (absurd hp ·) id fun npq hp => npq.elim (absurd hp ·) id
example : p False ↔ p := theorem or_false_iff : p False ↔ p :=
Iff.intro (fun hpf => hpf.elim id False.elim) Or.inl Iff.intro (fun hpf => hpf.elim id False.elim) Or.inl
example : p ∧ False ↔ False := theorem and_false_iff : p ∧ False ↔ False :=
Iff.intro (fun ⟨_, hf⟩ => hf) False.elim Iff.intro (fun ⟨_, hf⟩ => hf) False.elim
example : (p → q) → (¬q → ¬p) := theorem imp_imp_not_imp_not : (p → q) → (¬q → ¬p) :=
fun hpq nq hp => absurd (hpq hp) nq fun hpq nq hp => absurd (hpq hp) nq
end ex1 end ex1
-- ======================================== /-! #### Exercise 2
-- Exercise 2
-- Prove the following identities. These require classical reasoning.
-- Prove the following identities. These require classical reasoning. -/
-- ========================================
namespace ex2 namespace ex2
@ -116,34 +115,34 @@ open Classical
variable (p q r s : Prop) variable (p q r s : Prop)
example (hp : p) : (p → r s) → ((p → r) (p → s)) := theorem imp_or_mp (hp : p) : (p → r s) → ((p → r) (p → s)) :=
fun h => (h hp).elim fun h => (h hp).elim
(fun hr => Or.inl (fun _ => hr)) (fun hr => Or.inl (fun _ => hr))
(fun hs => Or.inr (fun _ => hs)) (fun hs => Or.inr (fun _ => hs))
example : ¬(p ∧ q) → ¬p ¬q := theorem not_and_iff_or_not : ¬(p ∧ q) → ¬p ¬q :=
fun npq => (em p).elim fun npq => (em p).elim
(fun hp => (em q).elim (fun hp => (em q).elim
(fun hq => False.elim (npq ⟨hp, hq⟩)) (fun hq => False.elim (npq ⟨hp, hq⟩))
Or.inr) Or.inr)
Or.inl Or.inl
example : ¬(p → q) → p ∧ ¬q := theorem not_imp_mp : ¬(p → q) → p ∧ ¬q :=
fun h => fun h =>
have lhs : p := byContradiction have lhs : p := byContradiction
fun np => h (fun (hp : p) => absurd hp np) fun np => h (fun (hp : p) => absurd hp np)
⟨lhs, fun hq => h (fun _ => hq)⟩ ⟨lhs, fun hq => h (fun _ => hq)⟩
example : (p → q) → (¬p q) := theorem not_or_of_imp : (p → q) → (¬p q) :=
fun hpq => (em p).elim (fun hp => Or.inr (hpq hp)) Or.inl fun hpq => (em p).elim (fun hp => Or.inr (hpq hp)) Or.inl
example : (¬q → ¬p) → (p → q) := theorem not_imp_not_imp_imp : (¬q → ¬p) → (p → q) :=
fun h hp => byContradiction fun h hp => byContradiction
fun nq => absurd hp (h nq) fun nq => absurd hp (h nq)
example : p ¬p := em p theorem or_not : p ¬p := em p
example : (((p → q) → p) → p) := theorem imp_imp_imp : (((p → q) → p) → p) :=
fun h => byContradiction fun h => byContradiction
fun np => fun np =>
suffices hp : p from absurd hp np suffices hp : p from absurd hp np
@ -151,17 +150,18 @@ example : (((p → q) → p) → p) :=
end ex2 end ex2
-- ======================================== /-! #### Exercise 3
-- Exercise 3
-- Prove `¬(p ↔ ¬p)` without using classical logic.
-- Prove `¬(p ↔ ¬p)` without using classical logic. -/
-- ========================================
namespace ex3 namespace ex3
variable (p : Prop) variable (p : Prop)
example (hp : p) : ¬(p ↔ ¬p) := theorem iff_not_self (hp : p) : ¬(p ↔ ¬p) :=
fun h => absurd hp (Iff.mp h hp) fun h => absurd hp (Iff.mp h hp)
end ex3 end ex3
end Exercises.Avigad.Chapter3

View File

@ -1,32 +1,35 @@
/- /-! # Exercises.Avigad.Chapter4
Chapter 4
Quantifiers and Equality Quantifiers and Equality
-/ -/
-- ======================================== /-! #### Exercise 1
-- Exercise 1
-- Prove these equivalences. You should also try to understand why the reverse
-- Prove these equivalences. You should also try to understand why the reverse implication is not derivable in the last example.
-- implication is not derivable in the last example. -/
-- ========================================
namespace Exercises.Avigad.Chapter4
namespace ex1 namespace ex1
variable (α : Type _) variable (α : Type _)
variable (p q : α → Prop) variable (p q : α → Prop)
example : (∀ x, p x ∧ q x) ↔ (∀ x, p x) ∧ (∀ x, q x) := theorem forall_and
: (∀ x, p x ∧ q x) ↔ (∀ x, p x) ∧ (∀ x, q x) :=
Iff.intro Iff.intro
(fun h => ⟨fun x => And.left (h x), fun x => And.right (h x)⟩) (fun h => ⟨fun x => And.left (h x), fun x => And.right (h x)⟩)
(fun ⟨h₁, h₂⟩ x => ⟨h₁ x, h₂ x⟩) (fun ⟨h₁, h₂⟩ x => ⟨h₁ x, h₂ x⟩)
example : (∀ x, p x → q x) → (∀ x, p x) → (∀ x, q x) := theorem forall_imp_distrib
: (∀ x, p x → q x) → (∀ x, p x) → (∀ x, q x) :=
fun h₁ h₂ x => fun h₁ h₂ x =>
have px : p x := h₂ x have px : p x := h₂ x
h₁ x px h₁ x px
example : (∀ x, p x) (∀ x, q x) → ∀ x, p x q x := theorem forall_or_distrib
: (∀ x, p x) (∀ x, q x) → ∀ x, p x q x :=
fun h₁ x => h₁.elim fun h₁ x => h₁.elim
(fun h₂ => Or.inl (h₂ x)) (fun h₂ => Or.inl (h₂ x))
(fun h₂ => Or.inr (h₂ x)) (fun h₂ => Or.inr (h₂ x))
@ -37,13 +40,12 @@ example : (∀ x, p x) (∀ x, q x) → ∀ x, p x q x :=
end ex1 end ex1
-- ======================================== /-! #### Exercise 2
-- Exercise 2
-- It is often possible to bring a component of a formula outside a universal
-- It is often possible to bring a component of a formula outside a universal quantifier, when it does not depend on the quantified variable. Try proving
-- quantifier, when it does not depend on the quantified variable. Try proving these (one direction of the second of these requires classical logic).
-- these (one direction of the second of these requires classical logic). -/
-- ========================================
namespace ex2 namespace ex2
@ -51,14 +53,14 @@ variable (α : Type _)
variable (p q : α → Prop) variable (p q : α → Prop)
variable (r : Prop) variable (r : Prop)
example : α → ((∀ _ : α, r) ↔ r) := theorem self_imp_forall : α → ((∀ _ : α, r) ↔ r) :=
fun a => Iff.intro (fun h => h a) (fun hr _ => hr) fun a => Iff.intro (fun h => h a) (fun hr _ => hr)
section section
open Classical open Classical
example : (∀ x, p x r) ↔ (∀ x, p x) r := theorem forall_or_right : (∀ x, p x r) ↔ (∀ x, p x) r :=
Iff.intro Iff.intro
(fun h₁ => (em r).elim (fun h₁ => (em r).elim
Or.inr Or.inr
@ -69,20 +71,19 @@ example : (∀ x, p x r) ↔ (∀ x, p x) r :=
end end
example : (∀ x, r → p x) ↔ (r → ∀ x, p x) := theorem forall_swap : (∀ x, r → p x) ↔ (r → ∀ x, p x) :=
Iff.intro Iff.intro
(fun h hr hx => h hx hr) (fun h hr hx => h hx hr)
(fun h hx hr => h hr hx) (fun h hx hr => h hr hx)
end ex2 end ex2
-- ======================================== /-! #### Exercise 3
-- Exercise 3
-- Consider the "barber paradox," that is, the claim that in a certain town there
-- Consider the "barber paradox," that is, the claim that in a certain town is a (male) barber that shaves all and only the men who do not shave themselves.
-- there is a (male) barber that shaves all and only the men who do not shave Prove that this is a contradiction.
-- themselves. Prove that this is a contradiction. -/
-- ========================================
namespace ex3 namespace ex3
@ -92,7 +93,7 @@ variable (men : Type _)
variable (barber : men) variable (barber : men)
variable (shaves : men → men → Prop) variable (shaves : men → men → Prop)
example (h : ∀ x : men, shaves barber x ↔ ¬shaves x x) : False := theorem barber_paradox (h : ∀ x : men, shaves barber x ↔ ¬shaves x x) : False :=
have b : shaves barber barber ↔ ¬shaves barber barber := h barber have b : shaves barber barber ↔ ¬shaves barber barber := h barber
(em (shaves barber barber)).elim (em (shaves barber barber)).elim
(fun b' => absurd b' (Iff.mp b b')) (fun b' => absurd b' (Iff.mp b b'))
@ -100,18 +101,16 @@ example (h : ∀ x : men, shaves barber x ↔ ¬shaves x x) : False :=
end ex3 end ex3
-- ======================================== /-! #### Exercise 4
-- Exercise 4
-- Remember that, without any parameters, an expression of type `Prop` is just an
-- Remember that, without any parameters, an expression of type `Prop` is just assertion. Fill in the definitions of `prime` and `Fermat_prime` below, and
-- an assertion. Fill in the definitions of `prime` and `Fermat_prime` below, construct each of the given assertions. For example, you can say that there are
-- and construct each of the given assertions. For example, you can say that infinitely many primes by asserting that for every natural number `n`, there is
-- there are infinitely many primes by asserting that for every natural number a prime number greater than `n.` Goldbachs weak conjecture states that every
-- `n`, there is a prime number greater than `n.` Goldbachs weak conjecture odd number greater than `5` is the sum of three primes. Look up the definition
-- states that every odd number greater than `5` is the sum of three primes. of a Fermat prime or any of the other statements, if necessary.
-- Look up the definition of a Fermat prime or any of the other statements, if -/
-- necessary.
-- ========================================
namespace ex4 namespace ex4
@ -144,11 +143,10 @@ def Fermat'sLastTheorem : Prop :=
end ex4 end ex4
-- ======================================== /-! #### Exercise 5
-- Exercise 5
-- Prove as many of the identities listed in Section 4.4 as you can.
-- Prove as many of the identities listed in Section 4.4 as you can. -/
-- ========================================
namespace ex5 namespace ex5
@ -158,18 +156,18 @@ variable (α : Type _)
variable (p q : α → Prop) variable (p q : α → Prop)
variable (r s : Prop) variable (r s : Prop)
example : (∃ _ : α, r) → r := theorem exists_imp : (∃ _ : α, r) → r :=
fun ⟨_, hr⟩ => hr fun ⟨_, hr⟩ => hr
example (a : α) : r → (∃ _ : α, r) := theorem exists_intro (a : α) : r → (∃ _ : α, r) :=
fun hr => ⟨a, hr⟩ fun hr => ⟨a, hr⟩
example : (∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r := theorem exists_and_right : (∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r :=
Iff.intro Iff.intro
(fun ⟨hx, ⟨hp, hr⟩⟩ => ⟨⟨hx, hp⟩, hr⟩) (fun ⟨hx, ⟨hp, hr⟩⟩ => ⟨⟨hx, hp⟩, hr⟩)
(fun ⟨⟨hx, hp⟩, hr⟩ => ⟨hx, ⟨hp, hr⟩⟩) (fun ⟨⟨hx, hp⟩, hr⟩ => ⟨hx, ⟨hp, hr⟩⟩)
example : (∃ x, p x q x) ↔ (∃ x, p x) (∃ x, q x) := theorem exists_or : (∃ x, p x q x) ↔ (∃ x, p x) (∃ x, q x) :=
Iff.intro Iff.intro
(fun ⟨hx, hpq⟩ => hpq.elim (fun ⟨hx, hpq⟩ => hpq.elim
(fun hp => Or.inl ⟨hx, hp⟩) (fun hp => Or.inl ⟨hx, hp⟩)
@ -178,19 +176,19 @@ example : (∃ x, p x q x) ↔ (∃ x, p x) (∃ x, q x) :=
(fun ⟨hx, hp⟩ => ⟨hx, Or.inl hp⟩) (fun ⟨hx, hp⟩ => ⟨hx, Or.inl hp⟩)
(fun ⟨hx, hq⟩ => ⟨hx, Or.inr hq⟩)) (fun ⟨hx, hq⟩ => ⟨hx, Or.inr hq⟩))
example : (∀ x, p x) ↔ ¬(∃ x, ¬p x) := theorem forall_iff_not_exists : (∀ x, p x) ↔ ¬(∃ x, ¬p x) :=
Iff.intro Iff.intro
(fun h ⟨hx, np⟩ => np (h hx)) (fun h ⟨hx, np⟩ => np (h hx))
(fun h hx => byContradiction (fun h hx => byContradiction
fun np => h ⟨hx, np⟩) fun np => h ⟨hx, np⟩)
example : (∃ x, p x) ↔ ¬(∀ x, ¬p x) := theorem exists_iff_not_forall : (∃ x, p x) ↔ ¬(∀ x, ¬p x) :=
Iff.intro Iff.intro
(fun ⟨hx, hp⟩ h => absurd hp (h hx)) (fun ⟨hx, hp⟩ h => absurd hp (h hx))
(fun h => byContradiction (fun h => byContradiction
fun h' => h (fun (x : α) hp => h' ⟨x, hp⟩)) fun h' => h (fun (x : α) hp => h' ⟨x, hp⟩))
example : (¬∃ x, p x) ↔ (∀ x, ¬p x) := theorem not_exists : (¬∃ x, p x) ↔ (∀ x, ¬p x) :=
Iff.intro Iff.intro
(fun h hx hp => h ⟨hx, hp⟩) (fun h hx hp => h ⟨hx, hp⟩)
(fun h ⟨hx, hp⟩ => absurd hp (h hx)) (fun h ⟨hx, hp⟩ => absurd hp (h hx))
@ -202,15 +200,15 @@ theorem forall_negation : (¬∀ x, p x) ↔ (∃ x, ¬p x) :=
fun np => h' ⟨x, np⟩)) fun np => h' ⟨x, np⟩))
(fun ⟨hx, np⟩ h => absurd (h hx) np) (fun ⟨hx, np⟩ h => absurd (h hx) np)
example : (¬∀ x, p x) ↔ (∃ x, ¬p x) := theorem not_forall : (¬∀ x, p x) ↔ (∃ x, ¬p x) :=
forall_negation α p forall_negation α p
example : (∀ x, p x → r) ↔ (∃ x, p x) → r := theorem forall_iff_exists_imp : (∀ x, p x → r) ↔ (∃ x, p x) → r :=
Iff.intro Iff.intro
(fun h ⟨hx, hp⟩ => h hx hp) (fun h ⟨hx, hp⟩ => h hx hp)
(fun h hx hp => h ⟨hx, hp⟩) (fun h hx hp => h ⟨hx, hp⟩)
example (a : α) : (∃ x, p x → r) ↔ (∀ x, p x) → r := theorem exists_iff_forall_imp (a : α) : (∃ x, p x → r) ↔ (∀ x, p x) → r :=
Iff.intro Iff.intro
(fun ⟨hx, hp⟩ h => hp (h hx)) (fun ⟨hx, hp⟩ h => hp (h hx))
(fun h₁ => (em (∀ x, p x)).elim (fun h₁ => (em (∀ x, p x)).elim
@ -220,7 +218,7 @@ example (a : α) : (∃ x, p x → r) ↔ (∀ x, p x) → r :=
match h₃ with match h₃ with
| ⟨hx, hp⟩ => ⟨hx, fun hp' => absurd hp' hp⟩)) | ⟨hx, hp⟩ => ⟨hx, fun hp' => absurd hp' hp⟩))
example (a : α) : (∃ x, r → p x) ↔ (r → ∃ x, p x) := theorem exists_self_iff_self_exists (a : α) : (∃ x, r → p x) ↔ (r → ∃ x, p x) :=
Iff.intro Iff.intro
(fun ⟨hx, hrp⟩ hr => ⟨hx, hrp hr⟩) (fun ⟨hx, hrp⟩ hr => ⟨hx, hrp hr⟩)
(fun h => (em r).elim (fun h => (em r).elim
@ -230,11 +228,10 @@ example (a : α) : (∃ x, r → p x) ↔ (r → ∃ x, p x) :=
end ex5 end ex5
-- ======================================== /-! #### Exercise 6
-- Exercise 6
-- Give a calculational proof of the theorem `log_mul` below.
-- Give a calculational proof of the theorem `log_mul` below. -/
-- ========================================
namespace ex6 namespace ex6
@ -244,16 +241,21 @@ variable (exp_log_eq : ∀ {x}, x > 0 → exp (log x) = x)
variable (exp_pos : ∀ x, exp x > 0) variable (exp_pos : ∀ x, exp x > 0)
variable (exp_add : ∀ x y, exp (x + y) = exp x * exp y) variable (exp_add : ∀ x y, exp (x + y) = exp x * exp y)
example (x y z : Float) : exp (x + y + z) = exp x * exp y * exp z := theorem exp_add_mul_exp (x y z : Float)
: exp (x + y + z) = exp x * exp y * exp z :=
by rw [exp_add, exp_add] by rw [exp_add, exp_add]
example (y : Float) (h : y > 0) : exp (log y) = y := exp_log_eq h theorem exp_log_eq_self (y : Float) (h : y > 0)
: exp (log y) = y := exp_log_eq h
theorem log_mul {x y : Float} (hx : x > 0) (hy : y > 0) : theorem log_mul {x y : Float} (hx : x > 0) (hy : y > 0) :
log (x * y) = log x + log y := log (x * y) = log x + log y :=
calc log (x * y) = log (x * exp (log y)) := by rw [exp_log_eq hy] calc log (x * y)
_ = log (exp (log x) * exp (log y)) := by rw [exp_log_eq hx] _ = log (x * exp (log y)) := by rw [exp_log_eq hy]
_ = log (exp (log x + log y)) := by rw [exp_add] _ = log (exp (log x) * exp (log y)) := by rw [exp_log_eq hx]
_ = log x + log y := by rw [log_exp_eq] _ = log (exp (log x + log y)) := by rw [exp_add]
_ = log x + log y := by rw [log_exp_eq]
end ex6 end ex6
end Exercises.Avigad.Chapter4

View File

@ -1,35 +1,33 @@
/- /-! # Exercises.Avigad.Chapter5
Chapter 5
Tactics Tactics
-/ -/
-- ======================================== /-! #### Exercise 1
-- Exercise 1
-- Go back to the exercises in Chapter 3 and Chapter 4 and redo as many as you can
-- Go back to the exercises in Chapter 3 and Chapter 4 and redo as many as you now with tactic proofs, using also `rw` and `simp` as appropriate.
-- can now with tactic proofs, using also `rw` and `simp` as appropriate. -/
-- ========================================
namespace Exercises.Avigad.Chapter5
namespace ex1 namespace ex1
-- ---------------------------------------- /-! ##### Exercises 3.1 -/
-- Exercises 3.1
-- ----------------------------------------
section ex3_1 section ex3_1
variable (p q r : Prop) variable (p q r : Prop)
-- Commutativity of ∧ and -- Commutativity of ∧ and
example : p ∧ q ↔ q ∧ p := by theorem and_comm' : p ∧ q ↔ q ∧ p := by
apply Iff.intro apply Iff.intro
· intro ⟨hp, hq⟩ · intro ⟨hp, hq⟩
exact ⟨hq, hp⟩ exact ⟨hq, hp⟩
· intro ⟨hq, hp⟩ · intro ⟨hq, hp⟩
exact ⟨hp, hq⟩ exact ⟨hp, hq⟩
example : p q ↔ q p := by theorem or_comm' : p q ↔ q p := by
apply Iff.intro apply Iff.intro
· intro · intro
| Or.inl hp => exact Or.inr hp | Or.inl hp => exact Or.inr hp
@ -39,14 +37,14 @@ example : p q ↔ q p := by
| Or.inr hp => exact Or.inl hp | Or.inr hp => exact Or.inl hp
-- Associativity of ∧ and -- Associativity of ∧ and
example : (p ∧ q) ∧ r ↔ p ∧ (q ∧ r) := by theorem and_assoc : (p ∧ q) ∧ r ↔ p ∧ (q ∧ r) := by
apply Iff.intro apply Iff.intro
· intro ⟨⟨hp, hq⟩, hr⟩ · intro ⟨⟨hp, hq⟩, hr⟩
exact ⟨hp, hq, hr⟩ exact ⟨hp, hq, hr⟩
· intro ⟨hp, hq, hr⟩ · intro ⟨hp, hq, hr⟩
exact ⟨⟨hp, hq⟩, hr⟩ exact ⟨⟨hp, hq⟩, hr⟩
example : (p q) r ↔ p (q r) := by theorem or_assoc' : (p q) r ↔ p (q r) := by
apply Iff.intro apply Iff.intro
· intro · intro
| Or.inl (Or.inl hp) => exact Or.inl hp | Or.inl (Or.inl hp) => exact Or.inl hp
@ -58,7 +56,7 @@ example : (p q) r ↔ p (q r) := by
| Or.inr (Or.inr hr) => exact Or.inr hr | Or.inr (Or.inr hr) => exact Or.inr hr
-- Distributivity -- Distributivity
example : p ∧ (q r) ↔ (p ∧ q) (p ∧ r) := by theorem and_or_left : p ∧ (q r) ↔ (p ∧ q) (p ∧ r) := by
apply Iff.intro apply Iff.intro
· intro · intro
| ⟨hp, Or.inl hq⟩ => exact Or.inl ⟨hp, hq⟩ | ⟨hp, Or.inl hq⟩ => exact Or.inl ⟨hp, hq⟩
@ -67,7 +65,7 @@ example : p ∧ (q r) ↔ (p ∧ q) (p ∧ r) := by
| Or.inl ⟨hp, hq⟩ => exact ⟨hp, Or.inl hq⟩ | Or.inl ⟨hp, hq⟩ => exact ⟨hp, Or.inl hq⟩
| Or.inr ⟨hp, hr⟩ => exact ⟨hp, Or.inr hr⟩ | Or.inr ⟨hp, hr⟩ => exact ⟨hp, Or.inr hr⟩
example : p (q ∧ r) ↔ (p q) ∧ (p r) := by theorem or_and_left : p (q ∧ r) ↔ (p q) ∧ (p r) := by
apply Iff.intro apply Iff.intro
· intro · intro
| Or.inl hp => exact ⟨Or.inl hp, Or.inl hp⟩ | Or.inl hp => exact ⟨Or.inl hp, Or.inl hp⟩
@ -78,14 +76,14 @@ example : p (q ∧ r) ↔ (p q) ∧ (p r) := by
| ⟨Or.inr hq, Or.inr hr⟩ => exact Or.inr ⟨hq, hr⟩ | ⟨Or.inr hq, Or.inr hr⟩ => exact Or.inr ⟨hq, hr⟩
-- Other properties -- Other properties
example : (p → (q → r)) ↔ (p ∧ q → r) := by theorem imp_imp_iff_and_imp : (p → (q → r)) ↔ (p ∧ q → r) := by
apply Iff.intro apply Iff.intro
· intro h ⟨hp, hq⟩ · intro h ⟨hp, hq⟩
exact h hp hq exact h hp hq
· intro h hp hq · intro h hp hq
exact h ⟨hp, hq⟩ exact h ⟨hp, hq⟩
example : ((p q) → r) ↔ (p → r) ∧ (q → r) := by theorem or_imp : ((p q) → r) ↔ (p → r) ∧ (q → r) := by
apply Iff.intro apply Iff.intro
· intro h · intro h
apply And.intro apply And.intro
@ -100,7 +98,7 @@ example : ((p q) → r) ↔ (p → r) ∧ (q → r) := by
· intro hq · intro hq
exact hqr hq exact hqr hq
example : ¬(p q) ↔ ¬p ∧ ¬q := by theorem nor_or : ¬(p q) ↔ ¬p ∧ ¬q := by
apply Iff.intro apply Iff.intro
· intro h · intro h
apply And.intro apply And.intro
@ -113,29 +111,29 @@ example : ¬(p q) ↔ ¬p ∧ ¬q := by
| Or.inl hp => exact absurd hp np | Or.inl hp => exact absurd hp np
| Or.inr hq => exact absurd hq nq | Or.inr hq => exact absurd hq nq
example : ¬p ¬q → ¬(p ∧ q) := by theorem not_and_or_mpr : ¬p ¬q → ¬(p ∧ q) := by
intro intro
| Or.inl np => intro h; exact absurd h.left np | Or.inl np => intro h; exact absurd h.left np
| Or.inr nq => intro h; exact absurd h.right nq | Or.inr nq => intro h; exact absurd h.right nq
example : ¬(p ∧ ¬p) := by theorem and_not_self : ¬(p ∧ ¬p) := by
intro ⟨hp, np⟩ intro ⟨hp, np⟩
exact absurd hp np exact absurd hp np
example : p ∧ ¬q → ¬(p → q) := by theorem not_imp_o_and_not : p ∧ ¬q → ¬(p → q) := by
intro ⟨hp, nq⟩ h intro ⟨hp, nq⟩ h
exact absurd (h hp) nq exact absurd (h hp) nq
example : ¬p → (p → q) := by theorem false_elim_self : ¬p → (p → q) := by
intro np hp intro np hp
exact absurd hp np exact absurd hp np
example : (¬p q) → (p → q) := by theorem not_or_imp_imp : (¬p q) → (p → q) := by
intro intro
| Or.inl np => intro hp; exact absurd hp np | Or.inl np => intro hp; exact absurd hp np
| Or.inr hq => exact fun _ => hq | Or.inr hq => exact fun _ => hq
example : p False ↔ p := by theorem or_false_iff : p False ↔ p := by
apply Iff.intro apply Iff.intro
· intro · intro
| Or.inl hp => exact hp | Or.inl hp => exact hp
@ -143,22 +141,20 @@ example : p False ↔ p := by
· intro hp · intro hp
exact Or.inl hp exact Or.inl hp
example : p ∧ False ↔ False := by theorem and_false_iff : p ∧ False ↔ False := by
apply Iff.intro apply Iff.intro
· intro ⟨_, ff⟩ · intro ⟨_, ff⟩
exact ff exact ff
· intro ff · intro ff
exact False.elim ff exact False.elim ff
example : (p → q) → (¬q → ¬p) := by theorem imp_imp_not_imp_not : (p → q) → (¬q → ¬p) := by
intro hpq nq hp intro hpq nq hp
exact absurd (hpq hp) nq exact absurd (hpq hp) nq
end ex3_1 end ex3_1
-- ---------------------------------------- /-! ##### Exercises 3.2 -/
-- Exercises 3.2
-- ----------------------------------------
section ex3_2 section ex3_2
@ -166,7 +162,7 @@ open Classical
variable (p q r s : Prop) variable (p q r s : Prop)
example (hp : p) : (p → r s) → ((p → r) (p → s)) := by theorem imp_or_mp (hp : p) : (p → r s) → ((p → r) (p → s)) := by
intro h intro h
apply (h hp).elim apply (h hp).elim
· intro hr · intro hr
@ -174,7 +170,7 @@ example (hp : p) : (p → r s) → ((p → r) (p → s)) := by
· intro hs · intro hs
exact Or.inr (fun _ => hs) exact Or.inr (fun _ => hs)
example : ¬(p ∧ q) → ¬p ¬q := by theorem not_and_iff_or_not : ¬(p ∧ q) → ¬p ¬q := by
intro h intro h
apply (em p).elim apply (em p).elim
· intro hp · intro hp
@ -186,7 +182,7 @@ example : ¬(p ∧ q) → ¬p ¬q := by
· intro np · intro np
exact Or.inl np exact Or.inl np
example : ¬(p → q) → p ∧ ¬q := by theorem not_imp_mp : ¬(p → q) → p ∧ ¬q := by
intro h intro h
apply And.intro apply And.intro
· apply byContradiction · apply byContradiction
@ -199,7 +195,7 @@ example : ¬(p → q) → p ∧ ¬q := by
intro _ intro _
exact hq exact hq
example : (p → q) → (¬p q) := by theorem not_or_of_imp : (p → q) → (¬p q) := by
intro hpq intro hpq
apply (em p).elim apply (em p).elim
· intro hp · intro hp
@ -207,15 +203,15 @@ example : (p → q) → (¬p q) := by
· intro np · intro np
exact Or.inl np exact Or.inl np
example : (¬q → ¬p) → (p → q) := by theorem not_imp_not_imp_imp : (¬q → ¬p) → (p → q) := by
intro hqp hp intro hqp hp
apply byContradiction apply byContradiction
intro nq intro nq
exact absurd hp (hqp nq) exact absurd hp (hqp nq)
example : p ¬p := by apply em theorem or_not : p ¬p := by apply em
example : (((p → q) → p) → p) := by theorem imp_imp_imp : (((p → q) → p) → p) := by
intro h intro h
apply (em p).elim apply (em p).elim
· intro hp · intro hp
@ -227,30 +223,26 @@ example : (((p → q) → p) → p) := by
end ex3_2 end ex3_2
-- ---------------------------------------- /-! ##### Exercises 3.3 -/
-- Exercises 3.3
-- ----------------------------------------
section ex3_3 section ex3_3
variable (p : Prop) variable (p : Prop)
example (hp : p) : ¬(p ↔ ¬p) := by theorem iff_not_self (hp : p) : ¬(p ↔ ¬p) := by
intro h intro h
exact absurd hp (h.mp hp) exact absurd hp (h.mp hp)
end ex3_3 end ex3_3
-- ---------------------------------------- /-! ##### Exercises 4.1 -/
-- Exercises 4.1
-- ----------------------------------------
section ex4_1 section ex4_1
variable (α : Type _) variable (α : Type _)
variable (p q : α → Prop) variable (p q : α → Prop)
example : (∀ x, p x ∧ q x) ↔ (∀ x, p x) ∧ (∀ x, q x) := by theorem forall_and : (∀ x, p x ∧ q x) ↔ (∀ x, p x) ∧ (∀ x, q x) := by
apply Iff.intro apply Iff.intro
· intro h · intro h
apply And.intro apply And.intro
@ -261,20 +253,18 @@ example : (∀ x, p x ∧ q x) ↔ (∀ x, p x) ∧ (∀ x, q x) := by
have rhs : ∀ (x : α), q x := And.right h have rhs : ∀ (x : α), q x := And.right h
exact ⟨lhs hx, rhs hx⟩ exact ⟨lhs hx, rhs hx⟩
example : (∀ x, p x → q x) → (∀ x, p x) → (∀ x, q x) := by theorem forall_imp_distrib : (∀ x, p x → q x) → (∀ x, p x) → (∀ x, q x) := by
intro h₁ h₂ hx intro h₁ h₂ hx
exact h₁ hx (h₂ hx) exact h₁ hx (h₂ hx)
example : (∀ x, p x) (∀ x, q x) → ∀ x, p x q x := by theorem forall_or_distrib : (∀ x, p x) (∀ x, q x) → ∀ x, p x q x := by
intro intro
| Or.inl h => intro hx; exact Or.inl (h hx) | Or.inl h => intro hx; exact Or.inl (h hx)
| Or.inr h => intro hx; exact Or.inr (h hx) | Or.inr h => intro hx; exact Or.inr (h hx)
end ex4_1 end ex4_1
-- ---------------------------------------- /-! ##### Exercises 4.2 -/
-- Exercises 4.2
-- ----------------------------------------
section ex4_2 section ex4_2
@ -282,7 +272,7 @@ variable (α : Type _)
variable (p q : α → Prop) variable (p q : α → Prop)
variable (r : Prop) variable (r : Prop)
example : α → ((∀ _ : α, r) ↔ r) := by theorem self_imp_forall : α → ((∀ _ : α, r) ↔ r) := by
intro ha intro ha
apply Iff.intro apply Iff.intro
· intro har · intro har
@ -295,7 +285,7 @@ section
open Classical open Classical
example : (∀ x, p x r) ↔ (∀ x, p x) r := by theorem forall_or_right : (∀ x, p x r) ↔ (∀ x, p x) r := by
apply Iff.intro apply Iff.intro
· intro h · intro h
apply (em r).elim apply (em r).elim
@ -317,7 +307,7 @@ example : (∀ x, p x r) ↔ (∀ x, p x) r := by
end end
example : (∀ x, r → p x) ↔ (r → ∀ x, p x) := by theorem forall_swap : (∀ x, r → p x) ↔ (r → ∀ x, p x) := by
apply Iff.intro apply Iff.intro
· intro h hr hx · intro h hr hx
exact h hx hr exact h hx hr
@ -326,9 +316,7 @@ example : (∀ x, r → p x) ↔ (r → ∀ x, p x) := by
end ex4_2 end ex4_2
-- ---------------------------------------- /-! ##### Exercises 4.3 -/
-- Exercises 4.3
-- ----------------------------------------
section ex4_3 section ex4_3
@ -338,7 +326,8 @@ variable (men : Type _)
variable (barber : men) variable (barber : men)
variable (shaves : men → men → Prop) variable (shaves : men → men → Prop)
example (h : ∀ x : men, shaves barber x ↔ ¬ shaves x x) : False := by theorem barber_paradox (h : ∀ x : men, shaves barber x ↔ ¬ shaves x x)
: False := by
apply (em (shaves barber barber)).elim apply (em (shaves barber barber)).elim
· intro hb · intro hb
exact absurd hb ((h barber).mp hb) exact absurd hb ((h barber).mp hb)
@ -347,9 +336,7 @@ example (h : ∀ x : men, shaves barber x ↔ ¬ shaves x x) : False := by
end ex4_3 end ex4_3
-- ---------------------------------------- /-! ##### Exercises 4.5 -/
-- Exercises 4.5
-- ----------------------------------------
section ex4_5 section ex4_5
@ -359,22 +346,22 @@ variable (α : Type _)
variable (p q : α → Prop) variable (p q : α → Prop)
variable (r s : Prop) variable (r s : Prop)
example : (∃ _ : α, r) → r := by theorem exists_imp : (∃ _ : α, r) → r := by
intro ⟨_, hr⟩ intro ⟨_, hr⟩
exact hr exact hr
example (a : α) : r → (∃ _ : α, r) := by theorem exists_intro (a : α) : r → (∃ _ : α, r) := by
intro hr intro hr
exact ⟨a, hr⟩ exact ⟨a, hr⟩
example : (∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r := by theorem exists_and_right : (∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r := by
apply Iff.intro apply Iff.intro
· intro ⟨hx, hp, hr⟩ · intro ⟨hx, hp, hr⟩
exact ⟨⟨hx, hp⟩, hr⟩ exact ⟨⟨hx, hp⟩, hr⟩
· intro ⟨⟨hx, hp⟩, hr⟩ · intro ⟨⟨hx, hp⟩, hr⟩
exact ⟨hx, hp, hr⟩ exact ⟨hx, hp, hr⟩
example : (∃ x, p x q x) ↔ (∃ x, p x) (∃ x, q x) := by theorem exists_or : (∃ x, p x q x) ↔ (∃ x, p x) (∃ x, q x) := by
apply Iff.intro apply Iff.intro
· intro · intro
| ⟨hx, Or.inl hp⟩ => exact Or.inl ⟨hx, hp⟩ | ⟨hx, Or.inl hp⟩ => exact Or.inl ⟨hx, hp⟩
@ -383,7 +370,7 @@ example : (∃ x, p x q x) ↔ (∃ x, p x) (∃ x, q x) := by
| Or.inl ⟨hx, hp⟩ => exact ⟨hx, Or.inl hp⟩ | Or.inl ⟨hx, hp⟩ => exact ⟨hx, Or.inl hp⟩
| Or.inr ⟨hx, hq⟩ => exact ⟨hx, Or.inr hq⟩ | Or.inr ⟨hx, hq⟩ => exact ⟨hx, Or.inr hq⟩
example : (∀ x, p x) ↔ ¬(∃ x, ¬p x) := by theorem forall_iff_not_exists : (∀ x, p x) ↔ ¬(∃ x, ¬p x) := by
apply Iff.intro apply Iff.intro
· intro ha ⟨hx, np⟩ · intro ha ⟨hx, np⟩
exact absurd (ha hx) np exact absurd (ha hx) np
@ -392,7 +379,7 @@ example : (∀ x, p x) ↔ ¬(∃ x, ¬p x) := by
intro np intro np
exact he ⟨hx, np⟩ exact he ⟨hx, np⟩
example : (∃ x, p x) ↔ ¬(∀ x, ¬p x) := by theorem exists_iff_not_forall : (∃ x, p x) ↔ ¬(∀ x, ¬p x) := by
apply Iff.intro apply Iff.intro
· intro ⟨hx, hp⟩ h · intro ⟨hx, hp⟩ h
exact absurd hp (h hx) exact absurd hp (h hx)
@ -403,7 +390,7 @@ example : (∃ x, p x) ↔ ¬(∀ x, ¬p x) := by
intro hx hp intro hx hp
exact h₂ ⟨hx, hp⟩ exact h₂ ⟨hx, hp⟩
example : (¬∃ x, p x) ↔ (∀ x, ¬p x) := by theorem not_exists : (¬∃ x, p x) ↔ (∀ x, ¬p x) := by
apply Iff.intro apply Iff.intro
· intro h hx hp · intro h hx hp
exact h ⟨hx, hp⟩ exact h ⟨hx, hp⟩
@ -422,16 +409,16 @@ theorem forall_negation : (¬∀ x, p x) ↔ (∃ x, ¬p x) := by
· intro ⟨hx, np⟩ h · intro ⟨hx, np⟩ h
exact absurd (h hx) np exact absurd (h hx) np
example : (¬∀ x, p x) ↔ (∃ x, ¬p x) := forall_negation α p theorem not_forall : (¬∀ x, p x) ↔ (∃ x, ¬p x) := forall_negation α p
example : (∀ x, p x → r) ↔ (∃ x, p x) → r := by theorem forall_iff_exists_imp : (∀ x, p x → r) ↔ (∃ x, p x) → r := by
apply Iff.intro apply Iff.intro
· intro h ⟨hx, hp⟩ · intro h ⟨hx, hp⟩
exact h hx hp exact h hx hp
· intro h hx hp · intro h hx hp
exact h ⟨hx, hp⟩ exact h ⟨hx, hp⟩
example (a : α) : (∃ x, p x → r) ↔ (∀ x, p x) → r := by theorem exists_iff_forall_imp (a : α) : (∃ x, p x → r) ↔ (∀ x, p x) → r := by
apply Iff.intro apply Iff.intro
· intro ⟨hx, hp⟩ h · intro ⟨hx, hp⟩ h
apply hp apply hp
@ -444,7 +431,8 @@ example (a : α) : (∃ x, p x → r) ↔ (∀ x, p x) → r := by
have ⟨hx, np⟩ : (∃ x, ¬p x) := (forall_negation α p).mp h₂ have ⟨hx, np⟩ : (∃ x, ¬p x) := (forall_negation α p).mp h₂
exact ⟨hx, fun hp => absurd hp np⟩ exact ⟨hx, fun hp => absurd hp np⟩
example (a : α) : (∃ x, r → p x) ↔ (r → ∃ x, p x) := by theorem exists_self_iff_self_exists (a : α)
: (∃ x, r → p x) ↔ (r → ∃ x, p x) := by
apply Iff.intro apply Iff.intro
· intro ⟨hx, h⟩ hr · intro ⟨hx, h⟩ hr
exact ⟨hx, h hr⟩ exact ⟨hx, h hr⟩
@ -460,15 +448,17 @@ end ex4_5
end ex1 end ex1
-- ======================================== /-! #### Exercise 2
-- Exercise 2
-- Use tactic combinators to obtain a one line proof of the following:
-- Use tactic combinators to obtain a one line proof of the following: -/
-- ========================================
namespace ex2 namespace ex2
example (p q r : Prop) (hp : p) : (p q r) ∧ (q p r) ∧ (q r p) := theorem or_and_or_and_or (p q r : Prop) (hp : p)
by simp [*] : (p q r) ∧ (q p r) ∧ (q r p) := by
simp [*]
end ex2 end ex2
end Exercises.Avigad.Chapter5

View File

@ -1,22 +1,22 @@
/- /-! # Exercises.Avigad.Chapter7
Chapter 7
Inductive Types Inductive Types
-/ -/
-- ======================================== namespace Exercises.Avigad.Chapter7
-- Exercise 1
-- /-! #### Exercise 1
-- Try defining other operations on the natural numbers, such as multiplication,
-- the predecessor function (with `pred 0 = 0`), truncated subtraction (with Try defining other operations on the natural numbers, such as multiplication,
-- `n - m = 0` when `m` is greater than or equal to `n`), and exponentiation. the predecessor function (with `pred 0 = 0`), truncated subtraction (with
-- Then try proving some of their basic properties, building on the theorems we `n - m = 0` when `m` is greater than or equal to `n`), and exponentiation. Then
-- have already proved. try proving some of their basic properties, building on the theorems we have
-- already proved.
-- Since many of these are already defined in Leans core library, you should
-- work within a namespace named hide, or something like that, in order to avoid Since many of these are already defined in Leans core library, you should work
-- name clashes. within a namespace named hide, or something like that, in order to avoid name
-- ======================================== clashes.
-/
namespace ex1 namespace ex1
@ -77,16 +77,17 @@ end Nat
end ex1 end ex1
-- ======================================== /-! #### Exercise 2
-- Exercise 2
-- Define some operations on lists, like a `length` function or the `reverse`
-- Define some operations on lists, like a `length` function or the `reverse` function. Prove some properties, such as the following:
-- function. Prove some properties, such as the following:
-- a. `length (s ++ t) = length s + length t`
-- a. `length (s ++ t) = length s + length t`
-- b. `length (reverse t) = length t` b. `length (reverse t) = length t`
-- c. `reverse (reverse t) = t`
-- ======================================== c. `reverse (reverse t) = t`
-/
namespace ex2 namespace ex2
@ -177,20 +178,22 @@ theorem reverse_reverse (t : List α)
end ex2 end ex2
-- ======================================== /-! #### Exercise 3
-- Exercise 3
-- Define an inductive data type consisting of terms built up from the following
-- Define an inductive data type consisting of terms built up from the following constructors:
-- constructors:
-- • `const n`, a constant denoting the natural number `n`
-- • `const n`, a constant denoting the natural number `n`
-- • `var n`, a variable, numbered `n` • `var n`, a variable, numbered `n`
-- • `plus s t`, denoting the sum of `s` and `t`
-- • `times s t`, denoting the product of `s` and `t` • `plus s t`, denoting the sum of `s` and `t`
--
-- Recursively define a function that evaluates any such term with respect to an • `times s t`, denoting the product of `s` and `t`
-- assignment of values to the variables.
-- ======================================== Recursively define a function that evaluates any such term with respect to an
assignment of values to the variables.
-/
namespace ex3 namespace ex3
@ -213,3 +216,5 @@ def eval_foo : Foo → List Nat → Nat
| (Foo.times m n), vs => eval_foo m vs * eval_foo n vs | (Foo.times m n), vs => eval_foo m vs * eval_foo n vs
end ex3 end ex3
end Exercises.Avigad.Chapter7

View File

@ -1,17 +1,17 @@
/- /-! # Exercises.Avigad.Chapter8
Chapter 8
Induction and Recursion Induction and Recursion
-/ -/
-- ======================================== namespace Exercises.Avigad.Chapter8
-- Exercise 1
-- /-! #### Exercise 1
-- Open a namespace `Hidden` to avoid naming conflicts, and use the equation
-- compiler to define addition, multiplication, and exponentiation on the Open a namespace `Hidden` to avoid naming conflicts, and use the equation
-- natural numbers. Then use the equation compiler to derive some of their basic compiler to define addition, multiplication, and exponentiation on the natural
-- properties. numbers. Then use the equation compiler to derive some of their basic
-- ======================================== properties.
-/
namespace ex1 namespace ex1
@ -29,13 +29,12 @@ def exp : Nat → Nat → Nat
end ex1 end ex1
-- ======================================== /-! #### Exercise 2
-- Exercise 2
-- Similarly, use the equation compiler to define some basic operations on lists
-- Similarly, use the equation compiler to define some basic operations on lists (like the reverse function) and prove theorems about lists by induction (such as
-- (like the reverse function) and prove theorems about lists by induction (such the fact that `reverse (reverse xs) = xs` for any list `xs`).
-- as the fact that `reverse (reverse xs) = xs` for any list `xs`). -/
-- ========================================
namespace ex2 namespace ex2
@ -49,13 +48,12 @@ def reverse : List α → List α
end ex2 end ex2
-- ======================================== /-! #### Exercise 3
-- Exercise 3
-- Define your own function to carry out course-of-value recursion on the natural
-- Define your own function to carry out course-of-value recursion on the numbers. Similarly, see if you can figure out how to define `WellFounded.fix` on
-- natural numbers. Similarly, see if you can figure out how to define your own.
-- `WellFounded.fix` on your own. -/
-- ========================================
namespace ex3 namespace ex3
@ -88,13 +86,12 @@ noncomputable def brecOn {motive : Nat → Sort u}
end ex3 end ex3
-- ======================================== /-! #### Exercise 4
-- Exercise 4
-- Following the examples in Section Dependent Pattern Matching, define a function
-- Following the examples in Section Dependent Pattern Matching, define a that will append two vectors. This is tricky; you will have to define an
-- function that will append two vectors. This is tricky; you will have to auxiliary function.
-- define an auxiliary function. -/
-- ========================================
namespace ex4 namespace ex4
@ -116,11 +113,10 @@ end Vector
end ex4 end ex4
-- ======================================== /-! #### Exercise 5
-- Exercise 5
-- Consider the following type of arithmetic expressions.
-- Consider the following type of arithmetic expressions. The ideSure, looks like RDS w -/
-- ========================================
namespace ex5 namespace ex5
@ -153,12 +149,13 @@ def sampleVal : Nat → Nat
-- Try it out. You should get 47 here. -- Try it out. You should get 47 here.
#eval eval sampleVal sampleExpr #eval eval sampleVal sampleExpr
-- ---------------------------------------- /-! ##### Constant Fusion
-- Implement "constant fusion," a procedure that simplifies subterms like
-- `5 + 7` to `12`. Using the auxiliary function `simpConst`, define a function Implement "constant fusion," a procedure that simplifies subterms like `5 + 7
-- "fuse": to simplify a plus or a times, first simplify the arguments to `12`. Using the auxiliary function `simpConst`, define a function "fuse": to
-- recursively, and then apply `simpConst` to try to simplify the result. simplify a plus or a times, first simplify the arguments recursively, and then
-- ---------------------------------------- apply `simpConst` to try to simplify the result.
-/
def simpConst : Expr → Expr def simpConst : Expr → Expr
| plus (const n₁) (const n₂) => const (n₁ + n₂) | plus (const n₁) (const n₂) => const (n₁ + n₂)
@ -208,3 +205,5 @@ theorem fuse_eq (v : Nat → Nat)
-- The last two theorems show that the definitions preserve the value. -- The last two theorems show that the definitions preserve the value.
end ex5 end ex5
end Exercises.Avigad.Chapter8

View File

@ -1,3 +1 @@
-- Enderton, Herbert B. A Mathematical Introduction to Logic. 2nd ed. San Diego:
-- Harcourt/Academic Press, 2001.
import Exercises.Enderton.Chapter0 import Exercises.Enderton.Chapter0

View File

@ -1,10 +1,11 @@
/- import Bookshelf.LTuple.Basic
Chapter 0
/-! # Exercises.Enderton.Chapter0
Useful Facts About Sets Useful Facts About Sets
-/ -/
import Bookshelf.LTuple.Basic namespace Exercises.Enderton.Chapter0
/-- /--
The following describes a so-called "generic" tuple. Like an `LTuple`, a generic The following describes a so-called "generic" tuple. Like an `LTuple`, a generic
@ -45,9 +46,7 @@ namespace GTuple
open scoped LTuple open scoped LTuple
-- ======================================== /-! ## Normalization -/
-- Normalization
-- ========================================
/-- /--
Converts an `GTuple` into "normal form". Converts an `GTuple` into "normal form".
@ -104,9 +103,7 @@ theorem norm_snoc_eq_concat {t₁ : GTuple α (p, q)} {t₂ : LTuple α n}
: norm (snoc t₁ t₂) = LTuple.concat t₁.norm t₂ := by : norm (snoc t₁ t₂) = LTuple.concat t₁.norm t₂ := by
conv => lhs; unfold norm conv => lhs; unfold norm
-- ======================================== /-! ## Equality -/
-- Equality
-- ========================================
/-- /--
Implements Boolean equality for `GTuple α n` provided `α` has decidable Implements Boolean equality for `GTuple α n` provided `α` has decidable
@ -115,9 +112,7 @@ equality.
instance BEq [DecidableEq α] : BEq (GTuple α n) where instance BEq [DecidableEq α] : BEq (GTuple α n) where
beq t₁ t₂ := t₁.norm == t₂.norm beq t₁ t₂ := t₁.norm == t₂.norm
-- ======================================== /-! ## Basic API -/
-- Basic API
-- ========================================
/-- /--
Returns the number of entries in the `GTuple`. Returns the number of entries in the `GTuple`.
@ -176,12 +171,7 @@ def snd : GTuple α (m, n) → LTuple α n
end GTuple end GTuple
-- ======================================== /-! ## Lemma 0A -/
-- Lemma 0A
--
-- Assume that `⟨x₁, ..., xₘ⟩ = ⟨y₁, ..., yₘ, ..., yₘ₊ₖ⟩`. Then
-- `x₁ = ⟨y₁, ..., yₖ₊₁⟩`.
-- ========================================
section section
@ -238,8 +228,7 @@ private def cast_fst : GTuple α (n, m - 1) → LTuple α (k + 1)
private def cast_take (ys : LTuple α (m + k)) := private def cast_take (ys : LTuple α (m + k)) :=
cast (by rw [min_comm_succ_eq p]) (ys.take (k + 1)) cast (by rw [min_comm_succ_eq p]) (ys.take (k + 1))
/-- /-- #### Lemma 0A
Lemma 0A
Assume that `⟨x₁, ..., xₘ⟩ = ⟨y₁, ..., yₘ, ..., yₘ₊ₖ⟩`. Then Assume that `⟨x₁, ..., xₘ⟩ = ⟨y₁, ..., yₘ, ..., yₘ₊ₖ⟩`. Then
`x₁ = ⟨y₁, ..., yₖ₊₁⟩`. `x₁ = ⟨y₁, ..., yₖ₊₁⟩`.
@ -284,4 +273,6 @@ theorem lemma_0a (xs : GTuple α (n, m - 1)) (ys : LTuple α (m + k))
(show LTuple α (min (n + (m - 1)) n) = LTuple α n by simp) (show LTuple α (min (n + (m - 1)) n) = LTuple α n by simp)
h₂ h₂
end end
end Exercises.Enderton.Chapter0

View File

@ -1,2 +1 @@
-- Fraleigh, John B. A First Course in Abstract Algebra, n.d.
import Exercises.Fraleigh.Chapter1 import Exercises.Fraleigh.Chapter1

View File

@ -1,18 +1,24 @@
/- import Mathlib.Data.Complex.Basic
Chapter 1
/-! # Exercises.Fraleign.Chapter1
Introduction and Examples Introduction and Examples
-/ -/
import Mathlib.Data.Complex.Basic namespace Exercises.Fraleign.Chapter1
open Complex open Complex
open HPow open HPow
-- In Exercises 1 through 9 compute the given arithmetic expression and give the /-! ## Exercises 1 Through 9
-- answer in the form $a + bi$ for $a, b ∈ $.
theorem ex1_1 : I^3 = 0 + (-1) * I := calc In Exercises 1 through 9 compute the given arithmetic expression and give the
answer in the form `a + bi` for `a, b ∈ `.
-/
theorem exercise1 : I^3 = 0 + (-1) * I := calc
I^3 I^3
= I * (I * hPow I 1) := rfl = I * (I * hPow I 1) := rfl
_ = 0 + (-1) * I := by simp _ = 0 + (-1) * I := by simp
end Exercises.Fraleign.Chapter1