lean2/library/data/nat/basic.lean
2014-12-23 21:14:35 -05:00

326 lines
10 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) 2014 Floris van Doorn. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Module: data.nat.basic
Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad
Basic operations on the natural numbers.
-/
import logic.connectives data.num algebra.binary
open eq.ops binary
namespace nat
/- a variant of add, defined by recursion on the first argument -/
definition addl (x y : ) : :=
nat.rec y (λ n r, succ r) x
infix `⊕`:65 := addl
theorem addl.succ_right (n m : ) : n ⊕ succ m = succ (n ⊕ m) :=
nat.induction_on n
rfl
(λ n₁ ih, calc
succ n₁ ⊕ succ m = succ (n₁ ⊕ succ m) : rfl
... = succ (succ (n₁ ⊕ m)) : ih
... = succ (succ n₁ ⊕ m) : rfl)
theorem add_eq_addl (x : ) : ∀y, x + y = x ⊕ y :=
nat.induction_on x
(λ y, nat.induction_on y
rfl
(λ y₁ ih, calc
zero + succ y₁ = succ (zero + y₁) : rfl
... = succ (zero ⊕ y₁) : {ih}
... = zero ⊕ (succ y₁) : rfl))
(λ x₁ ih₁ y, nat.induction_on y
(calc
succ x₁ + zero = succ (x₁ + zero) : rfl
... = succ (x₁ ⊕ zero) : {ih₁ zero}
... = succ x₁ ⊕ zero : rfl)
(λ y₁ ih₂, calc
succ x₁ + succ y₁ = succ (succ x₁ + y₁) : rfl
... = succ (succ x₁ ⊕ y₁) : {ih₂}
... = succ x₁ ⊕ succ y₁ : addl.succ_right))
/- successor and predecessor -/
theorem succ_ne_zero (n : ) : succ n ≠ 0 :=
assume H, no_confusion H
-- add_rewrite succ_ne_zero
theorem pred.zero : pred 0 = 0 :=
rfl
theorem pred.succ (n : ) : pred (succ n) = n :=
rfl
irreducible pred
theorem eq_zero_or_eq_succ_pred (n : ) : n = 0 n = succ (pred n) :=
induction_on n
(or.inl rfl)
(take m IH, or.inr
(show succ m = succ (pred (succ m)), from congr_arg succ !pred.succ⁻¹))
--theorem eq_zero_or_exists_eq_succ (n : ) : n = 0 ∃k, n = succ k :=
--or_of_or_of_imp_of_imp (eq_zero_or_eq_succ_pred n) (assume H, H)
-- (assume H : n = succ (pred n), exists.intro (pred n) H)
theorem succ.inj {n m : } (H : succ n = succ m) : n = m :=
no_confusion H (λe, e)
theorem succ.ne_self {n : } : succ n ≠ n :=
induction_on n
(take H : 1 = 0,
have ne : 1 ≠ 0, from !succ_ne_zero,
absurd H ne)
(take k IH H, IH (succ.inj H))
theorem discriminate {B : Prop} {n : } (H1: n = 0 → B) (H2 : ∀m, n = succ m → B) : B :=
have H : n = n → B, from cases_on n H1 H2,
H rfl
theorem two_step_induction_on {P : → Prop} (a : ) (H1 : P 0) (H2 : P 1)
(H3 : ∀ (n : ) (IH1 : P n) (IH2 : P (succ n)), P (succ (succ n))) : P a :=
have stronger : P a ∧ P (succ a), from
induction_on a
(and.intro H1 H2)
(take k IH,
have IH1 : P k, from and.elim_left IH,
have IH2 : P (succ k), from and.elim_right IH,
and.intro IH2 (H3 k IH1 IH2)),
and.elim_left stronger
theorem sub_induction {P : → Prop} (n m : ) (H1 : ∀m, P 0 m)
(H2 : ∀n, P (succ n) 0) (H3 : ∀n m, P n m → P (succ n) (succ m)) : P n m :=
have general : ∀m, P n m, from induction_on n
(take m : , H1 m)
(take k : ,
assume IH : ∀m, P k m,
take m : ,
cases_on m (H2 k) (take l, (H3 k l (IH l)))),
general m
/-
discriminate
(assume Hm : m = 0, Hm⁻¹ ▸ (H2 k))
(take l : , assume Hm : m = succ l, Hm⁻¹ ▸ (H3 k l (IH l)))),
general m
-/
/- addition -/
theorem add.right_id (n : ) : n + 0 = n :=
rfl
theorem add_succ (n m : ) : n + succ m = succ (n + m) :=
rfl
irreducible add
theorem add.left_id (n : ) : 0 + n = n :=
induction_on n
!add.right_id
(take m IH, show 0 + succ m = succ m, from
calc
0 + succ m = succ (0 + m) : add_succ
... = succ m : IH)
theorem add.succ_left (n m : ) : (succ n) + m = succ (n + m) :=
induction_on m
(!add.right_id ▸ !add.right_id)
(take k IH, calc
succ n + succ k = succ (succ n + k) : add_succ
... = succ (succ (n + k)) : IH
... = succ (n + succ k) : add_succ)
theorem add.comm (n m : ) : n + m = m + n :=
induction_on m
(!add.right_id ⬝ !add.left_id⁻¹)
(take k IH, calc
n + succ k = succ (n+k) : add_succ
... = succ (k + n) : IH
... = succ k + n : add.succ_left)
theorem succ_add_eq_add_succ (n m : ) : succ n + m = n + succ m :=
!add.succ_left ⬝ !add_succ⁻¹
-- theorem add.comm_succ (n m : ) : n + succ m = m + succ n :=
-- !succ_add_eq_add_succ⁻¹ ⬝ !add.comm
theorem add.assoc (n m k : ) : (n + m) + k = n + (m + k) :=
induction_on k
(!add.right_id ▸ !add.right_id)
(take l IH,
calc
(n + m) + succ l = succ ((n + m) + l) : add_succ
... = succ (n + (m + l)) : IH
... = n + succ (m + l) : add_succ
... = n + (m + succ l) : add_succ)
theorem add.left_comm (n m k : ) : n + (m + k) = m + (n + k) :=
left_comm add.comm add.assoc n m k
theorem add.right_comm (n m k : ) : n + m + k = n + k + m :=
right_comm add.comm add.assoc n m k
-- ### cancelation
theorem add.cancel_left {n m k : } : n + m = n + k → m = k :=
induction_on n
(take H : 0 + m = 0 + k,
!add.left_id⁻¹ ⬝ H ⬝ !add.left_id)
(take (n : ) (IH : n + m = n + k → m = k) (H : succ n + m = succ n + k),
have H2 : succ (n + m) = succ (n + k),
from calc
succ (n + m) = succ n + m : add.succ_left
... = succ n + k : H
... = succ (n + k) : add.succ_left,
have H3 : n + m = n + k, from succ.inj H2,
IH H3)
theorem add.cancel_right {n m k : } (H : n + m = k + m) : n = k :=
have H2 : m + n = m + k, from !add.comm ⬝ H ⬝ !add.comm,
add.cancel_left H2
theorem eq_zero_of_add_eq_zero_right {n m : } : n + m = 0 → n = 0 :=
induction_on n
(take (H : 0 + m = 0), rfl)
(take k IH,
assume H : succ k + m = 0,
absurd
(show succ (k + m) = 0, from calc
succ (k + m) = succ k + m : add.succ_left
... = 0 : H)
!succ_ne_zero)
theorem eq_zero_of_add_eq_zero_left {n m : } (H : n + m = 0) : m = 0 :=
eq_zero_of_add_eq_zero_right (!add.comm ⬝ H)
theorem add.eq_zero {n m : } (H : n + m = 0) : n = 0 ∧ m = 0 :=
and.intro (eq_zero_of_add_eq_zero_right H) (eq_zero_of_add_eq_zero_left H)
-- ### misc
theorem add_one (n : ) : n + 1 = succ n :=
!add.right_id ▸ !add_succ
theorem one_add (n : ) : 1 + n = succ n :=
!add.left_id ▸ !add.succ_left
-- TODO: rename? remove?
-- theorem induction_plus_one {P : nat → Prop} (a : ) (H1 : P 0)
-- (H2 : ∀ (n : ) (IH : P n), P (n + 1)) : P a :=
-- nat.rec H1 (take n IH, !add.one ▸ (H2 n IH)) a
/- multiplication -/
theorem mul_zero (n : ) : n * 0 = 0 :=
rfl
theorem mul_succ (n m : ) : n * succ m = n * m + n :=
rfl
irreducible mul
-- ### commutativity, distributivity, associativity, identity
theorem zero_mul (n : ) : 0 * n = 0 :=
induction_on n
!mul_zero
(take m IH, !mul_succ ⬝ !add.right_id ⬝ IH)
theorem succ_mul (n m : ) : (succ n) * m = (n * m) + m :=
induction_on m
(!mul_zero ⬝ !mul_zero⁻¹ ⬝ !add.right_id⁻¹)
(take k IH, calc
succ n * succ k = succ n * k + succ n : mul_succ
... = n * k + k + succ n : IH
... = n * k + (k + succ n) : add.assoc
... = n * k + (succ n + k) : add.comm
... = n * k + (n + succ k) : succ_add_eq_add_succ
... = n * k + n + succ k : add.assoc
... = n * succ k + succ k : mul_succ)
theorem mul.comm (n m : ) : n * m = m * n :=
induction_on m
(!mul_zero ⬝ !zero_mul⁻¹)
(take k IH, calc
n * succ k = n * k + n : mul_succ
... = k * n + n : IH
... = (succ k) * n : succ_mul)
theorem mul.right_distrib (n m k : ) : (n + m) * k = n * k + m * k :=
induction_on k
(calc
(n + m) * 0 = 0 : mul_zero
... = 0 + 0 : add.right_id
... = n * 0 + 0 : mul_zero
... = n * 0 + m * 0 : mul_zero)
(take l IH, calc
(n + m) * succ l = (n + m) * l + (n + m) : mul_succ
... = n * l + m * l + (n + m) : IH
... = n * l + m * l + n + m : add.assoc
... = n * l + n + m * l + m : add.right_comm
... = n * l + n + (m * l + m) : add.assoc
... = n * succ l + (m * l + m) : mul_succ
... = n * succ l + m * succ l : mul_succ)
theorem mul.left_distrib (n m k : ) : n * (m + k) = n * m + n * k :=
calc
n * (m + k) = (m + k) * n : mul.comm
... = m * n + k * n : mul.right_distrib
... = n * m + k * n : mul.comm
... = n * m + n * k : mul.comm
theorem mul.assoc (n m k : ) : (n * m) * k = n * (m * k) :=
induction_on k
(calc
(n * m) * 0 = 0 : mul_zero
... = n * 0 : mul_zero
... = n * (m * 0) : mul_zero)
(take l IH,
calc
(n * m) * succ l = (n * m) * l + n * m : mul_succ
... = n * (m * l) + n * m : IH
... = n * (m * l + m) : mul.left_distrib
... = n * (m * succ l) : mul_succ)
theorem mul.left_comm (n m k : ) : n * (m * k) = m * (n * k) :=
left_comm mul.comm mul.assoc n m k
theorem mul.right_comm (n m k : ) : n * m * k = n * k * m :=
right_comm mul.comm mul.assoc n m k
theorem mul.right_id (n : ) : n * 1 = n :=
calc
n * 1 = n * 0 + n : mul_succ
... = 0 + n : mul_zero
... = n : add.left_id
theorem mul.left_id (n : ) : 1 * n = n :=
calc
1 * n = n * 1 : mul.comm
... = n : mul.right_id
theorem eq_zero_or_eq_zero_of_mul_eq_zero {n m : } : n * m = 0 → n = 0 m = 0 :=
cases_on n
(assume H, or.inl rfl)
(take n',
cases_on m
(assume H, or.inr rfl)
(take m',
assume H : succ n' * succ m' = 0,
absurd
((calc
0 = succ n' * succ m' : H
... = succ n' * m' + succ n' : mul_succ
... = succ (succ n' * m' + n') : add_succ)⁻¹)
!succ_ne_zero))
end nat