Addition

Analysis I, Section 2.2: Addition

This file is a translation of Section 2.2 of Analysis I to Lean 4. All numbering refers to the original text.

I have attempted to make the translation as faithful a paraphrasing as possible of the original text. When there is a choice between a more idiomatic Lean solution and a more faithful translation, I have generally chosen the latter. In particular, there will be places where the Lean code could be "golfed" to be more elegant and idiomatic, but I have consciously avoided doing so.

Main constructions and results of this section:

  • Definition of addition and order for the "Chapter 2" natural numbers, Chapter2.Nat : TypeChapter2.Nat.

  • Establishment of basic properties of addition and order.

Note: at the end of this chapter, the Chapter2.Nat : TypeChapter2.Nat class will be deprecated in favor of the standard Mathlib class Nat : Type_root_.Nat, or : Type. However, we will develop the properties of Chapter2.Nat : TypeChapter2.Nat "by hand" for pedagogical purposes.

Tips from past users

Users of the companion who have completed the exercises in this section are welcome to send their tips for future users in this section as PRs.

  • (Add tip here)

namespace Chapter2

Definition 2.2.1. (Addition of natural numbers). Compare with Mathlib's Chapter2.Nat.add (n m : Nat) : NatNat.add

abbrev Nat.add (n m : Nat) : Nat := Nat.recurse (fun _ sum sum++) m n

This instance allows for the notation to be used for natural number addition.

instance Nat.instAdd : Add Nat where add := add

Compare with Mathlib's Chapter2.Nat.zero_add (m : Nat) : 0 + m = mNat.zero_add.

@[simp] theorem Nat.zero_add (m: Nat) : 0 + m = m := recurse_zero (fun _ sum sum++) _

Compare with Mathlib's Chapter2.Nat.succ_add (n m : Nat) : n++ + m = (n + m)++Nat.succ_add.

theorem Nat.succ_add (n m: Nat) : n++ + m = (n+m)++ := n:Natm:Natn++ + m = (n + m)++ All goals completed! 🐙

Compare with Mathlib's Chapter2.Nat.one_add (m : Nat) : 1 + m = m++Nat.one_add.

theorem Nat.one_add (m:Nat) : 1 + m = m++ := m:Nat1 + m = m++ All goals completed! 🐙
theorem Nat.two_add (m:Nat) : 2 + m = (m++)++ := m:Nat2 + m = m++++ All goals completed! 🐙example : (2:Nat) + 3 = 5 := 2 + 3 = 5 All goals completed! 🐙
fun n m => n + m : Nat  Nat  Nat

Lemma 2.2.2 (n + 0 = n). Compare with Mathlib's Chapter2.Nat.add_zero (n : Nat) : n + 0 = nNat.add_zero.

@[simp] lemma Nat.add_zero (n:Nat) : n + 0 = n := n:Natn + 0 = n -- This proof is written to follow the structure of the original text. (n : Nat), n + 0 = n; 0 + 0 = 0 (n : Nat), n + 0 = n n++ + 0 = n++ 0 + 0 = 0 All goals completed! 🐙 n:Natih:n + 0 = nn++ + 0 = n++ calc (n++) + 0 = (n + 0)++ := n:Natih:n + 0 = nn++ + 0 = (n + 0)++ All goals completed! 🐙 _ = n++ := n:Natih:n + 0 = n(n + 0)++ = n++ All goals completed! 🐙

Lemma 2.2.3 (n+(m++) = (n+m)++). Compare with Mathlib's Chapter2.Nat.add_succ (n m : Nat) : n + m++ = (n + m)++Nat.add_succ.

lemma Nat.add_succ (n m:Nat) : n + (m++) = (n + m)++ := n:Natm:Natn + m++ = (n + m)++ -- this proof is written to follow the structure of the original text. m:Nat (n : Nat), n + m++ = (n + m)++; m:Nat0 + m++ = (0 + m)++m:Nat (n : Nat), n + m++ = (n + m)++ n++ + m++ = (n++ + m)++ m:Nat0 + m++ = (0 + m)++ All goals completed! 🐙 m:Natn:Natih:n + m++ = (n + m)++n++ + m++ = (n++ + m)++ m:Natn:Natih:n + m++ = (n + m)++(n + m)++++ = (n++ + m)++ All goals completed! 🐙

