feat(init/data/int,init/data/nat,init/algebra): more algebra theorems

This commit is contained in:
Mario Carneiro 2017-05-31 08:48:25 -04:00 committed by Leonardo de Moura
parent d8f03082b7
commit d82b8ed59e
7 changed files with 121 additions and 77 deletions

View file

@ -52,6 +52,9 @@ instance comm_semigroup_to_is_commutative [comm_semigroup α] : is_commutative
@[simp] lemma mul_left_comm [comm_semigroup α] : ∀ a b c : α, a * (b * c) = b * (a * c) :=
left_comm has_mul.mul mul_comm mul_assoc
lemma mul_right_comm [comm_semigroup α] : ∀ a b c : α, a * b * c = a * c * b :=
right_comm has_mul.mul mul_comm mul_assoc
lemma mul_left_cancel [left_cancel_semigroup α] {a b c : α} : a * b = a * c → b = c :=
left_cancel_semigroup.mul_left_cancel a b c
@ -252,6 +255,7 @@ meta def multiplicative_to_additive_pairs : list (name × name) :=
(`mul_assoc, `add_assoc),
(`mul_comm, `add_comm),
(`mul_left_comm, `add_left_comm),
(`mul_right_comm, `add_right_comm),
(`one_mul, `zero_add),
(`mul_one, `add_zero),
(`mul_left_inv, `add_left_neg),

View file

@ -53,6 +53,9 @@ weak_order.le_antisymm
lemma le_of_eq [weak_order α] {a b : α} : a = b → a ≤ b :=
λ h, h ▸ le_refl a
lemma le_antisymm_iff [weak_order α] {a b : α} : a = b ↔ a ≤ b ∧ b ≤ a :=
⟨λe, ⟨le_of_eq e, le_of_eq e.symm⟩, λ⟨h1, h2⟩, le_antisymm h1 h2⟩
@[trans] lemma ge_trans [weak_order α] : ∀ {a b c : α}, a ≥ b → b ≥ c → a ≥ c :=
λ a b c h₁ h₂, le_trans h₂ h₁

View file

@ -37,6 +37,9 @@ lemma le_mul_of_ge_one_right {a b : α} (hb : b ≥ 0) (h : a ≥ 1) : b ≤ b *
suffices b * 1 ≤ b * a, by rwa mul_one at this,
mul_le_mul_of_nonneg_left h hb
lemma le_mul_of_ge_one_left {a b : α} (hb : b ≥ 0) (h : a ≥ 1) : b ≤ a * b :=
by rw mul_comm; exact le_mul_of_ge_one_right hb h
lemma lt_mul_of_gt_one_right {a b : α} (hb : b > 0) (h : a > 1) : b < b * a :=
suffices b * 1 < b * a, by rwa mul_one at this,
mul_lt_mul_of_pos_left h hb

View file

@ -61,10 +61,10 @@ calc
a * b < c * b : mul_lt_mul_of_pos_right hac pos_b
... ≤ c * d : mul_le_mul_of_nonneg_left hbd nn_c
lemma mul_lt_mul' {a b c d : α} (h1 : a < c) (h2 : b < d) (h3 : b ≥ 0) (h4 : c > 0) :
lemma mul_lt_mul' {a b c d : α} (h1 : a c) (h2 : b < d) (h3 : b ≥ 0) (h4 : c > 0) :
a * b < c * d :=
calc
a * b ≤ c * b : mul_le_mul_of_nonneg_right (le_of_lt h1) h3
a * b ≤ c * b : mul_le_mul_of_nonneg_right h1 h3
... < c * d : mul_lt_mul_of_pos_left h2 h4
lemma mul_pos {a b : α} (ha : a > 0) (hb : b > 0) : a * b > 0 :=
@ -83,7 +83,7 @@ lemma mul_self_le_mul_self {a b : α} (h1 : 0 ≤ a) (h2 : a ≤ b) : a * a ≤
mul_le_mul h2 h2 h1 (le_trans h1 h2)
lemma mul_self_lt_mul_self {a b : α} (h1 : 0 ≤ a) (h2 : a < b) : a * a < b * b :=
mul_lt_mul' h2 h2 h1 (lt_of_le_of_lt h1 h2)
mul_lt_mul' (le_of_lt h2) h2 h1 (lt_of_le_of_lt h1 h2)
end ordered_semiring
class linear_ordered_semiring (α : Type u) extends ordered_semiring α, linear_strong_order_pair α :=

