Skip to content

Commit ef9ae2a

Browse files
committed
feat(gcongr): support @[gcongr] for Monotone and friends (#28339)
This PR adds the feature to `gcongr` that you can now tag lemmas whose conclusion is `Monotone f`, `Antitone f`, etc.
1 parent 4086670 commit ef9ae2a

File tree

22 files changed

+122
-94
lines changed

22 files changed

+122
-94
lines changed

Mathlib/Algebra/Order/Floor/Ring.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,11 @@ theorem lt_succ_floor (a : R) : a < ⌊a⌋.succ :=
128128
theorem lt_floor_add_one (a : R) : a < ⌊a⌋ + 1 := by
129129
simpa only [Int.succ, Int.cast_add, Int.cast_one] using lt_succ_floor a
130130

131-
@[mono]
131+
@[gcongr, mono]
132132
theorem floor_mono : Monotone (floor : R → ℤ) :=
133133
gc_coe_floor.monotone_u
134134

135-
@[gcongr, bound] lemma floor_le_floor (hab : a ≤ b) : ⌊a⌋ ≤ ⌊b⌋ := floor_mono hab
135+
@[bound] lemma floor_le_floor (hab : a ≤ b) : ⌊a⌋ ≤ ⌊b⌋ := floor_mono hab
136136

137137
theorem floor_pos : 0 < ⌊a⌋ ↔ 1 ≤ a := by
138138
rw [Int.lt_iff_add_one_le, zero_add, le_floor, cast_one]

Mathlib/Algebra/Order/Floor/Semiring.lean

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,14 @@ theorem floor_of_nonpos (ha : a ≤ 0) : ⌊a⌋₊ = 0 :=
8181
rintro rfl
8282
exact floor_zero
8383

84+
@[gcongr]
8485
theorem floor_mono : Monotone (floor : R → ℕ) := fun a b h => by
8586
obtain ha | ha := le_total a 0
8687
· rw [floor_of_nonpos ha]
8788
exact Nat.zero_le _
8889
· exact le_floor ((floor_le ha).trans h)
8990

90-
@[gcongr, bound] lemma floor_le_floor (hab : a ≤ b) : ⌊a⌋₊ ≤ ⌊b⌋₊ := floor_mono hab
91+
@[bound] lemma floor_le_floor (hab : a ≤ b) : ⌊a⌋₊ ≤ ⌊b⌋₊ := floor_mono hab
9192

9293
theorem le_floor_iff' (hn : n ≠ 0) : n ≤ ⌊a⌋₊ ↔ (n : R) ≤ a := by
9394
obtain ha | ha := le_total a 0

Mathlib/Algebra/Order/Module/Algebra.lean

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,10 @@ section OrderedSemiring
2323
variable (β)
2424
variable [Semiring β] [PartialOrder β] [IsOrderedRing β] [Algebra α β] [SMulPosMono α β] {a : α}
2525

26-
@[mono] lemma algebraMap_mono : Monotone (algebraMap α β) :=
26+
@[gcongr, mono] lemma algebraMap_mono : Monotone (algebraMap α β) :=
2727
fun a₁ a₂ ha ↦ by
2828
simpa only [Algebra.algebraMap_eq_smul_one] using smul_le_smul_of_nonneg_right ha zero_le_one
2929

30-
/-- A version of `algebraMap_mono` for use by `gcongr` since it currently does not preprocess
31-
`Monotone` conclusions. -/
32-
@[gcongr] protected lemma GCongr.algebraMap_le_algebraMap {a₁ a₂ : α} (ha : a₁ ≤ a₂) :
33-
algebraMap α β a₁ ≤ algebraMap α β a₂ := algebraMap_mono _ ha
34-
3530
lemma algebraMap_nonneg (ha : 0 ≤ a) : 0 ≤ algebraMap α β a := by simpa using algebraMap_mono β ha
3631

3732
end OrderedSemiring
@@ -51,15 +46,10 @@ section SMulPosStrictMono
5146
variable [SMulPosStrictMono α β] {a a₁ a₂ : α}
5247
variable (β)
5348

54-
@[mono] lemma algebraMap_strictMono : StrictMono (algebraMap α β) :=
49+
@[gcongr, mono] lemma algebraMap_strictMono : StrictMono (algebraMap α β) :=
5550
fun a₁ a₂ ha ↦ by
5651
simpa only [Algebra.algebraMap_eq_smul_one] using smul_lt_smul_of_pos_right ha zero_lt_one
5752

58-
/-- A version of `algebraMap_strictMono` for use by `gcongr` since it currently does not preprocess
59-
`Monotone` conclusions. -/
60-
@[gcongr] protected lemma GCongr.algebraMap_lt_algebraMap {a₁ a₂ : α} (ha : a₁ < a₂) :
61-
algebraMap α β a₁ < algebraMap α β a₂ := algebraMap_strictMono _ ha
62-
6353
lemma algebraMap_pos (ha : 0 < a) : 0 < algebraMap α β a := by
6454
simpa using algebraMap_strictMono β ha
6555

Mathlib/Algebra/Order/Ring/Cast.lean

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,14 @@ section OrderedAddCommGroupWithOne
3030
variable [AddCommGroupWithOne R] [PartialOrder R] [AddLeftMono R]
3131
variable [ZeroLEOneClass R]
3232

33+
@[gcongr]
3334
lemma cast_mono : Monotone (Int.cast : ℤ → R) := by
3435
intro m n h
3536
rw [← sub_nonneg] at h
3637
lift n - m to ℕ using h with k hk
3738
rw [← sub_nonneg, ← cast_sub, ← hk, cast_natCast]
3839
exact k.cast_nonneg'
3940

40-
@[gcongr] protected lemma GCongr.intCast_mono {m n : ℤ} (hmn : m ≤ n) : (m : R) ≤ n := cast_mono hmn
41-
4241
variable [NeZero (1 : R)] {m n : ℤ}
4342

4443
@[simp] lemma cast_nonneg : ∀ {n : ℤ}, (0 : R) ≤ n ↔ 0 ≤ n

Mathlib/Algebra/Ring/Subring/Basic.lean

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,32 +69,32 @@ variable [Ring S] [Ring T]
6969
namespace Subring
7070
variable {s t : Subring R}
7171

72-
@[mono]
72+
@[gcongr, mono]
7373
theorem toSubsemiring_strictMono : StrictMono (toSubsemiring : Subring R → Subsemiring R) :=
7474
fun _ _ => id
7575

76-
@[mono]
76+
@[gcongr, mono]
7777
theorem toSubsemiring_mono : Monotone (toSubsemiring : Subring R → Subsemiring R) :=
7878
toSubsemiring_strictMono.monotone
7979

80-
@[gcongr]
80+
@[deprecated toSubsemiring_strictMono (since := "2025-10-20")]
8181
lemma toSubsemiring_lt_toSubsemiring (hst : s < t) : s.toSubsemiring < t.toSubsemiring := hst
8282

83-
@[gcongr]
83+
@[deprecated toSubsemiring_mono (since := "2025-10-20")]
8484
lemma toSubsemiring_le_toSubsemiring (hst : s ≤ t) : s.toSubsemiring ≤ t.toSubsemiring := hst
8585

86-
@[mono]
86+
@[gcongr, mono]
8787
theorem toAddSubgroup_strictMono : StrictMono (toAddSubgroup : Subring R → AddSubgroup R) :=
8888
fun _ _ => id
8989

90-
@[mono]
90+
@[gcongr, mono]
9191
theorem toAddSubgroup_mono : Monotone (toAddSubgroup : Subring R → AddSubgroup R) :=
9292
toAddSubgroup_strictMono.monotone
9393

94-
@[gcongr]
94+
@[deprecated toAddSubgroup_strictMono (since := "2025-10-20")]
9595
lemma toAddSubgroup_lt_toAddSubgroup (hst : s < t) : s.toAddSubgroup < t.toAddSubgroup := hst
9696

97-
@[gcongr]
97+
@[deprecated toAddSubgroup_mono (since := "2025-10-20")]
9898
lemma toAddSubgroup_le_toAddSubgroup (hst : s ≤ t) : s.toAddSubgroup ≤ t.toAddSubgroup := hst
9999

100100
@[mono]

Mathlib/Analysis/Complex/Exponential.lean

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,20 +288,20 @@ theorem abs_exp (x : ℝ) : |exp x| = exp x :=
288288
lemma exp_abs_le (x : ℝ) : exp |x| ≤ exp x + exp (-x) := by
289289
cases le_total x 0 <;> simp [abs_of_nonpos, abs_of_nonneg, exp_nonneg, *]
290290

291-
@[mono]
291+
@[mono, gcongr]
292292
theorem exp_strictMono : StrictMono exp := fun x y h => by
293293
rw [← sub_add_cancel y x, Real.exp_add]
294294
exact (lt_mul_iff_one_lt_left (exp_pos _)).2
295295
(lt_of_lt_of_le (by linarith) (add_one_le_exp_of_nonneg (by linarith)))
296296

297-
@[gcongr]
297+
@[deprecated exp_strictMono (since := "2025-10-20")]
298298
theorem exp_lt_exp_of_lt {x y : ℝ} (h : x < y) : exp x < exp y := exp_strictMono h
299299

300-
@[mono]
300+
@[gcongr, mono]
301301
theorem exp_monotone : Monotone exp :=
302302
exp_strictMono.monotone
303303

304-
@[gcongr, bound]
304+
@[bound] -- temporary lemma for the `bound` tactic
305305
theorem exp_le_exp_of_le {x y : ℝ} (h : x ≤ y) : exp x ≤ exp y := exp_monotone h
306306

307307
@[simp]

Mathlib/Analysis/SpecialFunctions/Log/ERealExp.lean

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ end Definition
5454
/-! ### Monotonicity -/
5555
section Monotonicity
5656

57+
@[gcongr]
5758
lemma exp_strictMono : StrictMono exp := by
5859
intro x y h
5960
induction x
@@ -62,10 +63,11 @@ lemma exp_strictMono : StrictMono exp := by
6263
· induction y
6364
· simp at h
6465
· simp_rw [exp_coe]
65-
exact ENNReal.ofReal_lt_ofReal_iff'.mpr ⟨Real.exp_lt_exp_of_lt (mod_cast h), Real.exp_pos _⟩
66+
exact ENNReal.ofReal_lt_ofReal_iff'.mpr ⟨Real.exp_strictMono (mod_cast h), Real.exp_pos _⟩
6667
· simp
6768
· exact (not_top_lt h).elim
6869

70+
@[gcongr]
6971
lemma exp_monotone : Monotone exp := exp_strictMono.monotone
7072

7173
@[simp] lemma exp_lt_exp_iff {a b : EReal} : exp a < exp b ↔ a < b := exp_strictMono.lt_iff_lt
@@ -84,9 +86,11 @@ lemma exp_monotone : Monotone exp := exp_strictMono.monotone
8486

8587
@[simp] lemma one_le_exp_iff {a : EReal} : 1 ≤ exp a ↔ 0 ≤ a := exp_zero ▸ @exp_le_exp_iff 0 a
8688

87-
@[gcongr] lemma exp_le_exp {a b : EReal} (h : a ≤ b) : exp a ≤ exp b := by simpa
89+
@[deprecated exp_monotone (since := "2025-10-20")]
90+
lemma exp_le_exp {a b : EReal} (h : a ≤ b) : exp a ≤ exp b := by simpa
8891

89-
@[gcongr] lemma exp_lt_exp {a b : EReal} (h : a < b) : exp a < exp b := by simpa
92+
@[deprecated exp_strictMono (since := "2025-10-20")]
93+
lemma exp_lt_exp {a b : EReal} (h : a < b) : exp a < exp b := by simpa
9094

9195
end Monotonicity
9296

Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,19 @@ theorem arcsin_eq_arctan (h : x ∈ Ioo (-(1 : ℝ)) 1) :
156156
@[simp]
157157
theorem arctan_zero : arctan 0 = 0 := by simp [arctan_eq_arcsin]
158158

159-
@[mono]
159+
@[gcongr, mono]
160160
theorem arctan_strictMono : StrictMono arctan := tanOrderIso.symm.strictMono
161161

162+
@[gcongr]
162163
theorem arctan_mono : Monotone arctan := arctan_strictMono.monotone
163164

164-
@[gcongr]
165+
@[deprecated arctan_strictMono (since := "2025-10-20")]
165166
lemma arctan_lt_arctan (hxy : x < y) : arctan x < arctan y := arctan_strictMono hxy
166167

167168
@[simp]
168169
theorem arctan_lt_arctan_iff : arctan x < arctan y ↔ x < y := arctan_strictMono.lt_iff_lt
169170

170-
@[gcongr]
171+
@[deprecated arctan_mono (since := "2025-10-20")]
171172
lemma arctan_le_arctan (hxy : x ≤ y) : arctan x ≤ arctan y :=
172173
arctan_strictMono.monotone hxy
173174

Mathlib/Combinatorics/Extremal/RuzsaSzemeredi.lean

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,9 @@ noncomputable def ruzsaSzemerediNumberNat (n : ℕ) : ℕ := ruzsaSzemerediNumbe
8888
lemma ruzsaSzemerediNumberNat_card : ruzsaSzemerediNumberNat (card α) = ruzsaSzemerediNumber α :=
8989
ruzsaSzemerediNumber_congr (Fintype.equivFin _).symm
9090

91-
-- TODO: Remove once #28339 lands?
92-
@[gcongr] lemma ruzsaSzemerediNumberNat_le_ruzsaSzemerediNumberNat (hmn : m ≤ n) :
93-
ruzsaSzemerediNumberNat m ≤ ruzsaSzemerediNumberNat n :=
94-
ruzsaSzemerediNumber_mono (Fin.castLEEmb hmn)
95-
96-
lemma ruzsaSzemerediNumberNat_mono : Monotone ruzsaSzemerediNumberNat :=
97-
fun _m _n => ruzsaSzemerediNumberNat_le_ruzsaSzemerediNumberNat
91+
@[gcongr]
92+
lemma ruzsaSzemerediNumberNat_mono : Monotone ruzsaSzemerediNumberNat := fun _m _n h =>
93+
ruzsaSzemerediNumber_mono (Fin.castLEEmb h)
9894

9995
lemma ruzsaSzemerediNumberNat_le : ruzsaSzemerediNumberNat n ≤ n.choose 3 :=
10096
ruzsaSzemerediNumber_le.trans_eq <| by rw [Fintype.card_fin]

Mathlib/Data/Finsupp/Order.lean

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,10 @@ variable [AddCommMonoid α] [PartialOrder α] [IsOrderedAddMonoid α]
8181
instance isOrderedAddMonoid : IsOrderedAddMonoid (ι →₀ α) :=
8282
{ add_le_add_left := fun _a _b h c s => add_le_add_left (h s) (c s) }
8383

84+
@[gcongr]
8485
lemma mapDomain_mono : Monotone (mapDomain f : (ι →₀ α) → (κ →₀ α)) := by
8586
classical exact fun g₁ g₂ h ↦ sum_le_sum_index h (fun _ _ ↦ single_mono) (by simp)
8687

87-
@[gcongr] protected lemma GCongr.mapDomain_mono (hg : g₁ ≤ g₂) : g₁.mapDomain f ≤ g₂.mapDomain f :=
88-
mapDomain_mono hg
89-
9088
lemma mapDomain_nonneg (hg : 0 ≤ g) : 0 ≤ g.mapDomain f := by simpa using mapDomain_mono hg
9189
lemma mapDomain_nonpos (hg : g ≤ 0) : g.mapDomain f ≤ 0 := by simpa using mapDomain_mono hg
9290

0 commit comments

Comments
 (0)