n++ = n + 1 (Why?). Compare with Mathlib's Chapter2.Nat.succ_eq_add_one (n : Nat) : n++ = n + 1Nat.succ_eq_add_one

theorem declaration uses 'sorry'Nat.succ_eq_add_one (n:Nat) : n++ = n + 1 := n:Natn++ = n + 1 All goals completed! 🐙

Proposition 2.2.4 (Addition is commutative). Compare with Mathlib's Chapter2.Nat.add_comm (n m : Nat) : n + m = m + nNat.add_comm

theorem Nat.add_comm (n m:Nat) : n + m = m + n := n:Natm:Natn + m = m + n -- this proof is written to follow the structure of the original text. m:Nat (n : Nat), n + m = m + n; m:Nat0 + m = m + 0m:Nat (n : Nat), n + m = m + n n++ + m = m + n++ m:Nat0 + m = m + 0 All goals completed! 🐙 m:Natn:Natih:n + m = m + nn++ + m = m + n++ m:Natn:Natih:n + m = m + n(n + m)++ = m + n++ All goals completed! 🐙

Proposition 2.2.5 (Addition is associative) / Exercise 2.2.1 Compare with Mathlib's Chapter2.Nat.add_assoc (a b c : Nat) : a + b + c = a + (b + c)Nat.add_assoc.

theorem declaration uses 'sorry'Nat.add_assoc (a b c:Nat) : (a + b) + c = a + (b + c) := a:Natb:Natc:Nata + b + c = a + (b + c) All goals completed! 🐙

Proposition 2.2.6 (Cancellation law). Compare with Mathlib's Chapter2.Nat.add_left_cancel (a b c : Nat) (habc : a + b = a + c) : b = cNat.add_left_cancel.

