feat(lib/init/data/nat): add function pow and a Galois connection between div and mul

This commit is contained in:
Simon Hudon 2017-03-10 16:14:37 -08:00 committed by Leonardo de Moura
parent c694dbd600
commit b6889e91fe
4 changed files with 242 additions and 2 deletions

View file

@ -207,6 +207,9 @@ match lt_trichotomy a b with
| or.inr (or.inr hgt) := or.inr hgt
end
lemma lt_iff_not_ge [linear_strong_order_pair α] (x y : α) : x < y ↔ ¬ x ≥ y :=
⟨not_le_of_gt, lt_of_not_ge⟩
/- The following lemma can be used when defining a decidable_linear_order instance, and the concrete structure
does not have its own definition for decidable le -/
def decidable_le_of_decidable_lt [linear_strong_order_pair α] [∀ a b : α, decidable (a < b)] (a b : α) : decidable (a ≤ b) :=

View file

@ -4,4 +4,4 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import init.data.nat.basic init.data.nat.div init.data.nat.lemmas
import init.data.nat.basic init.data.nat.div init.data.nat.pow init.data.nat.lemmas

View file

@ -4,7 +4,7 @@ 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.meta init.algebra.functions
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
@ -314,6 +314,15 @@ match le.dest h with
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))
@ -626,10 +635,45 @@ protected theorem sub_sub : ∀ (n m k : ), n - m - k = 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]
@ -822,6 +866,50 @@ 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
@ -870,4 +958,129 @@ protected lemma div_le_self : ∀ (m n : ), m / n ≤ m
... ≤ 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

View file

@ -0,0 +1,24 @@
/-
Copyright (c) 2017 Galois Inc. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Simon Hudon
exponentiation on natural numbers
This is a work-in-progress
-/
prelude
import init.data.nat.basic init.meta
namespace nat
def pow (b : ) :
| 0 := 1
| (succ n) := pow n * b
infix `^` := pow
@[simp] lemma pow_succ (b n : ) : b^(succ n) = b^n * b := rfl
end nat