lean4-htt/library/init/algebra/functions.lean

485 lines
17 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: Jeremy Avigad, Leonardo de Moura
-/
prelude
import init.algebra.ordered_field
universe u
definition min {α : Type u} [decidable_linear_order α] (a b : α) : α := if a ≤ b then a else b
definition max {α : Type u} [decidable_linear_order α] (a b : α) : α := if a ≤ b then b else a
definition abs {α : Type u} [decidable_linear_ordered_comm_group α] (a : α) : α := max a (-a)
section
open decidable tactic
variables {α : Type u} [decidable_linear_order α]
private meta def min_tac_step : tactic unit :=
solve1 $ intros
>> `[unfold min max]
>> try `[simp_using_hs [if_pos, if_neg]]
>> try `[apply le_refl]
>> try `[apply le_of_not_le, assumption]
meta def tactic.interactive.min_tac (a b : interactive.parse lean.parser.qexpr) : tactic unit :=
`[apply @by_cases (%%a ≤ %%b), repeat {min_tac_step}]
lemma min_le_left (a b : α) : min a b ≤ a :=
by min_tac a b
lemma min_le_right (a b : α) : min a b ≤ b :=
by min_tac a b
lemma le_min {a b c : α} (h₁ : c ≤ a) (h₂ : c ≤ b) : c ≤ min a b :=
by min_tac a b
lemma le_max_left (a b : α) : a ≤ max a b :=
by min_tac a b
lemma le_max_right (a b : α) : b ≤ max a b :=
by min_tac a b
lemma max_le {a b c : α} (h₁ : a ≤ c) (h₂ : b ≤ c) : max a b ≤ c :=
by min_tac a b
lemma eq_min {a b c : α} (h₁ : c ≤ a) (h₂ : c ≤ b) (h₃ : ∀{d}, d ≤ a → d ≤ b → d ≤ c) : c = min a b :=
le_antisymm (le_min h₁ h₂) (h₃ (min_le_left a b) (min_le_right a b))
lemma min_comm (a b : α) : min a b = min b a :=
eq_min (min_le_right a b) (min_le_left a b) (λ c h₁ h₂, le_min h₂ h₁)
lemma min_assoc (a b c : α) : min (min a b) c = min a (min b c) :=
begin
apply eq_min,
{ apply le_trans, apply min_le_left, apply min_le_left },
{ apply le_min, apply le_trans, apply min_le_left, apply min_le_right, apply min_le_right },
{ intros d h₁ h₂, apply le_min, apply le_min h₁, apply le_trans h₂, apply min_le_left,
apply le_trans h₂, apply min_le_right }
end
lemma min_left_comm : ∀ (a b c : α), min a (min b c) = min b (min a c) :=
left_comm (@min α _) (@min_comm α _) (@min_assoc α _)
@[simp]
lemma min_self (a : α) : min a a = a :=
by min_tac a a
@[ematch]
lemma min_eq_left {a b : α} (h : a ≤ b) : min a b = a :=
begin apply eq.symm, apply eq_min (le_refl _) h, intros, assumption end
@[ematch]
lemma min_eq_right {a b : α} (h : b ≤ a) : min a b = b :=
eq.subst (min_comm b a) (min_eq_left h)
lemma eq_max {a b c : α} (h₁ : a ≤ c) (h₂ : b ≤ c) (h₃ : ∀{d}, a ≤ d → b ≤ d → c ≤ d) : c = max a b :=
le_antisymm (h₃ (le_max_left a b) (le_max_right a b)) (max_le h₁ h₂)
lemma max_comm (a b : α) : max a b = max b a :=
eq_max (le_max_right a b) (le_max_left a b) (λ c h₁ h₂, max_le h₂ h₁)
lemma max_assoc (a b c : α) : max (max a b) c = max a (max b c) :=
begin
apply eq_max,
{ apply le_trans, apply le_max_left a b, apply le_max_left },
{ apply max_le, apply le_trans, apply le_max_right a b, apply le_max_left, apply le_max_right },
{ intros d h₁ h₂, apply max_le, apply max_le h₁, apply le_trans (le_max_left _ _) h₂,
apply le_trans (le_max_right _ _) h₂}
end
lemma max_left_comm : ∀ (a b c : α), max a (max b c) = max b (max a c) :=
left_comm (@max α _) (@max_comm α _) (@max_assoc α _)
@[simp]
lemma max_self (a : α) : max a a = a :=
by min_tac a a
lemma max_eq_left {a b : α} (h : b ≤ a) : max a b = a :=
begin apply eq.symm, apply eq_max (le_refl _) h, intros, assumption end
lemma max_eq_right {a b : α} (h : a ≤ b) : max a b = b :=
eq.subst (max_comm b a) (max_eq_left h)
/- these rely on lt_of_lt -/
lemma min_eq_left_of_lt {a b : α} (h : a < b) : min a b = a :=
min_eq_left (le_of_lt h)
lemma min_eq_right_of_lt {a b : α} (h : b < a) : min a b = b :=
min_eq_right (le_of_lt h)
lemma max_eq_left_of_lt {a b : α} (h : b < a) : max a b = a :=
max_eq_left (le_of_lt h)
lemma max_eq_right_of_lt {a b : α} (h : a < b) : max a b = b :=
max_eq_right (le_of_lt h)
/- these use the fact that it is a linear ordering -/
lemma lt_min {a b c : α} (h₁ : a < b) (h₂ : a < c) : a < min b c :=
or.elim (le_or_gt b c)
(assume h : b ≤ c, by min_tac b c)
(assume h : b > c, by min_tac b c)
lemma max_lt {a b c : α} (h₁ : a < c) (h₂ : b < c) : max a b < c :=
or.elim (le_or_gt a b)
(assume h : a ≤ b, by min_tac a b)
(assume h : a > b, by min_tac a b)
end
section
variables {α : Type u} [decidable_linear_ordered_cancel_comm_monoid α]
lemma min_add_add_left (a b c : α) : min (a + b) (a + c) = a + min b c :=
eq.symm (eq_min
(show a + min b c ≤ a + b, from add_le_add_left (min_le_left _ _) _)
(show a + min b c ≤ a + c, from add_le_add_left (min_le_right _ _) _)
(take d,
suppose d ≤ a + b,
suppose d ≤ a + c,
decidable.by_cases
(suppose b ≤ c, by rwa [min_eq_left this])
(suppose ¬ b ≤ c, by rwa [min_eq_right (le_of_lt (lt_of_not_ge this))])))
lemma min_add_add_right (a b c : α) : min (a + c) (b + c) = min a b + c :=
begin rw [add_comm a c, add_comm b c, add_comm _ c], apply min_add_add_left end
lemma max_add_add_left (a b c : α) : max (a + b) (a + c) = a + max b c :=
eq.symm (eq_max
(add_le_add_left (le_max_left _ _) _)
(add_le_add_left (le_max_right _ _) _)
(take d,
suppose a + b ≤ d,
suppose a + c ≤ d,
decidable.by_cases
(suppose b ≤ c, by rwa [max_eq_right this])
(suppose ¬ b ≤ c, by rwa [max_eq_left (le_of_lt (lt_of_not_ge this))])))
lemma max_add_add_right (a b c : α) : max (a + c) (b + c) = max a b + c :=
begin rw [add_comm a c, add_comm b c, add_comm _ c], apply max_add_add_left end
end
section
variables {α : Type u} [decidable_linear_ordered_comm_group α]
lemma max_neg_neg (a b : α) : max (-a) (-b) = - min a b :=
eq.symm (eq_max
(show -a ≤ -(min a b), from neg_le_neg $ min_le_left a b)
(show -b ≤ -(min a b), from neg_le_neg $ min_le_right a b)
(take d,
assume H₁ : -a ≤ d,
assume H₂ : -b ≤ d,
have H : -d ≤ min a b,
from le_min (neg_le_of_neg_le H₁) (neg_le_of_neg_le H₂),
show -(min a b) ≤ d, from neg_le_of_neg_le H))
lemma min_eq_neg_max_neg_neg (a b : α) : min a b = - max (-a) (-b) :=
by rw [max_neg_neg, neg_neg]
lemma min_neg_neg (a b : α) : min (-a) (-b) = - max a b :=
by rw [min_eq_neg_max_neg_neg, neg_neg, neg_neg]
lemma max_eq_neg_min_neg_neg (a b : α) : max a b = - min (-a) (-b) :=
by rw [min_neg_neg, neg_neg]
end
section decidable_linear_ordered_comm_group
variables {α : Type u} [decidable_linear_ordered_comm_group α]
lemma abs_of_nonneg {a : α} (h : a ≥ 0) : abs a = a :=
have h' : -a ≤ a, from le_trans (neg_nonpos_of_nonneg h) h,
max_eq_left h'
lemma abs_of_pos {a : α} (h : a > 0) : abs a = a :=
abs_of_nonneg (le_of_lt h)
lemma abs_of_nonpos {a : α} (h : a ≤ 0) : abs a = -a :=
have h' : a ≤ -a, from le_trans h (neg_nonneg_of_nonpos h),
max_eq_right h'
lemma abs_of_neg {a : α} (h : a < 0) : abs a = -a :=
abs_of_nonpos (le_of_lt h)
lemma abs_zero : abs 0 = (0:α) :=
abs_of_nonneg (le_refl _)
lemma abs_neg (a : α) : abs (-a) = abs a :=
begin unfold abs, rw [max_comm, neg_neg] end
lemma abs_pos_of_pos {a : α} (h : a > 0) : abs a > 0 :=
by rwa (abs_of_pos h)
lemma abs_pos_of_neg {a : α} (h : a < 0) : abs a > 0 :=
abs_neg a ▸ abs_pos_of_pos (neg_pos_of_neg h)
lemma abs_sub (a b : α) : abs (a - b) = abs (b - a) :=
by rw [-neg_sub, abs_neg]
lemma ne_zero_of_abs_ne_zero {a : α} (h : abs a ≠ 0) : a ≠ 0 :=
assume ha, h (eq.symm ha ▸ abs_zero)
/- these assume a linear order -/
lemma eq_zero_of_neg_eq {a : α} (h : -a = a) : a = 0 :=
match lt_trichotomy a 0 with
| or.inl h₁ :=
have a > 0, from h ▸ neg_pos_of_neg h₁,
absurd h₁ (lt_asymm this)
| or.inr (or.inl h₁) := h₁
| or.inr (or.inr h₁) :=
have a < 0, from h ▸ neg_neg_of_pos h₁,
absurd h₁ (lt_asymm this)
end
lemma abs_nonneg (a : α) : abs a ≥ 0 :=
or.elim (le_total 0 a)
(assume h : 0 ≤ a, by rwa (abs_of_nonneg h))
(assume h : a ≤ 0, calc
0 ≤ -a : neg_nonneg_of_nonpos h
... = abs a : eq.symm (abs_of_nonpos h))
lemma abs_abs (a : α) : abs (abs a) = abs a :=
abs_of_nonneg $ abs_nonneg a
lemma le_abs_self (a : α) : a ≤ abs a :=
or.elim (le_total 0 a)
(assume h : 0 ≤ a,
begin rw [abs_of_nonneg h], apply le_refl end)
(assume h : a ≤ 0, le_trans h $ abs_nonneg a)
lemma neg_le_abs_self (a : α) : -a ≤ abs a :=
abs_neg a ▸ le_abs_self (-a)
lemma eq_zero_of_abs_eq_zero {a : α} (h : abs a = 0) : a = 0 :=
have h₁ : a ≤ 0, from h ▸ le_abs_self a,
have h₂ : -a ≤ 0, from h ▸ abs_neg a ▸ le_abs_self (-a),
le_antisymm h₁ (nonneg_of_neg_nonpos h₂)
lemma eq_of_abs_sub_eq_zero {a b : α} (h : abs (a - b) = 0) : a = b :=
have a - b = 0, from eq_zero_of_abs_eq_zero h,
show a = b, from eq_of_sub_eq_zero this
lemma abs_pos_of_ne_zero {a : α} (h : a ≠ 0) : abs a > 0 :=
or.elim (lt_or_gt_of_ne h) abs_pos_of_neg abs_pos_of_pos
lemma abs_by_cases (P : α → Prop) {a : α} (h1 : P a) (h2 : P (-a)) : P (abs a) :=
or.elim (le_total 0 a)
(assume h : 0 ≤ a, eq.symm (abs_of_nonneg h) ▸ h1)
(assume h : a ≤ 0, eq.symm (abs_of_nonpos h) ▸ h2)
lemma abs_le_of_le_of_neg_le {a b : α} (h1 : a ≤ b) (h2 : -a ≤ b) : abs a ≤ b :=
abs_by_cases (λ x : α, x ≤ b) h1 h2
lemma abs_lt_of_lt_of_neg_lt {a b : α} (h1 : a < b) (h2 : -a < b) : abs a < b :=
abs_by_cases (λ x : α, x < b) h1 h2
private lemma aux1 {a b : α} (h1 : a + b ≥ 0) (h2 : a ≥ 0) : abs (a + b) ≤ abs a + abs b :=
decidable.by_cases
(assume h3 : b ≥ 0, calc
abs (a + b) ≤ abs (a + b) : by apply le_refl
... = a + b : by rw (abs_of_nonneg h1)
... = abs a + b : by rw (abs_of_nonneg h2)
... = abs a + abs b : by rw (abs_of_nonneg h3))
(assume h3 : ¬ b ≥ 0,
have h4 : b ≤ 0, from le_of_lt (lt_of_not_ge h3),
calc
abs (a + b) = a + b : by rw (abs_of_nonneg h1)
... = abs a + b : by rw (abs_of_nonneg h2)
... ≤ abs a + 0 : add_le_add_left h4 _
... ≤ abs a + -b : add_le_add_left (neg_nonneg_of_nonpos h4) _
... = abs a + abs b : by rw (abs_of_nonpos h4))
private lemma aux2 {a b : α} (h1 : a + b ≥ 0) : abs (a + b) ≤ abs a + abs b :=
or.elim (le_total b 0)
(assume h2 : b ≤ 0,
have h3 : ¬ a < 0, from
assume h4 : a < 0,
have h5 : a + b < 0,
begin
note aux := add_lt_add_of_lt_of_le h4 h2,
rwa [add_zero] at aux
end,
not_lt_of_ge h1 h5,
aux1 h1 (le_of_not_gt h3))
(assume h2 : 0 ≤ b,
begin
assert h3 : abs (b + a) ≤ abs b + abs a,
begin
rw add_comm at h1,
exact aux1 h1 h2
end,
rw [add_comm, add_comm (abs a)],
exact h3
end)
lemma abs_add_le_abs_add_abs (a b : α) : abs (a + b) ≤ abs a + abs b :=
or.elim (le_total 0 (a + b))
(assume h2 : 0 ≤ a + b, aux2 h2)
(assume h2 : a + b ≤ 0,
have h3 : -a + -b = -(a + b), by rw neg_add,
have h4 : -(a + b) ≥ 0, from neg_nonneg_of_nonpos h2,
have h5 : -a + -b ≥ 0, begin rw -h3 at h4, exact h4 end,
calc
abs (a + b) = abs (-a + -b) : by rw [-abs_neg, neg_add]
... ≤ abs (-a) + abs (-b) : aux2 h5
... = abs a + abs b : by rw [abs_neg, abs_neg])
lemma abs_sub_abs_le_abs_sub (a b : α) : abs a - abs b ≤ abs (a - b) :=
have h1 : abs a - abs b + abs b ≤ abs (a - b) + abs b, from
calc
abs a - abs b + abs b = abs a : by rw sub_add_cancel
... = abs (a - b + b) : by rw sub_add_cancel
... ≤ abs (a - b) + abs b : by apply abs_add_le_abs_add_abs,
le_of_add_le_add_right h1
lemma abs_sub_le (a b c : α) : abs (a - c) ≤ abs (a - b) + abs (b - c) :=
calc
abs (a - c) = abs (a - b + (b - c)) : by rw [sub_eq_add_neg, sub_eq_add_neg, sub_eq_add_neg,
add_assoc, neg_add_cancel_left]
... ≤ abs (a - b) + abs (b - c) : by apply abs_add_le_abs_add_abs
lemma abs_add_three (a b c : α) : abs (a + b + c) ≤ abs a + abs b + abs c :=
begin
apply le_trans,
apply abs_add_le_abs_add_abs,
apply le_trans,
apply add_le_add_right,
apply abs_add_le_abs_add_abs,
apply le_refl
end
lemma dist_bdd_within_interval {a b lb ub : α} (h : lb < ub) (hal : lb ≤ a) (hau : a ≤ ub)
(hbl : lb ≤ b) (hbu : b ≤ ub) : abs (a - b) ≤ ub - lb :=
begin
cases (decidable.em (b ≤ a)) with hba hba,
rw (abs_of_nonneg (sub_nonneg_of_le hba)),
apply sub_le_sub,
apply hau,
apply hbl,
rw [abs_of_neg (sub_neg_of_lt (lt_of_not_ge hba)), neg_sub],
apply sub_le_sub,
apply hbu,
apply hal
end
end decidable_linear_ordered_comm_group
section decidable_linear_ordered_comm_ring
variables {α : Type u} [decidable_linear_ordered_comm_ring α]
lemma abs_mul (a b : α) : abs (a * b) = abs a * abs b :=
or.elim (le_total 0 a)
(assume h1 : 0 ≤ a,
or.elim (le_total 0 b)
(assume h2 : 0 ≤ b,
calc
abs (a * b) = a * b : abs_of_nonneg (mul_nonneg h1 h2)
... = abs a * b : by rw (abs_of_nonneg h1)
... = abs a * abs b : by rw (abs_of_nonneg h2))
(assume h2 : b ≤ 0,
calc
abs (a * b) = -(a * b) : abs_of_nonpos (mul_nonpos_of_nonneg_of_nonpos h1 h2)
... = a * -b : by rw neg_mul_eq_mul_neg
... = abs a * -b : by rw (abs_of_nonneg h1)
... = abs a * abs b : by rw (abs_of_nonpos h2)))
(assume h1 : a ≤ 0,
or.elim (le_total 0 b)
(assume h2 : 0 ≤ b,
calc
abs (a * b) = -(a * b) : abs_of_nonpos (mul_nonpos_of_nonpos_of_nonneg h1 h2)
... = -a * b : by rw neg_mul_eq_neg_mul
... = abs a * b : by rw (abs_of_nonpos h1)
... = abs a * abs b : by rw (abs_of_nonneg h2))
(assume h2 : b ≤ 0,
calc
abs (a * b) = a * b : abs_of_nonneg (mul_nonneg_of_nonpos_of_nonpos h1 h2)
... = -a * -b : by rw neg_mul_neg
... = abs a * -b : by rw (abs_of_nonpos h1)
... = abs a * abs b : by rw (abs_of_nonpos h2)))
lemma abs_mul_abs_self (a : α) : abs a * abs a = a * a :=
abs_by_cases (λ x, x * x = a * a) rfl (neg_mul_neg a a)
lemma abs_mul_self (a : α) : abs (a * a) = a * a :=
by rw [abs_mul, abs_mul_abs_self]
lemma sub_le_of_abs_sub_le_left {a b c : α} (h : abs (a - b) ≤ c) : b - c ≤ a :=
if hz : 0 ≤ a - b then
(calc
a ≥ b : le_of_sub_nonneg hz
... ≥ b - c : sub_le_self _ (le_trans (abs_nonneg _) h))
else
have habs : b - a ≤ c, by rwa [abs_of_neg (lt_of_not_ge hz), neg_sub] at h,
have habs' : b ≤ c + a, from le_add_of_sub_right_le habs,
sub_left_le_of_le_add habs'
lemma sub_le_of_abs_sub_le_right {a b c : α} (h : abs (a - b) ≤ c) : a - c ≤ b :=
sub_le_of_abs_sub_le_left (abs_sub a b ▸ h)
lemma sub_lt_of_abs_sub_lt_left {a b c : α} (h : abs (a - b) < c) : b - c < a :=
if hz : 0 ≤ a - b then
(calc
a ≥ b : le_of_sub_nonneg hz
... > b - c : sub_lt_self _ (lt_of_le_of_lt (abs_nonneg _) h))
else
have habs : b - a < c, by rwa [abs_of_neg (lt_of_not_ge hz), neg_sub] at h,
have habs' : b < c + a, from lt_add_of_sub_right_lt habs,
sub_left_lt_of_lt_add habs'
lemma sub_lt_of_abs_sub_lt_right {a b c : α} (h : abs (a - b) < c) : a - c < b :=
sub_lt_of_abs_sub_lt_left (abs_sub a b ▸ h)
lemma abs_sub_square (a b : α) : abs (a - b) * abs (a - b) = a * a + b * b - (1 + 1) * a * b :=
begin
rw abs_mul_abs_self,
simp [left_distrib, right_distrib]
end
lemma eq_zero_of_mul_self_add_mul_self_eq_zero {x y : α} (h : x * x + y * y = 0) : x = 0 :=
have x * x ≤ (0 : α), from calc
x * x ≤ x * x + y * y : le_add_of_nonneg_right (mul_self_nonneg y)
... = 0 : h,
eq_zero_of_mul_self_eq_zero (le_antisymm this (mul_self_nonneg x))
lemma abs_abs_sub_abs_le_abs_sub (a b : α) : abs (abs a - abs b) ≤ abs (a - b) :=
begin
apply nonneg_le_nonneg_of_squares_le,
repeat {apply abs_nonneg},
repeat {rw abs_sub_square},
repeat {rw abs_abs},
repeat {rw abs_mul_abs_self},
apply sub_le_sub_left,
repeat {rw mul_assoc},
apply mul_le_mul_of_nonneg_left,
rw -abs_mul,
apply le_abs_self,
apply le_of_lt,
apply add_pos,
apply zero_lt_one,
apply zero_lt_one
end
end decidable_linear_ordered_comm_ring
section discrete_linear_ordered_field
variables {α : Type u} [discrete_linear_ordered_field α]
lemma abs_div (a b : α) : abs (a / b) = abs a / abs b :=
decidable.by_cases
(suppose h : b = 0, by rw [h, abs_zero, div_zero, div_zero, abs_zero])
(suppose h : b ≠ 0,
have h₁ : abs b ≠ 0, from
assume h₂, h (eq_zero_of_abs_eq_zero h₂),
eq_div_of_mul_eq _ _ h₁
(show abs (a / b) * abs b = abs a, by rw [-abs_mul, div_mul_cancel _ h]))
lemma abs_one_div (a : α) : abs (1 / a) = 1 / abs a :=
by rw [abs_div, abs_of_nonneg (zero_le_one : 1 ≥ (0 : α))]
end discrete_linear_ordered_field