theorem Nat.add_left_cancel (a b c:Nat) (habc: a + b = a + c) : b = c := a:Natb:Natc:Nathabc:a + b = a + cb = c -- This proof is written to follow the structure of the original text. b:Natc:Nat (a : Nat), a + b = a + c b = c; b:Natc:Nat0 + b = 0 + c b = cb:Natc:Nat (n : Nat), (n + b = n + c b = c) n++ + b = n++ + c b = c b:Natc:Nat0 + b = 0 + c b = c b:Natc:Nathbc:0 + b = 0 + cb = c rwa [zero_add, zero_addb:Natc:Nathbc:b = cb = c at hbc b:Natc:Nata:Natih:a + b = a + c b = ca++ + b = a++ + c b = c b:Natc:Nata:Natih:a + b = a + c b = chbc:a++ + b = a++ + cb = c b:Natc:Nata:Natih:a + b = a + c b = chbc:(a + b)++ = (a + c)++b = c b:Natc:Nata:Natih:a + b = a + c b = chbc:?_mvar.2309 := Chapter2.Nat.succ_cancel _fvar.2300b = c All goals completed! 🐙

(Not from textbook) Nat can be given the structure of a commutative additive monoid. This permits tactics such as Unknown identifier `abel`abel to apply to the Chapter 2 natural numbers.

instance Nat.addCommMonoid : AddCommMonoid Nat where add_assoc := add_assoc add_comm := add_comm zero_add := zero_add add_zero := add_zero nsmul := nsmulRec

This illustration of the Unknown identifier `abel`abel tactic is not from the textbook.

example (a b c d:Nat) : (a+b)+(c+0+d) = (b+c)+(d+a) := a:Natb:Natc:Natd:Nata + b + (c + 0 + d) = b + c + (d + a) All goals completed! 🐙

Definition 2.2.7 (Positive natural numbers).

def Nat.IsPos (n:Nat) : Prop := n 0
theorem Nat.isPos_iff (n:Nat) : n.IsPos n 0 := n:Natn.IsPos n 0 All goals completed! 🐙

Proposition 2.2.8 (positive plus natural number is positive). Compare with Mathlib's Chapter2.Nat.add_pos_left {a : Nat} (b : Nat) (ha : a.IsPos) : (a + b).IsPosNat.add_pos_left.

theorem Nat.add_pos_left {a:Nat} (b:Nat) (ha: a.IsPos) : (a + b).IsPos := a:Natb:Natha:a.IsPos(a + b).IsPos -- This proof is written to follow the structure of the original text. a:Natha:a.IsPos (b : Nat), (a + b).IsPos; a:Natha:a.IsPos(a + 0).IsPosa:Natha:a.IsPos (n : Nat), (a + n).IsPos (a + n++).IsPos a:Natha:a.IsPos(a + 0).IsPos rwa [add_zeroa:Natha:a.IsPosa.IsPos a:Natha:a.IsPosb:Nathab:(a + b).IsPos(a + b++).IsPos a:Natha:a.IsPosb:Nathab:(a + b).IsPos(a + b)++.IsPos a:Natha:a.IsPosb:Nathab:(a + b).IsPosthis:(_fvar.4023 + _fvar.4071)++ 0 := Chapter2.Nat.succ_ne ?_mvar.4176(a + b)++.IsPos All goals completed! 🐙

Compare with Mathlib's Chapter2.Nat.add_pos_right {a : Nat} (b : Nat) (ha : a.IsPos) : (b + a).IsPosNat.add_pos_right.

This theorem is a consequence of the previous theorem and add_comm.{u_1} {G : Type u_1} [AddCommMagma G] (a b : G) : a + b = b + aadd_comm, and Unknown identifier `grind`grind can automatically discover such proofs.

theorem Nat.add_pos_right {a:Nat} (b:Nat) (ha: a.IsPos) : (b + a).IsPos := a:Natb:Natha:a.IsPos(b + a).IsPos All goals completed! 🐙

Corollary 2.2.9 (if sum vanishes, then summands vanish). Compare with Mathlib's Chapter2.Nat.add_eq_zero (a b : Nat) (hab : a + b = 0) : a = 0 b = 0Nat.add_eq_zero.

theorem Nat.add_eq_zero (a b:Nat) (hab: a + b = 0) : a = 0 b = 0 := a:Natb:Nathab:a + b = 0a = 0 b = 0 -- This proof is written to follow the structure of the original text. a:Natb:Nathab:a + b = 0h:¬(a = 0 b = 0)False a:Natb:Nathab:a + b = 0h:a 0 b 0False a:Natb:Nathab:a + b = 0ha:a 0Falsea:Natb:Nathab:a + b = 0hb:b 0False a:Natb:Nathab:a + b = 0ha:a 0False a:Natb:Nathab:a + b = 0ha:a.IsPosFalse a:Natb:Nathab:a + b = 0ha:a.IsPosthis:(a + b).IsPosFalse All goals completed! 🐙 a:Natb:Nathab:a + b = 0hb:b.IsPosFalse a:Natb:Nathab:a + b = 0hb:b.IsPosthis:(a + b).IsPosFalse All goals completed! 🐙
existsUnique_of_exists_of_unique.{u_1} {α : Sort u_1} {p : α  Prop} (hex :  x, p x)
  (hunique :  (y₁ y₂ : α), p y₁  p y₂  y₁ = y₂) : ∃! x, p x

Lemma 2.2.10 (unique predecessor) / Exercise 2.2.2

lemma declaration uses 'sorry'Nat.uniq_succ_eq (a:Nat) (ha: a.IsPos) : ∃! b, b++ = a := a:Natha:a.IsPos∃! b, b++ = a All goals completed! 🐙

Definition 2.2.11 (Ordering of the natural numbers). This defines the notation on the natural numbers.

instance Nat.instLE : LE Nat where le n m := a:Nat, m = n + a

Definition 2.2.11 (Ordering of the natural numbers). This defines the notation on the natural numbers.

instance Nat.instLT : LT Nat where lt n m := n m n m
lemma Nat.le_iff (n m:Nat) : n m a:Nat, m = n + a := n:Natm:Natn m a, m = n + a All goals completed! 🐙lemma Nat.lt_iff (n m:Nat) : n < m ( a:Nat, m = n + a) n m := n:Natm:Natn < m (∃ a, m = n + a) n m All goals completed! 🐙

Compare with Mathlib's ge_iff_le.{u_1} {α : Type u_1} [LE α] {x y : α} : x y y xge_iff_le.

@[symm] lemma Nat.ge_iff_le (n m:Nat) : n m m n := n:Natm:Natn m m n All goals completed! 🐙

Compare with Mathlib's gt_iff_lt.{u_1} {α : Type u_1} [LT α] {x y : α} : x > y y < xgt_iff_lt.

@[symm] lemma Nat.gt_iff_lt (n m:Nat) : n > m m < n := n:Natm:Natn > m m < n All goals completed! 🐙

Compare with Mathlib's Chapter2.Nat.le_of_lt {n m : Nat} (hnm : n < m) : n mNat.le_of_lt.

lemma Nat.le_of_lt {n m:Nat} (hnm: n < m) : n m := hnm.1

Compare with Mathlib's Chapter2.Nat.le_iff_lt_or_eq (n m : Nat) : n m n < m n = mNat.le_iff_lt_or_eq.

lemma Nat.le_iff_lt_or_eq (n m:Nat) : n m n < m n = m := n:Natm:Natn m n < m n = m n:Natm:Nat(∃ a, m = n + a) (∃ a, m = n + a) n m n = m n:Natm:Nath:n = m(∃ a, m = n + a) (∃ a, m = n + a) n m n = mn:Natm:Nath:¬n = m(∃ a, m = n + a) (∃ a, m = n + a) n m n = m n:Natm:Nath:n = m(∃ a, m = n + a) (∃ a, m = n + a) n m n = m n:Natm:Nath:n = m a, m = m + a n:Natm:Nath:n = mm = m + 0 All goals completed! 🐙 All goals completed! 🐙
example : (8:Nat) > 5 := 8 > 5 (∃ a, 8 = 5 + a) 5 8 a, 8 = 5 + a5 8 a, 8 = 5 + a have : (8:Nat) = 5 + 3 := 8 > 5 All goals completed! 🐙 this:8 = 5 + 3 := ?_mvar.63377 a, 5 + 3 = 5 + a All goals completed! 🐙 All goals completed! 🐙

Compare with Mathlib's Nat.lt_succ_self (n : ) : n < n.succNat.lt_succ_self.

theorem declaration uses 'sorry'Nat.succ_gt_self (n:Nat) : n++ > n := n:Natn++ > n All goals completed! 🐙

Proposition 2.2.12 (Basic properties of order for natural numbers) / Exercise 2.2.3

(a) (Order is reflexive). Compare with Mathlib's Chapter2.Nat.le_refl (a : Nat) : a aNat.le_refl.

theorem declaration uses 'sorry'Nat.ge_refl (a:Nat) : a a := a:Nata a All goals completed! 🐙
@[refl] theorem Nat.le_refl (a:Nat) : a a := a.ge_refl

The refl tag allows for the rfl.{u} {α : Sort u} {a : α} : a = arfl tactic to work for inequalities.

example (a b:Nat): a+b a+b := a:Natb:Nata + b a + b All goals completed! 🐙

(b) (Order is transitive). The Unknown identifier `obtain`obtain tactic will be useful here. Compare with Mathlib's Chapter2.Nat.le_trans {a b c : Nat} (hab : a b) (hbc : b c) : a cNat.le_trans.

theorem declaration uses 'sorry'Nat.ge_trans {a b c:Nat} (hab: a b) (hbc: b c) : a c := a:Natb:Natc:Nathab:a bhbc:b ca c All goals completed! 🐙
theorem Nat.le_trans {a b c:Nat} (hab: a b) (hbc: b c) : a c := Nat.ge_trans hbc hab

(c) (Order is anti-symmetric). Compare with Mathlib's Nat.le_antisymm {n m : } (h₁ : n m) (h₂ : m n) : n = mNat.le_antisymm.

theorem declaration uses 'sorry'Nat.ge_antisymm {a b:Nat} (hab: a b) (hba: b a) : a = b := a:Natb:Nathab:a bhba:b aa = b All goals completed! 🐙

(d) (Addition preserves order). Compare with Mathlib's Chapter2.Nat.add_le_add_right (a b c : Nat) : a b a + c b + cNat.add_le_add_right.

theorem declaration uses 'sorry'Nat.add_ge_add_right (a b c:Nat) : a b a + c b + c := a:Natb:Natc:Nata b a + c b + c All goals completed! 🐙

(d) (Addition preserves order). Compare with Mathlib's Chapter2.Nat.add_le_add_left (a b c : Nat) : a b c + a c + bNat.add_le_add_left.

theorem Nat.add_ge_add_left (a b c:Nat) : a b c + a c + b := a:Natb:Natc:Nata b c + a c + b a:Natb:Natc:Nata b a + c b + c All goals completed! 🐙

(d) (Addition preserves order). Compare with Mathlib's Chapter2.Nat.add_le_add_right (a b c : Nat) : a b a + c b + cNat.add_le_add_right.

theorem Nat.add_le_add_right (a b c:Nat) : a b a + c b + c := add_ge_add_right _ _ _

(d) (Addition preserves order). Compare with Mathlib's Chapter2.Nat.add_le_add_left (a b c : Nat) : a b c + a c + bNat.add_le_add_left.

theorem Nat.add_le_add_left (a b c:Nat) : a b c + a c + b := add_ge_add_left _ _ _

(e) a < b iff a++ ≤ b. Compare with Mathlib's Nat.succ_le_iff {m n : } : m.succ n m < nNat.succ_le_iff.

theorem declaration uses 'sorry'Nat.lt_iff_succ_le (a b:Nat) : a < b a++ b := a:Natb:Nata < b a++ b All goals completed! 🐙

(f) a < b if and only if b = a + d for positive d.

theorem declaration uses 'sorry'Nat.lt_iff_add_pos (a b:Nat) : a < b d:Nat, d.IsPos b = a + d := a:Natb:Nata < b d, d.IsPos b = a + d All goals completed! 🐙

If a < b then a ̸= b,

theorem Nat.ne_of_lt (a b:Nat) : a < b a b := a:Natb:Nata < b a b a:Natb:Nath:a < ba b; All goals completed! 🐙

if a > b then a ̸= b.

theorem Nat.ne_of_gt (a b:Nat) : a > b a b := a:Natb:Nata > b a b a:Natb:Nath:a > ba b; All goals completed! 🐙

If a > b and a < b then contradiction

theorem Nat.not_lt_of_gt (a b:Nat) : a < b a > b False := a:Natb:Nata < b a > b False a:Natb:Nath:a < b a > bFalse a:Natb:Nath:a < b a > bthis:?_mvar.64965 := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)False a:Natb:Nath:a < b a > bthis✝:?_mvar.64965 := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)this:?_mvar.65002 := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)False All goals completed! 🐙
theorem Nat.not_lt_self {a: Nat} (h : a < a) : False := a:Nath:a < aFalse a:Nath:a < aa < a a > a All goals completed! 🐙theorem Nat.lt_of_le_of_lt {a b c : Nat} (hab: a b) (hbc: b < c) : a < c := a:Natb:Natc:Nathab:a bhbc:b < ca < c a:Natb:Natc:Nathab:a bhbc: d, d.IsPos c = b + d d, d.IsPos c = a + d a:Natb:Natc:Nathbc: d, d.IsPos c = b + dd:Nathd:b = a + d d, d.IsPos c = a + d a:Natb:Natc:Natd:Nathd:b = a + de:Nathe1:e.IsPoshe2:c = b + e d, d.IsPos c = a + d a:Natb:Natc:Natd:Nathd:b = a + de:Nathe1:e.IsPoshe2:c = b + e(d + e).IsPos c = a + (d + e); a:Natb:Natc:Natd:Nathd:b = a + de:Nathe1:e.IsPoshe2:c = b + e(d + e).IsPosa:Natb:Natc:Natd:Nathd:b = a + de:Nathe1:e.IsPoshe2:c = b + ec = a + (d + e) a:Natb:Natc:Natd:Nathd:b = a + de:Nathe1:e.IsPoshe2:c = b + e(d + e).IsPos All goals completed! 🐙 a:Natb:Natc:Natd:Nathd:b = a + de:Nathe1:e.IsPoshe2:c = b + ec = a + (d + e) All goals completed! 🐙

