Skip to content

Commit df8b2f4

Browse files
committed
chore: generalise pow monotonicity lemmas to groups with zero (#18967)
In particular they now apply to `ℤₘ₀` From FLT
1 parent 4c452d8 commit df8b2f4

File tree

69 files changed

+301
-200
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+301
-200
lines changed

Archive/Imo/Imo2001Q2.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ theorem bound (ha : 0 < a) (hb : 0 < b) (hc : 0 < c) :
3939
= a ^ 3 * (a * sqrt ((a ^ 3) ^ 2 + (8:ℝ) * b ^ 3 * c ^ 3)) := by ring
4040
_ ≤ a ^ 3 * (a ^ 4 + b ^ 4 + c ^ 4) := ?_
4141
gcongr
42-
apply le_of_pow_le_pow_left two_ne_zero (by positivity)
42+
apply le_of_pow_le_pow_left two_ne_zero (by positivity)
4343
rw [mul_pow, sq_sqrt (by positivity), ← sub_nonneg]
4444
calc
4545
(a ^ 4 + b ^ 4 + c ^ 4) ^ 2 - a ^ 2 * ((a ^ 3) ^ 2 + 8 * b ^ 3 * c ^ 3)

Archive/Imo/Imo2006Q3.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ theorem subst_wlog {x y z s : ℝ} (hxy : 0 ≤ x * y) (hxyz : x + y + z = 0) :
6464
_ ≤ (2 * (x ^ 2 + y ^ 2 + (x + y) ^ 2) + 2 * s ^ 2) ^ 4 / 4 ^ 4 := by
6565
gcongr (?_ + _) ^ 4 / _
6666
apply rhs_ineq
67-
refine le_of_pow_le_pow_left two_ne_zero (by positivity) ?_
67+
refine le_of_pow_le_pow_left two_ne_zero (by positivity) ?_
6868
calc
6969
(32 * |x * y * z * s|) ^ 2 = 32 * (2 * s ^ 2 * (16 * x ^ 2 * y ^ 2 * (x + y) ^ 2)) := by
7070
rw [mul_pow, sq_abs, hz]; ring

Archive/Imo/Imo2008Q3.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ theorem p_lemma (p : ℕ) (hpp : Nat.Prime p) (hp_mod_4_eq_1 : p ≡ 1 [MOD 4])
6060
have hreal₂ : (p : ℝ) > 20 := by assumption_mod_cast
6161
have hreal₃ : (k : ℝ) ^ 2 + 4 ≥ p := by assumption_mod_cast
6262
have hreal₅ : (k : ℝ) > 4 := by
63-
refine lt_of_pow_lt_pow_left 2 k.cast_nonneg ?_
63+
refine lt_of_pow_lt_pow_left 2 k.cast_nonneg ?_
6464
linarith only [hreal₂, hreal₃]
6565
have hreal₆ : (k : ℝ) > sqrt (2 * n) := by
66-
refine lt_of_pow_lt_pow_left 2 k.cast_nonneg ?_
66+
refine lt_of_pow_lt_pow_left 2 k.cast_nonneg ?_
6767
rw [sq_sqrt (mul_nonneg zero_le_two n.cast_nonneg)]
6868
linarith only [hreal₁, hreal₃, hreal₅]
6969
exact ⟨n, hnat₁, by linarith only [hreal₆, hreal₁]⟩

Archive/Imo/Imo2008Q4.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ open Real
2727
namespace Imo2008Q4
2828

2929
theorem abs_eq_one_of_pow_eq_one (x : ℝ) (n : ℕ) (hn : n ≠ 0) (h : x ^ n = 1) : |x| = 1 := by
30-
rw [← pow_left_inj (abs_nonneg x) zero_le_one hn, one_pow, pow_abs, h, abs_one]
30+
rw [← pow_left_inj (abs_nonneg x) zero_le_one hn, one_pow, pow_abs, h, abs_one]
3131

3232
end Imo2008Q4
3333

Archive/Wiedijk100Theorems/PerfectNumbers.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ theorem eq_two_pow_mul_prime_mersenne_of_even_perfect {n : ℕ} (ev : Even n) (p
103103
| .succ k =>
104104
apply ne_of_lt _ jcon2
105105
rw [mersenne, ← Nat.pred_eq_sub_one, Nat.lt_pred_iff, ← pow_one (Nat.succ 1)]
106-
apply pow_lt_pow_right (Nat.lt_succ_self 1) (Nat.succ_lt_succ (Nat.succ_pos k))
106+
apply pow_lt_pow_right (Nat.lt_succ_self 1) (Nat.succ_lt_succ k.succ_pos)
107107
contrapose! hm
108108
simp [hm]
109109

Mathlib/Algebra/Order/CompleteField.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ theorem le_inducedMap_mul_self_of_mem_cutMap (ha : 0 < a) (b : β) (hb : b ∈ c
237237
· rw [pow_two] at hqa ⊢
238238
exact mul_self_le_mul_self (mod_cast hq'.le)
239239
(le_csSup (cutMap_bddAbove β a) <|
240-
coe_mem_cutMap_iff.2 <| lt_of_mul_self_lt_mul_self ha.le hqa)
240+
coe_mem_cutMap_iff.2 <| lt_of_mul_self_lt_mul_self ha.le hqa)
241241

242242
/-- Preparatory lemma for `inducedOrderRingHom`. -/
243243
theorem exists_mem_cutMap_mul_self_of_lt_inducedMap_mul_self (ha : 0 < a) (b : β)
@@ -251,7 +251,7 @@ theorem exists_mem_cutMap_mul_self_of_lt_inducedMap_mul_self (ha : 0 < a) (b :
251251
refine ⟨(q ^ 2 : ℚ), coe_mem_cutMap_iff.2 ?_, hbq⟩
252252
rw [pow_two] at hqa ⊢
253253
push_cast
254-
obtain ⟨q', hq', hqa'⟩ := lt_inducedMap_iff.1 (lt_of_mul_self_lt_mul_self
254+
obtain ⟨q', hq', hqa'⟩ := lt_inducedMap_iff.1 (lt_of_mul_self_lt_mul_self
255255
(inducedMap_nonneg ha.le) hqa)
256256
exact mul_self_lt_mul_self (mod_cast hq.le) (hqa'.trans' <| by assumption_mod_cast)
257257

Mathlib/Algebra/Order/Field/Basic.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ theorem one_div_pow_le_one_div_pow_of_le (a1 : 1 ≤ a) {m n : ℕ} (mn : m ≤
411411

412412
theorem one_div_pow_lt_one_div_pow_of_lt (a1 : 1 < a) {m n : ℕ} (mn : m < n) :
413413
1 / a ^ n < 1 / a ^ m := by
414-
refine (one_div_lt_one_div ?_ ?_).2 (pow_lt_pow_right a1 mn) <;>
414+
refine (one_div_lt_one_div ?_ ?_).2 (pow_lt_pow_right a1 mn) <;>
415415
exact pow_pos (zero_lt_one.trans a1) _
416416

417417
theorem one_div_pow_anti (a1 : 1 ≤ a) : Antitone fun n : ℕ => 1 / a ^ n := fun _ _ =>

Mathlib/Algebra/Order/Group/Nat.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ instance instOrderedSub : OrderedSub ℕ := by
4747

4848
variable {α : Type*} {n : ℕ} {f : α → ℕ}
4949

50-
/-- See also `pow_left_strictMonoOn`. -/
50+
/-- See also `pow_left_strictMonoOn`. -/
5151
protected lemma pow_left_strictMono (hn : n ≠ 0) : StrictMono (· ^ n : ℕ → ℕ) :=
5252
fun _ _ h ↦ Nat.pow_lt_pow_left h hn
5353

Mathlib/Algebra/Order/GroupWithZero/Canonical.lean

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,6 @@ lemma pow_lt_pow_succ (ha : 1 < a) : a ^ n < a ^ n.succ := by
235235
rw [← one_mul (a ^ n), pow_succ']
236236
exact mul_lt_mul_of_pos_right ha (pow_pos (zero_lt_one.trans ha) _)
237237

238-
lemma pow_lt_pow_right₀ (ha : 1 < a) (hmn : m < n) : a ^ m < a ^ n := by
239-
induction' hmn with n _ ih; exacts [pow_lt_pow_succ ha, lt_trans ih (pow_lt_pow_succ ha)]
240-
241238
end LinearOrderedCommGroupWithZero
242239

243240
instance instLinearOrderedCommMonoidWithZeroMultiplicativeOrderDual

Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean

Lines changed: 142 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Mathlib.Algebra.Order.Monoid.Unbundled.Defs
99
import Mathlib.Algebra.Order.ZeroLEOne
1010
import Mathlib.Tactic.Bound.Attribute
1111
import Mathlib.Tactic.GCongr.CoreAttrs
12+
import Mathlib.Tactic.Monotonicity.Attr
1213
import Mathlib.Tactic.Nontriviality
1314

1415
/-!
@@ -1008,12 +1009,30 @@ lemma pow_right_mono₀ (h : 1 ≤ a) : Monotone (a ^ ·) :=
10081009
monotone_nat_of_le_succ fun n => by
10091010
rw [pow_succ']; exact le_mul_of_one_le_left (pow_nonneg (zero_le_one.trans h) _) h
10101011

1012+
/-- `bound` lemma for branching on `1 ≤ a ∨ a ≤ 1` when proving `a ^ n ≤ a ^ m` -/
1013+
@[bound]
1014+
lemma Bound.pow_le_pow_right_of_le_one_or_one_le (h : 1 ≤ a ∧ n ≤ m ∨ 0 ≤ a ∧ a ≤ 1 ∧ m ≤ n) :
1015+
a ^ n ≤ a ^ m := by
1016+
obtain ⟨a1, nm⟩ | ⟨a0, a1, mn⟩ := h
1017+
· exact pow_right_mono₀ a1 nm
1018+
· exact pow_le_pow_of_le_one a0 a1 mn
1019+
10111020
@[gcongr]
10121021
lemma pow_le_pow_right₀ (ha : 1 ≤ a) (hmn : m ≤ n) : a ^ m ≤ a ^ n := pow_right_mono₀ ha hmn
10131022

10141023
lemma le_self_pow₀ (ha : 1 ≤ a) (hn : n ≠ 0) : a ≤ a ^ n := by
10151024
simpa only [pow_one] using pow_le_pow_right₀ ha <| Nat.pos_iff_ne_zero.2 hn
10161025

1026+
/-- The `bound` tactic can't handle `m ≠ 0` goals yet, so we express as `0 < m` -/
1027+
@[bound]
1028+
lemma Bound.le_self_pow_of_pos (ha : 1 ≤ a) (hn : 0 < n) : a ≤ a ^ n := le_self_pow₀ ha hn.ne'
1029+
1030+
@[mono, gcongr, bound]
1031+
theorem pow_le_pow_left₀ (ha : 0 ≤ a) (hab : a ≤ b) : ∀ n, a ^ n ≤ b ^ n
1032+
| 0 => by simp
1033+
| n + 1 => by simpa only [pow_succ']
1034+
using mul_le_mul hab (pow_le_pow_left₀ ha hab _) (pow_nonneg ha _) (ha.trans hab)
1035+
10171036
end
10181037

10191038
variable [Preorder α] {f g : α → M₀}
@@ -1044,11 +1063,7 @@ end Preorder
10441063

10451064

10461065
section PartialOrder
1047-
variable [PartialOrder M₀] {a b c d : M₀}
1048-
1049-
@[simp] lemma pow_pos [ZeroLEOneClass M₀] [PosMulStrictMono M₀] (ha : 0 < a) : ∀ n, 0 < a ^ n
1050-
| 0 => by nontriviality; rw [pow_zero]; exact zero_lt_one
1051-
| _ + 1 => pow_succ a _ ▸ mul_pos (pow_pos ha _) ha
1066+
variable [PartialOrder M₀] {a b c d : M₀} {m n : ℕ}
10521067

10531068
lemma mul_self_lt_mul_self [PosMulStrictMono M₀] [MulPosMono M₀] (ha : 0 ≤ a) (hab : a < b) :
10541069
a * a < b * b := mul_lt_mul' hab.le hab ha <| ha.trans_lt hab
@@ -1076,6 +1091,61 @@ lemma lt_mul_right [PosMulStrictMono M₀] (ha : 0 < a) (hb : 1 < b) : a < a * b
10761091
lemma lt_mul_self [ZeroLEOneClass M₀] [MulPosStrictMono M₀] (ha : 1 < a) : a < a * a :=
10771092
lt_mul_left (ha.trans_le' zero_le_one) ha
10781093

1094+
section strict_mono
1095+
variable [ZeroLEOneClass M₀] [PosMulStrictMono M₀]
1096+
1097+
@[simp] lemma pow_pos (ha : 0 < a) : ∀ n, 0 < a ^ n
1098+
| 0 => by nontriviality; rw [pow_zero]; exact zero_lt_one
1099+
| _ + 1 => pow_succ a _ ▸ mul_pos (pow_pos ha _) ha
1100+
1101+
lemma sq_pos_of_pos (ha : 0 < a) : 0 < a ^ 2 := pow_pos ha _
1102+
1103+
variable [MulPosStrictMono M₀]
1104+
1105+
@[gcongr, bound]
1106+
lemma pow_lt_pow_left₀ (hab : a < b)
1107+
(ha : 0 ≤ a) : ∀ {n : ℕ}, n ≠ 0 → a ^ n < b ^ n
1108+
| n + 1, _ => by
1109+
simpa only [pow_succ] using mul_lt_mul_of_le_of_lt_of_nonneg_of_pos
1110+
(pow_le_pow_left₀ ha hab.le _) hab ha (pow_pos (ha.trans_lt hab) _)
1111+
1112+
/-- See also `pow_left_strictMono₀` and `Nat.pow_left_strictMono`. -/
1113+
lemma pow_left_strictMonoOn₀ (hn : n ≠ 0) : StrictMonoOn (· ^ n : M₀ → M₀) {a | 0 ≤ a} :=
1114+
fun _a ha _b _ hab ↦ pow_lt_pow_left₀ hab ha hn
1115+
1116+
/-- See also `pow_right_strictMono'`. -/
1117+
lemma pow_right_strictMono₀ (h : 1 < a) : StrictMono (a ^ ·) :=
1118+
have : 0 < a := zero_le_one.trans_lt h
1119+
strictMono_nat_of_lt_succ fun n => by
1120+
simpa only [one_mul, pow_succ'] using mul_lt_mul h (le_refl (a ^ n)) (pow_pos this _) this.le
1121+
1122+
@[gcongr]
1123+
lemma pow_lt_pow_right₀ (h : 1 < a) (hmn : m < n) : a ^ m < a ^ n := pow_right_strictMono₀ h hmn
1124+
1125+
lemma pow_lt_pow_iff_right₀ (h : 1 < a) : a ^ n < a ^ m ↔ n < m :=
1126+
(pow_right_strictMono₀ h).lt_iff_lt
1127+
1128+
lemma pow_le_pow_iff_right₀ (h : 1 < a) : a ^ n ≤ a ^ m ↔ n ≤ m :=
1129+
(pow_right_strictMono₀ h).le_iff_le
1130+
1131+
lemma lt_self_pow₀ (h : 1 < a) (hm : 1 < m) : a < a ^ m := by
1132+
simpa only [pow_one] using pow_lt_pow_right₀ h hm
1133+
1134+
lemma pow_right_strictAnti₀ (h₀ : 0 < a) (h₁ : a < 1) : StrictAnti (a ^ ·) :=
1135+
strictAnti_nat_of_succ_lt fun n => by
1136+
simpa only [pow_succ', one_mul] using mul_lt_mul h₁ le_rfl (pow_pos h₀ n) zero_le_one
1137+
1138+
lemma pow_lt_pow_iff_right_of_lt_one₀ (h₀ : 0 < a) (h₁ : a < 1) : a ^ m < a ^ n ↔ n < m :=
1139+
(pow_right_strictAnti₀ h₀ h₁).lt_iff_lt
1140+
1141+
lemma pow_lt_pow_right_of_lt_one₀ (h₀ : 0 < a) (h₁ : a < 1) (hmn : m < n) : a ^ n < a ^ m :=
1142+
(pow_lt_pow_iff_right_of_lt_one₀ h₀ h₁).2 hmn
1143+
1144+
lemma pow_lt_self_of_lt_one₀ (h₀ : 0 < a) (h₁ : a < 1) (hn : 1 < n) : a ^ n < a := by
1145+
simpa only [pow_one] using pow_lt_pow_right_of_lt_one₀ h₀ h₁ hn
1146+
1147+
end strict_mono
1148+
10791149
variable [Preorder α] {f g : α → M₀}
10801150

10811151
lemma strictMono_mul_left_of_pos [PosMulStrictMono M₀] (ha : 0 < a) :
@@ -1108,7 +1178,72 @@ lemma StrictMono.mul [PosMulStrictMono M₀] [MulPosStrictMono M₀] (hf : Stric
11081178
(hg : StrictMono g) (hf₀ : ∀ x, 0 ≤ f x) (hg₀ : ∀ x, 0 ≤ g x) :
11091179
StrictMono (f * g) := fun _ _ h ↦ mul_lt_mul'' (hf h) (hg h) (hf₀ _) (hg₀ _)
11101180

1111-
end MonoidWithZero.PartialOrder
1181+
end PartialOrder
1182+
1183+
section LinearOrder
1184+
variable [LinearOrder M₀] [ZeroLEOneClass M₀] [PosMulStrictMono M₀] [MulPosStrictMono M₀] {a b : M₀}
1185+
{m n : ℕ}
1186+
1187+
lemma pow_le_pow_iff_left₀ (ha : 0 ≤ a) (hb : 0 ≤ b) (hn : n ≠ 0) : a ^ n ≤ b ^ n ↔ a ≤ b :=
1188+
(pow_left_strictMonoOn₀ hn).le_iff_le ha hb
1189+
1190+
lemma pow_lt_pow_iff_left₀ (ha : 0 ≤ a) (hb : 0 ≤ b) (hn : n ≠ 0) : a ^ n < b ^ n ↔ a < b :=
1191+
(pow_left_strictMonoOn₀ hn).lt_iff_lt ha hb
1192+
1193+
@[simp]
1194+
lemma pow_left_inj₀ (ha : 0 ≤ a) (hb : 0 ≤ b) (hn : n ≠ 0) : a ^ n = b ^ n ↔ a = b :=
1195+
(pow_left_strictMonoOn₀ hn).eq_iff_eq ha hb
1196+
1197+
lemma pow_right_injective₀ (ha₀ : 0 < a) (ha₁ : a ≠ 1) : Injective (a ^ ·) := by
1198+
obtain ha₁ | ha₁ := ha₁.lt_or_lt
1199+
· exact (pow_right_strictAnti₀ ha₀ ha₁).injective
1200+
· exact (pow_right_strictMono₀ ha₁).injective
1201+
1202+
@[simp]
1203+
lemma pow_right_inj₀ (ha₀ : 0 < a) (ha₁ : a ≠ 1) : a ^ m = a ^ n ↔ m = n :=
1204+
(pow_right_injective₀ ha₀ ha₁).eq_iff
1205+
1206+
lemma pow_le_one_iff_of_nonneg (ha : 0 ≤ a) (hn : n ≠ 0) : a ^ n ≤ 1 ↔ a ≤ 1 := by
1207+
simpa only [one_pow] using pow_le_pow_iff_left₀ ha zero_le_one hn
1208+
1209+
lemma one_le_pow_iff_of_nonneg (ha : 0 ≤ a) (hn : n ≠ 0) : 1 ≤ a ^ n ↔ 1 ≤ a := by
1210+
simpa only [one_pow] using pow_le_pow_iff_left₀ zero_le_one ha hn
1211+
1212+
lemma pow_lt_one_iff_of_nonneg (ha : 0 ≤ a) (hn : n ≠ 0) : a ^ n < 1 ↔ a < 1 :=
1213+
lt_iff_lt_of_le_iff_le (one_le_pow_iff_of_nonneg ha hn)
1214+
1215+
lemma one_lt_pow_iff_of_nonneg (ha : 0 ≤ a) (hn : n ≠ 0) : 1 < a ^ n ↔ 1 < a := by
1216+
simpa only [one_pow] using pow_lt_pow_iff_left₀ zero_le_one ha hn
1217+
1218+
lemma pow_eq_one_iff_of_nonneg (ha : 0 ≤ a) (hn : n ≠ 0) : a ^ n = 1 ↔ a = 1 := by
1219+
simpa only [one_pow] using pow_left_inj₀ ha zero_le_one hn
1220+
1221+
lemma sq_le_one_iff₀ (ha : 0 ≤ a) : a ^ 21 ↔ a ≤ 1 :=
1222+
pow_le_one_iff_of_nonneg ha (Nat.succ_ne_zero _)
1223+
1224+
lemma sq_lt_one_iff₀ (ha : 0 ≤ a) : a ^ 2 < 1 ↔ a < 1 :=
1225+
pow_lt_one_iff_of_nonneg ha (Nat.succ_ne_zero _)
1226+
1227+
lemma one_le_sq_iff₀ (ha : 0 ≤ a) : 1 ≤ a ^ 21 ≤ a :=
1228+
one_le_pow_iff_of_nonneg ha (Nat.succ_ne_zero _)
1229+
1230+
lemma one_lt_sq_iff₀ (ha : 0 ≤ a) : 1 < a ^ 21 < a :=
1231+
one_lt_pow_iff_of_nonneg ha (Nat.succ_ne_zero _)
1232+
1233+
lemma lt_of_pow_lt_pow_left₀ (n : ℕ) (hb : 0 ≤ b) (h : a ^ n < b ^ n) : a < b :=
1234+
lt_of_not_ge fun hn => not_lt_of_ge (pow_le_pow_left₀ hb hn _) h
1235+
1236+
lemma le_of_pow_le_pow_left₀ (hn : n ≠ 0) (hb : 0 ≤ b) (h : a ^ n ≤ b ^ n) : a ≤ b :=
1237+
le_of_not_lt fun h1 => not_le_of_lt (pow_lt_pow_left₀ h1 hb hn) h
1238+
1239+
@[simp]
1240+
lemma sq_eq_sq₀ (ha : 0 ≤ a) (hb : 0 ≤ b) : a ^ 2 = b ^ 2 ↔ a = b := pow_left_inj₀ ha hb (by decide)
1241+
1242+
lemma lt_of_mul_self_lt_mul_self₀ (hb : 0 ≤ b) : a * a < b * b → a < b := by
1243+
simp_rw [← sq]
1244+
exact lt_of_pow_lt_pow_left₀ _ hb
1245+
1246+
end MonoidWithZero.LinearOrder
11121247

11131248
section CancelMonoidWithZero
11141249

@@ -1654,4 +1789,4 @@ lemma div_lt_comm₀ (hb : 0 < b) (hc : 0 < c) : a / b < c ↔ a / c < b := by
16541789
end PosMulStrictMono
16551790
end CommGroupWithZero
16561791

1657-
set_option linter.style.longFile 1700
1792+
set_option linter.style.longFile 1900

0 commit comments

Comments
 (0)