View file

@ -368,8 +368,18 @@ protected lemma coe_nat_sub {n m : } : n ≤ m → (↑(m - n) : ) = ↑m
protected lemma sub_nat_nat_eq_coe {m n : } : sub_nat_nat m n = ↑m - ↑n :=
sub_nat_nat_elim m n (λm n i, i = ↑m - ↑n)
(λi n, by simp[int.coe_nat_add]; refl)
(λi n, by simp[int.coe_nat_add, int.coe_nat_one, int.neg_succ_of_nat_eq];
(λi n, by simp [int.coe_nat_add]; refl)
(λi n, by simp [int.coe_nat_add, int.coe_nat_one, int.neg_succ_of_nat_eq];
apply congr_arg; rw[add_left_comm]; simp)
def to_nat :
| (n : ) := n
| -[1+ n] := 0
theorem to_nat_sub (m n : ) : to_nat (m - n) = m - n :=
by rw -int.sub_nat_nat_eq_coe; exact sub_nat_nat_elim m n
(λm n i, to_nat i = m - n)
(λi n, by rw [nat.add_sub_cancel_left]; refl)
(λi n, by rw [add_assoc, nat.sub_eq_zero_of_le (nat.le_add_right _ _)]; refl)
end int

View file

@ -229,6 +229,14 @@ instance : decidable_linear_ordered_comm_ring int :=
instance : decidable_linear_ordered_comm_group int :=
by apply_instance
lemma eq_nat_abs_of_zero_le {a : } (h : 0 ≤ a) : a = nat_abs a :=
let ⟨n, e⟩ := eq_coe_of_zero_le h in by rw e; refl
lemma le_nat_abs {a : } : a ≤ nat_abs a :=
or.elim (le_total 0 a)
(λh, by rw eq_nat_abs_of_zero_le h; refl)
(λh, le_trans h (coe_zero_le _))
end int
-- TODO(Jeremy): add more facts specific to the integers

View file

@ -236,6 +236,9 @@ less_than_or_equal.cases_on h₁ (λ a, rfl) (λ a b c, absurd (nat.lt_of_le_of_
instance : weak_order :=
⟨@nat.less_than_or_equal, @nat.le_refl, @nat.le_trans, @nat.le_antisymm⟩
lemma eq_zero_of_le_zero {n : nat} (h : n ≤ 0) : n = 0 :=
le_antisymm h (zero_le _)
lemma lt_le_antisymm {n m : } (h₁ : n < m) (h₂ : m ≤ n) : false :=
le_lt_antisymm h₂ h₁
@ -331,7 +334,7 @@ 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],
rw [nat.add_comm _ k, nat.add_comm _ k],
apply nat.le_of_add_le_add_left
end
@ -710,7 +713,7 @@ 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]
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 :=
@ -902,8 +905,10 @@ begin
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_eq_sub_mod {a b : nat} (h : a ≥ b) : a % b = (a - b) % b :=
or.elim (eq_zero_or_pos b)
(λb0, by rw [b0, nat.sub_zero])
(λh₂, by rw [mod_def, if_pos (and.intro h₂ h)])
lemma mod_lt (x : nat) {y : nat} (h : y > 0) : x % y < y :=
begin
@ -912,16 +917,21 @@ begin
{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 h₁ : succ x % y = (succ x - y) % y, {exact mod_eq_sub_mod (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 mod_le (x y : ) : x % y ≤ x :=
or.elim (lt_or_ge x y)
(λxlty, by rw mod_eq_of_lt xlty; refl)
(λylex, or.elim (eq_zero_or_pos y)
(λy0, by rw [y0, mod_zero]; refl)
(λypos, le_trans (le_of_lt (mod_lt _ ypos)) ylex))
@[simp] theorem add_mod_right (x z : ) : (x + z) % z = x % z :=
or.elim (eq_zero_or_pos z)
(λz0, by simph)
(λh, by rw [mod_eq_sub_mod h (nat.le_add_left _ _), nat.add_sub_cancel])
by rw [mod_eq_sub_mod (nat.le_add_left _ _), nat.add_sub_cancel]
@[simp] theorem add_mod_left (x z : ) : (x + z) % x = z % x :=
by rw [add_comm, add_mod_right]
@ -939,11 +949,7 @@ by rw [-(zero_add (m*n)), add_mul_mod_self_left, zero_mod]
by rw [mul_comm, mul_mod_right]
theorem mod_self (n : nat) : n % n = 0 :=
by {cases n, exact zero_mod _, rw [mod_eq_sub_mod (succ_pos _) (le_refl _), nat.sub_self, zero_mod]}
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)
by rw [mod_eq_sub_mod (le_refl _), nat.sub_self, zero_mod]
lemma mod_one (n : ) : n % 1 = 0 :=
have n % 1 < 1, from (mod_lt n) (succ_pos 0),
@ -959,8 +965,8 @@ else x.strong_induction_on $ λn IH,
have z0 : z > 0, from nat.pos_of_ne_zero z0,
or.elim (le_or_gt y n)
(λyn, by rw [
mod_eq_sub_mod y0 yn,
mod_eq_sub_mod (mul_pos z0 y0) (mul_le_mul_left z yn),
mod_eq_sub_mod yn,
mod_eq_sub_mod (mul_le_mul_left z yn),
-nat.mul_sub_left_distrib];
exact IH _ (sub_lt (lt_of_lt_of_le y0 yn) y0))
(λyn, by rw [mod_eq_of_lt yn, mod_eq_of_lt (mul_lt_mul_of_pos_left yn z0)])
@ -994,10 +1000,7 @@ begin
{ rw h },
end
lemma sub_mul_mod (x k n : )
(h₀ : 0 < n)
(h₁ : n*k ≤ x)
: (x - n*k) % n = x % n :=
lemma sub_mul_mod (x k n : ) (h₁ : n*k ≤ x) : (x - n*k) % n = x % n :=
begin
induction k with k,
{ simp },
@ -1009,7 +1012,7 @@ begin
{ 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₂] }
rw [mul_succ, -nat.sub_sub, -mod_eq_sub_mod h₄, ih_1 h₂] }
end
/- div & mod -/
@ -1028,8 +1031,8 @@ begin
{ 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] },
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
@ -1063,38 +1066,35 @@ 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 :=
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],
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 :=
lemma sub_mul_div (x n p : ) (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] }
cases eq_zero_or_pos n with h₀ h₀,
{ rw [h₀, nat.div_zero, nat.div_zero, nat.zero_sub] },
{ 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 :=
lemma div_eq_of_lt {a b : } (h₀ : a < b) : a / b = 0 :=
begin
rw [div_def a,if_neg],
rw [div_def a, if_neg],
intro h₁,
apply not_le_of_gt h₀ h₁.right
end
@ -1121,15 +1121,15 @@ begin
-- 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],
{ 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] },
{ simp [zero_mul, zero_le_iff_true] },
{ assert Hlt : y - k < y,
{ apply sub_lt_of_pos_le ; assumption },
rw [ -add_one_eq_succ
@ -1205,14 +1205,37 @@ end
@[simp] lemma pow_one (b : ) : b^1 = b := by simp [pow_succ]
lemma pos_pow_of_pos {b : } : ∀ (n : ) (h : 0 < b), 0 < b^n
| 0 _ := nat.le_refl _
| (succ n) h :=
theorem pow_le_pow_of_le_left {x y : } (H : x ≤ y) : ∀ i, x^i ≤ y^i
| 0 := le_refl _
| (succ i) := mul_le_mul (pow_le_pow_of_le_left i) H (zero_le _) (zero_le _)
theorem pow_le_pow_of_le_right {x : } (H : x > 0) {i} : ∀ {j}, i ≤ j → x^i ≤ x^j
| 0 h := by rw eq_zero_of_le_zero h; apply le_refl
| (succ j) h := (lt_or_eq_of_le h).elim
(λhl, by rw [pow_succ, -mul_one (x^i)]; exact
mul_le_mul (pow_le_pow_of_le_right $ le_of_lt_succ hl) H (zero_le _) (zero_le _))
(λe, by rw e; refl)
lemma pos_pow_of_pos {b : } (n : ) (h : 0 < b) : 0 < b^n :=
pow_le_pow_of_le_right h (zero_le _)
lemma zero_pow {n : } (h : 0 < n) : 0^n = 0 :=
by rw [-succ_pred_eq_of_pos h, pow_succ, mul_zero]
theorem pow_lt_pow_of_lt_left {x y : } (H : x < y) {i} (h : i > 0) : x^i < y^i :=
begin
rw -mul_zero 0,
apply mul_lt_mul (pos_pow_of_pos _ h) h,
apply nat.le_refl,
apply zero_le
cases i with i, { exact absurd h (not_lt_zero _) },
rw [pow_succ, pow_succ],
exact mul_lt_mul' (pow_le_pow_of_le_left (le_of_lt H) _) H (zero_le _)
(pos_pow_of_pos _ $ lt_of_le_of_lt (zero_le _) H)
end
theorem pow_lt_pow_of_lt_right {x : } (H : x > 1) {i j} (h : i < j) : x^i < x^j :=
begin
note xpos := lt_of_succ_lt H,
refine lt_of_lt_of_le _ (pow_le_pow_of_le_right xpos h),
rw [-mul_one (x^i), pow_succ],
exact nat.mul_lt_mul_of_pos_left H (pos_pow_of_pos _ xpos)
end
/- mod / div / pow -/
@ -1227,34 +1250,27 @@ begin
-- base case: p < b^succ w
{ assert h₂ : p / b < b^w,
{ rw [div_lt_iff_lt_mul p _ b_pos],
simp [nat.pow_succ] at h₁,
simp [h₁]
},
rw [mod_eq_of_lt h₁,mod_eq_of_lt h₂],
simp [mod_add_div],
},
simp [pow_succ] at h₁,
simp [h₁] },
rw [mod_eq_of_lt h₁, mod_eq_of_lt h₂],
simp [mod_add_div] },
-- step: p ≥ b^succ w
{ -- Generate condiition for induction principal
assert h₂ : p - b^succ w < p,
{ apply sub_lt_of_pos_le _ _ (pos_pow_of_pos _ b_pos) h₁ },
-- Apply induction
rw [mod_eq_sub_mod (pos_pow_of_pos _ b_pos) h₁, IH _ h₂],
rw [mod_eq_sub_mod h₁, IH _ h₂],
-- Normalize goal and h1
simp [pow_succ],
simp [ge, pow_succ] at h₁,
-- Pull subtraction outside mod and div
rw [sub_mul_mod _ _ _ b_pos h₁],
rw [sub_mul_div _ _ _ b_pos h₁],
rw [sub_mul_mod _ _ _ h₁, sub_mul_div _ _ _ h₁],
-- Cancel subtraction inside mod b^w
note b_w_pos : b^w > 0 := pos_pow_of_pos _ b_pos,
assert p_b_ge : b^w ≤ p / b,
{
rw [le_div_iff_mul_le _ _ b_pos],
simp [h₁],
},
rw [eq.symm (mod_eq_sub_mod b_w_pos p_b_ge)],
}
{ rw [le_div_iff_mul_le _ _ b_pos],
simp [h₁] },
rw [eq.symm (mod_eq_sub_mod p_b_ge)] }
end
end nat