Documentation

Mathlib.Data.Nat.Basic

Basic operations on the natural numbers #

This file contains:

• instances on the natural numbers
• some basic lemmas about natural numbers
• extra recursors:
• le_rec_on, le_induction: recursion and induction principles starting at non-zero numbers
• decreasing_induction: recursion growing downwards
• le_rec_on', decreasing_induction': versions with slightly weaker assumptions
• strong_rec': recursion based on strong inequalities
• decidability instances on predicates about the natural numbers

Many theorems that used to live in this file have been moved to Data.Nat.Order, so that this file requires fewer imports. For each section here there is a corresponding section in that file with additional results. It may be possible to move some of these results here, by tweaking their proofs.

instances #

instance Nat.nontrivial :
Equations
instance Nat.commSemiring :
Equations

Extra instances to short-circuit type class resolution and ensure computability

Equations
Equations
instance Nat.monoid :
Equations
instance Nat.commMonoid :
Equations
Equations
instance Nat.semigroup :
Equations
Equations
Equations
instance Nat.distrib :
Equations
instance Nat.semiring :
Equations
theorem Nat.nsmul_eq_mul (m : ) (n : ) :
m n = m * n
Equations

Recursion and forall/exists#

theorem Nat.and_forall_succ {p : } :
p 0 ((n : ) → p (n + 1)) (n : ) → p n
theorem Nat.or_exists_succ {p : } :
(p 0 n, p (n + 1)) n, p n

succ#

theorem LT.lt.nat_succ_le {n : } {m : } (h : n < m) :
m
theorem Nat.eq_of_lt_succ_of_not_lt {a : } {b : } (h1 : a < b + 1) (h2 : ¬a < b) :
a = b
theorem Nat.eq_of_le_of_lt_succ {n : } {m : } (h₁ : n m) (h₂ : m < n + 1) :
m = n
@[simp]
theorem Nat.succ_pos' {n : } :
0 <
theorem Nat.succ_ne_succ {n : } {m : } :
n m
@[simp]
theorem Nat.one_lt_succ_succ (n : ) :
1 < Nat.succ ()
theorem Nat.max_succ_succ {m : } {n : } :
max () () = Nat.succ (max m n)
theorem Nat.lt_succ_iff {m : } {n : } :
m < m n
theorem Nat.succ_le_iff {m : } {n : } :
n m < n
theorem Nat.lt_iff_add_one_le {m : } {n : } :
m < n m + 1 n
theorem Nat.lt_add_one_iff {a : } {b : } :
a < b + 1 a b
theorem Nat.lt_one_add_iff {a : } {b : } :
a < 1 + b a b
theorem Nat.add_one_le_iff {a : } {b : } :
a + 1 b a < b
theorem Nat.one_add_le_iff {a : } {b : } :
1 + a b a < b
theorem Nat.of_le_succ {n : } {m : } (H : n ) :
n m n =
theorem Nat.succ_lt_succ_iff {m : } {n : } :
m < n
theorem Nat.div_le_iff_le_mul_add_pred {m : } {n : } {k : } (n0 : 0 < n) :
m / n k m n * k + (n - 1)
theorem Nat.two_lt_of_ne {n : } :
n 0n 1n 22 < n
theorem Nat.forall_lt_succ {P : } {n : } :
((m : ) → m < n + 1P m) ((m : ) → m < nP m) P n
theorem Nat.exists_lt_succ {P : } {n : } :
(m, m < n + 1 P m) (m, m < n P m) P n

add#

@[simp]
theorem Nat.add_def {a : } {b : } :
Nat.add a b = a + b
@[simp]
theorem Nat.mul_def {a : } {b : } :
Nat.mul a b = a * b
theorem Nat.exists_eq_add_of_le {m : } {n : } (h : m n) :
k, n = m + k
theorem Nat.exists_eq_add_of_le' {m : } {n : } (h : m n) :
k, n = k + m
theorem Nat.exists_eq_add_of_lt {m : } {n : } (h : m < n) :
k, n = m + k + 1

pred#