This lemma was a Unknown identifier `why?`why? statement from Proposition 2.2.13, but is more broadly useful, so is extracted here.

theorem declaration uses 'sorry'Nat.zero_le (a:Nat) : 0 a := a:Nat0 a All goals completed! 🐙

Proposition 2.2.13 (Trichotomy of order for natural numbers) / Exercise 2.2.4 Compare with Mathlib's trichotomous.{u_1} {α : Sort u_1} {r : α α Prop} [IsTrichotomous α r] (a b : α) : r a b a = b r b atrichotomous. Parts of this theorem have been placed in the preceding Lean theorems.

theorem declaration uses 'sorry'Nat.trichotomous (a b:Nat) : a < b a = b a > b := a:Natb:Nata < b a = b a > b -- This proof is written to follow the structure of the original text. b:Nat (a : Nat), a < b a = b a > b; b:Nat0 < b 0 = b 0 > bb:Nat (n : Nat), n < b n = b n > b n++ < b n++ = b n++ > b b:Nat0 < b 0 = b 0 > b b:Natwhy:0 b0 < b 0 = b 0 > b b:Natwhy:0 < b 0 = b0 < b 0 = b 0 > b All goals completed! 🐙 b:Nata:Natih:a < b a = b a > ba++ < b a++ = b a++ > b b:Nata:Natcase1:a < ba++ < b a++ = b a++ > bb:Nata:Natcase2:a = ba++ < b a++ = b a++ > bb:Nata:Natcase3:a > ba++ < b a++ = b a++ > b b:Nata:Natcase1:a < ba++ < b a++ = b a++ > b b:Nata:Natcase1:a++ ba++ < b a++ = b a++ > b b:Nata:Natcase1:a++ < b a++ = ba++ < b a++ = b a++ > b All goals completed! 🐙 b:Nata:Natcase2:a = ba++ < b a++ = b a++ > b have why : a++ > b := a:Natb:Nata < b a = b a > b All goals completed! 🐙 All goals completed! 🐙 have why : a++ > b := a:Natb:Nata < b a = b a > b All goals completed! 🐙 All goals completed! 🐙

