Skip to content

Commit 413b8b1

Browse files
SnirBroshixroblot
authored andcommitted
refactor(LinearAlgebra/Matrix/Rank): generalize Matrix.rank/LinearMap.rank to semirings (leanprover-community#39158)
- Generalize `Matrix.rank` from `CommRing` to `CommSemiring` - Generalize `LinearMap.rank` from `AddCommGroup`s over `Ring`s to `AddCommMonoid`s over `Semiring`s (which are the minimum requirements for `Module`) - Many `Matrix.rank` theorems now require `StrongRankCondition` explicitly (which `CommRing` used to provide) - `Matrix.cRank` theorems don't need commutativity
1 parent 676fbc6 commit 413b8b1

2 files changed

Lines changed: 59 additions & 65 deletions

File tree

Mathlib/LinearAlgebra/Dimension/LinearMap.lean

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ namespace LinearMap
3131

3232
section Ring
3333

34-
variable [Ring K] [AddCommGroup V] [Module K V] [AddCommGroup V₁] [Module K V₁]
35-
variable [AddCommGroup V'] [Module K V']
34+
variable [Semiring K] [AddCommMonoid V] [Module K V] [AddCommMonoid V₁] [Module K V₁]
35+
variable [AddCommMonoid V'] [Module K V']
3636

3737
/-- `rank f` is the rank of a `LinearMap` `f`, defined as the dimension of `f.range`. -/
3838
abbrev rank (f : V →ₗ[K] V') : Cardinal :=
@@ -48,7 +48,7 @@ theorem rank_le_domain (f : V →ₗ[K] V₁) : rank f ≤ Module.rank K V :=
4848
theorem rank_zero [Nontrivial K] : rank (0 : V →ₗ[K] V') = 0 := by
4949
rw [rank, LinearMap.range_zero, rank_bot]
5050

51-
variable [AddCommGroup V''] [Module K V'']
51+
variable [AddCommMonoid V''] [Module K V'']
5252

5353
theorem rank_comp_le_left (g : V →ₗ[K] V') (f : V' →ₗ[K] V'') : rank (f.comp g) ≤ rank f := by
5454
refine Submodule.rank_mono ?_

Mathlib/LinearAlgebra/Matrix/Rank.lean

Lines changed: 56 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -114,97 +114,93 @@ end Infinite
114114

115115
variable [Fintype n] [Fintype o]
116116

117-
section CommRing
118-
119-
variable [CommRing R]
120-
121117
/-- The rank of a matrix is the rank of its image. -/
122-
noncomputable def rank (A : Matrix m n R) : ℕ :=
118+
noncomputable def rank [CommSemiring R] (A : Matrix m n R) : ℕ :=
123119
finrank R <| LinearMap.range A.mulVecLin
124120

125121
@[simp]
126-
theorem rank_subsingleton [Subsingleton R] (A : Matrix m n R) : A.rank = 1 :=
122+
theorem rank_subsingleton [CommSemiring R] [Subsingleton R] (A : Matrix m n R) : A.rank = 1 :=
127123
finrank_subsingleton
128124

129125
@[simp]
130-
theorem cRank_one [Nontrivial R] [DecidableEq m] :
126+
theorem cRank_one [Semiring R] [Nontrivial R] [DecidableEq m] [StrongRankCondition R] :
131127
(cRank (1 : Matrix m m R)) = lift.{uR} #m := by
132128
have h : LinearIndependent R (1 : Matrix m m R)ᵀ := by
133129
convert! Pi.linearIndependent_single_one m R
134130
simp [funext_iff, Matrix.one_eq_pi_single]
135131
rw [cRank, rank_span h, ← lift_umax, ← Cardinal.mk_range_eq_of_injective h.injective, lift_id']
136132

137-
@[simp] theorem eRank_one [Nontrivial R] [DecidableEq m] :
133+
@[simp] theorem eRank_one [Semiring R] [Nontrivial R] [DecidableEq m] [StrongRankCondition R] :
138134
(eRank (1 : Matrix m m R)) = ENat.card m := by
139135
rw [eRank, cRank_one, toENat_lift, ENat.card]
140136

141137
@[simp]
142-
theorem rank_one [Nontrivial R] [DecidableEq n] :
138+
theorem rank_one [CommSemiring R] [DecidableEq n] [StrongRankCondition R] :
143139
rank (1 : Matrix n n R) = Fintype.card n := by
144140
rw [rank, mulVecLin_one, LinearMap.range_id, finrank_top, finrank_pi]
145141

146142
@[simp]
147-
theorem rank_zero [Nontrivial R] : rank (0 : Matrix m n R) = 0 := by
143+
theorem rank_zero [CommSemiring R] [Nontrivial R] : rank (0 : Matrix m n R) = 0 := by
148144
rw [rank, mulVecLin_zero, LinearMap.range_zero, finrank_bot]
149145

150146
set_option backward.isDefEq.respectTransparency false in
151147
@[simp]
152-
theorem cRank_zero {m n : Type*} [Nontrivial R] : cRank (0 : Matrix m n R) = 0 := by
148+
theorem cRank_zero {m n : Type*} [Semiring R] [Nontrivial R] : cRank (0 : Matrix m n R) = 0 := by
153149
obtain hn | hn := isEmpty_or_nonempty n
154150
· rw [cRank, range_eq_empty, span_empty, rank_bot]
155151
rw [cRank, transpose_zero, range_zero, span_zero_singleton, rank_bot]
156152

157153
@[simp]
158-
theorem eRank_zero {m n : Type*} [Nontrivial R] : eRank (0 : Matrix m n R) = 0 := by
154+
theorem eRank_zero {m n : Type*} [Semiring R] [Nontrivial R] : eRank (0 : Matrix m n R) = 0 := by
159155
simp [eRank]
160156

161-
theorem rank_le_card_width [Nontrivial R] (A : Matrix m n R) :
162-
A.rank ≤ Fintype.card n := by
163-
exact A.mulVecLin.finrank_range_le.trans_eq (finrank_pi _)
157+
theorem rank_le_card_width [CommSemiring R] [StrongRankCondition R] (A : Matrix m n R) :
158+
A.rank ≤ Fintype.card n :=
159+
A.mulVecLin.finrank_range_le.trans_eq <| finrank_pi R
164160

165-
theorem rank_le_width [Nontrivial R] {m n : ℕ} (A : Matrix (Fin m) (Fin n) R) :
166-
A.rank ≤ n :=
161+
theorem rank_le_width [CommSemiring R] [StrongRankCondition R] {m n : ℕ}
162+
(A : Matrix (Fin m) (Fin n) R) : A.rank ≤ n :=
167163
A.rank_le_card_width.trans <| (Fintype.card_fin n).le
168164

169-
theorem rank_mul_le_left (A : Matrix m n R) (B : Matrix n o R) :
170-
(A * B).rank ≤ A.rank := by
165+
theorem rank_mul_le_left [CommSemiring R] [StrongRankCondition R] (A : Matrix m n R)
166+
(B : Matrix n o R) : (A * B).rank ≤ A.rank := by
171167
nontriviality R
172168
rw [rank, rank, mulVecLin_mul]
173-
exact Cardinal.toNat_le_toNat (LinearMap.rank_comp_le_left _ _) (rank_lt_aleph0 _ _)
169+
exact Cardinal.toNat_le_toNat (LinearMap.rank_comp_le_left ..) (rank_lt_aleph0 R _)
174170

175-
theorem rank_mul_le_right (A : Matrix m n R) (B : Matrix n o R) :
176-
(A * B).rank ≤ B.rank := by
171+
theorem rank_mul_le_right [CommSemiring R] [StrongRankCondition R] (A : Matrix m n R)
172+
(B : Matrix n o R) : (A * B).rank ≤ B.rank := by
177173
nontriviality R
178174
rw [rank, rank, mulVecLin_mul]
179175
exact finrank_le_finrank_of_rank_le_rank (LinearMap.lift_rank_comp_le_right _ _)
180176
(rank_lt_aleph0 _ _)
181177

182-
theorem rank_mul_le (A : Matrix m n R) (B : Matrix n o R) :
178+
theorem rank_mul_le [CommSemiring R] [StrongRankCondition R] (A : Matrix m n R) (B : Matrix n o R) :
183179
(A * B).rank ≤ min A.rank B.rank :=
184180
le_min (rank_mul_le_left _ _) (rank_mul_le_right _ _)
185181

186-
theorem rank_vecMulVec_le (w : m → R) (v : n → R) : (Matrix.vecMulVec w v).rank ≤ 1 := by
182+
theorem rank_vecMulVec_le [CommSemiring R] [StrongRankCondition R] (w : m → R) (v : n → R) :
183+
(Matrix.vecMulVec w v).rank ≤ 1 := by
187184
rw [Matrix.vecMulVec_eq Unit]
188185
refine le_trans (rank_mul_le_left _ _) ?_
189186
nontriviality R
190187
exact rank_le_card_width _
191188

192-
theorem rank_unit [Nontrivial R] [DecidableEq n] (A : (Matrix n n R)ˣ) :
189+
theorem rank_unit [DecidableEq n] [CommSemiring R] [StrongRankCondition R] (A : (Matrix n n R)ˣ) :
193190
(A : Matrix n n R).rank = Fintype.card n := by
194191
apply le_antisymm (rank_le_card_width (A : Matrix n n R)) _
195192
have := rank_mul_le_left (A : Matrix n n R) (↑A⁻¹ : Matrix n n R)
196193
rwa [← Units.val_mul, mul_inv_cancel, Units.val_one, rank_one] at this
197194

198-
theorem rank_of_isUnit [Nontrivial R] [DecidableEq n] (A : Matrix n n R) (h : IsUnit A) :
199-
A.rank = Fintype.card n := by
195+
theorem rank_of_isUnit [DecidableEq n] [CommSemiring R] [StrongRankCondition R] (A : Matrix n n R)
196+
(h : IsUnit A) : A.rank = Fintype.card n := by
200197
obtain ⟨A, rfl⟩ := h
201198
exact rank_unit A
202199

203200
/-- Right multiplying by an invertible matrix does not change the rank -/
204201
@[simp]
205-
lemma rank_mul_eq_left_of_isUnit_det [DecidableEq n]
206-
(A : Matrix n n R) (B : Matrix m n R) (hA : IsUnit A.det) :
207-
(B * A).rank = B.rank := by
202+
lemma rank_mul_eq_left_of_isUnit_det {R : Type*} [CommRing R] [DecidableEq n] (A : Matrix n n R)
203+
(B : Matrix m n R) (hA : IsUnit A.det) : (B * A).rank = B.rank := by
208204
suffices Function.Surjective A.mulVecLin by
209205
rw [rank, mulVecLin_mul, LinearMap.range_comp_of_range_eq_top _
210206
(LinearMap.range_eq_top.mpr this), ← rank]
@@ -213,18 +209,17 @@ lemma rank_mul_eq_left_of_isUnit_det [DecidableEq n]
213209

214210
/-- Left multiplying by an invertible matrix does not change the rank -/
215211
@[simp]
216-
lemma rank_mul_eq_right_of_isUnit_det [Fintype m] [DecidableEq m]
217-
(A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
218-
(A * B).rank = B.rank := by
212+
lemma rank_mul_eq_right_of_isUnit_det {R : Type*} [CommRing R] [Fintype m] [DecidableEq m]
213+
(A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) : (A * B).rank = B.rank := by
219214
let b : Basis m R (m → R) := Pi.basisFun R m
220215
replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
221216
convert! hA; rw [← LinearEquiv.eq_symm_apply]; rfl
222217
have hAB : mulVecLin (A * B) = (LinearEquiv.ofIsUnitDet hA).comp (mulVecLin B) := by ext; simp
223218
rw [rank, rank, hAB, LinearMap.range_comp, LinearEquiv.finrank_map_eq]
224219

225220
/-- Taking a subset of the rows and columns reduces the rank. -/
226-
theorem rank_submatrix_le [Fintype n₀] (A : Matrix m n R) (r : m₀ → m) (c : n₀ → n) :
227-
(A.submatrix r c).rank ≤ A.rank := by
221+
theorem rank_submatrix_le [CommSemiring R] [StrongRankCondition R] [Fintype n₀] (A : Matrix m n R)
222+
(r : m₀ → m) (c : n₀ → n) : (A.submatrix r c).rank ≤ A.rank := by
228223
nontriviality R
229224
have := Module.Finite.span_of_finite R (Set.finite_range (A.submatrix r id).col)
230225
calc
@@ -242,49 +237,50 @@ theorem rank_submatrix_le [Fintype n₀] (A : Matrix m n R) (r : m₀ → m) (c
242237
(Equiv.refl n).symm from rfl, LinearEquiv.range, Submodule.map_top]
243238
exact Submodule.finrank_map_le _ _
244239

245-
theorem rank_reindex [Fintype n₀] (em : m ≃ m₀) (en : n ≃ n₀) (A : Matrix m n R) :
240+
theorem rank_reindex [Fintype n₀] [CommSemiring R] (em : m ≃ m₀) (en : n ≃ n₀) (A : Matrix m n R) :
246241
rank (A.reindex em en) = rank A := by
247242
rw [rank, rank, mulVecLin_reindex, LinearMap.range_comp, LinearMap.range_comp,
248243
LinearEquiv.range, Submodule.map_top, LinearEquiv.finrank_map_eq]
249244

250245
@[simp]
251-
theorem rank_submatrix [Fintype n₀] (A : Matrix m n R) (em : m₀ ≃ m) (en : n₀ ≃ n) :
252-
rank (A.submatrix em en) = rank A := by
246+
theorem rank_submatrix [Fintype n₀] [CommSemiring R] (A : Matrix m n R) (em : m₀ ≃ m)
247+
(en : n₀ ≃ n) : rank (A.submatrix em en) = rank A := by
253248
simpa only [reindex_apply] using! rank_reindex em.symm en.symm A
254249

255250
@[simp]
256-
theorem lift_cRank_submatrix {n : Type un} (A : Matrix m n R) (em : m₀ ≃ m) (en : n₀ ≃ n) :
257-
lift.{um} (cRank (A.submatrix em en)) = lift.{um₀} (cRank A) :=
251+
theorem lift_cRank_submatrix {n : Type un} [Semiring R] (A : Matrix m n R) (em : m₀ ≃ m)
252+
(en : n₀ ≃ n) : lift.{um} (cRank (A.submatrix em en)) = lift.{um₀} (cRank A) :=
258253
(A.lift_cRank_submatrix_le em en).antisymm
259254
<| by simpa using ((A.reindex em.symm en.symm).lift_cRank_submatrix_le em.symm en.symm)
260255

261256
/-- A special case of `lift_cRank_submatrix` for when the row types are in the same universe. -/
262257
@[simp]
263-
theorem cRank_submatrix {m₀ : Type um} {n : Type un} (A : Matrix m n R) (em : m₀ ≃ m)
258+
theorem cRank_submatrix {m₀ : Type um} {n : Type un} [Semiring R] (A : Matrix m n R) (em : m₀ ≃ m)
264259
(en : n₀ ≃ n) : cRank (A.submatrix em en) = cRank A := by
265260
simpa [-lift_cRank_submatrix] using A.lift_cRank_submatrix em en
266261

267-
theorem lift_cRank_reindex {n : Type un} (A : Matrix m n R) (em : m ≃ m₀) (en : n ≃ n₀) :
268-
lift.{um} (cRank (A.reindex em en)) = lift.{um₀} (cRank A) :=
262+
theorem lift_cRank_reindex {n : Type un} [Semiring R] (A : Matrix m n R) (em : m ≃ m₀)
263+
(en : n ≃ n₀) : lift.{um} (cRank (A.reindex em en)) = lift.{um₀} (cRank A) :=
269264
lift_cRank_submatrix ..
270265

271266
/-- A special case of `lift_cRank_reindex` for when the row types are in the same universe. -/
272-
theorem cRank_reindex {m₀ : Type um} {n : Type un} (A : Matrix m n R) (em : m ≃ m₀) (en : n ≃ n₀) :
273-
cRank (A.reindex em en) = cRank A :=
267+
theorem cRank_reindex {m₀ : Type um} {n : Type un} [Semiring R] (A : Matrix m n R) (em : m ≃ m₀)
268+
(en : n ≃ n₀) : cRank (A.reindex em en) = cRank A :=
274269
cRank_submatrix ..
275270

276271
@[simp]
277-
theorem eRank_submatrix {n : Type un} (A : Matrix m n R) (em : m₀ ≃ m) (en : n₀ ≃ n) :
272+
theorem eRank_submatrix {n : Type un} [Semiring R] (A : Matrix m n R) (em : m₀ ≃ m) (en : n₀ ≃ n) :
278273
eRank (A.submatrix em en) = eRank A := by
279274
simpa [-lift_cRank_submatrix] using! congr_arg Cardinal.toENat <| A.lift_cRank_submatrix em en
280275

281-
theorem eRank_reindex {m₀ : Type um} {n : Type un} (A : Matrix m n R) (em : m ≃ m₀) (en : n ≃ n₀) :
282-
eRank (A.reindex em en) = eRank A :=
276+
theorem eRank_reindex {m₀ : Type um} {n : Type un} [Semiring R] (A : Matrix m n R) (em : m ≃ m₀)
277+
(en : n ≃ n₀) : eRank (A.reindex em en) = eRank A :=
283278
eRank_submatrix ..
284279

285-
theorem rank_eq_finrank_range_toLin [Finite m] [DecidableEq n] {M₁ M₂ : Type*} [AddCommGroup M₁]
286-
[AddCommGroup M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R) (v₁ : Basis m R M₁)
287-
(v₂ : Basis n R M₂) : A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
280+
theorem rank_eq_finrank_range_toLin [Finite m] [DecidableEq n] {M₁ M₂ : Type*} [CommSemiring R]
281+
[AddCommMonoid M₁] [AddCommMonoid M₂] [Module R M₁] [Module R M₂] (A : Matrix m n R)
282+
(v₁ : Basis m R M₁) (v₂ : Basis n R M₂) :
283+
A.rank = finrank R (LinearMap.range (toLin v₂ v₁ A)) := by
288284
cases nonempty_fintype m
289285
let e₁ := (Pi.basisFun R m).equiv v₁ (Equiv.refl _)
290286
let e₂ := (Pi.basisFun R n).equiv v₂ (Equiv.refl _)
@@ -301,28 +297,26 @@ theorem rank_eq_finrank_range_toLin [Finite m] [DecidableEq n] {M₁ M₂ : Type
301297
simp only [e₁, e₂, LinearMap.comp_apply, LinearEquiv.coe_coe, Equiv.refl_apply,
302298
aux₁, aux₂, LinearMap.coe_single, toLin_self, map_sum, map_smul, Basis.equiv_apply]
303299

304-
theorem rank_le_card_height [Fintype m] [Nontrivial R] (A : Matrix m n R) :
305-
A.rank ≤ Fintype.card m := by
306-
exact (Submodule.finrank_le _).trans (finrank_pi R).le
300+
theorem rank_le_card_height [Fintype m] [CommSemiring R] [StrongRankCondition R]
301+
(A : Matrix m n R) : A.rank ≤ Fintype.card m :=
302+
(Submodule.finrank_le _).trans (finrank_pi R).le
307303

308-
theorem rank_le_height [Nontrivial R] {m n : ℕ} (A : Matrix (Fin m) (Fin n) R) :
309-
A.rank ≤ m :=
310-
A.rank_le_card_height.trans <| (Fintype.card_fin m).le
304+
theorem rank_le_height [CommSemiring R] [StrongRankCondition R] {m n : ℕ}
305+
(A : Matrix (Fin m) (Fin n) R) : A.rank ≤ m :=
306+
A.rank_le_card_height.trans (Fintype.card_fin m).le
311307

312308
/-- The rank of a matrix is the rank of the space spanned by its columns. -/
313-
theorem rank_eq_finrank_span_cols (A : Matrix m n R) :
309+
theorem rank_eq_finrank_span_cols [CommSemiring R] (A : Matrix m n R) :
314310
A.rank = finrank R (Submodule.span R (Set.range A.col)) := by rw [rank, Matrix.range_mulVecLin]
315311

316312
@[simp]
317-
theorem cRank_toNat_eq_rank (A : Matrix m n R) : A.cRank.toNat = A.rank := by
313+
theorem cRank_toNat_eq_rank [CommSemiring R] (A : Matrix m n R) : A.cRank.toNat = A.rank := by
318314
rw [cRank_toNat_eq_finrank, ← rank_eq_finrank_span_cols]
319315

320316
@[simp]
321-
theorem eRank_toNat_eq_rank (A : Matrix m n R) : A.eRank.toNat = A.rank := by
317+
theorem eRank_toNat_eq_rank [CommSemiring R] (A : Matrix m n R) : A.eRank.toNat = A.rank := by
322318
rw [eRank_toNat_eq_finrank, ← rank_eq_finrank_span_cols]
323319

324-
end CommRing
325-
326320
section Field
327321

328322
variable [Field R]

0 commit comments

Comments
 (0)