/- 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