(Not from textbook) Establish the decidability of this order computably. The portion of the proof involving decidability has been provided; the remaining sorries involve claims about the natural numbers. One could also have established this result by the Unknown identifier `classical`classical tactic followed by Unknown identifier `exact`exact Classical.decRel _, but this would make this definition (as well as some instances below) noncomputable.

Compare with Mathlib's Chapter2.Nat.decLe (a b : Nat) : Decidable (a b)Nat.decLe.

def declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'Nat.decLe : (a b : Nat) Decidable (a b) b:NatDecidable (0 b) b:NatDecidable (0 b) b:Nat0 b All goals completed! 🐙 a:Natb:NatDecidable (a++ b) a:Natb:NatDecidable (a++ b) cases decLe a b with a:Natb:Nath:a bDecidable (a++ b) cases decEq a b with a:Natb:Nath✝:a bh:a = bDecidable (a++ b) a:Natb:Nath✝:a bh:a = b¬a++ b All goals completed! 🐙 a:Natb:Nath✝:a bh:¬a = bDecidable (a++ b) a:Natb:Nath✝:a bh:¬a = ba++ b All goals completed! 🐙 a:Natb:Nath:¬a bDecidable (a++ b) a:Natb:Nath:¬a b¬a++ b All goals completed! 🐙
instance Nat.decidableRel : DecidableRel (· ·: Nat Nat Prop) := Nat.decLe

