# Transvections #

Transvections are matrices of the form 1 + stdBasisMatrix i j c, where stdBasisMatrix i j c is the basic matrix with a c at position (i, j). Multiplying by such a transvection on the left (resp. on the right) amounts to adding c times the j-th row to the i-th row (resp c times the i-th column to the j-th column). Therefore, they are useful to present algorithms operating on rows and columns.

Transvections are a special case of elementary matrices (according to most references, these also contain the matrices exchanging rows, and the matrices multiplying a row by a constant).

We show that, over a field, any matrix can be written as L * D * L', where L and L' are products of transvections and D is diagonal. In other words, one can reduce a matrix to diagonal form by operations on its rows and columns, a variant of Gauss' pivot algorithm.

## Implementation details #

The proof of the reduction results is done inductively on the size of the matrices, reducing an (r + 1) × (r + 1) matrix to a matrix whose last row and column are zeroes, except possibly for the last diagonal entry. This step is done as follows.

If all the coefficients on the last row and column are zero, there is nothing to do. Otherwise, one can put a nonzero coefficient in the last diagonal entry by a row or column operation, and then subtract this last diagonal entry from the other entries in the last row and column to make them vanish.

This step is done in the type Fin r ⊕ Unit, where Fin r is useful to choose arbitrarily some order in which we cancel the coefficients, and the sum structure is useful to use the formalism of block matrices.

To proceed with the induction, we reindex our matrices to reduce to the above situation.

def Matrix.transvection {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) (c : R) :
Matrix n n R

The transvection matrix transvection i j c is equal to the identity plus c at position (i, j). Multiplying by it on the left (as in transvection i j c * M) corresponds to adding c times the j-th row of M to its i-th row. Multiplying by it on the right corresponds to adding c times the i-th column to the j-th column.

Equations
Instances For
@[simp]
theorem Matrix.transvection_zero {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) :
= 1
theorem Matrix.updateRow_eq_transvection {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) [] (c : R) :
Matrix.updateRow 1 i (1 i + c 1 j) =

A transvection matrix is obtained from the identity by adding c times the j-th row to the i-th row.

theorem Matrix.transvection_mul_transvection_same {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) [] (h : i j) (c : R) (d : R) :
@[simp]
theorem Matrix.transvection_mul_apply_same {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) [] (b : n) (c : R) (M : Matrix n n R) :
( * M) i b = M i b + c * M j b
@[simp]
theorem Matrix.mul_transvection_apply_same {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) [] (a : n) (c : R) (M : Matrix n n R) :
(M * ) a j = M a j + c * M a i
@[simp]
theorem Matrix.transvection_mul_apply_of_ne {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) [] (a : n) (b : n) (ha : a i) (c : R) (M : Matrix n n R) :
( * M) a b = M a b
@[simp]
theorem Matrix.mul_transvection_apply_of_ne {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) [] (a : n) (b : n) (hb : b j) (c : R) (M : Matrix n n R) :
(M * ) a b = M a b
@[simp]
theorem Matrix.det_transvection_of_ne {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) [] (h : i j) (c : R) :
().det = 1
structure Matrix.TransvectionStruct (n : Type u_1) (R : Type u₂) :
Type (max u_1 u₂)

A structure containing all the information from which one can build a nontrivial transvection. This structure is easier to manipulate than transvections as one has a direct access to all the relevant fields.

• i : n
• j : n
• hij : self.i self.j
• c : R
Instances For
theorem Matrix.TransvectionStruct.hij {n : Type u_1} {R : Type u₂} (self : ) :
self.i self.j
instance Matrix.instNonemptyTransvectionStructOfNontrivial (n : Type u_1) (R : Type u₂) [] [] :
Equations
• =
def Matrix.TransvectionStruct.toMatrix {n : Type u_1} {R : Type u₂} [] [] (t : ) :
Matrix n n R

Associating to a transvection_struct the corresponding transvection matrix.

Equations
Instances For
@[simp]
theorem Matrix.TransvectionStruct.toMatrix_mk {n : Type u_1} {R : Type u₂} [] [] (i : n) (j : n) (hij : i j) (c : R) :
{ i := i, j := j, hij := hij, c := c }.toMatrix =
@[simp]
theorem Matrix.TransvectionStruct.det {n : Type u_1} {R : Type u₂} [] [] [] (t : ) :
t.toMatrix.det = 1
@[simp]
theorem Matrix.TransvectionStruct.det_toMatrix_prod {n : Type u_1} {𝕜 : Type u_3} [] [] [] (L : ) :
(List.map Matrix.TransvectionStruct.toMatrix L).prod.det = 1
@[simp]
theorem Matrix.TransvectionStruct.inv_c {n : Type u_1} {R : Type u₂} [] (t : ) :
t.inv.c = -t.c
@[simp]
theorem Matrix.TransvectionStruct.inv_i {n : Type u_1} {R : Type u₂} [] (t : ) :
t.inv.i = t.i
@[simp]
theorem Matrix.TransvectionStruct.inv_j {n : Type u_1} {R : Type u₂} [] (t : ) :
t.inv.j = t.j
def Matrix.TransvectionStruct.inv {n : Type u_1} {R : Type u₂} [] (t : ) :

