lean4-htt/library/init/data/nat/lemmas.lean

1086 lines
36 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Jeremy Avigad
-/
prelude
import init.data.nat.basic init.data.nat.div init.data.nat.pow init.meta init.algebra.functions
namespace nat
attribute [pre_smt] nat_zero_eq_zero
protected lemma zero_add : ∀ n : , 0 + n = n
| 0 := rfl
| (n+1) := congr_arg succ (zero_add n)
lemma succ_add : ∀ n m : , (succ n) + m = succ (n + m)
| n 0 := rfl
| n (m+1) := congr_arg succ (succ_add n m)
lemma add_succ : ∀ n m : , n + succ m = succ (n + m) :=
λ n m, rfl
protected lemma add_zero : ∀ n : , n + 0 = n :=
λ n, rfl
lemma add_one_eq_succ : ∀ n : , n + 1 = succ n :=
λ n, rfl
protected lemma add_comm : ∀ n m : , n + m = m + n
| n 0 := eq.symm (nat.zero_add n)
| n (m+1) :=
suffices succ (n + m) = succ (m + n), from
eq.symm (succ_add m n) ▸ this,
congr_arg succ (add_comm n m)
protected lemma add_assoc : ∀ n m k : , (n + m) + k = n + (m + k)
| n m 0 := rfl
| n m (succ k) := by simp [add_succ, add_assoc n m k]
protected lemma add_left_comm : ∀ (n m k : ), n + (m + k) = m + (n + k) :=
left_comm nat.add nat.add_comm nat.add_assoc
protected lemma add_left_cancel : ∀ {n m k : }, n + m = n + k → m = k
| 0 m k := by simp [nat.zero_add] {contextual := tt}
| (succ n) m k := λ h,
have n+m = n+k, begin simp [succ_add] at h, injection h, assumption end,
add_left_cancel this
protected lemma add_right_cancel {n m k : } (h : n + m = k + m) : n = k :=
have m + n = m + k, begin rw [nat.add_comm n m, nat.add_comm k m] at h, assumption end,
nat.add_left_cancel this
lemma succ_ne_zero (n : ) : succ n ≠ 0 :=
assume h, nat.no_confusion h
lemma succ_ne_self : ∀ n : , succ n ≠ n
| 0 h := absurd h (nat.succ_ne_zero 0)
| (n+1) h := succ_ne_self n (nat.no_confusion h (λ h, h))
protected lemma one_ne_zero : 1 ≠ (0 : ) :=
assume h, nat.no_confusion h
protected lemma zero_ne_one : 0 ≠ (1 : ) :=
assume h, nat.no_confusion h
lemma eq_zero_of_add_eq_zero_right : ∀ {n m : }, n + m = 0 → n = 0
| 0 m := by simp [nat.zero_add]
| (n+1) m := λ h,
begin
exfalso,
rw [add_one_eq_succ, succ_add] at h,
apply succ_ne_zero _ h
end
lemma eq_zero_of_add_eq_zero_left {n m : } (h : n + m = 0) : m = 0 :=
@eq_zero_of_add_eq_zero_right m n (nat.add_comm n m ▸ h)
@[simp]
lemma pred_zero : pred 0 = 0 :=
rfl
@[simp]
lemma pred_succ (n : ) : pred (succ n) = n :=
rfl
protected lemma mul_zero (n : ) : n * 0 = 0 :=
rfl
lemma mul_succ (n m : ) : n * succ m = n * m + n :=
rfl
protected theorem zero_mul : ∀ (n : ), 0 * n = 0
| 0 := rfl
| (succ n) := by rw [mul_succ, zero_mul]
private meta def sort_add :=
`[simp [nat.add_assoc, nat.add_comm, nat.add_left_comm]]
lemma succ_mul : ∀ (n m : ), (succ n) * m = (n * m) + m
| n 0 := rfl
| n (succ m) :=
begin
simp [mul_succ, add_succ, succ_mul n m],
sort_add
end
protected lemma right_distrib : ∀ (n m k : ), (n + m) * k = n * k + m * k
| n m 0 := rfl
| n m (succ k) :=
begin simp [mul_succ, right_distrib n m k], sort_add end
protected lemma left_distrib : ∀ (n m k : ), n * (m + k) = n * m + n * k
| 0 m k := by simp [nat.zero_mul]
| (succ n) m k :=
begin simp [succ_mul, left_distrib n m k], sort_add end
protected lemma mul_comm : ∀ (n m : ), n * m = m * n
| n 0 := by rw [nat.zero_mul, nat.mul_zero]
| n (succ m) := by simp [mul_succ, succ_mul, mul_comm n m]
protected lemma mul_assoc : ∀ (n m k : ), (n * m) * k = n * (m * k)
| n m 0 := rfl
| n m (succ k) := by simp [mul_succ, nat.left_distrib, mul_assoc n m k]
protected lemma mul_one : ∀ (n : ), n * 1 = n
| 0 := rfl
| (succ n) := by simp [succ_mul, mul_one n, add_one_eq_succ]
protected lemma one_mul (n : ) : 1 * n = n :=
by rw [nat.mul_comm, nat.mul_one]
lemma eq_zero_or_eq_zero_of_mul_eq_zero : ∀ {n m : }, n * m = 0 → n = 0 m = 0
| 0 m := λ h, or.inl rfl
| (succ n) m :=
begin
rw succ_mul, intro h,
exact or.inr (eq_zero_of_add_eq_zero_left h)
end
instance : comm_semiring nat :=
{add := nat.add,
add_assoc := nat.add_assoc,
zero := nat.zero,
zero_add := nat.zero_add,
add_zero := nat.add_zero,
add_comm := nat.add_comm,
mul := nat.mul,
mul_assoc := nat.mul_assoc,
one := nat.succ nat.zero,
one_mul := nat.one_mul,
mul_one := nat.mul_one,
left_distrib := nat.left_distrib,
right_distrib := nat.right_distrib,
zero_mul := nat.zero_mul,
mul_zero := nat.mul_zero,
mul_comm := nat.mul_comm}
/- properties of inequality -/
protected lemma le_of_eq {n m : } (p : n = m) : n ≤ m :=
p ▸ less_than_or_equal.refl n
lemma le_succ_iff_true (n : ) : n ≤ succ n ↔ true :=
iff_true_intro (le_succ n)
lemma pred_le_iff_true (n : ) : pred n ≤ n ↔ true :=
iff_true_intro (pred_le n)
lemma le_succ_of_le {n m : } (h : n ≤ m) : n ≤ succ m :=
nat.le_trans h (le_succ m)
lemma le_of_succ_le {n m : } (h : succ n ≤ m) : n ≤ m :=
nat.le_trans (le_succ n) h
protected lemma le_of_lt {n m : } (h : n < m) : n ≤ m :=
le_of_succ_le h
lemma le_succ_of_pred_le {n m : } : pred n ≤ m → n ≤ succ m :=
nat.cases_on n less_than_or_equal.step (λ a, succ_le_succ)
lemma succ_le_zero_iff_false (n : ) : succ n ≤ 0 ↔ false :=
iff_false_intro (not_succ_le_zero n)
lemma succ_le_self_iff_false (n : ) : succ n ≤ n ↔ false :=
iff_false_intro (not_succ_le_self n)
lemma zero_le_iff_true (n : ) : 0 ≤ n ↔ true :=
iff_true_intro (zero_le n)
def lt.step {n m : } : n < m → n < succ m := less_than_or_equal.step
lemma zero_lt_succ_iff_true (n : ) : 0 < succ n ↔ true :=
iff_true_intro (zero_lt_succ n)
def succ_pos_iff_true := zero_lt_succ_iff_true
protected lemma pos_of_ne_zero {n : nat} (h : n ≠ 0) : n > 0 :=
begin cases n, contradiction, apply succ_pos end
protected lemma lt_trans {n m k : } (h₁ : n < m) : m < k → n < k :=
nat.le_trans (less_than_or_equal.step h₁)
protected lemma lt_of_le_of_lt {n m k : } (h₁ : n ≤ m) : m < k → n < k :=
nat.le_trans (succ_le_succ h₁)
lemma lt_self_iff_false (n : ) : n < n ↔ false :=
iff_false_intro (λ h, absurd h (nat.lt_irrefl n))
lemma self_lt_succ (n : ) : n < succ n := nat.le_refl (succ n)
def lt_succ_self := @self_lt_succ
lemma self_lt_succ_iff_true (n : ) : n < succ n ↔ true :=
iff_true_intro (self_lt_succ n)
def lt_succ_self_iff_true := @self_lt_succ_iff_true
def lt.base (n : ) : n < succ n := nat.le_refl (succ n)
lemma le_lt_antisymm {n m : } (h₁ : n ≤ m) (h₂ : m < n) : false :=
nat.lt_irrefl n (nat.lt_of_le_of_lt h₁ h₂)
protected lemma le_antisymm {n m : } (h₁ : n ≤ m) : m ≤ n → n = m :=
less_than_or_equal.cases_on h₁ (λ a, rfl) (λ a b c, absurd (nat.lt_of_le_of_lt b c) (nat.lt_irrefl n))
instance : weak_order :=
⟨@nat.less_than_or_equal, @nat.le_refl, @nat.le_trans, @nat.le_antisymm⟩
lemma lt_le_antisymm {n m : } (h₁ : n < m) (h₂ : m ≤ n) : false :=
le_lt_antisymm h₂ h₁
protected lemma nat.lt_asymm {n m : } (h₁ : n < m) : ¬ m < n :=
le_lt_antisymm (nat.le_of_lt h₁)
lemma lt_zero_iff_false (a : ) : a < 0 ↔ false :=
iff_false_intro (not_lt_zero a)
protected lemma le_of_eq_or_lt {a b : } (h : a = b a < b) : a ≤ b :=
or.elim h nat.le_of_eq nat.le_of_lt
lemma succ_lt_succ {a b : } : a < b → succ a < succ b :=
succ_le_succ
lemma lt_of_succ_lt {a b : } : succ a < b → a < b :=
le_of_succ_le
lemma lt_of_succ_lt_succ {a b : } : succ a < succ b → a < b :=
le_of_succ_le_succ
protected lemma lt_or_ge : ∀ (a b : ), a < b a ≥ b
| a 0 := or.inr (zero_le a)
| a (b+1) :=
match lt_or_ge a b with
| or.inl h := or.inl (le_succ_of_le h)
| or.inr h :=
match nat.eq_or_lt_of_le h with
| or.inl h1 := or.inl (h1 ▸ self_lt_succ b)
| or.inr h1 := or.inr h1
end
end
protected def {u} lt_ge_by_cases {a b : } {C : Sort u} (h₁ : a < b → C) (h₂ : a ≥ b → C) : C :=
decidable.by_cases h₁ (λ h, h₂ (or.elim (nat.lt_or_ge a b) (λ a, absurd a h) (λ a, a)))
protected def {u} lt_by_cases {a b : } {C : Sort u} (h₁ : a < b → C) (h₂ : a = b → C)
(h₃ : b < a → C) : C :=
nat.lt_ge_by_cases h₁ (λ h₁,
nat.lt_ge_by_cases h₃ (λ h, h₂ (nat.le_antisymm h h₁)))
protected lemma lt_trichotomy (a b : ) : a < b a = b b < a :=
nat.lt_by_cases (λ h, or.inl h) (λ h, or.inr (or.inl h)) (λ h, or.inr (or.inr h))
protected lemma eq_or_lt_of_not_lt {a b : } (hnlt : ¬ a < b) : a = b b < a :=
or.elim (nat.lt_trichotomy a b)
(λ hlt, absurd hlt hnlt)
(λ h, h)
lemma lt_of_succ_le {a b : } (h : succ a ≤ b) : a < b := h
lemma succ_le_of_lt {a b : } (h : a < b) : succ a ≤ b := h
lemma le_add_right : ∀ (n k : ), n ≤ n + k
| n 0 := nat.le_refl n
| n (k+1) := le_succ_of_le (le_add_right n k)
lemma le_add_left (n m : ): n ≤ m + n :=
nat.add_comm n m ▸ le_add_right n m
lemma le.dest : ∀ {n m : }, n ≤ m → ∃ k, n + k = m
| n .n (less_than_or_equal.refl .n) := ⟨0, rfl⟩
| n .(succ m) (@less_than_or_equal.step .n m h) :=
match le.dest h with
| ⟨w, hw⟩ := ⟨succ w, hw ▸ add_succ n w⟩
end
lemma le.intro {n m k : } (h : n + k = m) : n ≤ m :=
h ▸ le_add_right n k
protected lemma add_le_add_left {n m : } (h : n ≤ m) (k : ) : k + n ≤ k + m :=
match le.dest h with
| ⟨w, hw⟩ := @le.intro _ _ w begin rw [nat.add_assoc, hw] end
end
protected lemma add_le_add_right {n m : } (h : n ≤ m) (k : ) : n + k ≤ m + k :=
begin rw [nat.add_comm n k, nat.add_comm m k], apply nat.add_le_add_left h end
protected lemma le_of_add_le_add_left {k n m : } (h : k + n ≤ k + m) : n ≤ m :=
match le.dest h with
| ⟨w, hw⟩ := @le.intro _ _ w
begin
dsimp at hw,
rw [nat.add_assoc] at hw,
apply nat.add_left_cancel hw
end
end
protected lemma le_of_add_le_add_right {k n m : } : n + k ≤ m + k → n ≤ m :=
begin
rw [nat.add_comm _ k,nat.add_comm _ k],
apply nat.le_of_add_le_add_left
end
protected lemma add_le_add_iff_le_right (k n m : ) : n + k ≤ m + k ↔ n ≤ m :=
⟨ nat.le_of_add_le_add_right , take h, nat.add_le_add_right h _ ⟩
protected lemma lt_of_le_and_ne {m n : } (h1 : m ≤ n) : m ≠ n → m < n :=
or.resolve_right (or.swap (nat.eq_or_lt_of_le h1))
protected theorem lt_of_add_lt_add_left {k n m : } (h : k + n < k + m) : n < m :=
let h' := nat.le_of_lt h in
nat.lt_of_le_and_ne
(nat.le_of_add_le_add_left h')
(λ heq, nat.lt_irrefl (k + m) begin rw heq at h, assumption end)
protected lemma add_lt_add_left {n m : } (h : n < m) (k : ) : k + n < k + m :=
lt_of_succ_le (add_succ k n ▸ nat.add_le_add_left (succ_le_of_lt h) k)
protected lemma add_lt_add_right {n m : } (h : n < m) (k : ) : n + k < m + k :=
nat.add_comm k m ▸ nat.add_comm k n ▸ nat.add_lt_add_left h k
protected lemma lt_add_of_pos_right {n k : } (h : k > 0) : n < n + k :=
nat.add_lt_add_left h n
protected lemma zero_lt_one : 0 < (1:nat) :=
zero_lt_succ 0
def one_pos := nat.zero_lt_one
protected lemma le_total {m n : } : m ≤ n n ≤ m :=
or.imp_left nat.le_of_lt (nat.lt_or_ge m n)
protected lemma le_of_lt_or_eq {m n : } (h : m < n m = n) : m ≤ n :=
nat.le_of_eq_or_lt (or.swap h)
protected lemma lt_or_eq_of_le {m n : } (h : m ≤ n) : m < n m = n :=
or.swap (nat.eq_or_lt_of_le h)
protected lemma le_iff_lt_or_eq (m n : ) : m ≤ n ↔ m < n m = n :=
iff.intro nat.lt_or_eq_of_le nat.le_of_lt_or_eq
lemma mul_le_mul_left {n m : } (k : ) (h : n ≤ m) : k * n ≤ k * m :=
match le.dest h with
| ⟨l, hl⟩ :=
have k * n + k * l = k * m, by rw [-left_distrib, hl],
le.intro this
end
lemma mul_le_mul_right {n m : } (k : ) (h : n ≤ m) : n * k ≤ m * k :=
mul_comm k m ▸ mul_comm k n ▸ mul_le_mul_left k h
protected lemma mul_lt_mul_of_pos_left {n m k : } (h : n < m) (hk : k > 0) : k * n < k * m :=
nat.lt_of_lt_of_le (nat.lt_add_of_pos_right hk) (mul_succ k n ▸ nat.mul_le_mul_left k (succ_le_of_lt h))
protected lemma mul_lt_mul_of_pos_right {n m k : } (h : n < m) (hk : k > 0) : n * k < m * k :=
mul_comm k m ▸ mul_comm k n ▸ nat.mul_lt_mul_of_pos_left h hk
instance : decidable_linear_ordered_semiring nat :=
{ nat.comm_semiring with
add_left_cancel := @nat.add_left_cancel,
add_right_cancel := @nat.add_right_cancel,
lt := nat.lt,
le := nat.le,
le_refl := nat.le_refl,
le_trans := @nat.le_trans,
le_antisymm := @nat.le_antisymm,
le_total := @nat.le_total,
le_iff_lt_or_eq := @nat.le_iff_lt_or_eq,
le_of_lt := @nat.le_of_lt,
lt_irrefl := @nat.lt_irrefl,
lt_of_lt_of_le := @nat.lt_of_lt_of_le,
lt_of_le_of_lt := @nat.lt_of_le_of_lt,
lt_of_add_lt_add_left := @nat.lt_of_add_lt_add_left,
add_lt_add_left := @nat.add_lt_add_left,
add_le_add_left := @nat.add_le_add_left,
le_of_add_le_add_left := @nat.le_of_add_le_add_left,
zero_lt_one := zero_lt_succ 0,
mul_le_mul_of_nonneg_left := (take a b c h₁ h₂, nat.mul_le_mul_left c h₁),
mul_le_mul_of_nonneg_right := (take a b c h₁ h₂, nat.mul_le_mul_right c h₁),
mul_lt_mul_of_pos_left := @nat.mul_lt_mul_of_pos_left,
mul_lt_mul_of_pos_right := @nat.mul_lt_mul_of_pos_right,
decidable_lt := nat.decidable_lt,
decidable_le := nat.decidable_le,
decidable_eq := nat.decidable_eq }
lemma le_of_lt_succ {m n : nat} : m < succ n → m ≤ n :=
le_of_succ_le_succ
/- sub properties -/
lemma sub_eq_succ_sub_succ (a b : ) : a - b = succ a - succ b :=
eq.symm (succ_sub_succ_eq_sub a b)
lemma zero_sub_eq_zero : ∀ a : , 0 - a = 0
| 0 := rfl
| (a+1) := congr_arg pred (zero_sub_eq_zero a)
lemma zero_eq_zero_sub (a : ) : 0 = 0 - a :=
eq.symm (zero_sub_eq_zero a)
lemma sub_le_iff_true (a b : ) : a - b ≤ a ↔ true :=
iff_true_intro (sub_le a b)
lemma sub_lt_succ (a b : ) : a - b < succ a :=
lt_succ_of_le (sub_le a b)
lemma sub_lt_succ_iff_true (a b : ) : a - b < succ a ↔ true :=
iff_true_intro (sub_lt_succ a b)
protected theorem sub_le_sub_right {n m : } (h : n ≤ m) : ∀ k, n - k ≤ m - k
| 0 := h
| (succ z) := pred_le_pred (sub_le_sub_right z)
/- bit0/bit1 properties -/
protected lemma bit0_succ_eq (n : ) : bit0 (succ n) = succ (succ (bit0 n)) :=
show succ (succ n + n) = succ (succ (n + n)), from
congr_arg succ (succ_add n n)
protected lemma bit1_eq_succ_bit0 (n : ) : bit1 n = succ (bit0 n) :=
rfl
protected lemma bit1_succ_eq (n : ) : bit1 (succ n) = succ (succ (bit1 n)) :=
eq.trans (nat.bit1_eq_succ_bit0 (succ n)) (congr_arg succ (nat.bit0_succ_eq n))
protected lemma bit0_ne_zero : ∀ {n : }, n ≠ 0 → bit0 n ≠ 0
| 0 h := absurd rfl h
| (n+1) h := succ_ne_zero _
protected lemma bit1_ne_zero (n : ) : bit1 n ≠ 0 :=
show succ (n + n) ≠ 0, from
succ_ne_zero (n + n)
protected lemma bit1_ne_one : ∀ {n : }, n ≠ 0 → bit1 n ≠ 1
| 0 h h1 := absurd rfl h
| (n+1) h h1 := nat.no_confusion h1 (λ h2, absurd h2 (succ_ne_zero _))
protected lemma bit0_ne_one : ∀ n : , bit0 n ≠ 1
| 0 h := absurd h (ne.symm nat.one_ne_zero)
| (n+1) h :=
have h1 : succ (succ (n + n)) = 1, from succ_add n n ▸ h,
nat.no_confusion h1
(λ h2, absurd h2 (succ_ne_zero (n + n)))
protected lemma add_self_ne_one : ∀ (n : ), n + n ≠ 1
| 0 h := nat.no_confusion h
| (n+1) h :=
have h1 : succ (succ (n + n)) = 1, from succ_add n n ▸ h,
nat.no_confusion h1 (λ h2, absurd h2 (nat.succ_ne_zero (n + n)))
protected lemma bit1_ne_bit0 : ∀ (n m : ), bit1 n ≠ bit0 m
| 0 m h := absurd h (ne.symm (nat.add_self_ne_one m))
| (n+1) 0 h :=
have h1 : succ (bit0 (succ n)) = 0, from h,
absurd h1 (nat.succ_ne_zero _)
| (n+1) (m+1) h :=
have h1 : succ (succ (bit1 n)) = succ (succ (bit0 m)), from
nat.bit0_succ_eq m ▸ nat.bit1_succ_eq n ▸ h,
have h2 : bit1 n = bit0 m, from
nat.no_confusion h1 (λ h2', nat.no_confusion h2' (λ h2'', h2'')),
absurd h2 (bit1_ne_bit0 n m)
protected lemma bit0_ne_bit1 : ∀ (n m : ), bit0 n ≠ bit1 m :=
λ n m : nat, ne.symm (nat.bit1_ne_bit0 m n)
protected lemma bit0_inj : ∀ {n m : }, bit0 n = bit0 m → n = m
| 0 0 h := rfl
| 0 (m+1) h := by contradiction
| (n+1) 0 h := by contradiction
| (n+1) (m+1) h :=
have succ (succ (n + n)) = succ (succ (m + m)),
begin unfold bit0 at h, simp [add_one_eq_succ, add_succ, succ_add] at h, exact h end,
have n + n = m + m, begin repeat {injection this with this}, assumption end,
have n = m, from bit0_inj this,
by rw this
protected lemma bit1_inj : ∀ {n m : }, bit1 n = bit1 m → n = m :=
λ n m h,
have succ (bit0 n) = succ (bit0 m), begin simp [nat.bit1_eq_succ_bit0] at h, assumption end,
have bit0 n = bit0 m, from begin injection this, assumption end,
nat.bit0_inj this
protected lemma bit0_ne {n m : } : n ≠ m → bit0 n ≠ bit0 m :=
λ h₁ h₂, absurd (nat.bit0_inj h₂) h₁
protected lemma bit1_ne {n m : } : n ≠ m → bit1 n ≠ bit1 m :=
λ h₁ h₂, absurd (nat.bit1_inj h₂) h₁
protected lemma zero_ne_bit0 {n : } : n ≠ 0 → 0 ≠ bit0 n :=
λ h, ne.symm (nat.bit0_ne_zero h)
protected lemma zero_ne_bit1 (n : ) : 0 ≠ bit1 n :=
ne.symm (nat.bit1_ne_zero n)
protected lemma one_ne_bit0 (n : ) : 1 ≠ bit0 n :=
ne.symm (nat.bit0_ne_one n)
protected lemma one_ne_bit1 {n : } : n ≠ 0 → 1 ≠ bit1 n :=
λ h, ne.symm (nat.bit1_ne_one h)
protected lemma zero_lt_bit1 (n : nat) : 0 < bit1 n :=
zero_lt_succ _
protected lemma zero_lt_bit0 : ∀ {n : nat}, n ≠ 0 → 0 < bit0 n
| 0 h := by contradiction
| (succ n) h :=
begin
rw nat.bit0_succ_eq,
apply zero_lt_succ
end
protected lemma one_lt_bit1 : ∀ {n : nat}, n ≠ 0 → 1 < bit1 n
| 0 h := by contradiction
| (succ n) h :=
begin
rw nat.bit1_succ_eq,
apply succ_lt_succ,
apply zero_lt_succ
end
protected lemma one_lt_bit0 : ∀ {n : nat}, n ≠ 0 → 1 < bit0 n
| 0 h := by contradiction
| (succ n) h :=
begin
rw nat.bit0_succ_eq,
apply succ_lt_succ,
apply zero_lt_succ
end
protected lemma bit0_lt {n m : nat} (h : n < m) : bit0 n < bit0 m :=
add_lt_add h h
protected lemma bit1_lt {n m : nat} (h : n < m) : bit1 n < bit1 m :=
succ_lt_succ (add_lt_add h h)
protected lemma bit0_lt_bit1 {n m : nat} (h : n ≤ m) : bit0 n < bit1 m :=
lt_succ_of_le (add_le_add h h)
protected lemma bit1_lt_bit0 : ∀ {n m : nat}, n < m → bit1 n < bit0 m
| n 0 h := absurd h (not_lt_zero _)
| n (succ m) h :=
have n ≤ m, from le_of_lt_succ h,
have succ (n + n) ≤ succ (m + m), from succ_le_succ (add_le_add this this),
have succ (n + n) ≤ succ m + m, {rw succ_add, assumption},
show succ (n + n) < succ (succ m + m), from lt_succ_of_le this
protected lemma one_le_bit1 (n : ) : 1 ≤ bit1 n :=
show 1 ≤ succ (bit0 n), from
succ_le_succ (zero_le (bit0 n))
protected lemma one_le_bit0 : ∀ (n : ), n ≠ 0 → 1 ≤ bit0 n
| 0 h := absurd rfl h
| (n+1) h :=
suffices 1 ≤ succ (succ (bit0 n)), from
eq.symm (nat.bit0_succ_eq n) ▸ this,
succ_le_succ (zero_le (succ (bit0 n)))
/- Extra instances to short-circuit type class resolution -/
instance : add_comm_monoid nat := by apply_instance
instance : add_monoid nat := by apply_instance
instance : monoid nat := by apply_instance
instance : comm_monoid nat := by apply_instance
instance : comm_semigroup nat := by apply_instance
instance : semigroup nat := by apply_instance
instance : add_comm_semigroup nat := by apply_instance
instance : add_semigroup nat := by apply_instance
instance : distrib nat := by apply_instance
instance : semiring nat := by apply_instance
instance : ordered_semiring nat := by apply_instance
/- subtraction -/
@[simp]
protected theorem sub_zero (n : ) : n - 0 = n :=
rfl
theorem sub_succ (n m : ) : n - succ m = pred (n - m) :=
rfl
protected theorem zero_sub : ∀ (n : ), 0 - n = 0
| 0 := by rw nat.sub_zero
| (succ n) := by rw [nat.sub_succ, zero_sub n, pred_zero]
theorem succ_sub_succ (n m : ) : succ n - succ m = n - m :=
succ_sub_succ_eq_sub n m
protected theorem sub_self : ∀ (n : ), n - n = 0
| 0 := by rw nat.sub_zero
| (succ n) := by rw [succ_sub_succ, sub_self n]
/- TODO(Leo): remove the following ematch annotations as soon as we have
arithmetic theory in the smt_stactic -/
@[ematch_lhs]
protected theorem add_sub_add_right : ∀ (n k m : ), (n + k) - (m + k) = n - m
| n 0 m := by rw [add_zero, add_zero]
| n (succ k) m := by rw [add_succ, add_succ, succ_sub_succ, add_sub_add_right n k m]
@[ematch_lhs]
protected theorem add_sub_add_left (k n m : ) : (k + n) - (k + m) = n - m :=
by rw [add_comm k n, add_comm k m, nat.add_sub_add_right]
@[ematch_lhs]
protected theorem add_sub_cancel (n m : ) : n + m - m = n :=
suffices n + m - (0 + m) = n, from
by rwa [zero_add] at this,
by rw [nat.add_sub_add_right, nat.sub_zero]
@[ematch_lhs]
protected theorem add_sub_cancel_left (n m : ) : n + m - n = m :=
show n + m - (n + 0) = m, from
by rw [nat.add_sub_add_left, nat.sub_zero]
protected theorem sub_sub : ∀ (n m k : ), n - m - k = n - (m + k)
| n m 0 := by rw [add_zero, nat.sub_zero]
| n m (succ k) := by rw [add_succ, nat.sub_succ, nat.sub_succ, sub_sub n m k]
theorem succ_sub_sub_succ (n m k : ) : succ n - m - succ k = n - m - k :=
by rw [nat.sub_sub, nat.sub_sub, add_succ, succ_sub_succ]
theorem le_of_le_of_sub_le_sub_right {n m k : }
(h₀ : k ≤ m)
(h₁ : n - k ≤ m - k)
: n ≤ m :=
begin
revert k m,
induction n with n ; intros k m h₀ h₁,
{ apply zero_le },
{ cases k with k,
{ apply h₁ },
cases m with m,
{ cases not_succ_le_zero _ h₀ },
{ simp [succ_sub_succ] at h₁,
apply succ_le_succ,
apply ih_1 _ h₁,
apply le_of_succ_le_succ h₀ }, }
end
protected theorem sub_le_sub_right_iff (n m k : )
(h : k ≤ m)
: n - k ≤ m - k ↔ n ≤ m :=
⟨ le_of_le_of_sub_le_sub_right h , assume h, nat.sub_le_sub_right h k ⟩
theorem sub_self_add (n m : ) : n - (n + m) = 0 :=
show (n + 0) - (n + m) = 0, from
by rw [nat.add_sub_add_left, nat.zero_sub]
theorem add_le_to_le_sub (x : ) {y k : }
(h : k ≤ y)
: x + k ≤ y ↔ x ≤ y - k :=
by rw [-nat.add_sub_cancel x k,nat.sub_le_sub_right_iff _ _ _ h,nat.add_sub_cancel]
lemma sub_lt_of_pos_le (a b : ) (h₀ : 0 < a) (h₁ : a ≤ b)
: b - a < b :=
begin
apply sub_lt _ h₀,
apply lt_of_lt_of_le h₀ h₁
end
protected theorem sub.right_comm (m n k : ) : m - n - k = m - k - n :=
by rw [nat.sub_sub, nat.sub_sub, add_comm]
theorem sub_one (n : ) : n - 1 = pred n :=
rfl
theorem succ_sub_one (n : ) : succ n - 1 = n :=
rfl
theorem succ_pred_eq_of_pos : ∀ {n : }, n > 0 → succ (pred n) = n
| 0 h := absurd h (lt_irrefl 0)
| (succ k) h := rfl
theorem mul_pred_left : ∀ (n m : ), pred n * m = n * m - m
| 0 m := by simp [nat.zero_sub, pred_zero, zero_mul]
| (succ n) m := by rw [pred_succ, succ_mul, nat.add_sub_cancel]
theorem mul_pred_right (n m : ) : n * pred m = n * m - n :=
by rw [mul_comm, mul_pred_left, mul_comm]
protected theorem mul_sub_right_distrib : ∀ (n m k : ), (n - m) * k = n * k - m * k
| n 0 k := by simp [nat.sub_zero]
| n (succ m) k := by rw [nat.sub_succ, mul_pred_left, mul_sub_right_distrib, succ_mul, nat.sub_sub]
protected theorem mul_sub_left_distrib (n m k : ) : n * (m - k) = n * m - n * k :=
by rw [mul_comm, nat.mul_sub_right_distrib, mul_comm m n, mul_comm n k]
protected theorem mul_self_sub_mul_self_eq (a b : nat) : a * a - b * b = (a + b) * (a - b) :=
by rw [nat.mul_sub_left_distrib, right_distrib, right_distrib, mul_comm b a, add_comm (a*a) (a*b),
nat.add_sub_add_left]
theorem succ_mul_succ_eq (a : nat) : succ a * succ a = a*a + a + a + 1 :=
begin rw [-add_one_eq_succ], simp [right_distrib, left_distrib] end
theorem sub_eq_zero_of_le {n m : } (h : n ≤ m) : n - m = 0 :=
exists.elim (nat.le.dest h)
(take k, assume hk : n + k = m, by rw [-hk, sub_self_add])
protected theorem le_of_sub_eq_zero : ∀{n m : }, n - m = 0 → n ≤ m
| n 0 H := begin rw [nat.sub_zero] at H, simp [H] end
| 0 (m+1) H := zero_le _
| (n+1) (m+1) H := add_le_add_right
(le_of_sub_eq_zero begin simp [nat.add_sub_add_right] at H, exact H end) _
protected theorem sub_eq_zero_iff_le {n m : } : n - m = 0 ↔ n ≤ m :=
⟨nat.le_of_sub_eq_zero, nat.sub_eq_zero_of_le⟩
theorem succ_sub {m n : } (h : m ≥ n) : succ m - n = succ (m - n) :=
exists.elim (nat.le.dest h)
(take k, assume hk : n + k = m,
by rw [-hk, nat.add_sub_cancel_left, -add_succ, nat.add_sub_cancel_left])
theorem add_sub_of_le {n m : } (h : n ≤ m) : n + (m - n) = m :=
exists.elim (nat.le.dest h)
(take k, assume hk : n + k = m,
by rw [-hk, nat.add_sub_cancel_left])
protected theorem sub_add_cancel {n m : } (h : n ≥ m) : n - m + m = n :=
by rw [add_comm, add_sub_of_le h]
protected theorem sub_pos_of_lt {m n : } (h : m < n) : n - m > 0 :=
have 0 + m < n - m + m, begin rw [zero_add, nat.sub_add_cancel (le_of_lt h)], exact h end,
lt_of_add_lt_add_right this
protected theorem add_sub_assoc {m k : } (h : k ≤ m) (n : ) : n + m - k = n + (m - k) :=
exists.elim (nat.le.dest h)
(take l, assume hl : k + l = m,
by rw [-hl, nat.add_sub_cancel_left, add_comm k, -add_assoc, nat.add_sub_cancel])
protected lemma sub_eq_iff_eq_add {a b c : } (ab : b ≤ a) : a - b = c ↔ a = c + b :=
⟨take c_eq, begin rw [c_eq^.symm, nat.sub_add_cancel ab] end,
take a_eq, begin rw [a_eq, nat.add_sub_cancel] end⟩
protected lemma lt_of_sub_eq_succ {m n l : } (H : m - n = nat.succ l) : n < m :=
lt_of_not_ge
(take (H' : n ≥ m), begin simp [nat.sub_eq_zero_of_le H'] at H, contradiction end)
@[simp] lemma min_zero_left (a : ) : min 0 a = 0 :=
min_eq_left (zero_le a)
@[simp] lemma min_zero_right (a : ) : min a 0 = 0 :=
min_eq_right (zero_le a)
theorem zero_min (a : ) : min 0 a = 0 :=
min_zero_left a
theorem min_zero (a : ) : min a 0 = 0 :=
min_zero_right a
-- Distribute succ over min
lemma min_succ_succ (x y : ) : min (succ x) (succ y) = succ (min x y) :=
have f : x ≤ y → min (succ x) (succ y) = succ (min x y), from λp,
calc min (succ x) (succ y)
= succ x : if_pos (succ_le_succ p)
... = succ (min x y) : congr_arg succ (eq.symm (if_pos p)),
have g : ¬ (x ≤ y) → min (succ x) (succ y) = succ (min x y), from λp,
calc min (succ x) (succ y)
= succ y : if_neg (λeq, p (pred_le_pred eq))
... = succ (min x y) : congr_arg succ (eq.symm (if_neg p)),
decidable.by_cases f g
lemma sub_eq_sub_min (n m : ) : n - m = n - min n m :=
if h : n ≥ m then by rewrite [min_eq_right h]
else by rewrite [sub_eq_zero_of_le (le_of_not_ge h), min_eq_left (le_of_not_ge h), nat.sub_self]
@[simp]
lemma sub_add_min_cancel (n m : ) : n - m + min n m = n :=
by rewrite [sub_eq_sub_min, nat.sub_add_cancel (min_le_left n m)]
lemma pred_inj : ∀ {a b : nat}, a > 0 → b > 0 → nat.pred a = nat.pred b → a = b
| (succ a) (succ b) ha hb h := have a = b, from h, by rw this
| (succ a) 0 ha hb h := absurd hb (lt_irrefl _)
| 0 (succ b) ha hb h := absurd ha (lt_irrefl _)
| 0 0 ha hb h := rfl
/- TODO(Leo): sub + inequalities -/
protected def {u} strong_rec_on {p : nat → Sort u} (n : nat) (h : ∀ n, (∀ m, m < n → p m) → p n) : p n :=
suffices ∀ n m, m < n → p m, from this (succ n) n (lt_succ_self _),
begin
intros n, induction n with n ih,
{intros m h₁, exact absurd h₁ (not_lt_zero _)},
{intros m h₁,
apply or.by_cases (lt_or_eq_of_le (le_of_lt_succ h₁)),
{intros, apply ih, assumption},
{intros, subst m, apply h _ ih}}
end
protected lemma strong_induction_on {p : nat → Prop} (n : nat) (h : ∀ n, (∀ m, m < n → p m) → p n) : p n :=
nat.strong_rec_on n h
protected lemma case_strong_induction_on {p : nat → Prop} (a : nat)
(hz : p 0)
(hi : ∀ n, (∀ m, m ≤ n → p m) → p (succ n)) : p a :=
nat.strong_induction_on a $ λ n,
match n with
| 0 := λ _, hz
| (n+1) := λ h₁, hi n (λ m h₂, h₁ _ (lt_succ_of_le h₂))
end
/- mod -/
lemma mod_def (x y : nat) : mod x y = if 0 < y ∧ y ≤ x then mod (x - y) y else x :=
by note h := mod_def_aux x y; rwa [dif_eq_if] at h
lemma mod_zero (a : nat) : a % 0 = a :=
begin
rw mod_def,
assert h : ¬ (0 < 0 ∧ 0 ≤ a),
simp [lt_irrefl],
simp [if_neg, h]
end
lemma mod_eq_of_lt {a b : nat} (h : a < b) : a % b = a :=
begin
rw mod_def,
assert h' : ¬(0 < b ∧ b ≤ a),
simp [not_le_of_gt h],
simp [if_neg, h']
end
lemma zero_mod (b : nat) : 0 % b = 0 :=
begin
rw mod_def,
assert h : ¬(0 < b ∧ b ≤ 0),
{intro hn, cases hn with l r, exact absurd (lt_of_lt_of_le l r) (lt_irrefl 0)},
simp [if_neg, h]
end
lemma mod_eq_sub_mod {a b : nat} (h₁ : b > 0) (h₂ : a ≥ b) : a % b = (a - b) % b :=
by rw [mod_def, if_pos (and.intro h₁ h₂)]
lemma mod_lt (x : nat) {y : nat} (h : y > 0) : x % y < y :=
begin
induction x using nat.case_strong_induction_on with x ih,
{rw zero_mod, assumption},
{apply or.elim (decidable.em (succ x < y)),
{intro h₁, rwa [mod_eq_of_lt h₁]},
{intro h₁,
assert h₁ : succ x % y = (succ x - y) % y, {exact mod_eq_sub_mod h (le_of_not_gt h₁)},
assert this : succ x - y ≤ x, {exact le_of_lt_succ (sub_lt (succ_pos x) h)},
assert h₂ : (succ x - y) % y < y, {exact ih _ this},
rwa -h₁ at h₂}}
end
lemma eq_zero_of_le_zero : ∀ {n : nat}, n ≤ 0 → n = 0
| 0 h := rfl
| (n+1) h := absurd (zero_lt_succ n) (not_lt_of_ge h)
lemma mod_one (n : ) : n % 1 = 0 :=
have n % 1 < 1, from (mod_lt n) (succ_pos 0),
eq_zero_of_le_zero (le_of_lt_succ this)
lemma mod_two_eq_zero_or_one (n : )
: n % 2 = 0 n % 2 = 1 :=
begin
assert h : ((n % 2 < 1) (n % 2 = 1)),
{ apply lt_or_eq_of_le,
apply nat.le_of_succ_le_succ,
apply @nat.mod_lt n 2 (nat.le_succ _) },
cases h with h h,
{ left,
apply nat.le_antisymm ,
{ apply nat.le_of_succ_le_succ h },
{ apply nat.zero_le } },
{ right,
apply h }
end
lemma cond_to_bool_mod_two (x : ) [d : decidable (x % 2 = 1)]
: cond (@to_bool (x % 2 = 1) d) 1 0 = x % 2 :=
begin
cases d with h h
; unfold decidable.to_bool cond,
{ cases mod_two_eq_zero_or_one x with h' h',
rw h', cases h h' },
{ rw h },
end
lemma sub_mul_mod (x k n : )
(h₀ : 0 < n)
(h₁ : n*k ≤ x)
: (x - n*k) % n = x % n :=
begin
induction k with k,
{ simp },
{ assert h₂ : n * k ≤ x,
{ rw [mul_succ] at h₁,
apply nat.le_trans _ h₁,
apply le_add_right _ n },
assert h₄ : x - n * k ≥ n,
{ apply @nat.le_of_add_le_add_right (n*k),
rw [nat.sub_add_cancel h₂],
simp [mul_succ] at h₁, simp [h₁] },
rw [mul_succ,-nat.sub_sub,-mod_eq_sub_mod h₀ h₄,ih_1 h₂] }
end
/- div & mod -/
lemma div_def (x y : nat) : div x y = if 0 < y ∧ y ≤ x then div (x - y) y + 1 else 0 :=
by note h := div_def_aux x y; rwa dif_eq_if at h
lemma mod_add_div (m k : )
: m % k + k * (m / k) = m :=
begin
apply nat.strong_induction_on m,
clear m,
intros m IH,
cases decidable.em (0 < k ∧ k ≤ m) with h h',
-- 0 < k ∧ k ≤ m
{ assert h' : m - k < m,
{ apply nat.sub_lt _ h^.left,
apply lt_of_lt_of_le h^.left h^.right },
rw [div_def, mod_def, if_pos h, if_pos h],
simp [left_distrib,IH _ h'],
rw [-nat.add_sub_assoc h^.right,nat.add_sub_cancel_left] },
-- ¬ (0 < k ∧ k ≤ m)
{ rw [div_def, mod_def, if_neg h', if_neg h'], simp },
end
/- div -/
protected lemma div_one (n : ) : n / 1 = n :=
have n % 1 + 1 * (n / 1) = n, from mod_add_div _ _,
by simp [mod_one] at this; assumption
protected lemma div_zero (n : ) : n / 0 = 0 :=
begin rw [div_def], simp [lt_irrefl] end
protected lemma div_le_of_le_mul {m n : } : ∀ {k}, m ≤ k * n → m / k ≤ n
| 0 h := by simp [nat.div_zero]; apply zero_le
| (succ k) h :=
suffices succ k * (m / succ k) ≤ succ k * n, from le_of_mul_le_mul_left this (zero_lt_succ _),
calc
succ k * (m / succ k) ≤ m % succ k + succ k * (m / succ k) : le_add_left _ _
... = m : by rw mod_add_div
... ≤ succ k * n : h
protected lemma div_le_self : ∀ (m n : ), m / n ≤ m
| m 0 := by simp [nat.div_zero]; apply zero_le
| m (succ n) :=
have m ≤ succ n * m, from calc
m = 1 * m : by simp
... ≤ succ n * m : mul_le_mul_right _ (succ_le_succ (zero_le _)),
nat.div_le_of_le_mul this
lemma div_eq_sub_div {a b : nat} (h₁ : b > 0) (h₂ : a ≥ b)
: a / b = (a - b) / b + 1 :=
begin
rw [div_def a,if_pos],
split ; assumption
end
lemma sub_mul_div (x n p : )
(h₀ : 0 < n)
(h₁ : n*p ≤ x)
: (x - n*p) / n = x / n - p :=
begin
induction p with p,
{ simp },
{ assert h₂ : n*p ≤ x,
{ transitivity,
{ apply nat.mul_le_mul_left, apply le_succ },
{ apply h₁ } },
assert h₃ : x - n * p ≥ n,
{ apply le_of_add_le_add_right,
rw [nat.sub_add_cancel h₂,add_comm],
rw [mul_succ] at h₁,
apply h₁ },
rw [sub_succ,-ih_1 h₂],
rw [@div_eq_sub_div (x - n*p) _ h₀ h₃],
simp [add_one_eq_succ,pred_succ,mul_succ,nat.sub_sub] }
end
lemma div_eq_of_lt {a b : } (h₀ : a < b)
: a / b = 0 :=
begin
rw [div_def a,if_neg],
intro h₁,
apply not_le_of_gt h₀ h₁^.right
end
-- this is a Galois connection
-- f x ≤ y ↔ x ≤ g y
-- with
-- f x = x * k
-- g y = y / k
theorem le_div_iff_mul_le (x y : ) {k : }
(Hk : k > 0)
: x ≤ y / k ↔ x * k ≤ y :=
begin
-- Hk is needed because, despite div being made total, y / 0 := 0
-- x * 0 ≤ y ↔ x ≤ y / 0
-- ↔ 0 ≤ y ↔ x ≤ 0
-- ↔ true ↔ x = 0
-- ↔ x = 0
revert x,
apply nat.strong_induction_on y _,
clear y,
intros y IH x,
cases lt_or_ge y k with h h,
-- base case: y < k
{ rw [div_eq_of_lt h],
cases x with x,
{ simp [zero_mul,zero_le_iff_true] },
{ simp [succ_mul,succ_le_zero_iff_false],
apply not_le_of_gt,
apply lt_of_lt_of_le h,
apply le_add_right } },
-- step: k ≤ y
{ rw [div_eq_sub_div Hk h],
cases x with x,
{ simp [zero_mul,zero_le_iff_true] },
{ assert Hlt : y - k < y,
{ apply sub_lt_of_pos_le ; assumption },
rw [ -add_one_eq_succ
, nat.add_le_add_iff_le_right
, IH (y - k) Hlt x
, succ_mul,add_le_to_le_sub _ h] } }
end
theorem div_lt_iff_lt_mul (x y : ) {k : }
(Hk : k > 0)
: x / k < y ↔ x < y * k :=
begin
simp [lt_iff_not_ge],
apply not_iff_not_of_iff,
apply le_div_iff_mul_le _ _ Hk
end
/- pow -/
lemma pos_pow_of_pos {b : } : ∀ (n : ) (h : 0 < b), 0 < b^n
| 0 _ := nat.le_refl _
| (succ n) h :=
begin
rw -mul_zero 0,
apply mul_lt_mul (pos_pow_of_pos _ h) h,
apply nat.le_refl,
apply zero_le
end
/- mod / div / pow -/
theorem mod_pow_succ {b : } (b_pos : b > 0) (w m : )
: m % (b^succ w) = b * (m/b % b^w) + m % b :=
begin
apply nat.strong_induction_on m,
clear m,
intros p IH,
cases lt_or_ge p (b^succ w) with h₁ h₁,
-- base case: p < b^succ w
{ assert h₂ : p / b < b^w,
{ apply (div_lt_iff_lt_mul p _ b_pos)^.mpr,
simp at h₁, simp [h₁] },
rw [mod_eq_of_lt h₁,mod_eq_of_lt h₂], simp [mod_add_div], },
-- step: p ≥ b^succ w
{ assert h₄ : ∀ {x}, b^x > 0,
{ intro x, apply pos_pow_of_pos _ b_pos },
assert h₂ : p - b^succ w < p,
{ apply sub_lt_of_pos_le _ _ h₄ h₁ },
assert h₅ : b * b^w ≤ p,
{ simp at h₁, simp [h₁] },
rw [mod_eq_sub_mod h₄ h₁,IH _ h₂,pow_succ],
apply congr, apply congr_arg,
{ assert h₃ : p / b ≥ b^w,
{ apply (le_div_iff_mul_le _ p b_pos)^.mpr, simp [h₅] },
simp [nat.sub_mul_div _ _ _ b_pos h₅,mod_eq_sub_mod h₄ h₃] },
{ simp [nat.sub_mul_mod p (b^w) _ b_pos h₅] } }
end
end nat