(Not from textbook) Nat has the structure of a linear ordering. This allows for tactics such as Unknown identifier `order`order and to be applicable to the Chapter 2 natural numbers.

instance Nat.instLinearOrder : LinearOrder Nat where le_refl := ge_refl le_trans a b c hab hbc := ge_trans hbc hab lt_iff_le_not_ge a b := a:Natb:Nata < b a b ¬b a a:Natb:Nata < b a b ¬b aa:Natb:Nata b ¬b a a < b a:Natb:Nata < b a b ¬b a a:Natb:Nath:a < ba b ¬b a; a:Natb:Nath:a < b¬b a a:Natb:Nath:a < bh':b aFalse All goals completed! 🐙 a:Natb:Nath1:a bh2:¬b aa < b a:Natb:Nath1:a bh2:¬b aa b a b; a:Natb:Nath1:a bh2:¬b aa b a:Natb:Nath1:a bh2:¬b ah:a = bFalse a:Nath1:a ah2:¬a aFalse All goals completed! 🐙 le_antisymm a b hab hba := ge_antisymm hba hab le_total a b := a:Natb:Nata b b a a:Natb:Nath:a < ba b b aa:Nata a a aa:Natb:Nath:a > ba b b a a:Natb:Nath:a < ba b b a a:Natb:Nath:a < ba b; All goals completed! 🐙 a:Nata a a a All goals completed! 🐙 a:Natb:Nath:a > ba b b a a:Natb:Nath:a > bb a; All goals completed! 🐙 toDecidableLE := decidableRel