The inverse of a TransvectionStruct, designed so that t.inv.toMatrix is the inverse of t.toMatrix.

Equations
• t.inv = { i := t.i, j := t.j, hij := , c := -t.c }
Instances For
theorem Matrix.TransvectionStruct.inv_mul {n : Type u_1} {R : Type u₂} [] [] [] (t : ) :
t.inv.toMatrix * t.toMatrix = 1
theorem Matrix.TransvectionStruct.mul_inv {n : Type u_1} {R : Type u₂} [] [] [] (t : ) :
t.toMatrix * t.inv.toMatrix = 1
theorem Matrix.TransvectionStruct.reverse_inv_prod_mul_prod {n : Type u_1} {R : Type u₂} [] [] [] (L : ) :
(List.map (Matrix.TransvectionStruct.toMatrix Matrix.TransvectionStruct.inv) L.reverse).prod * (List.map Matrix.TransvectionStruct.toMatrix L).prod = 1
theorem Matrix.TransvectionStruct.prod_mul_reverse_inv_prod {n : Type u_1} {R : Type u₂} [] [] [] (L : ) :
(List.map Matrix.TransvectionStruct.toMatrix L).prod * (List.map (Matrix.TransvectionStruct.toMatrix Matrix.TransvectionStruct.inv) L.reverse).prod = 1
theorem Matrix.mem_range_scalar_of_commute_transvectionStruct {n : Type u_1} {R : Type u₂} [] [] [] {M : Matrix n n R} (hM : ∀ (t : ), Commute t.toMatrix M) :
M

M is a scalar matrix if it commutes with every nontrivial transvection (elementary matrix).

theorem Matrix.mem_range_scalar_iff_commute_transvectionStruct {n : Type u_1} {R : Type u₂} [] [] [] {M : Matrix n n R} :
M ∀ (t : ), Commute t.toMatrix M
def Matrix.TransvectionStruct.sumInl {n : Type u_1} (p : Type u_2) {R : Type u₂} (t : ) :

Given a TransvectionStruct on n, define the corresponding TransvectionStruct on n ⊕ p using the identity on p.

Equations
Instances For
theorem Matrix.TransvectionStruct.toMatrix_sumInl {n : Type u_1} (p : Type u_2) {R : Type u₂} [] [] [] (t : ) :
.toMatrix = Matrix.fromBlocks t.toMatrix 0 0 1
@[simp]
theorem Matrix.TransvectionStruct.sumInl_toMatrix_prod_mul {n : Type u_1} (p : Type u_2) {R : Type u₂} [] [] [] [] [] (M : Matrix n n R) (L : ) (N : Matrix p p R) :
(List.map (Matrix.TransvectionStruct.toMatrix ) L).prod * = Matrix.fromBlocks ((List.map Matrix.TransvectionStruct.toMatrix L).prod * M) 0 0 N
@[simp]
theorem Matrix.TransvectionStruct.mul_sumInl_toMatrix_prod {n : Type u_1} (p : Type u_2) {R : Type u₂} [] [] [] [] [] (M : Matrix n n R) (L : ) (N : Matrix p p R) :
* (List.map (Matrix.TransvectionStruct.toMatrix ) L).prod = Matrix.fromBlocks (M * (List.map Matrix.TransvectionStruct.toMatrix L).prod) 0 0 N
def Matrix.TransvectionStruct.reindexEquiv {n : Type u_1} {p : Type u_2} {R : Type u₂} (e : n p) (t : ) :

Given a TransvectionStruct on n and an equivalence between n and p, define the corresponding TransvectionStruct on p.

Equations
• = { i := e t.i, j := e t.j, hij := , c := t.c }
Instances For
theorem Matrix.TransvectionStruct.toMatrix_reindexEquiv {n : Type u_1} {p : Type u_2} {R : Type u₂} [] [] [] [] [] (e : n p) (t : ) :
.toMatrix = () t.toMatrix
theorem Matrix.TransvectionStruct.toMatrix_reindexEquiv_prod {n : Type u_1} {p : Type u_2} {R : Type u₂} [] [] [] [] [] (e : n p) (L : ) :
(List.map (Matrix.TransvectionStruct.toMatrix ) L).prod = () (List.map Matrix.TransvectionStruct.toMatrix L).prod

# Reducing matrices by left and right multiplication by transvections #

