1
1
/-
2
2
Copyright (c) 2024 Florent Schaffhauser. All rights reserved.
3
3
Released under Apache 2.0 license as described in the file LICENSE.
4
- Authors: Florent Schaffhauser
4
+ Authors: Florent Schaffhauser, Artie Khovanov
5
5
-/
6
- import Mathlib.Algebra.BigOperators. Group.Finset.Basic
7
- import Mathlib.Algebra.Group.Submonoid .Basic
8
- import Mathlib.Algebra.Order. Ring.Defs
9
-
6
+ import Mathlib.Algebra.Group.Subgroup.Even
7
+ import Mathlib.Algebra.Order.Ring .Basic
8
+ import Mathlib.Algebra.Ring.Subsemiring.Basic
9
+ import Mathlib.Tactic.ApplyFun
10
10
/-!
11
11
# Sums of squares
12
12
@@ -18,7 +18,8 @@ We introduce a predicate for sums of squares in a ring.
18
18
an inductive predicate defining the property of being a sum of squares in `R`.
19
19
`0 : R` is a sum of squares and if `S` is a sum of squares, then, for all `a : R`,
20
20
`a * a + s` is a sum of squares.
21
- - `AddMonoid.sumSq R`: the submonoid of sums of squares in an additive monoid `R`
21
+ - `AddMonoid.sumSq R` and `Subsemiring.sumSq R`: respectively
22
+ the submonoid or subsemiring of sums of squares in an additive monoid or semiring `R`
22
23
with multiplication.
23
24
24
25
-/
@@ -37,6 +38,17 @@ inductive IsSumSq [Mul R] [Add R] [Zero R] : R → Prop
37
38
38
39
@[deprecated (since := "2024-08-09")] alias isSumSq := IsSumSq
39
40
41
+ /-- Alternative induction scheme for `IsSumSq` which uses `IsSquare`. -/
42
+ theorem IsSumSq.rec' [Mul R] [Add R] [Zero R]
43
+ {motive : (s : R) → (h : IsSumSq s) → Prop }
44
+ (zero : motive 0 zero)
45
+ (sq_add : ∀ {x s}, (hx : IsSquare x) → (hs : IsSumSq s) → motive s hs →
46
+ motive (x + s) (by rcases hx with ⟨_, rfl⟩; exact sq_add _ hs))
47
+ {s : R} (h : IsSumSq s) : motive s h :=
48
+ match h with
49
+ | .zero => zero
50
+ | .sq_add _ hs => sq_add (.mul_self _) hs (rec ' zero sq_add _)
51
+
40
52
/--
41
53
In an additive monoid with multiplication,
42
54
if `s₁` and `s₂` are sums of squares, then `s₁ + s₂` is a sum of squares.
@@ -71,50 +83,133 @@ end AddSubmonoid
71
83
@[deprecated (since := "2025-01-03")] alias sumSqIn := AddSubmonoid.sumSq
72
84
@[deprecated (since := "2025-01-06")] alias sumSq := AddSubmonoid.sumSq
73
85
86
+ /-- In an additive unital magma with multiplication, `x * x` is a sum of squares for all `x`. -/
87
+ @[simp] theorem IsSumSq.mul_self [AddZeroClass R] [Mul R] (a : R) : IsSumSq (a * a) := by
88
+ simpa using sq_add a zero
89
+
74
90
/--
75
- In an additive monoid with multiplication, squares are sums of squares
91
+ In an additive unital magma with multiplication, squares are sums of squares
76
92
(see Mathlib.Algebra.Group.Even).
77
93
-/
78
- theorem mem_sumSq_of_isSquare [AddMonoid R] [Mul R] {x : R} (hx : IsSquare x) :
79
- x ∈ AddSubmonoid.sumSq R := by
80
- rcases hx with ⟨y, hy⟩
81
- rw [hy, ← AddMonoid.add_zero (y * y)]
82
- exact IsSumSq.sq_add _ IsSumSq.zero
83
-
84
- @[deprecated (since := "2024-08-09")] alias SquaresInSumSq := mem_sumSq_of_isSquare
85
- @[deprecated (since := "2025-01-03")] alias mem_sumSqIn_of_isSquare := mem_sumSq_of_isSquare
94
+ theorem IsSquare.isSumSq [AddZeroClass R] [Mul R] {x : R} (hx : IsSquare x) :
95
+ IsSumSq x := by rcases hx with ⟨_, rfl⟩; apply IsSumSq.mul_self
86
96
87
97
/--
88
98
In an additive monoid with multiplication `R`, the submonoid generated by the squares is the set of
89
99
sums of squares in `R`.
90
100
-/
101
+ @[simp]
91
102
theorem AddSubmonoid.closure_isSquare [AddMonoid R] [Mul R] :
92
103
closure {x : R | IsSquare x} = sumSq R := by
93
- refine le_antisymm (closure_le.2 (fun x hx ↦ mem_sumSq_of_isSquare hx)) (fun x hx ↦ ?_)
94
- induction hx <;> aesop
104
+ refine closure_eq_of_le (fun x hx ↦ IsSquare.isSumSq hx) (fun x hx ↦ ?_)
105
+ induction hx with
106
+ | zero => apply zero_mem
107
+ | sq_add a hs ih => exact add_mem (subset_closure (IsSquare.mul_self a)) ih
95
108
96
109
@[deprecated (since := "2024-08-09")] alias SquaresAddClosure := AddSubmonoid.closure_isSquare
97
110
111
+ /--
112
+ In an additive commutative monoid with multiplication, a finite sum of sums of squares
113
+ is a sum of squares.
114
+ -/
115
+ theorem IsSumSq.sum [AddCommMonoid R] [Mul R] {ι : Type *} {I : Finset ι} {s : ι → R}
116
+ (hs : ∀ i ∈ I, IsSumSq <| s i) : IsSumSq (∑ i ∈ I, s i) := by
117
+ simpa using sum_mem (S := AddSubmonoid.sumSq _) hs
118
+
119
+ /--
120
+ In an additive commutative monoid with multiplication,
121
+ `∑ i ∈ I, x i`, where each `x i` is a square, is a sum of squares.
122
+ -/
123
+ theorem IsSumSq.sum_isSquare [AddCommMonoid R] [Mul R] {ι : Type *} (I : Finset ι) {x : ι → R}
124
+ (hx : ∀ i ∈ I, IsSquare <| x i) : IsSumSq (∑ i ∈ I, x i) :=
125
+ .sum fun _ hi => IsSquare.isSumSq (hx _ hi)
126
+
98
127
/--
99
128
In an additive commutative monoid with multiplication,
100
129
`∑ i ∈ I, a i * a i` is a sum of squares.
101
130
-/
131
+ @[simp]
102
132
theorem IsSumSq.sum_mul_self [AddCommMonoid R] [Mul R] {ι : Type *} (I : Finset ι) (a : ι → R) :
103
- IsSumSq (∑ i ∈ I, a i * a i) := by
104
- induction I using Finset.cons_induction with
105
- | empty => simpa using IsSumSq.zero
106
- | cons i _ hi h => exact (Finset.sum_cons (β := R) hi) ▸ IsSumSq.sq_add (a i) h
133
+ IsSumSq (∑ i ∈ I, a i * a i) := .sum fun _ _ => .mul_self _
107
134
108
135
@[deprecated (since := "2024-12-27")] alias isSumSq_sum_mul_self := IsSumSq.sum_mul_self
109
136
137
+ namespace NonUnitalSubsemiring
138
+ variable {T : Type *} [NonUnitalCommSemiring T]
139
+
140
+ variable (T) in
141
+ /--
142
+ In a commutative (possibly non-unital) semiring `R`, `NonUnitalSubsemiring.sumSq R` is
143
+ the (possibly non-unital) subsemiring of sums of squares in `R`.
144
+ -/
145
+ def sumSq : NonUnitalSubsemiring T := (Subsemigroup.square T).nonUnitalSubsemiringClosure
146
+
147
+ @[simp] theorem sumSq_toAddSubmonoid : (sumSq T).toAddSubmonoid = .sumSq T := by
148
+ simp [sumSq, ← AddSubmonoid.closure_isSquare,
149
+ Subsemigroup.nonUnitalSubsemiringClosure_toAddSubmonoid]
150
+
151
+ @[simp]
152
+ theorem mem_sumSq {s : T} : s ∈ sumSq T ↔ IsSumSq s := by
153
+ simp [← NonUnitalSubsemiring.mem_toAddSubmonoid]
154
+
155
+ @[simp, norm_cast] theorem coe_sumSq : sumSq T = {s : T | IsSumSq s} := by ext; simp
156
+
157
+ @[simp] theorem closure_isSquare : closure {x : T | IsSquare x} = sumSq T := by
158
+ simp [sumSq, Subsemigroup.nonUnitalSubsemiringClosure_eq_closure]
159
+
160
+ end NonUnitalSubsemiring
161
+
162
+ /--
163
+ In a commutative (possibly non-unital) semiring,
164
+ if `s₁` and `s₂` are sums of squares, then `s₁ * s₂` is a sum of squares.
165
+ -/
166
+ theorem IsSumSq.mul [NonUnitalCommSemiring R] {s₁ s₂ : R}
167
+ (h₁ : IsSumSq s₁) (h₂ : IsSumSq s₂) : IsSumSq (s₁ * s₂) := by
168
+ simpa using mul_mem (by simpa : _ ∈ NonUnitalSubsemiring.sumSq R) (by simpa)
169
+
170
+ private theorem Submonoid.square_subsemiringClosure {T : Type *} [CommSemiring T] :
171
+ (Submonoid.square T).subsemiringClosure = .closure {x : T | IsSquare x} := by
172
+ simp [Submonoid.subsemiringClosure_eq_closure]
173
+
174
+ namespace Subsemiring
175
+ variable {T : Type *} [CommSemiring T]
176
+
177
+ variable (T) in
178
+ /--
179
+ In a commutative semiring `R`, `Subsemiring.sumSq R` is the subsemiring of sums of squares in `R`.
180
+ -/
181
+ def sumSq : Subsemiring T where
182
+ __ := NonUnitalSubsemiring.sumSq T
183
+ one_mem' := by simpa using IsSquare.one.isSumSq
184
+
185
+ @[simp] theorem sumSq_toNonUnitalSubsemiring :
186
+ (sumSq T).toNonUnitalSubsemiring = .sumSq T := rfl
187
+
188
+ @[simp]
189
+ theorem mem_sumSq {s : T} : s ∈ sumSq T ↔ IsSumSq s := by
190
+ simp [← Subsemiring.mem_toNonUnitalSubsemiring]
191
+
192
+ @[simp, norm_cast] theorem coe_sumSq : sumSq T = {s : T | IsSumSq s} := by ext; simp
193
+
194
+ @[simp] theorem closure_isSquare : closure {x : T | IsSquare x} = sumSq T := by
195
+ apply_fun toNonUnitalSubsemiring using toNonUnitalSubsemiring_injective
196
+ simp [← Submonoid.square_subsemiringClosure]
197
+
198
+ end Subsemiring
199
+
200
+ /-- In a commutative semiring, a finite product of sums of squares is a sum of squares. -/
201
+ theorem IsSumSq.prod [CommSemiring R] {ι : Type *} {I : Finset ι} {x : ι → R}
202
+ (hx : ∀ i ∈ I, IsSumSq <| x i) : IsSumSq (∏ i ∈ I, x i) := by
203
+ simpa using prod_mem (S := Subsemiring.sumSq R) (by simpa)
204
+
110
205
/--
111
206
In a linearly ordered semiring with the property `a ≤ b → ∃ c, a + c = b` (e.g. `ℕ`),
112
207
sums of squares are non-negative.
113
208
-/
114
209
theorem IsSumSq.nonneg {R : Type *} [LinearOrderedSemiring R] [ExistsAddOfLE R] {s : R}
115
210
(hs : IsSumSq s) : 0 ≤ s := by
116
- induction hs with
117
- | zero => simp only [le_refl]
118
- | sq_add x _ ih => apply add_nonneg ?_ ih; simp only [← pow_two x, sq_nonneg]
211
+ induction hs using IsSumSq.rec' with
212
+ | zero => simp
213
+ | sq_add hx _ h => exact add_nonneg (IsSquare.nonneg hx) h
119
214
120
215
@[deprecated (since := "2024-08-09")] alias isSumSq.nonneg := IsSumSq.nonneg
0 commit comments