This illustration of the Unknown identifier `order`order tactic is not from the textbook.

example (a b c d:Nat) (hab: a b) (hbc: b c) (hcd: c d) (hda: d a) : a = c := a:Natb:Natc:Natd:Nathab:a bhbc:b chcd:c dhda:d aa = c All goals completed! 🐙

An illustration of the tactic with .

example (a b c d e:Nat) (hab: a b) (hbc: b < c) (hcd: c d) (hde: d e) : a + 0 < e := a:Natb:Natc:Natd:Nate:Nathab:a bhbc:b < chcd:c dhde:d ea + 0 < e calc a + 0 = a := a:Natb:Natc:Natd:Nate:Nathab:a bhbc:b < chcd:c dhde:d ea + 0 = a All goals completed! 🐙 _ b := hab _ < c := hbc _ d := hcd _ e := hde

(Not from textbook) Nat has the structure of an ordered monoid. This allows for tactics such as Unknown identifier `gcongr`gcongr to be applicable to the Chapter 2 natural numbers.

instance Nat.isOrderedAddMonoid : IsOrderedAddMonoid Nat where add_le_add_left a b hab c := (add_le_add_left a b c).mp hab

This illustration of the Unknown identifier `gcongr`gcongr tactic is not from the textbook.

example (a b c d e:Nat) (hab: a b) (hbc: b < c) (hde: d < e) : a + d c + e := a:Natb:Natc:Natd:Nate:Nathab:a bhbc:b < chde:d < ea + d c + e a:Natb:Natc:Natd:Nate:Nathab:a bhbc:b < chde:d < ea c All goals completed! 🐙

Proposition 2.2.14 (Strong principle of induction) / Exercise 2.2.5 Compare with Mathlib's Nat.strong_induction_on {p : Prop} (n : ) (h : (n : ), (∀ m < n, p m) p n) : p nNat.strong_induction_on.

theorem declaration uses 'sorry'Nat.strong_induction {m₀:Nat} {P: Nat Prop} (hind: m, m m₀ ( m', m₀ m' m' < m P m') P m) : m, m m₀ P m := m₀:NatP:Nat Prophind: m m₀, (∀ (m' : Nat), m₀ m' m' < m P m') P m m m₀, P m All goals completed! 🐙

Exercise 2.2.6 (backwards induction) Compare with Mathlib's Nat.decreasingInduction.{u_1} {n : } {motive : (m : ) m n Sort u_1} (of_succ : (k : ) (h : k < n) motive (k + 1) h motive k ) (self : motive n ) {m : } (mn : m n) : motive m mnNat.decreasingInduction.

theorem declaration uses 'sorry'Nat.backwards_induction {n:Nat} {P: Nat Prop} (hind: m, P (m++) P m) (hn: P n) : m, m n P m := n:NatP:Nat Prophind: (m : Nat), P (m++) P mhn:P n m n, P m All goals completed! 🐙

Exercise 2.2.7 (induction from a starting point) Compare with Mathlib's Nat.le_induction {m : } {P : (n : ) m n Prop} (base : P m ) (succ : (n : ) (hmn : m n), P n hmn P (n + 1) ) (n : ) (hmn : m n) : P n hmnNat.le_induction.

theorem declaration uses 'sorry'Nat.induction_from {n:Nat} {P: Nat Prop} (hind: m, P m P (m++)) : P n m, m n P m := n:NatP:Nat Prophind: (m : Nat), P m P (m++)P n m n, P m All goals completed! 🐙
end Chapter2