In this section, we show that any matrix can be reduced to diagonal form by left and right multiplication by transvections (or, equivalently, by elementary operations on lines and columns). The main step is to kill the last row and column of a matrix in Fin r ⊕ Unit with nonzero last coefficient, by subtracting this coefficient from the other ones. The list of these operations is recorded in list_transvec_col M and list_transvec_row M. We have to analyze inductively how these operations affect the coefficients in the last row and the last column to conclude that they have the desired effect.

Once this is done, one concludes the reduction by induction on the size of the matrices, through a suitable reindexing to identify any fintype with Fin r ⊕ Unit.

def Matrix.Pivot.listTransvecCol {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) :
List (Matrix (Fin r Unit) (Fin r Unit) 𝕜)

A list of transvections such that multiplying on the left with these transvections will replace the last column with zeroes.

Equations
Instances For
def Matrix.Pivot.listTransvecRow {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) :
List (Matrix (Fin r Unit) (Fin r Unit) 𝕜)

A list of transvections such that multiplying on the right with these transvections will replace the last row with zeroes.

Equations
Instances For
theorem Matrix.Pivot.listTransvecCol_mul_last_row_drop {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (i : Fin r Unit) {k : } (hk : k r) :
(.prod * M) () i = M () i

Multiplying by some of the matrices in listTransvecCol M does not change the last row.

theorem Matrix.Pivot.listTransvecCol_mul_last_row {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (i : Fin r Unit) :
(.prod * M) () i = M () i

Multiplying by all the matrices in listTransvecCol M does not change the last row.

theorem Matrix.Pivot.listTransvecCol_mul_last_col {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (hM : M () () 0) (i : Fin r) :
(.prod * M) () () = 0

Multiplying by all the matrices in listTransvecCol M kills all the coefficients in the last column but the last one.

theorem Matrix.Pivot.mul_listTransvecRow_last_col_take {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (i : Fin r Unit) {k : } (hk : k r) :
(M * .prod) i () = M i ()

Multiplying by some of the matrices in listTransvecRow M does not change the last column.

theorem Matrix.Pivot.mul_listTransvecRow_last_col {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (i : Fin r Unit) :
(M * .prod) i () = M i ()

Multiplying by all the matrices in listTransvecRow M does not change the last column.

theorem Matrix.Pivot.mul_listTransvecRow_last_row {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (hM : M () () 0) (i : Fin r) :
(M * .prod) () () = 0

Multiplying by all the matrices in listTransvecRow M kills all the coefficients in the last row but the last one.

theorem Matrix.Pivot.listTransvecCol_mul_mul_listTransvecRow_last_col {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (hM : M () () 0) (i : Fin r) :
(.prod * M * .prod) () () = 0

Multiplying by all the matrices either in listTransvecCol M and listTransvecRow M kills all the coefficients in the last row but the last one.

theorem Matrix.Pivot.listTransvecCol_mul_mul_listTransvecRow_last_row {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (hM : M () () 0) (i : Fin r) :
(.prod * M * .prod) () () = 0

Multiplying by all the matrices either in listTransvecCol M and listTransvecRow M kills all the coefficients in the last column but the last one.

theorem Matrix.Pivot.isTwoBlockDiagonal_listTransvecCol_mul_mul_listTransvecRow {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (hM : M () () 0) :
(.prod * M * .prod).IsTwoBlockDiagonal

Multiplying by all the matrices either in listTransvecCol M and listTransvecRow M turns the matrix in block-diagonal form.

theorem Matrix.Pivot.exists_isTwoBlockDiagonal_of_ne_zero {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) (hM : M () () 0) :
∃ (L : List ()) (L' : List ()), ((List.map Matrix.TransvectionStruct.toMatrix L).prod * M * (List.map Matrix.TransvectionStruct.toMatrix L').prod).IsTwoBlockDiagonal

There exist two lists of TransvectionStruct such that multiplying by them on the left and on the right makes a matrix block-diagonal, when the last coefficient is nonzero.

theorem Matrix.Pivot.exists_isTwoBlockDiagonal_list_transvec_mul_mul_list_transvec {𝕜 : Type u_3} [] {r : } (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) :
∃ (L : List ()) (L' : List ()), ((List.map Matrix.TransvectionStruct.toMatrix L).prod * M * (List.map Matrix.TransvectionStruct.toMatrix L').prod).IsTwoBlockDiagonal

There exist two lists of TransvectionStruct such that multiplying by them on the left and on the right makes a matrix block-diagonal.

theorem Matrix.Pivot.exists_list_transvec_mul_mul_list_transvec_eq_diagonal_induction {𝕜 : Type u_3} [] {r : } (IH : ∀ (M : Matrix (Fin r) (Fin r) 𝕜), ∃ (L₀ : List ()) (L₀' : List ()) (D₀ : Fin r𝕜), (List.map Matrix.TransvectionStruct.toMatrix L₀).prod * M * (List.map Matrix.TransvectionStruct.toMatrix L₀').prod = ) (M : Matrix (Fin r Unit) (Fin r Unit) 𝕜) :
∃ (L : List ()) (L' : List ()) (D : Fin r Unit𝕜), (List.map Matrix.TransvectionStruct.toMatrix L).prod * M * (List.map Matrix.TransvectionStruct.toMatrix L').prod =

Inductive step for the reduction: if one knows that any size r matrix can be reduced to diagonal form by elementary operations, then one deduces it for matrices over Fin r ⊕ Unit.

theorem Matrix.Pivot.reindex_exists_list_transvec_mul_mul_list_transvec_eq_diagonal {n : Type u_1} {p : Type u_2} {𝕜 : Type u_3} [] [] [] [] [] (M : Matrix p p 𝕜) (e : p n) (H : ∃ (L : ) (L' : ) (D : n𝕜), (List.map Matrix.TransvectionStruct.toMatrix L).prod * () M * (List.map Matrix.TransvectionStruct.toMatrix L').prod = ) :
∃ (L : ) (L' : ) (D : p𝕜), (List.map Matrix.TransvectionStruct.toMatrix L).prod * M * (List.map Matrix.TransvectionStruct.toMatrix L').prod =

Reduction to diagonal form by elementary operations is invariant under reindexing.

theorem Matrix.Pivot.exists_list_transvec_mul_mul_list_transvec_eq_diagonal_aux {𝕜 : Type u_3} [] (n : Type) [] [] (M : Matrix n n 𝕜) :
∃ (L : ) (L' : ) (D : n𝕜), (List.map Matrix.TransvectionStruct.toMatrix L).prod * M * (List.map Matrix.TransvectionStruct.toMatrix L').prod =

Any matrix can be reduced to diagonal form by elementary operations. Formulated here on Type 0 because we will make an induction using Fin r. See exists_list_transvec_mul_mul_list_transvec_eq_diagonal for the general version (which follows from this one and reindexing).

theorem Matrix.Pivot.exists_list_transvec_mul_mul_list_transvec_eq_diagonal {n : Type u_1} {𝕜 : Type u_3} [] [] [] (M : Matrix n n 𝕜) :
∃ (L : ) (L' : ) (D : n𝕜), (List.map Matrix.TransvectionStruct.toMatrix L).prod * M * (List.map Matrix.TransvectionStruct.toMatrix L').prod =

Any matrix can be reduced to diagonal form by elementary operations.

theorem Matrix.Pivot.exists_list_transvec_mul_diagonal_mul_list_transvec {n : Type u_1} {𝕜 : Type u_3} [] [] [] (M : Matrix n n 𝕜) :
∃ (L : ) (L' : ) (D : n𝕜), M = (List.map Matrix.TransvectionStruct.toMatrix L).prod * * (List.map Matrix.TransvectionStruct.toMatrix L').prod

Any matrix can be written as the product of transvections, a diagonal matrix, and transvections.

theorem Matrix.diagonal_transvection_induction {n : Type u_1} {𝕜 : Type u_3} [] [] [] (P : Matrix n n 𝕜Prop) (M : Matrix n n 𝕜) (hdiag : ∀ (D : n𝕜), ().det = M.detP ()) (htransvec : ∀ (t : ), P t.toMatrix) (hmul : ∀ (A B : Matrix n n 𝕜), P AP BP (A * B)) :
P M

Induction principle for matrices based on transvections: if a property is true for all diagonal matrices, all transvections, and is stable under product, then it is true for all matrices. This is the useful way to say that matrices are generated by diagonal matrices and transvections.

We state a slightly more general version: to prove a property for a matrix M, it suffices to assume that the diagonal matrices we consider have the same determinant as M. This is useful to obtain similar principles for SLₙ or GLₙ.

theorem Matrix.diagonal_transvection_induction_of_det_ne_zero {n : Type u_1} {𝕜 : Type u_3} [] [] [] (P : Matrix n n 𝕜Prop) (M : Matrix n n 𝕜) (hMdet : M.det 0) (hdiag : ∀ (D : n𝕜), ().det 0P ()) (htransvec : ∀ (t : ), P t.toMatrix) (hmul : ∀ (A B : Matrix n n 𝕜), A.det 0B.det 0P AP BP (A * B)) :
P M

Induction principle for invertible matrices based on transvections: if a property is true for all invertible diagonal matrices, all transvections, and is stable under product of invertible matrices, then it is true for all invertible matrices. This is the useful way to say that invertible matrices are generated by invertible diagonal matrices and transvections.