Skip to content

Commit 4c9ff10

Browse files
feat(NumberTheory/Height/Basic): add bounds for sums (leanprover-community#34330)
The main purpose of this PR (no. 3 in the series on heights) is to state and prove bounds for the height of `x + y` and for the height of a finite sum of field elements.
1 parent 3bbc5c7 commit 4c9ff10

3 files changed

Lines changed: 168 additions & 21 deletions

File tree

Mathlib/Algebra/Order/BigOperators/GroupWithZero/Multiset.lean

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ theorem prod_map_le_pow_card {F L : Type*} [FunLike F L R] {f : F} {r : R} {t :
4444
induction t using Quotient.inductionOn
4545
simp_all [List.prod_map_le_pow_length₀]
4646

47+
variable {α : Type*}
48+
49+
lemma prod_map_nonneg {s : Multiset α} {f : α → R} (h : ∀ a ∈ s, 0 ≤ f a) :
50+
0 ≤ (s.map f).prod := by
51+
refine prod_nonneg fun r hr ↦ ?_
52+
obtain ⟨a, ha, rfl⟩ := mem_map.mp hr
53+
exact h a ha
54+
55+
lemma one_le_prod_map {s : Multiset α} {f : α → R} (h : ∀ a ∈ s, 1 ≤ f a) :
56+
1 ≤ (s.map f).prod := by
57+
refine one_le_prod fun r hr ↦ ?_
58+
obtain ⟨a, ha, rfl⟩ := mem_map.mp hr
59+
exact h a ha
60+
4761
omit [PosMulMono R]
4862
variable [PosMulStrictMono R] [NeZero (1 : R)]
4963

Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ lemma prod_le_one (h0 : ∀ i ∈ s, 0 ≤ f i) (h1 : ∀ i ∈ s, f i ≤ 1) :
5656
convert ← prod_le_prod h0 h1
5757
exact Finset.prod_const_one
5858

59+
lemma le_prod_max_one {M : Type*} [CommMonoidWithZero M] [LinearOrder M] [ZeroLEOneClass M]
60+
[PosMulMono M] {i : ι} (hi : i ∈ s) (f : ι → M) :
61+
f i ≤ ∏ i ∈ s, max (f i) 1 := by
62+
classical
63+
rcases lt_or_ge (f i) 0 with hf | hf
64+
· exact (hf.trans_le <| prod_nonneg fun _ _ ↦ le_sup_of_le_right zero_le_one).le
65+
have : f i = ∏ j ∈ s, if i = j then f i else 1 := by
66+
rw [prod_eq_single_of_mem i hi fun _ _ _ ↦ by grind]
67+
simp
68+
exact this ▸ prod_le_prod (fun _ _ ↦ by grind [zero_le_one]) fun _ _ ↦ by grind
69+
5970
end PosMulMono
6071

6172
section PosMulStrictMono
@@ -85,6 +96,7 @@ lemma prod_lt_prod_of_nonempty (hf : ∀ i ∈ s, 0 < f i) (hfg : ∀ i ∈ s, f
8596
exact ⟨i, hi, hfg i hi⟩
8697

8798
end PosMulStrictMono
99+
88100
end CommMonoidWithZero
89101

90102
section OrderedSemiring

Mathlib/NumberTheory/Height/Basic.lean

Lines changed: 142 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ Authors: Michael Stoll
66
module
77

88
public import Mathlib.Analysis.SpecialFunctions.Log.Basic
9+
public import Mathlib.Tactic.Positivity.Core
910

11+
import Mathlib.Algebra.Order.BigOperators.GroupWithZero.Finset
1012
import Mathlib.Algebra.Order.Group.Indicator
13+
import Mathlib.Algebra.Order.Ring.IsNonarchimedean
1114
import Mathlib.Data.Fintype.Order
12-
public import Mathlib.RingTheory.Nilpotent.Defs
15+
import Mathlib.RingTheory.Nilpotent.Defs
1316

1417
/-!
1518
# Basic theory of heights
@@ -125,11 +128,9 @@ lemma mulHeight₁_one : mulHeight₁ (1 : K) = 1 := by
125128
simp [mulHeight₁_eq]
126129

127130
/-- The mutliplicative height of a field element is always at least `1`. -/
128-
lemma one_le_mulHeight₁ (x : K) : 1 ≤ mulHeight₁ x := by
129-
refine one_le_mul_of_one_le_of_one_le (Multiset.one_le_prod fun _ h ↦ ?_) ?_
130-
· obtain ⟨v, -, rfl⟩ := Multiset.mem_map.mp h
131-
exact le_max_right ..
132-
· exact one_le_finprod fun _ ↦ le_max_right ..
131+
lemma one_le_mulHeight₁ (x : K) : 1 ≤ mulHeight₁ x :=
132+
one_le_mul_of_one_le_of_one_le (Multiset.one_le_prod_map fun _ _ ↦ le_max_right ..) <|
133+
one_le_finprod fun _ ↦ le_max_right ..
133134

134135
-- This is needed as a side condition in proofs about logarithmic heights
135136
lemma mulHeight₁_pos (x : K) : 0 < mulHeight₁ x :=
@@ -276,14 +277,14 @@ private lemma max_eq_iSup {α : Type*} [ConditionallyCompleteLattice α] (a b :
276277
variable [Finite ι]
277278

278279
private lemma mulSupport_iSup_nonarchAbsVal_finite {x : ι → K} (hx : x ≠ 0) :
279-
(Function.mulSupport fun v : nonarchAbsVal ↦ ⨆ i, v.val (x i)).Finite := by
280+
(fun v : nonarchAbsVal ↦ ⨆ i, v.val (x i)).mulSupport.Finite := by
280281
have : Nonempty {j // x j ≠ 0} := nonempty_subtype.mpr <| Function.ne_iff.mp hx
281-
suffices (Function.mulSupport fun v : nonarchAbsVal ↦ ⨆ i : {j // x j ≠ 0}, v.val (x i)).Finite by
282+
suffices (fun v : nonarchAbsVal ↦ ⨆ i : {j // x j ≠ 0}, v.val (x i)).mulSupport.Finite by
282283
convert this with v
283-
have ⟨i, hi⟩ : ∃ j, x j ≠ 0 := Function.ne_iff.mp hx
284+
obtain ⟨i, hi⟩ : ∃ j, x j ≠ 0 := Function.ne_iff.mp hx
284285
have : Nonempty ι := .intro i
285-
refine le_antisymm (ciSup_le fun j ↦ ?_) <|
286-
ciSup_le fun ⟨j, hj⟩ ↦ le_ciSup_of_le (Finite.bddAbove_range _) j le_rfl
286+
refine le_antisymm ?_ (ciSup_le fun ⟨j, hj⟩ ↦ le_ciSup_of_le (Finite.bddAbove_range _) j le_rfl)
287+
refine ciSup_le fun j ↦ ?_
287288
rcases eq_or_ne (x j) 0 with h | h
288289
· rw [h, v.val.map_zero]
289290
exact Real.iSup_nonneg' ⟨⟨i, hi⟩, v.val.nonneg ..⟩
@@ -292,11 +293,9 @@ private lemma mulSupport_iSup_nonarchAbsVal_finite {x : ι → K} (hx : x ≠ 0)
292293
Function.mulSupport_iSup _
293294

294295
private lemma mulSupport_max_nonarchAbsVal_finite (x : K) :
295-
(Function.mulSupport fun v : nonarchAbsVal ↦ v.val x ⊔ 1).Finite := by
296-
convert mulSupport_iSup_nonarchAbsVal_finite (x := ![x, 1]) <| by simp with v
297-
rw [max_eq_iSup]
298-
congr 1
299-
ext1 i
296+
(fun v : nonarchAbsVal ↦ max (v.val x) 1).mulSupport.Finite := by
297+
simp_rw [max_eq_iSup]
298+
convert mulSupport_iSup_nonarchAbsVal_finite (x := ![x, 1]) <| by simp with v i
300299
fin_cases i <;> simp
301300

302301
/-- The multiplicative height of a tuple does not change under scaling. -/
@@ -317,11 +316,9 @@ lemma one_le_mulHeight (x : ι → K) : 1 ≤ mulHeight x := by
317316
obtain ⟨i, hi⟩ : ∃ i, x i ≠ 0 := Function.ne_iff.mp hx
318317
have hx' : (x i)⁻¹ • x ≠ 0 := by simp [hi, hx]
319318
rw [← mulHeight_smul_eq_mulHeight _ <| inv_ne_zero hi, mulHeight_eq hx']
320-
refine one_le_mul_of_one_le_of_one_le (Multiset.one_le_prod fun vx h ↦ ?_) ?_
321-
· simp only [Pi.smul_apply, smul_eq_mul, AbsoluteValue.map_mul, map_inv₀, Multiset.mem_map] at h
322-
obtain ⟨v, -, rfl⟩ := h
323-
refine le_ciSup_of_le (Finite.bddAbove_range _) i <| le_of_eq ?_
324-
exact (inv_mul_cancel₀ <| v.ne_zero_iff.mpr hi).symm
319+
refine one_le_mul_of_one_le_of_one_le (Multiset.one_le_prod_map fun v _ ↦ ?_) ?_
320+
· refine le_ciSup_of_le (Finite.bddAbove_range _) i <| le_of_eq ?_
321+
simpa using (inv_mul_cancel₀ <| v.ne_zero_iff.mpr hi).symm
325322
· refine one_le_finprod fun v ↦ le_ciSup_of_le (Finite.bddAbove_range _) i ?_
326323
simp [inv_mul_cancel₀ <| v.val.ne_zero_iff.mpr hi]
327324

@@ -477,3 +474,127 @@ lemma logHeight₁_zpow (x : K) (n : ℤ) : logHeight₁ (x ^ n) = n.natAbs * lo
477474
simp only [logHeight₁_eq_log_mulHeight₁, mulHeight₁_zpow, log_pow]
478475

479476
end Height
477+
478+
/-!
479+
### Bounds for the height of sums of field elements
480+
481+
We prove the general case (finite sums of arbitrary length) first and deduce the result
482+
for sums of two elements from it.
483+
-/
484+
485+
namespace Finset
486+
487+
variable {R S : Type*} [Semiring R] [CommSemiring S] [LinearOrder S] [IsOrderedRing S]
488+
489+
/-- The "local" version of the height bound for arbitrary sums for general (possibly archimedean)
490+
absolute values. -/
491+
lemma max_abv_sum_one_le [CharZero S] (v : AbsoluteValue R S) {ι : Type*} {s : Finset ι}
492+
(hs : s.Nonempty) (x : ι → R) :
493+
max (v (∑ i ∈ s, x i)) 1 ≤ #s * ∏ i ∈ s, max (v (x i)) 1 := by
494+
refine sup_le ?_ ?_
495+
· rw [← nsmul_eq_mul, ← sum_const]
496+
grw [v.sum_le s x]
497+
gcongr with i hi
498+
exact le_prod_max_one hi fun i ↦ v (x i)
499+
· nth_rewrite 1 [← mul_one 1]
500+
gcongr
501+
· simp [hs]
502+
· exact s.one_le_prod fun _ ↦ le_max_right ..
503+
504+
/-- The "local" version of the height bound for arbitrary sums for nonarchimedean
505+
absolute values. -/
506+
lemma max_abv_sum_one_le_of_isNonarchimedean {v : AbsoluteValue R S} (hv : IsNonarchimedean v)
507+
{ι : Type*} (s : Finset ι) (x : ι → R) :
508+
max (v (∑ i ∈ s, x i)) 1 ≤ ∏ i ∈ s, max (v (x i)) 1 := by
509+
rcases s.eq_empty_or_nonempty with rfl | hs
510+
· simp
511+
refine sup_le ?_ <| s.one_le_prod fun _ ↦ le_max_right ..
512+
grw [hv.apply_sum_le_sup_of_isNonarchimedean hs]
513+
exact sup'_le hs (fun i ↦ v (x i)) fun i hi ↦ le_prod_max_one hi fun i ↦ v (x i)
514+
515+
end Finset
516+
517+
namespace Height
518+
519+
variable {K : Type*} [Field K] [AdmissibleAbsValues K]
520+
521+
open AdmissibleAbsValues Real
522+
523+
open Finset Multiset in
524+
/-- The multiplicative height of a nonempty finite sum of field elements is at most
525+
`n ^ (totalWeight K)` times the product of the individual multiplicative
526+
heights, where `n` is the number of terms. -/
527+
lemma mulHeight₁_sum_le {α : Type*} {s : Finset α} (hs : s.Nonempty) (x : α → K) :
528+
mulHeight₁ (∑ a ∈ s, x a) ≤ #s ^ (totalWeight K) * ∏ a ∈ s, mulHeight₁ (x a) := by
529+
simp only [mulHeight₁_eq, totalWeight]
530+
rw [prod_mul_distrib, ← prod_replicate, ← map_const,
531+
← finprod_prod_comm _ _ fun i _ ↦ mulSupport_max_nonarchAbsVal_finite (x i),
532+
← prod_map_prod, ← mul_assoc, ← prod_map_mul]
533+
simp only [Function.const_apply]
534+
gcongr
535+
· exact finprod_nonneg fun _ ↦ by positivity
536+
· exact prod_map_nonneg fun _ h ↦ by positivity
537+
· exact prod_map_le_prod_map₀ _ _ (fun _ _ ↦ by positivity) fun _ _ ↦ max_abv_sum_one_le _ hs x
538+
· refine finprod_le_finprod (mulSupport_max_nonarchAbsVal_finite _) (fun _ ↦ by grind) ?_ ?_
539+
· exact (s.finite_toSet.biUnion fun _ _ ↦ mulSupport_max_nonarchAbsVal_finite _).subset <|
540+
s.mulSupport_prod fun i (v : nonarchAbsVal) ↦ max (v.val (x i)) 1
541+
· exact fun v ↦ max_abv_sum_one_le_of_isNonarchimedean (isNonarchimedean _ v.prop) _ x
542+
543+
open Finset in
544+
/-- The logarithmic height of a finite sum of field elements is at most
545+
`totalWeight K * log n` plus the sum of the individual logarithmic heights,
546+
where `n` is the number of terms.
547+
548+
(Note that here we do not need to assume that `s` is nonempty, due to the convenient
549+
junk value `log 0 = 0`.) -/
550+
lemma logHeight₁_sum_le {α : Type*} (s : Finset α) (x : α → K) :
551+
logHeight₁ (∑ a ∈ s, x a) ≤ (totalWeight K) * log #s + ∑ a ∈ s, logHeight₁ (x a) := by
552+
rcases s.eq_empty_or_nonempty with rfl | hs
553+
· simp
554+
simp only [logHeight₁_eq_log_mulHeight₁]
555+
have : ∀ a ∈ s, mulHeight₁ (x a) ≠ 0 := fun _ _ ↦ by positivity
556+
have : (#s : ℝ) ^ totalWeight K ≠ 0 := by simp [hs.ne_empty]
557+
pull (disch := first | assumption | positivity) log
558+
exact (log_le_log <| by positivity) <| mulHeight₁_sum_le hs x
559+
560+
/-- The multiplicative height of `-x` is the same as that of `x`. -/
561+
@[simp]
562+
lemma mulHeight₁_neg (x : K) : mulHeight₁ (-x) = mulHeight₁ x := by
563+
simp [mulHeight₁_eq]
564+
565+
/-- The logarithmic height of `-x` is the same as that of `x`. -/
566+
@[simp]
567+
lemma logHeight₁_neg (x : K) : logHeight₁ (-x) = logHeight₁ x := by
568+
simp [logHeight₁_eq_log_mulHeight₁, mulHeight₁_neg]
569+
570+
/-- The multiplicative height of `x + y` is at most `2 ^ totalWeight K`
571+
times the product of the multiplicative heights of `x` and `y`. -/
572+
lemma mulHeight₁_add_le (x y : K) :
573+
mulHeight₁ (x + y) ≤ 2 ^ totalWeight K * mulHeight₁ x * mulHeight₁ y := by
574+
rw [show x + y = Finset.univ.sum ![x, y] by simp, mul_assoc]
575+
grw [mulHeight₁_sum_le Finset.univ_nonempty ![x, y]]
576+
simp
577+
578+
/-- The logarithmic height of `x + y` is at most `totalWeight K * log 2`
579+
plus the sum of the logarithmic heights of `x` and `y`. -/
580+
lemma logHeight₁_add_le (x y : K) :
581+
logHeight₁ (x + y) ≤ totalWeight K * log 2 + logHeight₁ x + logHeight₁ y := by
582+
simp only [logHeight₁_eq_log_mulHeight₁]
583+
pull (disch := positivity) log
584+
exact (log_le_log <| by positivity) <| mulHeight₁_add_le ..
585+
586+
/-- The multiplicative height of `x - y` is at most `2 ^ totalWeight K`
587+
times the product of the multiplicative heights of `x` and `y`. -/
588+
lemma mulHeight₁_sub_le (x y : K) :
589+
mulHeight₁ (x - y) ≤ 2 ^ totalWeight K * mulHeight₁ x * mulHeight₁ y := by
590+
rw [sub_eq_add_neg, ← mulHeight₁_neg y]
591+
exact mulHeight₁_add_le x (-y)
592+
593+
/-- The logarithmic height of `x - y` is at most `totalWeight K * log 2`
594+
plus the sum of the logarithmic heights of `x` and `y`. -/
595+
lemma logHeight₁_sub_le (x y : K) :
596+
logHeight₁ (x - y) ≤ totalWeight K * log 2 + logHeight₁ x + logHeight₁ y := by
597+
rw [sub_eq_add_neg, ← logHeight₁_neg y]
598+
exact logHeight₁_add_le x (-y)
599+
600+
end Height

0 commit comments

Comments
 (0)