@[simp]
theorem Nat.add_succ_sub_one (n : ) (m : ) :
n + - 1 = n + m
@[simp]
theorem Nat.succ_add_sub_one (n : ) (m : ) :
+ m - 1 = n + m
theorem Nat.pred_eq_sub_one (n : ) :
= n - 1
theorem Nat.pred_eq_of_eq_succ {m : } {n : } (H : m = ) :
= n
@[simp]
theorem Nat.pred_eq_succ_iff {n : } {m : } :
n = m + 2
theorem Nat.pred_sub (n : ) (m : ) :
- m = Nat.pred (n - m)
theorem Nat.le_of_pred_lt {m : } {n : } :
< nm n
@[simp]
theorem Nat.pred_one_add (n : ) :
Nat.pred (1 + n) = n

This ensures that simp succeeds on pred (n + 1) = n.

mul#

theorem Nat.two_mul_ne_two_mul_add_one {n : } {m : } :
2 * n 2 * m + 1
theorem Nat.mul_ne_mul_left {a : } {b : } {c : } (ha : 0 < a) :
b * a c * a b c
theorem Nat.mul_ne_mul_right {a : } {b : } {c : } (ha : 0 < a) :
a * b a * c b c
theorem Nat.mul_right_eq_self_iff {a : } {b : } (ha : 0 < a) :
a * b = a b = 1
theorem Nat.mul_left_eq_self_iff {a : } {b : } (hb : 0 < b) :
a * b = b a = 1
theorem Nat.lt_succ_iff_lt_or_eq {n : } {i : } :
n < n < i n = i

Recursion and induction principles #

This section is here due to dependencies -- the lemmas here require some of the lemmas proved above, and some of the results in later sections depend on the definitions in this section.

@[simp]
theorem Nat.rec_zero {C : Sort u} (h0 : C 0) (h : (n : ) → C nC (n + 1)) :
(fun t => Nat.rec h0 h t) 0 = h0
@[simp]
theorem Nat.rec_add_one {C : Sort u} (h0 : C 0) (h : (n : ) → C nC (n + 1)) (n : ) :
(fun t => Nat.rec h0 h t) (n + 1) = h n ((fun t => Nat.rec h0 h t) n)
def Nat.leRecOn {C : Sort u} {n : } {m : } :
n m({k : } → C kC (k + 1)) → C nC m

Recursion starting at a non-zero number: given a map C k → C (k+1)→ C (k+1) for each k, there is a map from C n to each C m, n ≤ m≤ m. For a version where the assumption is only made when k ≥ n≥ n, see leRecOn.

Equations
theorem Nat.leRecOn_self {C : Sort u} {n : } {h : n n} {next : {k : } → C kC (k + 1)} (x : C n) :
Nat.leRecOn h (fun {k} => next k) x = x
theorem Nat.leRecOn_succ {C : Sort u} {n : } {m : } (h1 : n m) {h2 : n m + 1} {next : {k : } → C kC (k + 1)} (x : C n) :
Nat.leRecOn h2 next x = next m (Nat.leRecOn h1 next x)
theorem Nat.leRecOn_succ' {C : Sort u} {n : } {h : n n + 1} {next : {k : } → C kC (k + 1)} (x : C n) :
Nat.leRecOn h (fun {k} => next k) x = next n x
theorem Nat.leRecOn_trans {C : Sort u} {n : } {m : } {k : } (hnm : n m) (hmk : m k) {next : {k : } → C kC (k + 1)} (x : C n) :
Nat.leRecOn (_ : n k) next x = Nat.leRecOn hmk next (Nat.leRecOn hnm next x)
theorem Nat.leRecOn_succ_left {C : Sort u} {n : } {m : } (h1 : n m) (h2 : n + 1 m) {next : {k : } → C kC (k + 1)} (x : C n) :
Nat.leRecOn h2 (fun {k} => next k) (next n x) = Nat.leRecOn h1 (fun {k} => next k) x
theorem Nat.leRecOn_injective {C : Sort u} {n : } {m : } (hnm : n m) (next : {k : } → C kC (k + 1)) (Hnext : ∀ (n : ), Function.Injective (next n)) :
Function.Injective (Nat.leRecOn hnm fun {k} => next k)
theorem Nat.leRecOn_surjective {C : Sort u} {n : } {m : } (hnm : n m) (next : {k : } → C kC (k + 1)) (Hnext : ∀ (n : ), Function.Surjective (next n)) :
Function.Surjective (Nat.leRecOn hnm fun {k} => next k)
def Nat.strongRec' {p : Sort u} (H : (n : ) → ((m : ) → m < np m) → p n) (n : ) :
p n

