Skip to content

Commit eec581e

Browse files
committed
feat(Algebra/Ring): generalise and extend material about sums of squares and semireal rings (#16094)
* Generalise definition of a semireal ring, as discussed at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Formally.20real.20fields * Add facts about multiplicative structure of sums of squares -- preserved under multiplication, form a semiring, set of sums of squares is the semiring generated by the squares. * Add some lemmas to simpset * Update documentation Deletions: * `mem_sumSq_of_isSquare` (statement changed to `IsSquare.isSumSq`)
1 parent 918ca88 commit eec581e

File tree

2 files changed

+140
-37
lines changed

2 files changed

+140
-37
lines changed
Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
/-
22
Copyright (c) 2024 Florent Schaffhauser. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Florent Schaffhauser
4+
Authors: Florent Schaffhauser, Artie Khovanov
55
-/
66
import Mathlib.Algebra.Ring.SumsOfSquares
77

88
/-!
99
# Semireal rings
1010
11-
A semireal ring is a non-trivial commutative ring (with unit) in which `-1` is *not* a
12-
sum of squares.
11+
A semireal ring is a commutative ring (with unit) in which `-1` is *not* a sum of squares.
1312
1413
For instance, linearly ordered rings are semireal, because sums of squares are positive and `-1` is
1514
not.
@@ -24,22 +23,31 @@ not.
2423
[lam_1984](https://doi.org/10.1216/RMJ-1984-14-4-767)
2524
-/
2625

27-
variable (R : Type*)
26+
variable {R : Type*}
2827

28+
variable (R) in
2929
/--
30-
A semireal ring is a non-trivial commutative ring (with unit) in which `-1` is *not* a sum of
31-
squares. We define the class `IsSemireal R`
32-
for all additive monoids `R` equipped with a multiplication, a multiplicative unit and a negation.
30+
A semireal ring is a commutative ring (with unit) in which `-1` is *not* a sum of
31+
squares. We define the predicate `IsSemireal R` for structures `R` equipped with
32+
a multiplication, an addition, a multiplicative unit and an additive unit.
3333
-/
3434
@[mk_iff]
35-
class IsSemireal [AddMonoid R] [Mul R] [One R] [Neg R] : Prop where
36-
non_trivial : (0 : R) ≠ 1
37-
not_isSumSq_neg_one : ¬IsSumSq (-1 : R)
35+
class IsSemireal [Add R] [Mul R] [One R] [Zero R] : Prop where
36+
one_add_ne_zero {s : R} (hs : IsSumSq s) : 1 + s ≠ 0
3837

3938
@[deprecated (since := "2024-08-09")] alias isSemireal := IsSemireal
39+
40+
/-- In a semireal ring, `-1` is not a sum of squares. -/
41+
theorem IsSemireal.not_isSumSq_neg_one [AddGroup R] [One R] [Mul R] [IsSemireal R]:
42+
¬ IsSumSq (-1 : R) := (by simpa using one_add_ne_zero ·)
43+
4044
@[deprecated (since := "2024-08-09")] alias isSemireal.neg_one_not_SumSq :=
4145
IsSemireal.not_isSumSq_neg_one
4246

43-
instance [LinearOrderedRing R] : IsSemireal R where
44-
non_trivial := zero_ne_one
45-
not_isSumSq_neg_one := fun h ↦ (not_le (α := R)).2 neg_one_lt_zero h.nonneg
47+
/--
48+
Linearly ordered semirings with the property `a ≤ b → ∃ c, a + c = b` (e.g. `ℕ`)
49+
are semireal.
50+
-/
51+
instance [LinearOrderedSemiring R] [ExistsAddOfLE R] : IsSemireal R where
52+
one_add_ne_zero hs amo := zero_ne_one' R (le_antisymm zero_le_one
53+
(le_of_le_of_eq (le_add_of_nonneg_right hs.nonneg) amo))

Mathlib/Algebra/Ring/SumsOfSquares.lean

Lines changed: 119 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/-
22
Copyright (c) 2024 Florent Schaffhauser. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Florent Schaffhauser
4+
Authors: Florent Schaffhauser, Artie Khovanov
55
-/
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
1010
/-!
1111
# Sums of squares
1212
@@ -18,7 +18,8 @@ We introduce a predicate for sums of squares in a ring.
1818
an inductive predicate defining the property of being a sum of squares in `R`.
1919
`0 : R` is a sum of squares and if `S` is a sum of squares, then, for all `a : R`,
2020
`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`
2223
with multiplication.
2324
2425
-/
@@ -37,6 +38,17 @@ inductive IsSumSq [Mul R] [Add R] [Zero R] : R → Prop
3738

3839
@[deprecated (since := "2024-08-09")] alias isSumSq := IsSumSq
3940

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+
4052
/--
4153
In an additive monoid with multiplication,
4254
if `s₁` and `s₂` are sums of squares, then `s₁ + s₂` is a sum of squares.
@@ -71,50 +83,133 @@ end AddSubmonoid
7183
@[deprecated (since := "2025-01-03")] alias sumSqIn := AddSubmonoid.sumSq
7284
@[deprecated (since := "2025-01-06")] alias sumSq := AddSubmonoid.sumSq
7385

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+
7490
/--
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
7692
(see Mathlib.Algebra.Group.Even).
7793
-/
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
8696

8797
/--
8898
In an additive monoid with multiplication `R`, the submonoid generated by the squares is the set of
8999
sums of squares in `R`.
90100
-/
101+
@[simp]
91102
theorem AddSubmonoid.closure_isSquare [AddMonoid R] [Mul R] :
92103
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
95108

96109
@[deprecated (since := "2024-08-09")] alias SquaresAddClosure := AddSubmonoid.closure_isSquare
97110

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+
98127
/--
99128
In an additive commutative monoid with multiplication,
100129
`∑ i ∈ I, a i * a i` is a sum of squares.
101130
-/
131+
@[simp]
102132
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 _
107134

108135
@[deprecated (since := "2024-12-27")] alias isSumSq_sum_mul_self := IsSumSq.sum_mul_self
109136

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+
110205
/--
111206
In a linearly ordered semiring with the property `a ≤ b → ∃ c, a + c = b` (e.g. `ℕ`),
112207
sums of squares are non-negative.
113208
-/
114209
theorem IsSumSq.nonneg {R : Type*} [LinearOrderedSemiring R] [ExistsAddOfLE R] {s : R}
115210
(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
119214

120215
@[deprecated (since := "2024-08-09")] alias isSumSq.nonneg := IsSumSq.nonneg

0 commit comments

Comments
 (0)