Recursion principle based on <.

Equations
• = H x fun m x =>
def Nat.strongRecOn' {P : Sort u_1} (n : ) (h : (n : ) → ((m : ) → m < nP m) → P n) :
P n

Recursion principle based on < applied to some natural number.

Equations
theorem Nat.strongRecOn'_beta {P : Sort u_1} {h : (n : ) → ((m : ) → m < nP m) → P n} {n : } :
= h n fun m x =>
theorem Nat.le_induction {m : } {P : (n : ) → m nProp} (base : P m (_ : m m)) (succ : (n : ) → (hn : m n) → P n hnP (n + 1) (_ : m n + 1)) (n : ) (hn : m n) :
P n hn

Induction principle starting at a non-zero number. For maps to a Sort* see le_rec_on. To use in an induction proof, the syntax is induction n, hn using Nat.le_induction (or the same for induction').

def Nat.decreasingInduction {P : Sort u_1} (h : (n : ) → P (n + 1)P n) {m : } {n : } (mn : m n) (hP : P n) :
P m

Decreasing induction: if P (k+1) implies P k, then P n implies P m for all m ≤ n≤ n. Also works for functions to Sort*. For a version assuming only the assumption for k < n, see decreasing_induction'.

Equations
• = Nat.leRecOn (fun x => P xP m) m n mn (fun {k} ih hsk => ih (h k hsk)) (fun h => h) hP
@[simp]
theorem Nat.decreasingInduction_self {P : Sort u_1} (h : (n : ) → P (n + 1)P n) {n : } (nn : n n) (hP : P n) :
= hP
theorem Nat.decreasingInduction_succ {P : Sort u_1} (h : (n : ) → P (n + 1)P n) {m : } {n : } (mn : m n) (msn : m n + 1) (hP : P (n + 1)) :
@[simp]
theorem Nat.decreasingInduction_succ' {P : Sort u_1} (h : (n : ) → P (n + 1)P n) {m : } (msm : m m + 1) (hP : P (m + 1)) :
Nat.decreasingInduction h msm hP = h m hP
theorem Nat.decreasingInduction_trans {P : Sort u_1} (h : (n : ) → P (n + 1)P n) {m : } {n : } {k : } (mn : m n) (nk : n k) (hP : P k) :
theorem Nat.decreasingInduction_succ_left {P : Sort u_1} (h : (n : ) → P (n + 1)P n) {m : } {n : } (smn : m + 1 n) (mn : m n) (hP : P n) :
= h m (Nat.decreasingInduction h smn hP)
def Nat.strongSubRecursion {P : Sort u_1} (H : (a b : ) → ((x y : ) → x < ay < bP x y) → P a b) (n : ) (m : ) :
P n m

Given P : ℕ → ℕ → Sort*→ ℕ → Sort*→ Sort*, if for all a b : ℕ we can extend P from the rectangle strictly below (a,b) to P a b, then we have P n m for all n m : ℕ. Note that for non-Prop output it is preferable to use the equation compiler directly if possible, since this produces equation lemmas.

Equations
• = H x x fun x y x_1 x_2 =>
def Nat.pincerRecursion {P : Sort u_1} (Ha0 : (a : ) → P a 0) (H0b : (b : ) → P 0 b) (H : (x y : ) → P x ()P () yP () ()) (n : ) (m : ) :
P n m

Given P : ℕ → ℕ → Sort*→ ℕ → Sort*→ Sort*, if we have P i 0 and P 0 i for all i : ℕ, and for any x y : ℕ we can extend P from (x,y+1) and (x+1,y) to (x+1,y+1) then we have P n m for all n m : ℕ. Note that for non-Prop output it is preferable to use the equation compiler directly if possible, since this produces equation lemmas.

Equations
def Nat.leRecOn' {C : Sort u_1} {n : } {m : } :
n m(k : ⦄ → n kC kC (k + 1)) → C nC m

Recursion starting at a non-zero number: given a map C k → C (k+1)→ C (k+1) for each k ≥ n≥ n, there is a map from C n to each C m, n ≤ m≤ m.

Equations
def Nat.decreasingInduction' {P : Sort u_1} {m : } {n : } (h : (k : ) → k < nm kP (k + 1)P k) (mn : m n) (hP : P n) :
P m

Decreasing induction: if P (k+1) implies P k for all m ≤ k < n≤ k < n, then P n implies P m. Also works for functions to Sort*. Weakens the assumptions of decreasing_induction.

Equations
• One or more equations did not get rendered due to their size.

div#

theorem Nat.div_lt_self' (n : ) (b : ) :
(n + 1) / (b + 2) < n + 1

A version of Nat.div_lt_self using successors, rather than additional hypotheses.

theorem Nat.le_div_iff_mul_le' {x : } {y : } {k : } (k0 : 0 < k) :
x y / k x * k y
theorem Nat.div_lt_iff_lt_mul' {x : } {y : } {k : } (k0 : 0 < k) :
x / k < y x < y * k
theorem Nat.one_le_div_iff {a : } {b : } (hb : 0 < b) :
1 a / b b a
theorem Nat.div_lt_one_iff {a : } {b : } (hb : 0 < b) :
a / b < 1 a < b
theorem Nat.div_le_div_right {n : } {m : } (h : n m) {k : } :
n / k m / k
theorem Nat.lt_of_div_lt_div {m : } {n : } {k : } :
m / k < n / km < n
theorem Nat.div_pos {a : } {b : } (hba : b a) (hb : 0 < b) :
0 < a / b
theorem Nat.lt_mul_of_div_lt {a : } {b : } {c : } (h : a / c < b) (w : 0 < c) :
a < b * c
theorem Nat.mul_div_le_mul_div_assoc (a : ) (b : ) (c : ) :
a * (b / c) a * b / c
theorem Nat.eq_mul_of_div_eq_right {a : } {b : } {c : } (H1 : b a) (H2 : a / b = c) :
a = b * c
theorem Nat.div_eq_iff_eq_mul_right {a : } {b : } {c : } (H : 0 < b) (H' : b a) :
a / b = c a = b * c
theorem Nat.div_eq_iff_eq_mul_left {a : } {b : } {c : } (H : 0 < b) (H' : b a) :
a / b = c a = c * b
theorem Nat.eq_mul_of_div_eq_left {a : } {b : } {c : } (H1 : b a) (H2 : a / b = c) :
a = c * b
theorem Nat.mul_div_cancel_left' {a : } {b : } (Hd : a b) :
a * (b / a) = b
theorem Nat.lt_div_mul_add {a : } {b : } (hb : 0 < b) :
a < a / b * b + b
@[simp]
theorem Nat.div_left_inj {a : } {b : } {d : } (hda : d a) (hdb : d b) :
a / d = b / d a = b

mod, dvd#

theorem Nat.mod_eq_iff_lt {a : } {b : } (h : b 0) :
a % b = a a < b
@[simp]
theorem Nat.mod_succ_eq_iff_lt {a : } {b : } :
a % = a a <
theorem Nat.mod_add_div' (m : ) (k : ) :
m % k + m / k * k = m
theorem Nat.div_add_mod' (m : ) (k : ) :
m / k * k + m % k = m
theorem Nat.div_mod_unique {n : } {k : } {m : } {d : } (h : 0 < k) :
n / k = d n % k = m m + k * d = n m < k

See also Nat.divModEquiv for a similar statement as an Equiv.

theorem Nat.dvd_add_left {k : } {m : } {n : } (h : k n) :
k m + n k m
theorem Nat.dvd_add_right {k : } {m : } {n : } (h : k m) :
k m + n k n
theorem Nat.mul_dvd_mul_iff_left {a : } {b : } {c : } (ha : 0 < a) :
a * b a * c b c
theorem Nat.mul_dvd_mul_iff_right {a : } {b : } {c : } (hc : 0 < c) :
a * c b * c a b
@[simp]
theorem Nat.mod_mod_of_dvd (n : ) {m : } {k : } (h : m k) :
n % k % m = n % m
theorem Nat.add_mod_eq_add_mod_right {m : } {n : } {k : } (i : ) (H : m % n = k % n) :
(m + i) % n = (k + i) % n
theorem Nat.add_mod_eq_add_mod_left {m : } {n : } {k : } (i : ) (H : m % n = k % n) :
(i + m) % n = (i + k) % n
theorem Nat.mul_dvd_of_dvd_div {a : } {b : } {c : } (hab : c b) (h : a b / c) :
c * a b
theorem Nat.eq_of_dvd_of_div_eq_one {a : } {b : } (w : a b) (h : b / a = 1) :
a = b
theorem Nat.eq_zero_of_dvd_of_div_eq_zero {a : } {b : } (w : a b) (h : b / a = 0) :
b = 0
theorem Nat.div_le_div_left {a : } {b : } {c : } (h₁ : c b) (h₂ : 0 < c) :
a / b a / c
theorem Nat.lt_iff_le_pred {m : } {n : } :
0 < n → (m < n m n - 1)
theorem Nat.lt_mul_div_succ (m : ) {n : } (n0 : 0 < n) :
m < n * (m / n + 1)
theorem Nat.mul_add_mod (a : ) (b : ) (c : ) :
(a * b + c) % b = c % b
theorem Nat.mul_add_mod_of_lt {a : } {b : } {c : } (h : c < b) :
(a * b + c) % b = c
theorem Nat.pred_eq_self_iff {n : } :
= n n = 0

find#

theorem Nat.find_eq_iff {m : } {p : } [inst : ] (h : n, p n) :
= m p m ∀ (n : ), n < m¬p n
@[simp]
theorem Nat.find_lt_iff {p : } [inst : ] (h : n, p n) (n : ) :
< n m, m < n p m
@[simp]
theorem Nat.find_le_iff {p : } [inst : ] (h : n, p n) (n : ) :
n m, m n p m
@[simp]
theorem Nat.le_find_iff {p : } [inst : ] (h : n, p n) (n : ) :
n ∀ (m : ), m < n¬p m
@[simp]
theorem Nat.lt_find_iff {p : } [inst : ] (h : n, p n) (n : ) :
n < ∀ (m : ), m n¬p m
@[simp]
theorem Nat.find_eq_zero {p : } [inst : ] (h : n, p n) :
= 0 p 0
theorem Nat.find_mono {p : } {q : } [inst : ] [inst : ] (h : (n : ) → q np n) {hp : n, p n} {hq : n, q n} :
theorem Nat.find_le {n : } {p : } [inst : ] {h : n, p n} (hn : p n) :
n
theorem Nat.find_comp_succ {p : } [inst : ] (h₁ : n, p n) (h₂ : n, p (n + 1)) (h0 : ¬p 0) :
Nat.find h₁ = Nat.find h₂ + 1

find_greatest#

def Nat.findGreatest (P : ) [inst : ] :

find_greatest P b is the largest i ≤ bound≤ bound such that P i holds, or 0 if no such i exists

Equations
• = 0
• = if P (n + 1) then n + 1 else
@[simp]
theorem Nat.findGreatest_zero {P : } [inst : ] :
= 0
theorem Nat.findGreatest_succ {P : } [inst : ] (n : ) :
Nat.findGreatest P (n + 1) = if P (n + 1) then n + 1 else
@[simp]
theorem Nat.findGreatest_eq {P : } [inst : ] {b : } :
P b = b
@[simp]
theorem Nat.findGreatest_of_not {P : } [inst : ] {b : } (h : ¬P (b + 1)) :

decidability of predicates #

instance Nat.decidableBallLT (n : ) (P : (k : ) → k < nProp) [inst : (n : ) → (h : n < n) → Decidable (P n h)] :
Decidable ((n : ) → (h : n < n) → P n h)
Equations
• One or more equations did not get rendered due to their size.
instance Nat.decidableForallFin {n : } (P : Fin nProp) [inst : ] :
Decidable ((i : Fin n) → P i)
Equations
• = decidable_of_iff ((k : ) → (h : k < n) → P { val := k, isLt := h }) (_ : ((k : ) → (h : k < n) → P { val := k, isLt := h }) (i : Fin n) → P i)
instance Nat.decidableBallLe (n : ) (P : (k : ) → k nProp) [inst : (n : ) → (h : n n) → Decidable (P n h)] :
Decidable ((n : ) → (h : n n) → P n h)
Equations
instance Nat.decidableExistsLT {P : } [h : ] :
DecidablePred fun n => m, m < n P m
Equations
instance Nat.decidableExistsLe {P : } [inst : ] :
DecidablePred fun n => m, m n P m
Equations