Built with Alectryon, running Coq+SerAPI v8.19.0+0.19.3. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use instead of Ctrl.
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
Require Import Types.Sigma. Require Import Spaces.List.Core Spaces.List.Theory Spaces.List.Paths. Require Import Algebra.Rings.Ring Algebra.Rings.Module Algebra.Rings.CRing Algebra.Rings.KroneckerDelta Algebra.Rings.Vector. Require Import abstract_algebra. Require Import WildCat.Core WildCat.Paths. Require Import Modalities.ReflectiveSubuniverse. Set Universe Minimization ToSet. (** * Matrices *) (** ** Definition *) Definition Matrix@{i} (R : Type@{i}) (m n : nat) : Type@{i} := Vector (Vector R n) m. Instance istrunc_matrix (R : Type) k `{IsTrunc k.+2 R} m n : IsTrunc k.+2 (Matrix R m n) := _. (** Building a matrix from a function that takes row and column indices. *)
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R

Matrix R m n
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R

Matrix R m n
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R

forall i : nat, (i < m)%nat -> Vector R n
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R
i: nat
Hi: (i < m)%nat

Vector R n
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R
i: nat
Hi: (i < m)%nat

forall i : nat, (i < n)%nat -> R
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R
i: nat
Hi: (i < m)%nat
j: nat
Hj: (j < n)%nat

R
exact (M_fun i j Hi Hj). Defined. (** The length conditions here are decidable so can be inferred in proofs. *)
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l

Matrix R m n
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l

Matrix R m n
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l

list (Vector R n)
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l
(fun l : list (Vector R n) => length l = m) ?proj1
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l

list (Vector R n)
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l

list (list R)
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l
for_all (fun x : list R => length x = n) ?l
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l

list (list R)
exact l.
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l

for_all (fun x : list R => length x = n) l
exact wf_col.
R: Type
m, n: nat
l: list (list R)
wf_row: length l = m
wf_col: for_all (fun row : list R => length row = n) l

(fun l : list (Vector R n) => length l = m) (list_sigma (fun x : list R => length x = n) l wf_col)
by lhs napply length_list_sigma. Defined. Definition entries@{i|} {R : Type@{i}} {m n} (M : Matrix R m n) : list (list R) := list_map@{i i} pr1 (pr1 M). (** The entry at row [i] and column [j] of a matrix [M]. *) Definition entry {R : Type} {m n} (M : Matrix R m n) (i j : nat) {H1 : (i < m)%nat} {H2 : (j < n)%nat} : R := Vector.entry (Vector.entry M i) j. (** Mapping a function on all the entries of a matrix. *) Definition matrix_map {R S : Type} {m n} (f : R -> S) : Matrix R m n -> Matrix S m n := fun M => Build_Matrix S m n (fun i j _ _ => f (entry M i j)). Definition matrix_map2 {R S T : Type} {m n} (f : R -> S -> T) : Matrix R m n -> Matrix S m n -> Matrix T m n := fun M N => Build_Matrix T m n (fun i j _ _ => f (entry M i j) (entry N i j)). (** The [(i, j)]-entry of [Build_Matrix R m n M_fun] is [M_fun i j]. *)
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R
i, j: nat
H1: (i < m)%nat
H2: (j < n)%nat

entry (Build_Matrix R m n M_fun) i j = M_fun i j H1 H2
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R
i, j: nat
H1: (i < m)%nat
H2: (j < n)%nat

entry (Build_Matrix R m n M_fun) i j = M_fun i j H1 H2
R: Type
m, n: nat
M_fun: forall i j : nat, (i < m)%nat -> (j < n)%nat -> R
i, j: nat
H1: (i < m)%nat
H2: (j < n)%nat

Vector.entry (Vector.entry (Build_Matrix R m n M_fun) i) j = M_fun i j H1 H2
by rewrite 2 entry_Build_Vector. Defined. (** Two matrices are equal if all their entries are equal. *)
R: Type
m, n: nat
M, N: Matrix R m n
H: forall (i j : nat) (Hi : (i < m)%nat) (Hj : (j < n)%nat), entry M i j = entry N i j

M = N
R: Type
m, n: nat
M, N: Matrix R m n
H: forall (i j : nat) (Hi : (i < m)%nat) (Hj : (j < n)%nat), entry M i j = entry N i j

M = N
R: Type
m, n: nat
M, N: Matrix R m n
H: forall (i j : nat) (Hi : (i < m)%nat) (Hj : (j < n)%nat), entry M i j = entry N i j

forall (i : nat) (H : (i < m)%nat), Vector.entry M i = Vector.entry N i
R: Type
m, n: nat
M, N: Matrix R m n
H: forall (i j : nat) (Hi : (i < m)%nat) (Hj : (j < n)%nat), entry M i j = entry N i j
i: nat
Hi: (i < m)%nat

Vector.entry M i = Vector.entry N i
R: Type
m, n: nat
M, N: Matrix R m n
H: forall (i j : nat) (Hi : (i < m)%nat) (Hj : (j < n)%nat), entry M i j = entry N i j
i: nat
Hi: (i < m)%nat

forall (i0 : nat) (H : (i0 < n)%nat), Vector.entry (Vector.entry M i) i0 = Vector.entry (Vector.entry N i) i0
R: Type
m, n: nat
M, N: Matrix R m n
H: forall (i j : nat) (Hi : (i < m)%nat) (Hj : (j < n)%nat), entry M i j = entry N i j
i: nat
Hi: (i < m)%nat
j: nat
Hj: (j < n)%nat

Vector.entry (Vector.entry M i) j = Vector.entry (Vector.entry N i) j
exact (H i j Hi Hj). Defined. (** ** Addition and module structure *) (** Here we define the abelian group of (n x m)-matrices over a ring. This follows from the abelian group structure of the underlying vectors. We are also able to derive a left module structure when the entries come from a left module. *) Definition abgroup_matrix (A : AbGroup) (m n : nat) : AbGroup := abgroup_vector (abgroup_vector A n) m. Definition matrix_plus {A : AbGroup} {m n} : Matrix A m n -> Matrix A m n -> Matrix A m n := @sg_op (abgroup_matrix A m n) _. Definition matrix_zero (A : AbGroup) m n : Matrix A m n := @mon_unit (abgroup_matrix A m n) _. Definition matrix_negate {A : AbGroup} {m n} : Matrix A m n -> Matrix A m n := @negate (abgroup_matrix A m n) _.
A: AbGroup
m, n: nat
R: Ring
H: IsLeftModule R A

IsLeftModule R (abgroup_matrix A m n)
A: AbGroup
m, n: nat
R: Ring
H: IsLeftModule R A

IsLeftModule R (abgroup_matrix A m n)
A: AbGroup
m, n: nat
R: Ring
H: IsLeftModule R A

IsLeftModule R (abgroup_vector A n)
A: AbGroup
m, n: nat
R: Ring
H: IsLeftModule R A

IsLeftModule R A
exact _. Defined. (** As a special case, we get the left module of matrices over a ring. *) Instance isleftmodule_abgroup_matrix (R : Ring) (m n : nat) : IsLeftModule R (abgroup_matrix R m n) := _. Definition matrix_lact {R : Ring} {m n : nat} (r : R) (M : Matrix R m n) : Matrix R m n := lact r M. (** ** Multiplication *) (** Matrix multiplication is defined such that the entry at row [i] and column [j] of the resulting matrix is the sum of the products of the corresponding entries from the [i]th row of the first matrix and the [j]th column of the second matrix. Matrices correspond to module homomorphisms between free modules of finite rank (think vector spaces), and matrix multiplication represents the composition of these homomorphisms. **)
R: Ring
m, n, k: nat
M: Matrix R m n
N: Matrix R n k

Matrix R m k
R: Ring
m, n, k: nat
M: Matrix R m n
N: Matrix R n k

Matrix R m k
R: Ring
m, n, k: nat
M: Matrix R m n
N: Matrix R n k

forall i j : nat, (i < m)%nat -> (j < k)%nat -> R
R: Ring
m, n, k: nat
M: Matrix R m n
N: Matrix R n k
i, j: nat
Hi: (i < m)%nat
Hj: (j < k)%nat

R
exact (ab_sum n (fun k Hk => entry M i k * entry N k j)). Defined. (** The identity matrix is the matrix with ones on the diagonal and zeros elsewhere. It acts as the multiplicative identity for matrix multiplication. We define it here using the [kronecker_delta] function which will make proving properties about it conceptually easier later. *) Definition identity_matrix (R : Ring@{i}) (n : nat) : Matrix R n n := Build_Matrix R n n (fun i j _ _ => kronecker_delta i j). (** This is the most general statement of associativity for matrix multiplication. *)
R: Ring
m, n, p, q: nat

HeteroAssociative matrix_mult matrix_mult matrix_mult matrix_mult
R: Ring
m, n, p, q: nat

HeteroAssociative matrix_mult matrix_mult matrix_mult matrix_mult
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

entry (matrix_mult M (matrix_mult N P)) i j = entry (matrix_mult (matrix_mult M N) P) i j
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry (matrix_mult N P) k j) = ab_sum p (fun (k : nat) (Hk : (k < p)%nat) => entry (matrix_mult M N) i k * entry P k j)
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

forall (k : nat) (Hk : (k < n)%nat), entry M i k * entry (matrix_mult N P) k j = ?Goal k Hk
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat
ab_sum n ?Goal = ab_sum p (fun (k : nat) (Hk : (k < p)%nat) => entry (matrix_mult M N) i k * entry P k j)
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

forall (k : nat) (Hk : (k < n)%nat), entry M i k * entry (matrix_mult N P) k j = ?Goal k Hk
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat
k: nat
Hk: (k < n)%nat

entry M i k * entry (matrix_mult N P) k j = ?Goal k Hk
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat
k: nat
Hk: (k < n)%nat

entry M i k * ab_sum p (fun (k0 : nat) (Hk0 : (k0 < p)%nat) => entry N k k0 * entry P k0 j) = ?Goal k Hk
apply rng_sum_dist_l.
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => ab_sum p (fun (k0 : nat) (Hk0 : (k0 < p)%nat) => entry M i k * (fun (k1 : nat) (Hk1 : (k1 < p)%nat) => entry N k k1 * entry P k1 j) k0 Hk0)) = ab_sum p (fun (k : nat) (Hk : (k < p)%nat) => entry (matrix_mult M N) i k * entry P k j)
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

ab_sum p (fun (j0 : nat) (Hj0 : (j0 < p)%nat) => ab_sum n (fun (i0 : nat) (Hi0 : (i0 < n)%nat) => entry M i i0 * (entry N i0 j0 * entry P j0 j))) = ab_sum p (fun (k : nat) (Hk : (k < p)%nat) => entry (matrix_mult M N) i k * entry P k j)
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

ab_sum p (fun (j0 : nat) (Hj0 : (j0 < p)%nat) => ab_sum n (fun (i0 : nat) (Hi0 : (i0 < n)%nat) => entry M i i0 * (entry N i0 j0 * entry P j0 j))) = ab_sum p ?Goal
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat
forall (k : nat) (Hk : (k < p)%nat), entry (matrix_mult M N) i k * entry P k j = ?Goal k Hk
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

ab_sum p (fun (j0 : nat) (Hj0 : (j0 < p)%nat) => ab_sum n (fun (i0 : nat) (Hi0 : (i0 < n)%nat) => entry M i i0 * (entry N i0 j0 * entry P j0 j))) = ab_sum p (fun (k : nat) (Hk : (k < p)%nat) => ab_sum n (fun (k0 : nat) (Hk0 : (k0 < n)%nat) => entry M i k0 * entry N k0 k) * entry P k j)
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat

forall (k : nat) (Hk : (k < p)%nat), ab_sum n (fun (i0 : nat) (Hi0 : (i0 < n)%nat) => entry M i i0 * (entry N i0 k * entry P k j)) = ab_sum n (fun (k0 : nat) (Hk0 : (k0 < n)%nat) => entry M i k0 * entry N k0 k) * entry P k j
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat
k: nat
Hk: (k < p)%nat

ab_sum n (fun (i0 : nat) (Hi0 : (i0 < n)%nat) => entry M i i0 * (entry N i0 k * entry P k j)) = ab_sum n (fun (k0 : nat) (Hk0 : (k0 < n)%nat) => entry M i k0 * entry N k0 k) * entry P k j
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat
k: nat
Hk: (k < p)%nat

ab_sum n (fun (i0 : nat) (Hi0 : (i0 < n)%nat) => entry M i i0 * (entry N i0 k * entry P k j)) = ab_sum n (fun (k0 : nat) (Hk0 : (k0 < n)%nat) => entry M i k0 * entry N k0 k * entry P k j)
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat
k: nat
Hk: (k < p)%nat

forall (k0 : nat) (Hk0 : (k0 < n)%nat), entry M i k0 * (entry N k0 k * entry P k j) = entry M i k0 * entry N k0 k * entry P k j
R: Ring
m, n, p, q: nat
M: Matrix R m n
N: Matrix R n p
P: Matrix R p q
i, j: nat
Hi: (i < m)%nat
Hj: (j < q)%nat
k: nat
Hk: (k < p)%nat
l: nat
Hl: (l < n)%nat

entry M i l * (entry N l k * entry P k j) = entry M i l * entry N l k * entry P k j
apply associativity. Defined. (** Matrix multiplication distributes over addition of matrices on the left. *)
R: Ring
m, n, p: nat

LeftHeteroDistribute matrix_mult matrix_plus matrix_plus
R: Ring
m, n, p: nat

LeftHeteroDistribute matrix_mult matrix_plus matrix_plus
R: Ring
m, n, p: nat
M: Matrix R m n
N, P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

entry (matrix_mult M (matrix_plus N P)) i j = entry (matrix_plus (matrix_mult M N) (matrix_mult M P)) i j
R: Ring
m, n, p: nat
M: Matrix R m n
N, P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry (matrix_plus N P) k j) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry N k j) + ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry P k j)
R: Ring
m, n, p: nat
M: Matrix R m n
N, P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry (matrix_plus N P) k j) = sg_op (ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry N k j)) (ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry P k j))
R: Ring
m, n, p: nat
M: Matrix R m n
N, P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry (matrix_plus N P) k j) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => sg_op (entry M i k * entry N k j) (entry M i k * entry P k j))
R: Ring
m, n, p: nat
M: Matrix R m n
N, P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

forall (k : nat) (Hk : (k < n)%nat), entry M i k * entry (matrix_plus N P) k j = sg_op (entry M i k * entry N k j) (entry M i k * entry P k j)
R: Ring
m, n, p: nat
M: Matrix R m n
N, P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat
k: nat
Hk: (k < n)%nat

entry M i k * entry (matrix_plus N P) k j = sg_op (entry M i k * entry N k j) (entry M i k * entry P k j)
R: Ring
m, n, p: nat
M: Matrix R m n
N, P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat
k: nat
Hk: (k < n)%nat

entry M i k * (Vector.entry (Vector.entry N k) j + Vector.entry (Vector.entry P k) j) = sg_op (entry M i k * entry N k j) (entry M i k * entry P k j)
apply rng_dist_l. Defined. (** Matrix multiplication distributes over addition of matrices on the right. *)
R: Ring
m, n, p: nat

RightHeteroDistribute matrix_mult matrix_plus matrix_plus
R: Ring
m, n, p: nat

RightHeteroDistribute matrix_mult matrix_plus matrix_plus
R: Ring
m, n, p: nat
M, N: Matrix R m n
P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

entry (matrix_mult (matrix_plus M N) P) i j = entry (matrix_plus (matrix_mult M P) (matrix_mult N P)) i j
R: Ring
m, n, p: nat
M, N: Matrix R m n
P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry (matrix_plus M N) i k * entry P k j) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry P k j) + ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry N i k * entry P k j)
R: Ring
m, n, p: nat
M, N: Matrix R m n
P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry (matrix_plus M N) i k * entry P k j) = sg_op (ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry P k j)) (ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry N i k * entry P k j))
R: Ring
m, n, p: nat
M, N: Matrix R m n
P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry (matrix_plus M N) i k * entry P k j) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => sg_op (entry M i k * entry P k j) (entry N i k * entry P k j))
R: Ring
m, n, p: nat
M, N: Matrix R m n
P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

forall (k : nat) (Hk : (k < n)%nat), entry (matrix_plus M N) i k * entry P k j = sg_op (entry M i k * entry P k j) (entry N i k * entry P k j)
R: Ring
m, n, p: nat
M, N: Matrix R m n
P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat
k: nat
Hk: (k < n)%nat

entry (matrix_plus M N) i k * entry P k j = sg_op (entry M i k * entry P k j) (entry N i k * entry P k j)
R: Ring
m, n, p: nat
M, N: Matrix R m n
P: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat
k: nat
Hk: (k < n)%nat

(Vector.entry (Vector.entry M i) k + Vector.entry (Vector.entry N i) k) * entry P k j = sg_op (entry M i k * entry P k j) (entry N i k * entry P k j)
apply rng_dist_r. Defined. (** The identity matrix acts as a left identity for matrix multiplication. *)
R: Ring
m, n: nat

LeftIdentity matrix_mult (identity_matrix R m)
R: Ring
m, n: nat

LeftIdentity matrix_mult (identity_matrix R m)
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

entry (matrix_mult (identity_matrix R m) M) i j = entry M i j
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

ab_sum m (fun (k : nat) (Hk : (k < m)%nat) => entry (identity_matrix R m) i k * entry M k j) = entry M i j
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

forall (k : nat) (Hk : (k < m)%nat), entry (identity_matrix R m) i k * entry M k j = ?Goal k Hk
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat
ab_sum m ?Goal = entry M i j
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

ab_sum m (fun (k : nat) (Hk : (k < m)%nat) => kronecker_delta i k * entry M k j) = entry M i j
napply rng_sum_kronecker_delta_l. Defined. (** The identity matrix acts as a right identity for matrix multiplication. *)
R: Ring
m, n: nat

RightIdentity matrix_mult (identity_matrix R n)
R: Ring
m, n: nat

RightIdentity matrix_mult (identity_matrix R n)
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

entry (matrix_mult M (identity_matrix R n)) i j = entry M i j
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry (identity_matrix R n) k j) = entry M i j
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

forall (k : nat) (Hk : (k < n)%nat), entry M i k * entry (identity_matrix R n) k j = ?Goal k Hk
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat
ab_sum n ?Goal = entry M i j
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * kronecker_delta k j) = entry M i j
napply rng_sum_kronecker_delta_r'. Defined. (** TODO: define this as an R-algebra. What is an R-algebra over a non-commutative right however? (Here we have a bimodule which might be important) *) (** Matrices over a ring form a (generally) non-commutative ring. *)
R: Ring
n: nat

Ring
R: Ring
n: nat

Ring
R: Ring
n: nat

AbGroup
R: Ring
n: nat
Mult ?R
R: Ring
n: nat
One ?R
R: Ring
n: nat
Associative mult
R: Ring
n: nat
LeftDistribute mult plus
R: Ring
n: nat
RightDistribute mult plus
R: Ring
n: nat
LeftIdentity mult 1
R: Ring
n: nat
RightIdentity mult 1
R: Ring
n: nat

AbGroup
exact (abgroup_matrix R n n).
R: Ring
n: nat

Mult (abgroup_matrix R n n)
exact matrix_mult.
R: Ring
n: nat

One (abgroup_matrix R n n)
exact (identity_matrix R n).
R: Ring
n: nat

Associative mult
exact (associative_matrix_mult R n n n n).
R: Ring
n: nat

LeftDistribute mult plus
exact (left_distribute_matrix_mult R n n n).
R: Ring
n: nat

RightDistribute mult plus
exact (right_distribute_matrix_mult R n n n).
R: Ring
n: nat

LeftIdentity mult 1
exact (left_identity_matrix_mult R n n).
R: Ring
n: nat

RightIdentity mult 1
exact (right_identity_matrix_mult R n n). Defined. (** Matrix multiplication on the right preserves scalar multiplication in the sense that [matrix_lact r (matrix_mult M N) = matrix_mult (matrix_lact r M) N] for [r] a ring element and [M] and [N] matrices of compatible sizes. *)
R: Ring
m, n, p: nat

HeteroAssociative matrix_lact matrix_mult matrix_mult matrix_lact
R: Ring
m, n, p: nat

HeteroAssociative matrix_lact matrix_mult matrix_mult matrix_lact
R: Ring
m, n, p: nat
r: R
M: Matrix R m n
N: Matrix R n p

matrix_lact r (matrix_mult M N) = matrix_mult (matrix_lact r M) N
R: Ring
m, n, p: nat
r: R
M: Matrix R m n
N: Matrix R n p

forall (i j : nat) (Hi : (i < m)%nat) (Hj : (j < p)%nat), entry (matrix_lact r (matrix_mult M N)) i j = entry (matrix_mult (matrix_lact r M) N) i j
R: Ring
m, n, p: nat
r: R
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

entry (matrix_lact r (matrix_mult M N)) i j = entry (matrix_mult (matrix_lact r M) N) i j
R: Ring
m, n, p: nat
r: R
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

lact r (ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry N k j)) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry (matrix_lact r M) i k * entry N k j)
R: Ring
m, n, p: nat
r: R
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => r * (entry M i k * entry N k j)) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry (matrix_lact r M) i k * entry N k j)
R: Ring
m, n, p: nat
r: R
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

forall (k : nat) (Hk : (k < n)%nat), (fun (k0 : nat) (Hk0 : (k0 < n)%nat) => r * (entry M i k0 * entry N k0 j)) k Hk = (fun (k0 : nat) (Hk0 : (k0 < n)%nat) => entry (matrix_lact r M) i k0 * entry N k0 j) k Hk
R: Ring
m, n, p: nat
r: R
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat
k: nat
Hk: (k < n)%nat

r * (entry M i k * entry N k j) = entry (vector_lact r M) i k * entry N k j
R: Ring
m, n, p: nat
r: R
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat
k: nat
Hk: (k < n)%nat

r * (entry M i k * entry N k j) = lact r (Vector.entry (Vector.entry M i) k) * entry N k j
snapply rng_mult_assoc. Defined. (** The same doesn't hold for the right matrix, since the ring is not commutative. However we could say an analagous statement for the right action. We haven't yet stated a definition of right module yet though. *) (** In a commutative ring, matrix multiplication over the ring and the opposite ring agree. *)
R: CRing
m, n, p: nat
M: Matrix R m n
N: Matrix R n p

matrix_mult M N = matrix_mult M N
R: CRing
m, n, p: nat
M: Matrix R m n
N: Matrix R n p

matrix_mult M N = matrix_mult M N
R: CRing
m, n, p: nat
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

entry (matrix_mult M N) i j = entry (matrix_mult M N) i j
R: CRing
m, n, p: nat
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry N k j) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry N k j)
R: CRing
m, n, p: nat
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < m)%nat
Hj: (j < p)%nat
k: nat
Hk: (k < n)%nat

entry M i k * entry N k j = entry M i k * entry N k j
apply rng_mult_comm. Defined. (** ** Transpose *) (** The transpose of a matrix is the matrix with the rows and columns swapped. *) Definition matrix_transpose {R : Type} {m n} : Matrix R m n -> Matrix R n m := fun M => Build_Matrix R n m (fun i j H1 H2 => entry M j i). (** Transposing a matrix is involutive. *)
R: Type
m, n: nat
M: Matrix R m n

matrix_transpose (matrix_transpose M) = M
R: Type
m, n: nat
M: Matrix R m n

matrix_transpose (matrix_transpose M) = M
R: Type
m, n: nat
M: Matrix R m n

forall (i j : nat) (Hi : (i < m)%nat) (Hj : (j < n)%nat), entry (matrix_transpose (matrix_transpose M)) i j = entry M i j
R: Type
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

entry (matrix_transpose (matrix_transpose M)) i j = entry M i j
R: Type
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < m)%nat
Hj: (j < n)%nat

entry (matrix_transpose M) j i = entry M i j
napply entry_Build_Matrix. Defined. (** Transpose distributes over addition. *)
R: Ring
m, n: nat
M, N: Matrix R m n

matrix_transpose (matrix_plus M N) = matrix_plus (matrix_transpose M) (matrix_transpose N)
R: Ring
m, n: nat
M, N: Matrix R m n

matrix_transpose (matrix_plus M N) = matrix_plus (matrix_transpose M) (matrix_transpose N)
R: Ring
m, n: nat
M, N: Matrix R m n

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < m)%nat), entry (matrix_transpose (matrix_plus M N)) i j = entry (matrix_plus (matrix_transpose M) (matrix_transpose N)) i j
R: Ring
m, n: nat
M, N: Matrix R m n
i, j: nat
Hi: (i < n)%nat
Hj: (j < m)%nat

entry (matrix_transpose (matrix_plus M N)) i j = entry (matrix_plus (matrix_transpose M) (matrix_transpose N)) i j
by rewrite !entry_Build_Matrix, !entry_Build_Vector. Defined. (** Transpose commutes with scalar multiplication. *)
R: Ring
m, n: nat
r: R
M: Matrix R m n

matrix_transpose (matrix_lact r M) = matrix_lact r (matrix_transpose M)
R: Ring
m, n: nat
r: R
M: Matrix R m n

matrix_transpose (matrix_lact r M) = matrix_lact r (matrix_transpose M)
R: Ring
m, n: nat
r: R
M: Matrix R m n

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < m)%nat), entry (matrix_transpose (matrix_lact r M)) i j = entry (matrix_lact r (matrix_transpose M)) i j
R: Ring
m, n: nat
r: R
M: Matrix R m n
i, j: nat
Hi: (i < n)%nat
Hj: (j < m)%nat

entry (matrix_transpose (matrix_lact r M)) i j = entry (matrix_lact r (matrix_transpose M)) i j
by rewrite !entry_Build_Matrix, !entry_Build_Vector. Defined. (** The negation of a transposed matrix is the same as the transposed matrix of the negation. *)
R: Ring
m, n: nat
M: Matrix R m n

matrix_transpose (matrix_negate M) = matrix_negate (matrix_transpose M)
R: Ring
m, n: nat
M: Matrix R m n

matrix_transpose (matrix_negate M) = matrix_negate (matrix_transpose M)
R: Ring
m, n: nat
M: Matrix R m n

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < m)%nat), entry (matrix_transpose (matrix_negate M)) i j = entry (matrix_negate (matrix_transpose M)) i j
R: Ring
m, n: nat
M: Matrix R m n
i, j: nat
Hi: (i < n)%nat
Hj: (j < m)%nat

entry (matrix_transpose (matrix_negate M)) i j = entry (matrix_negate (matrix_transpose M)) i j
by rewrite !entry_Build_Matrix, !entry_Build_Vector. Defined. (** Transpose distributes over multiplication when you reverse the ring multiplication. *)
R: Ring
m, n, p: nat
M: Matrix R m n
N: Matrix R n p

matrix_transpose (matrix_mult M N) = matrix_mult (matrix_transpose N) (matrix_transpose M)
R: Ring
m, n, p: nat
M: Matrix R m n
N: Matrix R n p

matrix_transpose (matrix_mult M N) = matrix_mult (matrix_transpose N) (matrix_transpose M)
R: Ring
m, n, p: nat
M: Matrix R m n
N: Matrix R n p

forall (i j : nat) (Hi : (i < p)%nat) (Hj : (j < m)%nat), entry (matrix_transpose (matrix_mult M N)) i j = entry (matrix_mult (matrix_transpose N) (matrix_transpose M)) i j
R: Ring
m, n, p: nat
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < p)%nat
Hj: (j < m)%nat

entry (matrix_transpose (matrix_mult M N)) i j = entry (matrix_mult (matrix_transpose N) (matrix_transpose M)) i j
R: Ring
m, n, p: nat
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < p)%nat
Hj: (j < m)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M j k * entry N k i) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry (matrix_transpose N) i k * entry (matrix_transpose M) k j)
R: Ring
m, n, p: nat
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < p)%nat
Hj: (j < m)%nat

forall (k : nat) (Hk : (k < n)%nat), entry M j k * entry N k i = entry (matrix_transpose N) i k * entry (matrix_transpose M) k j
R: Ring
m, n, p: nat
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < p)%nat
Hj: (j < m)%nat
k: nat
Hk: (k < n)%nat

entry M j k * entry N k i = entry (matrix_transpose N) i k * entry (matrix_transpose M) k j
R: Ring
m, n, p: nat
M: Matrix R m n
N: Matrix R n p
i, j: nat
Hi: (i < p)%nat
Hj: (j < m)%nat
k: nat
Hk: (k < n)%nat

entry M j k * entry N k i = entry N k i * entry M j k
reflexivity. Defined. (** When the ring is commutative, there is no need to reverse the multiplication. *)
R: CRing
m, n, p: nat
M: Matrix R m n
N: Matrix R n p

matrix_transpose (matrix_mult M N) = matrix_mult (matrix_transpose N) (matrix_transpose M)
R: CRing
m, n, p: nat
M: Matrix R m n
N: Matrix R n p

matrix_transpose (matrix_mult M N) = matrix_mult (matrix_transpose N) (matrix_transpose M)
R: CRing
m, n, p: nat
M: Matrix R m n
N: Matrix R n p

matrix_mult (matrix_transpose N) (matrix_transpose M) = matrix_mult (matrix_transpose N) (matrix_transpose M)
apply matrix_mult_rng_op. Defined. (** The transpose of the zero matrix is the zero matrix. *)
R: Ring
m, n: nat

matrix_transpose (matrix_zero R m n) = matrix_zero R n m
R: Ring
m, n: nat

matrix_transpose (matrix_zero R m n) = matrix_zero R n m
R: Ring
m, n: nat

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < m)%nat), entry (matrix_transpose (matrix_zero R m n)) i j = entry (matrix_zero R n m) i j
R: Ring
m, n, i, j: nat
Hi: (i < n)%nat
Hj: (j < m)%nat

entry (matrix_transpose (matrix_zero R m n)) i j = entry (matrix_zero R n m) i j
by rewrite !entry_Build_Matrix. Defined. (** The transpose of the identity matrix is the identity matrix. *)
R: Ring
n: nat

matrix_transpose (identity_matrix R n) = identity_matrix R n
R: Ring
n: nat

matrix_transpose (identity_matrix R n) = identity_matrix R n
R: Ring
n: nat

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), entry (matrix_transpose (identity_matrix R n)) i j = entry (identity_matrix R n) i j
R: Ring
n, i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry (matrix_transpose (identity_matrix R n)) i j = entry (identity_matrix R n) i j
R: Ring
n, i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

kronecker_delta j i = kronecker_delta i j
apply kronecker_delta_symm. Defined. (** ** Diagonal matrices *) (** A diagonal matrix is a matrix with zeros everywhere except on the diagonal. Its entries are given by a vector. *)
R: Ring
n: nat
v: Vector R n

Matrix R n n
R: Ring
n: nat
v: Vector R n

Matrix R n n
R: Ring
n: nat
v: Vector R n

forall i j : nat, (i < n)%nat -> (j < n)%nat -> R
R: Ring
n: nat
v: Vector R n
i, j: nat
H1: (i < n)%nat
H2: (j < n)%nat

R
exact (kronecker_delta i j * Vector.entry v i). Defined. (** Addition of diagonal matrices is the same as addition of the corresponding vectors. *)
R: Ring
n: nat
v, w: Vector R n

matrix_plus (matrix_diag v) (matrix_diag w) = matrix_diag (vector_plus v w)
R: Ring
n: nat
v, w: Vector R n

matrix_plus (matrix_diag v) (matrix_diag w) = matrix_diag (vector_plus v w)
R: Ring
n: nat
v, w: Vector R n

matrix_diag (vector_plus v w) = matrix_plus (matrix_diag v) (matrix_diag w)
R: Ring
n: nat
v, w: Vector R n

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), entry (matrix_diag (vector_plus v w)) i j = entry (matrix_plus (matrix_diag v) (matrix_diag w)) i j
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry (matrix_diag (vector_plus v w)) i j = entry (matrix_plus (matrix_diag v) (matrix_diag w)) i j
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

kronecker_delta i j * (Vector.entry v i + Vector.entry w i) = kronecker_delta i j * Vector.entry v i + kronecker_delta i j * Vector.entry w i
napply rng_dist_l. Defined. (** Matrix multiplication of diagonal matrices is the same as multiplying the corresponding vectors pointwise. *)
R: Ring
n: nat
v, w: Vector R n

matrix_mult (matrix_diag v) (matrix_diag w) = matrix_diag (vector_map2 mult v w)
R: Ring
n: nat
v, w: Vector R n

matrix_mult (matrix_diag v) (matrix_diag w) = matrix_diag (vector_map2 mult v w)
R: Ring
n: nat
v, w: Vector R n

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), entry (matrix_mult (matrix_diag v) (matrix_diag w)) i j = entry (matrix_diag (vector_map2 mult v w)) i j
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry (matrix_mult (matrix_diag v) (matrix_diag w)) i j = entry (matrix_diag (vector_map2 mult v w)) i j
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry (matrix_diag v) i k * entry (matrix_diag w) k j) = kronecker_delta i j * Vector.entry (vector_map2 mult v w) i
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

forall (k : nat) (Hk : (k < n)%nat), entry (matrix_diag v) i k * entry (matrix_diag w) k j = ?Goal0 k Hk
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
ab_sum n ?Goal0 = kronecker_delta i j * Vector.entry (vector_map2 mult v w) i
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

forall (k : nat) (Hk : (k < n)%nat), entry (matrix_diag v) i k * entry (matrix_diag w) k j = ?Goal0 k Hk
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
k: nat
Hk: (k < n)%nat

entry (matrix_diag v) i k * entry (matrix_diag w) k j = ?Goal k Hk
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
k: nat
Hk: (k < n)%nat

kronecker_delta i k * Vector.entry v i * (kronecker_delta k j * Vector.entry w k) = ?Goal k Hk
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
k: nat
Hk: (k < n)%nat

kronecker_delta i k * Vector.entry v i * kronecker_delta k j * Vector.entry w k = ?Goal k Hk
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
k: nat
Hk: (k < n)%nat

kronecker_delta i k * (Vector.entry v i * kronecker_delta k j) * Vector.entry w k = ?Goal k Hk
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
k: nat
Hk: (k < n)%nat

kronecker_delta i k * (kronecker_delta k j * Vector.entry v i) * Vector.entry w k = ?Goal k Hk
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
k: nat
Hk: (k < n)%nat

kronecker_delta i k * (kronecker_delta k j * (Vector.entry v i * Vector.entry w k)) = ?Goal k Hk
reflexivity.
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => kronecker_delta i k * (kronecker_delta k j * (Vector.entry v i * Vector.entry w k))) = kronecker_delta i j * Vector.entry (vector_map2 mult v w) i
R: Ring
n: nat
v, w: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

kronecker_delta i j * (Vector.entry v i * Vector.entry w i) = kronecker_delta i j * Vector.entry (vector_map2 mult v w) i
by rewrite entry_Build_Vector. Defined. (** The transpose of a diagonal matrix is the same diagonal matrix. *)
R: Ring
n: nat
v: Vector R n

matrix_transpose (matrix_diag v) = matrix_diag v
R: Ring
n: nat
v: Vector R n

matrix_transpose (matrix_diag v) = matrix_diag v
R: Ring
n: nat
v: Vector R n

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), entry (matrix_transpose (matrix_diag v)) i j = entry (matrix_diag v) i j
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry (matrix_transpose (matrix_diag v)) i j = entry (matrix_diag v) i j
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

kronecker_delta j i * Vector.entry v j = kronecker_delta i j * Vector.entry v i
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

kronecker_delta i j * Vector.entry v j = kronecker_delta i j * Vector.entry v i
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

(if dec (i = j) then 1 else 0) * Vector.entry v j = (if dec (i = j) then 1 else 0) * Vector.entry v i
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
p: i = j

1 * Vector.entry v j = 1 * Vector.entry v i
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
np: i <> j
0 * Vector.entry v j = 0 * Vector.entry v i
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
np: i <> j

0 * Vector.entry v j = 0 * Vector.entry v i
by rewrite !rng_mult_zero_l. Defined. (** The diagonal matrix construction is injective. *)
R: Ring
n: nat

IsInjective matrix_diag
R: Ring
n: nat

IsInjective matrix_diag
R: Ring
n: nat
v1, v2: Vector R n
p: matrix_diag v1 = matrix_diag v2

v1 = v2
R: Ring
n: nat
v1, v2: Vector R n
p: matrix_diag v1 = matrix_diag v2

forall (i : nat) (H : (i < n)%nat), Vector.entry v1 i = Vector.entry v2 i
R: Ring
n: nat
v1, v2: Vector R n
p: matrix_diag v1 = matrix_diag v2
i: nat
Hi: (i < n)%nat

Vector.entry v1 i = Vector.entry v2 i
R: Ring
n: nat
v1, v2: Vector R n
i: nat
Hi: (i < n)%nat
p: entry (matrix_diag v1) i i = entry (matrix_diag v2) i i

Vector.entry v1 i = Vector.entry v2 i
R: Ring
n: nat
v1, v2: Vector R n
i: nat
Hi: (i < n)%nat
p: kronecker_delta i i * Vector.entry v1 i = kronecker_delta i i * Vector.entry v2 i

Vector.entry v1 i = Vector.entry v2 i
R: Ring
n: nat
v1, v2: Vector R n
i: nat
Hi: (i < n)%nat
p: 1 * Vector.entry v1 i = 1 * Vector.entry v2 i

Vector.entry v1 i = Vector.entry v2 i
by rewrite 2 rng_mult_one_l in p. Defined. (** A matrix is diagonal if it is equal to a diagonal matrix. *) Class IsDiagonal@{i} {R : Ring@{i}} {n : nat} (M : Matrix R n n) : Type@{i} := { isdiagonal_diag_vector : Vector R n; isdiagonal_diag : M = matrix_diag isdiagonal_diag_vector; }. Arguments isdiagonal_diag_vector {R n} M {_}. Arguments isdiagonal_diag {R n} M {_}. Definition issig_IsDiagonal {R : Ring@{i}} {n : nat} {M : Matrix R n n} : _ <~> IsDiagonal M := ltac:(issig). (** A matrix is diagonal in a unique way. *)
R: Ring
n: nat
M: Matrix R n n

IsHProp (IsDiagonal M)
R: Ring
n: nat
M: Matrix R n n

IsHProp (IsDiagonal M)
R: Ring
n: nat
M: Matrix R n n

forall x y : IsDiagonal M, x = y
R: Ring
n: nat
M: Matrix R n n
x, y: IsDiagonal M

x = y
R: Ring
n: nat
M: Matrix R n n
x, y: IsDiagonal M

issig_IsDiagonal^-1%equiv x = issig_IsDiagonal^-1%equiv y
R: Ring
n: nat
M: Matrix R n n
x, y: IsDiagonal M

isdiagonal_diag_vector M = isdiagonal_diag_vector M
R: Ring
n: nat
M: Matrix R n n
x, y: IsDiagonal M

matrix_diag (isdiagonal_diag_vector M) = matrix_diag (isdiagonal_diag_vector M)
exact ((isdiagonal_diag M)^ @ isdiagonal_diag M). Defined. (** The zero matrix is diagonal. *)
R: Ring
n: nat

IsDiagonal (matrix_zero R n n)
R: Ring
n: nat

IsDiagonal (matrix_zero R n n)
R: Ring
n: nat

matrix_zero R n n = matrix_diag (vector_zero R n)
R: Ring
n: nat

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), entry (matrix_zero R n n) i j = entry (matrix_diag (vector_zero R n)) i j
R: Ring
n, i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry (matrix_zero R n n) i j = entry (matrix_diag (vector_zero R n)) i j
R: Ring
n, i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

0 = kronecker_delta i j * 0
by rewrite rng_mult_zero_r. Defined. (** The identity matrix is diagonal. *)
R: Ring
n: nat

IsDiagonal (identity_matrix R n)
R: Ring
n: nat

IsDiagonal (identity_matrix R n)
R: Ring
n: nat

identity_matrix R n = matrix_diag (Build_Vector R n (fun (i : nat) (_ : (i < n)%nat) => 1))
R: Ring
n: nat

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), entry (identity_matrix R n) i j = entry (matrix_diag (Build_Vector R n (fun (i0 : nat) (_ : (i0 < n)%nat) => 1))) i j
R: Ring
n, i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry (identity_matrix R n) i j = entry (matrix_diag (Build_Vector R n (fun (i : nat) (_ : (i < n)%nat) => 1))) i j
R: Ring
n, i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

kronecker_delta i j = kronecker_delta i j * 1
by rewrite rng_mult_one_r. Defined. (** The sum of two diagonal matrices is diagonal. *)
R: Ring
n: nat
M, N: Matrix R n n
H: IsDiagonal M
H0: IsDiagonal N

IsDiagonal (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
H: IsDiagonal M
H0: IsDiagonal N

IsDiagonal (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
H: IsDiagonal M
H0: IsDiagonal N

matrix_plus M N = matrix_diag (vector_plus (isdiagonal_diag_vector M) (isdiagonal_diag_vector N))
R: Ring
n: nat
M, N: Matrix R n n
H: IsDiagonal M
H0: IsDiagonal N

matrix_plus (matrix_diag (isdiagonal_diag_vector M)) (matrix_diag (isdiagonal_diag_vector N)) = matrix_diag (vector_plus (isdiagonal_diag_vector M) (isdiagonal_diag_vector N))
apply matrix_diag_plus. Defined. (** The negative of a diagonal matrix is diagonal. *)
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

IsDiagonal (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

IsDiagonal (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

matrix_negate M = matrix_diag (vector_neg R n (isdiagonal_diag_vector M))
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

matrix_negate (matrix_diag (isdiagonal_diag_vector M)) = matrix_diag (vector_neg R n (isdiagonal_diag_vector M))
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), entry (matrix_negate (matrix_diag (isdiagonal_diag_vector M))) i j = entry (matrix_diag (vector_neg R n (isdiagonal_diag_vector M))) i j
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry (matrix_negate (matrix_diag (isdiagonal_diag_vector M))) i j = entry (matrix_diag (vector_neg R n (isdiagonal_diag_vector M))) i j
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

- (kronecker_delta i j * Vector.entry (isdiagonal_diag_vector M) i) = kronecker_delta i j * - Vector.entry (isdiagonal_diag_vector M) i
by rewrite rng_mult_negate_r. Defined. (** The product of two diagonal matrices is diagonal. *)
R: Ring
n: nat
M, N: Matrix R n n
H: IsDiagonal M
H0: IsDiagonal N

IsDiagonal (matrix_mult M N)
R: Ring
n: nat
M, N: Matrix R n n
H: IsDiagonal M
H0: IsDiagonal N

IsDiagonal (matrix_mult M N)
R: Ring
n: nat
M, N: Matrix R n n
H: IsDiagonal M
H0: IsDiagonal N

matrix_mult M N = matrix_diag (vector_map2 mult (isdiagonal_diag_vector M) (isdiagonal_diag_vector N))
R: Ring
n: nat
M, N: Matrix R n n
H: IsDiagonal M
H0: IsDiagonal N

matrix_mult (matrix_diag (isdiagonal_diag_vector M)) (matrix_diag (isdiagonal_diag_vector N)) = matrix_diag (vector_map2 mult (isdiagonal_diag_vector M) (isdiagonal_diag_vector N))
apply matrix_diag_mult. Defined. (** The transpose of a diagonal matrix is diagonal. *)
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

IsDiagonal (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

IsDiagonal (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

matrix_transpose M = matrix_diag (isdiagonal_diag_vector M)
R: Ring
n: nat
M: Matrix R n n
H: IsDiagonal M

matrix_transpose (matrix_diag (isdiagonal_diag_vector M)) = matrix_diag (isdiagonal_diag_vector M)
apply matrix_transpose_diag. Defined. (** Given a square matrix, we can extract the diagonal as a vector. *) Definition matrix_diag_vector {R : Ring} {n : nat} (M : Matrix R n n) : Vector R n := Build_Vector R n (fun i _ => entry M i i). (** Diagonal matrices form a subring of the ring of square matrices. *)
R: Ring
n: nat

Subring (matrix_ring R n)
R: Ring
n: nat

Subring (matrix_ring R n)
R: Ring
n: nat

forall x : matrix_ring R n, IsHProp (IsDiagonal x)
R: Ring
n: nat
forall x y : matrix_ring R n, IsDiagonal x -> IsDiagonal y -> IsDiagonal (x - y)
R: Ring
n: nat
forall x y : matrix_ring R n, IsDiagonal x -> IsDiagonal y -> IsDiagonal (x * y)
R: Ring
n: nat
IsDiagonal 1
R: Ring
n: nat

forall x : matrix_ring R n, IsHProp (IsDiagonal x)
intros; exact _.
R: Ring
n: nat

forall x y : matrix_ring R n, IsDiagonal x -> IsDiagonal y -> IsDiagonal (x - y)
R: Ring
n: nat
x, y: matrix_ring R n
dx: IsDiagonal x
dy: IsDiagonal y

IsDiagonal (x - y)
R: Ring
n: nat
x, y: matrix_ring R n
dx: IsDiagonal x
dy: IsDiagonal y

IsDiagonal (- y)
by napply isdiagonal_matrix_negate.
R: Ring
n: nat

forall x y : matrix_ring R n, IsDiagonal x -> IsDiagonal y -> IsDiagonal (x * y)
napply isdiagonal_matrix_mult.
R: Ring
n: nat

IsDiagonal 1
napply isdiagonal_identity_matrix. Defined. (** ** Trace *) (** The trace of a square matrix is the sum of the diagonal entries. *) Definition matrix_trace {R : Ring} {n} (M : Matrix R n n) : R := ab_sum n (fun i Hi => entry M i i). (** The trace of a matrix preserves addition. *)
R: Ring
n: nat
M, N: Matrix R n n

matrix_trace (matrix_plus M N) = matrix_trace M + matrix_trace N
R: Ring
n: nat
M, N: Matrix R n n

matrix_trace (matrix_plus M N) = matrix_trace M + matrix_trace N
R: Ring
n: nat
M, N: Matrix R n n

ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry (matrix_plus M N) i i) = ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry M i i) + ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry N i i)
R: Ring
n: nat
M, N: Matrix R n n

forall (k : nat) (Hk : (k < n)%nat), entry (matrix_plus M N) k k = ?Goal k Hk
R: Ring
n: nat
M, N: Matrix R n n
ab_sum n ?Goal = ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry M i i) + ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry N i i)
R: Ring
n: nat
M, N: Matrix R n n

forall (k : nat) (Hk : (k < n)%nat), entry (matrix_plus M N) k k = ?Goal k Hk
R: Ring
n: nat
M, N: Matrix R n n
i: nat
Hi: (i < n)%nat

entry (matrix_plus M N) i i = ?Goal i Hi
by rewrite entry_Build_Matrix.
R: Ring
n: nat
M, N: Matrix R n n

ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => Vector.entry (Vector.entry M i) i + Vector.entry (Vector.entry N i) i) = ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry M i i) + ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry N i i)
by rewrite ab_sum_plus. Defined. (** The trace of a matrix preserves scalar multiplication. *)
R: Ring
n: nat
r: R
M: Matrix R n n

matrix_trace (matrix_lact r M) = r * matrix_trace M
R: Ring
n: nat
r: R
M: Matrix R n n

matrix_trace (matrix_lact r M) = r * matrix_trace M
R: Ring
n: nat
r: R
M: Matrix R n n

ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry (matrix_lact r M) i i) = r * ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry M i i)
R: Ring
n: nat
r: R
M: Matrix R n n

ab_sum n (fun (i : nat) (Hi : (i < n)%nat) => entry (matrix_lact r M) i i) = ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => r * entry M k k)
R: Ring
n: nat
r: R
M: Matrix R n n

forall (k : nat) (Hk : (k < n)%nat), entry (matrix_lact r M) k k = r * entry M k k
R: Ring
n: nat
r: R
M: Matrix R n n
i: nat
Hi: (i < n)%nat

entry (matrix_lact r M) i i = r * entry M i i
by rewrite entry_Build_Matrix. Defined. (** The trace of a matrix multiplication is the same as the trace of the reverse multiplication. This holds only in a commutative ring. *)
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m

matrix_trace (matrix_mult M N) = matrix_trace (matrix_mult N M)
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m

matrix_trace (matrix_mult M N) = matrix_trace (matrix_mult N M)
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m

forall (k : nat) (Hk : (k < m)%nat), entry (matrix_mult M N) k k = ?Goal k Hk
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m
ab_sum m ?Goal = matrix_trace (matrix_mult N M)
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m

forall (k : nat) (Hk : (k < m)%nat), entry (matrix_mult M N) k k = ?Goal k Hk
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m
i: nat
Hi: (i < m)%nat

entry (matrix_mult M N) i i = ?Goal i Hi
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m
i: nat
Hi: (i < m)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry N k i) = ?Goal i Hi
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m
i: nat
Hi: (i < m)%nat

forall (k : nat) (Hk : (k < n)%nat), entry M i k * entry N k i = ?Goal0 k Hk
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m
i: nat
Hi: (i < m)%nat
j: nat
Hj: (j < n)%nat

entry M i j * entry N j i = ?Goal0 j Hj
apply rng_mult_comm.
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m

ab_sum m (fun (i : nat) (Hi : (i < m)%nat) => ab_sum n (fun (j : nat) (Hj : (j < n)%nat) => entry N j i * entry M i j)) = matrix_trace (matrix_mult N M)
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m

ab_sum n (fun (j : nat) (Hj : (j < n)%nat) => ab_sum m (fun (i : nat) (Hi : (i < m)%nat) => entry N j i * entry M i j)) = matrix_trace (matrix_mult N M)
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m

forall (k : nat) (Hk : (k < n)%nat), ab_sum m (fun (i : nat) (Hi : (i < m)%nat) => entry N k i * entry M i k) = entry (matrix_mult N M) k k
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m
i: nat
Hi: (i < n)%nat

ab_sum m (fun (i0 : nat) (Hi0 : (i0 < m)%nat) => entry N i i0 * entry M i0 i) = entry (matrix_mult N M) i i
R: CRing
m, n: nat
M: Matrix R m n
N: Matrix R n m
i: nat
Hi: (i < n)%nat

ab_sum m (fun (i0 : nat) (Hi0 : (i0 < m)%nat) => entry N i i0 * entry M i0 i) = ab_sum m (fun (k : nat) (Hk : (k < m)%nat) => entry N i k * entry M k i)
reflexivity. Defined. (** The trace of the transpose of a matrix is the same as the trace of the matrix. *)
R: Ring
n: nat
M: Matrix R n n

matrix_trace (matrix_transpose M) = matrix_trace M
R: Ring
n: nat
M: Matrix R n n

matrix_trace (matrix_transpose M) = matrix_trace M
R: Ring
n: nat
M: Matrix R n n

forall (k : nat) (Hk : (k < n)%nat), entry (matrix_transpose M) k k = entry M k k
R: Ring
n: nat
M: Matrix R n n
i: nat
Hi: (i < n)%nat

entry (matrix_transpose M) i i = entry M i i
napply entry_Build_Matrix. Defined. (** ** Matrix minors *) Definition skip (n : nat) : nat -> nat := fun i => if dec (i < n)%nat then i else i.+1%nat.
n: nat

IsInjective (skip n)
n: nat

IsInjective (skip n)
n: nat

forall x y : nat, skip n x = skip n y -> x = y
n, x, y: nat
p: skip n x = skip n y

x = y
n, x, y: nat
p: (if dec (x < n)%nat then x else x.+1%nat) = (if dec (y < n)%nat then y else y.+1%nat)

x = y
n, x, y: nat
H: (x < n)%nat
H': (y < n)%nat
p: x = y

x = y
n, x, y: nat
H: (x < n)%nat
H': ~ (y < n)%nat
p: x = y.+1%nat
x = y
n, x, y: nat
H: ~ (x < n)%nat
H': (y < n)%nat
p: x.+1%nat = y
x = y
n, x, y: nat
H: ~ (x < n)%nat
H': ~ (y < n)%nat
p: x.+1%nat = y.+1%nat
x = y
n, x, y: nat
H: (x < n)%nat
H': (y < n)%nat
p: x = y

x = y
exact p.
n, x, y: nat
H: (x < n)%nat
H': ~ (y < n)%nat
p: x = y.+1%nat

x = y
n, y: nat
H: (y.+1 < n)%nat
H': ~ (y < n)%nat

y.+1%nat = y
contradiction (H' (leq_trans _ H)).
n, x, y: nat
H: ~ (x < n)%nat
H': (y < n)%nat
p: x.+1%nat = y

x = y
n, x: nat
H: ~ (x < n)%nat
H': (x.+1 < n)%nat

x = x.+1%nat
contradiction (H (leq_trans _ H')).
n, x, y: nat
H: ~ (x < n)%nat
H': ~ (y < n)%nat
p: x.+1%nat = y.+1%nat

x = y
by apply path_nat_succ. Defined.
k, i, n: nat
H: (i < n.+1)%nat
H': (k < n)%nat

(skip i k < n.+1)%nat
k, i, n: nat
H: (i < n.+1)%nat
H': (k < n)%nat

(skip i k < n.+1)%nat
k, i, n: nat
H: (i < n.+1)%nat
H': (k < n)%nat

((if dec (k < i) then k else k.+1) < n.+1)%nat
destruct (dec (k < i))%nat as [H''|H'']; exact _. Defined. Definition matrix_minor {R : Ring@{i}} {n : nat} (i j : nat) {Hi : (i < n.+1)%nat} {Hj : (j < n.+1)%nat} (M : Matrix R n.+1 n.+1) : Matrix R n n := Build_Matrix R n n (fun k l _ _ => entry M (skip i k) (skip j l)). (** A minor of the zero matrix is again the zero matrix. *)
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat

matrix_minor i j (matrix_zero R n.+1 n.+1) = matrix_zero R n n
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat

matrix_minor i j (matrix_zero R n.+1 n.+1) = matrix_zero R n n
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat

forall (i0 j0 : nat) (Hi0 : (i0 < n)%nat) (Hj0 : (j0 < n)%nat), entry (matrix_minor i j (matrix_zero R n.+1 n.+1)) i0 j0 = entry (matrix_zero R n n) i0 j0
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
k, l: nat
Hk: (k < n)%nat
Hl: (l < n)%nat

entry (matrix_minor i j (matrix_zero R n.+1 n.+1)) k l = entry (matrix_zero R n n) k l
by rewrite !entry_Build_Matrix. Defined.
R: Ring
n, i: nat
Hi: (i < n.+1)%nat

matrix_minor i i (identity_matrix R n.+1) = identity_matrix R n
R: Ring
n, i: nat
Hi: (i < n.+1)%nat

matrix_minor i i (identity_matrix R n.+1) = identity_matrix R n
R: Ring
n, i: nat
Hi: (i < n.+1)%nat

forall (i0 j : nat) (Hi0 : (i0 < n)%nat) (Hj : (j < n)%nat), entry (matrix_minor i i (identity_matrix R n.+1)) i0 j = entry (identity_matrix R n) i0 j
R: Ring
n, i: nat
Hi: (i < n.+1)%nat
j, k: nat
Hj: (j < n)%nat
Hk: (k < n)%nat

entry (matrix_minor i i (identity_matrix R n.+1)) j k = entry (identity_matrix R n) j k
R: Ring
n, i: nat
Hi: (i < n.+1)%nat
j, k: nat
Hj: (j < n)%nat
Hk: (k < n)%nat

kronecker_delta (skip i j) (skip i k) = kronecker_delta j k
rapply kronecker_delta_map_inj. Defined.
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
M, N: Matrix R n.+1 n.+1

matrix_minor i j (matrix_plus M N) = matrix_plus (matrix_minor i j M) (matrix_minor i j N)
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
M, N: Matrix R n.+1 n.+1

matrix_minor i j (matrix_plus M N) = matrix_plus (matrix_minor i j M) (matrix_minor i j N)
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
M, N: Matrix R n.+1 n.+1

forall (i0 j0 : nat) (Hi0 : (i0 < n)%nat) (Hj0 : (j0 < n)%nat), entry (matrix_minor i j (matrix_plus M N)) i0 j0 = entry (matrix_plus (matrix_minor i j M) (matrix_minor i j N)) i0 j0
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
M, N: Matrix R n.+1 n.+1
k, l: nat
Hk: (k < n)%nat
Hl: (l < n)%nat

entry (matrix_minor i j (matrix_plus M N)) k l = entry (matrix_plus (matrix_minor i j M) (matrix_minor i j N)) k l
by rewrite !entry_Build_Matrix, !entry_Build_Vector. Defined.
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
r: R
M: Matrix R n.+1 n.+1

matrix_minor i j (matrix_lact r M) = matrix_lact r (matrix_minor i j M)
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
r: R
M: Matrix R n.+1 n.+1

matrix_minor i j (matrix_lact r M) = matrix_lact r (matrix_minor i j M)
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
r: R
M: Matrix R n.+1 n.+1

forall (i0 j0 : nat) (Hi0 : (i0 < n)%nat) (Hj0 : (j0 < n)%nat), entry (matrix_minor i j (matrix_lact r M)) i0 j0 = entry (matrix_lact r (matrix_minor i j M)) i0 j0
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
r: R
M: Matrix R n.+1 n.+1
k, l: nat
Hk: (k < n)%nat
Hl: (l < n)%nat

entry (matrix_minor i j (matrix_lact r M)) k l = entry (matrix_lact r (matrix_minor i j M)) k l
by rewrite !entry_Build_Matrix, !entry_Build_Vector. Defined.
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
M: Matrix R n.+1 n.+1

matrix_minor j i (matrix_transpose M) = matrix_transpose (matrix_minor i j M)
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
M: Matrix R n.+1 n.+1

matrix_minor j i (matrix_transpose M) = matrix_transpose (matrix_minor i j M)
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
M: Matrix R n.+1 n.+1

forall (i0 j0 : nat) (Hi0 : (i0 < n)%nat) (Hj0 : (j0 < n)%nat), entry (matrix_minor j i (matrix_transpose M)) i0 j0 = entry (matrix_transpose (matrix_minor i j M)) i0 j0
R: Ring
n, i, j: nat
Hi: (i < n.+1)%nat
Hj: (j < n.+1)%nat
M: Matrix R n.+1 n.+1
k, l: nat
Hk: (k < n)%nat
Hl: (l < n)%nat

entry (matrix_minor j i (matrix_transpose M)) k l = entry (matrix_transpose (matrix_minor i j M)) k l
by rewrite 4 entry_Build_Matrix. Defined. (** ** Triangular matrices *) (** A matrix is upper triangular if all the entries below the diagonal are zero. *) Class IsUpperTriangular@{i} {R : Ring@{i}} {n : nat} (M : Matrix@{i} R n n) : Type@{i} := upper_triangular : merely@{i} (forall i j (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0).
R: Ring
n: nat
M: Matrix R n n

IsHProp (IsUpperTriangular M)
R: Ring
n: nat
M: Matrix R n n

IsHProp (IsUpperTriangular M)
apply istrunc_truncation@{i i}. Defined. (** A matrix is lower triangular if all the entries above the diagonal are zero. We define it as the transpose being upper triangular. *) Class IsLowerTriangular {R : Ring@{i}} {n : nat} (M : Matrix@{i} R n n) : Type@{i} := upper_triangular_transpose :: IsUpperTriangular (matrix_transpose M).
R: Ring
n: nat
M: Matrix R n n

IsHProp (IsLowerTriangular M)
R: Ring
n: nat
M: Matrix R n n

IsHProp (IsLowerTriangular M)
apply istrunc_truncation@{i i}. Defined. (** The transpose of a matrix is lower triangular if and only if the matrix is upper triangular. *)
R: Ring
n: nat
M: Matrix R n n
IsUpperTriangular0: IsUpperTriangular M

IsLowerTriangular (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
IsUpperTriangular0: IsUpperTriangular M

IsLowerTriangular (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
IsUpperTriangular0: IsUpperTriangular M

IsUpperTriangular (matrix_transpose (matrix_transpose M))
by rewrite matrix_transpose_transpose. Defined. (** The sum of two upper triangular matrices is upper triangular. *)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsUpperTriangular M
H2: IsUpperTriangular N

IsUpperTriangular (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsUpperTriangular M
H2: IsUpperTriangular N

IsUpperTriangular (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsUpperTriangular M
H2: IsUpperTriangular N

merely (forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_plus M N) i j = 0)
(* We use [strip_reflections] rather than [strip_truncations] here and below because it generates fewer universe variables in some versions of Coq. *)
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_plus M N) i j = 0
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

entry (matrix_plus M N) i j = 0
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H1: entry M i j = 0
lt_i_j: (i < j)%nat

entry (matrix_plus M N) i j = 0
R: Ring
n: nat
M, N: Matrix R n n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H2: entry N i j = 0
H1: entry M i j = 0
lt_i_j: (i < j)%nat

entry (matrix_plus M N) i j = 0
R: Ring
n: nat
M, N: Matrix R n n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H2: entry N i j = 0
H1: entry M i j = 0
lt_i_j: (i < j)%nat

Vector.entry (Vector.entry M i) j + Vector.entry (Vector.entry N i) j = 0
R: Ring
n: nat
M, N: Matrix R n n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H2: entry N i j = 0
H1: entry M i j = 0
lt_i_j: (i < j)%nat

entry M i j + entry N i j = 0
R: Ring
n: nat
M, N: Matrix R n n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H2: entry N i j = 0
H1: entry M i j = 0
lt_i_j: (i < j)%nat

0 + 0 = 0
by rewrite rng_plus_zero_l. Defined. (** The sum of two lower triangular matrices is lower triangular. *)
R: Ring
n: nat
M, N: Matrix R n n
IsLowerTriangular0: IsLowerTriangular M
IsLowerTriangular1: IsLowerTriangular N

IsLowerTriangular (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
IsLowerTriangular0: IsLowerTriangular M
IsLowerTriangular1: IsLowerTriangular N

IsLowerTriangular (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
IsLowerTriangular0: IsLowerTriangular M
IsLowerTriangular1: IsLowerTriangular N

IsUpperTriangular (matrix_transpose (matrix_plus M N))
R: Ring
n: nat
M, N: Matrix R n n
IsLowerTriangular0: IsLowerTriangular M
IsLowerTriangular1: IsLowerTriangular N

IsUpperTriangular (matrix_plus (matrix_transpose M) (matrix_transpose N))
by apply upper_triangular_plus. Defined. (** The negation of an upper triangular matrix is upper triangular. *)
R: Ring
n: nat
M: Matrix R n n
H: IsUpperTriangular M

IsUpperTriangular (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
H: IsUpperTriangular M

IsUpperTriangular (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
H: IsUpperTriangular M

merely (forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_negate M) i j = 0)
R: Ring
n: nat
M: Matrix R n n
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_negate M) i j = 0
R: Ring
n: nat
M: Matrix R n n
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

entry (matrix_negate M) i j = 0
R: Ring
n: nat
M: Matrix R n n
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

- Vector.entry (Vector.entry M i) j = 0
R: Ring
n: nat
M: Matrix R n n
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

Vector.entry (Vector.entry M i) j = 0
by napply H. Defined. (** The negation of a lower triangular matrix is lower triangular. *)
R: Ring
n: nat
M: Matrix R n n
IsLowerTriangular0: IsLowerTriangular M

IsLowerTriangular (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
IsLowerTriangular0: IsLowerTriangular M

IsLowerTriangular (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
IsLowerTriangular0: IsLowerTriangular M

IsUpperTriangular (matrix_transpose (matrix_negate M))
R: Ring
n: nat
M: Matrix R n n
IsLowerTriangular0: IsLowerTriangular M

IsUpperTriangular (matrix_negate (matrix_transpose M))
by apply upper_triangular_negate. Defined. (** The product of two upper triangular matrices is upper triangular. *)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsUpperTriangular M
H2: IsUpperTriangular N

IsUpperTriangular (matrix_mult M N)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsUpperTriangular M
H2: IsUpperTriangular N

IsUpperTriangular (matrix_mult M N)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsUpperTriangular M
H2: IsUpperTriangular N

merely (forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_mult M N) i j = 0)
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_mult M N) i j = 0
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

entry (matrix_mult M N) i j = 0
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

ab_sum n (fun (k : nat) (Hk : (k < n)%nat) => entry M i k * entry N k j) = 0
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

forall (k : nat) (Hk : (k < n)%nat), entry M i k * entry N k j = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat

entry M i k * entry N k j = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
leq_k_i: (k <= i)%nat

entry M i k * entry N k j = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
gt_k_i: ~ (k <= i)%nat
entry M i k * entry N k j = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
leq_k_i: (k <= i)%nat

entry M i k * entry N k j = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
leq_k_i: (k <= i)%nat

entry M i k * 0 = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
leq_k_i: (k <= i)%nat
(k < j)%nat
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
leq_k_i: (k <= i)%nat

(k < j)%nat
rapply lt_leq_lt_trans.
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
gt_k_i: ~ (k <= i)%nat

entry M i k * entry N k j = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
gt_k_i: (k > i)%nat

entry M i k * entry N k j = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
gt_k_i: (k > i)%nat

0 * entry N k j = mon_unit
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
gt_k_i: (k > i)%nat
(i < k)%nat
R: Ring
n: nat
M, N: Matrix R n n
H2: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry N i j = 0
H1: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
k: nat
Hk: (k < n)%nat
gt_k_i: (k > i)%nat

(i < k)%nat
assumption. Defined. (** The product of two lower triangular matrices is lower triangular. *)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsLowerTriangular M
H2: IsLowerTriangular N

IsLowerTriangular (matrix_mult M N)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsLowerTriangular M
H2: IsLowerTriangular N

IsLowerTriangular (matrix_mult M N)
R: Ring
n: nat
M, N: Matrix R n n
H1: IsLowerTriangular M
H2: IsLowerTriangular N

IsUpperTriangular (matrix_transpose (matrix_mult M N))
R: Ring
n: nat
M, N: Matrix R n n
H1: IsLowerTriangular M
H2: IsLowerTriangular N

IsUpperTriangular (matrix_mult (matrix_transpose N) (matrix_transpose M))
napply (upper_triangular_mult (R:=rng_op R)); assumption. Defined. (** The zero matrix is upper triangular. *)
R: Ring
n: nat

IsUpperTriangular (matrix_zero R n n)
R: Ring
n: nat

IsUpperTriangular (matrix_zero R n n)
R: Ring
n: nat

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_zero R n n) i j = 0
by hnf; intros; rewrite entry_Build_Matrix. Defined. (** The zero matrix is lower triangular. *)
R: Ring
n: nat

IsLowerTriangular (matrix_zero R n n)
R: Ring
n: nat

IsLowerTriangular (matrix_zero R n n)
R: Ring
n: nat

IsUpperTriangular (matrix_transpose (matrix_zero R n n))
R: Ring
n: nat

IsUpperTriangular (matrix_zero R n n)
exact _. Defined. (** The identity matrix is upper triangular. *)
R: Ring
n: nat

IsUpperTriangular (identity_matrix R n)
R: Ring
n: nat

IsUpperTriangular (identity_matrix R n)
R: Ring
n: nat

merely (forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (identity_matrix R n) i j = 0)
R: Ring
n: nat

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (identity_matrix R n) i j = 0
R: Ring
n, i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

entry (identity_matrix R n) i j = 0
R: Ring
n, i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

kronecker_delta i j = 0
by apply kronecker_delta_lt. Defined. (** The identity matrix is lower triangular. *)
R: Ring
n: nat

IsLowerTriangular (identity_matrix R n)
R: Ring
n: nat

IsLowerTriangular (identity_matrix R n)
R: Ring
n: nat

IsUpperTriangular (matrix_transpose (identity_matrix R n))
R: Ring
n: nat

IsUpperTriangular (identity_matrix R n)
exact _. Defined. (** A diagonal matrix is upper triangular. *)
R: Ring
n: nat
v: Vector R n

IsUpperTriangular (matrix_diag v)
R: Ring
n: nat
v: Vector R n

IsUpperTriangular (matrix_diag v)
R: Ring
n: nat
v: Vector R n

merely (forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_diag v) i j = 0)
R: Ring
n: nat
v: Vector R n

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry (matrix_diag v) i j = 0
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

entry (matrix_diag v) i j = 0
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

kronecker_delta i j * Vector.entry v i = 0
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

0 * Vector.entry v i = 0
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat
(i < j)%nat
R: Ring
n: nat
v: Vector R n
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
lt_i_j: (i < j)%nat

(i < j)%nat
exact _. Defined. (** A diagonal matrix is lower triangular. *)
R: Ring
n: nat
v: Vector R n

IsLowerTriangular (matrix_diag v)
R: Ring
n: nat
v: Vector R n

IsLowerTriangular (matrix_diag v)
R: Ring
n: nat
v: Vector R n

IsUpperTriangular (matrix_transpose (matrix_diag v))
R: Ring
n: nat
v: Vector R n

IsUpperTriangular (matrix_diag v)
apply upper_triangular_diag. Defined. (** Upper triangular matrices are a subring of the ring of matrices. *)
R: Ring
n: nat

Subring (matrix_ring R n)
R: Ring
n: nat

Subring (matrix_ring R n)
R: Ring
n: nat

forall x : matrix_ring R n, IsHProp (IsUpperTriangular x)
R: Ring
n: nat
forall x y : matrix_ring R n, IsUpperTriangular x -> IsUpperTriangular y -> IsUpperTriangular (x - y)
R: Ring
n: nat
forall x y : matrix_ring R n, IsUpperTriangular x -> IsUpperTriangular y -> IsUpperTriangular (x * y)
R: Ring
n: nat
IsUpperTriangular 1
R: Ring
n: nat

forall x : matrix_ring R n, IsHProp (IsUpperTriangular x)
exact _. (* These can all be found by typeclass search, but being explicit makes this faster. *)
R: Ring
n: nat

forall x y : matrix_ring R n, IsUpperTriangular x -> IsUpperTriangular y -> IsUpperTriangular (x - y)
intros x y ? ?; exact (upper_triangular_plus x (-y)).
R: Ring
n: nat

forall x y : matrix_ring R n, IsUpperTriangular x -> IsUpperTriangular y -> IsUpperTriangular (x * y)
exact upper_triangular_mult.
R: Ring
n: nat

IsUpperTriangular 1
exact upper_triangular_identity. Defined. (** Lower triangular matrices are a subring of the ring of matrices. *)
R: Ring
n: nat

Subring (matrix_ring R n)
R: Ring
n: nat

Subring (matrix_ring R n)
R: Ring
n: nat

forall x : matrix_ring R n, IsHProp (IsLowerTriangular x)
R: Ring
n: nat
forall x y : matrix_ring R n, IsLowerTriangular x -> IsLowerTriangular y -> IsLowerTriangular (x - y)
R: Ring
n: nat
forall x y : matrix_ring R n, IsLowerTriangular x -> IsLowerTriangular y -> IsLowerTriangular (x * y)
R: Ring
n: nat
IsLowerTriangular 1
R: Ring
n: nat

forall x : matrix_ring R n, IsHProp (IsLowerTriangular x)
exact _. (* These can all be found by typeclass search, but being explicit makes this faster. *)
R: Ring
n: nat

forall x y : matrix_ring R n, IsLowerTriangular x -> IsLowerTriangular y -> IsLowerTriangular (x - y)
intros x y ? ?; exact (lower_triangular_plus x (-y)).
R: Ring
n: nat

forall x y : matrix_ring R n, IsLowerTriangular x -> IsLowerTriangular y -> IsLowerTriangular (x * y)
exact lower_triangular_mult.
R: Ring
n: nat

IsLowerTriangular 1
exact lower_triangular_identity. Defined. (** ** Symmetric Matrices *) (** A matrix is symmetric when it is equal to its transpose. *) Class IsSymmetric {R : Ring@{i}} {n : nat} (M : Matrix@{i} R n n) : Type@{i} := matrix_transpose_issymmetric : matrix_transpose M = M. Arguments matrix_transpose_issymmetric {R n} M {_}. (** The zero matrix is symmetric. *) Instance issymmetric_matrix_zero {R : Ring@{i}} {n : nat} : IsSymmetric (matrix_zero R n n) := matrix_transpose_zero. (** The identity matrix is symmetric. *) Instance issymmetric_matrix_identity {R : Ring@{i}} {n : nat} : IsSymmetric (identity_matrix R n) := matrix_transpose_identity. (** The sum of two symmetric matrices is symmetric. *)
R: Ring
n: nat
M, N: Matrix R n n
IsSymmetric0: IsSymmetric M
IsSymmetric1: IsSymmetric N

IsSymmetric (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
IsSymmetric0: IsSymmetric M
IsSymmetric1: IsSymmetric N

IsSymmetric (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
IsSymmetric0: IsSymmetric M
IsSymmetric1: IsSymmetric N

matrix_transpose (matrix_plus M N) = matrix_plus M N
R: Ring
n: nat
M, N: Matrix R n n
IsSymmetric0: IsSymmetric M
IsSymmetric1: IsSymmetric N

matrix_plus (matrix_transpose M) (matrix_transpose N) = matrix_plus M N
f_ap. Defined. (** The negation of a symmetric matrix is symmetric. *)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M

IsSymmetric (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M

IsSymmetric (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M

matrix_transpose (matrix_negate M) = matrix_negate M
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M

matrix_negate (matrix_transpose M) = matrix_negate M
f_ap. Defined. (** A scalar multiple of a symmetric matrix is symmetric. *)
R: Ring
n: nat
r: R
M: Matrix R n n
IsSymmetric0: IsSymmetric M

IsSymmetric (matrix_lact r M)
R: Ring
n: nat
r: R
M: Matrix R n n
IsSymmetric0: IsSymmetric M

IsSymmetric (matrix_lact r M)
R: Ring
n: nat
r: R
M: Matrix R n n
IsSymmetric0: IsSymmetric M

matrix_transpose (matrix_lact r M) = matrix_lact r M
R: Ring
n: nat
r: R
M: Matrix R n n
IsSymmetric0: IsSymmetric M

matrix_lact r (matrix_transpose M) = matrix_lact r M
f_ap. Defined. (** The transpose of a symmetric matrix is symmetric. *)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M

IsSymmetric (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M

IsSymmetric (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M

matrix_transpose (matrix_transpose M) = matrix_transpose M
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M

M = matrix_transpose M
by symmetry. Defined. (** A symmetric upper triangular matrix is diagonal. *)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
H: IsUpperTriangular M

IsDiagonal M
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
H: IsUpperTriangular M

IsDiagonal M
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
H: IsUpperTriangular M

M = matrix_diag (matrix_diag_vector M)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
H: IsUpperTriangular M

forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), entry M i j = entry (matrix_diag (matrix_diag_vector M)) i j
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
H: IsUpperTriangular M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry M i j = entry (matrix_diag (matrix_diag_vector M)) i j
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
H: IsUpperTriangular M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
p: i = j

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
np: i <> j
entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
p: i = j

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i: nat
Hi, Hj: (i < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0

entry M i i = kronecker_delta i i * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i: nat
Hi, Hj: (i < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0

entry M i i = 1 * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i: nat
Hi, Hj: (i < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0

entry M i i = entry M i i
f_ap; apply path_ishprop.
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
np: i <> j

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
np: ((i < j)%nat + (i > j)%nat)%type

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i < j)%nat

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i > j)%nat
entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i < j)%nat

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i < j)%nat

entry M i j = 0 * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i < j)%nat

entry M i j = 0
by rewrite H.
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i > j)%nat

entry M i j = kronecker_delta i j * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i > j)%nat

entry M i j = 0 * entry M i i
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i > j)%nat

entry M i j = 0
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i > j)%nat

entry (matrix_transpose M) i j = 0
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
i, j: nat
Hi: (i < n)%nat
Hj: (j < n)%nat
H: forall (i j : nat) (Hi : (i < n)%nat) (Hj : (j < n)%nat), (i < j)%nat -> entry M i j = 0
l: (i > j)%nat

entry M j i = 0
by rewrite H. Defined. (** A symmetric lower triangular matrix is diagonal. *)
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
IsLowerTriangular0: IsLowerTriangular M

IsDiagonal M
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
IsLowerTriangular0: IsLowerTriangular M

IsDiagonal M
R: Ring
n: nat
M: Matrix R n n
IsSymmetric0: IsSymmetric M
IsLowerTriangular0: IsLowerTriangular M

IsDiagonal (matrix_transpose M)
rapply isdiagonal_upper_triangular_issymmetric. Defined. (** Note that symmetric matrices do not form a subring (or subalgebra) but they do form a submodule of the module of matrices. *) (** ** Skew-symmetric Matrices *) (** A matrix is skew-symmetric when it is equal to the negation of its transpose. *) Class IsSkewSymmetric {R : Ring@{i}} {n : nat} (M : Matrix@{i} R n n) : Type@{i} := matrix_transpose_isskewsymmetric : matrix_transpose M = matrix_negate M. Arguments matrix_transpose_isskewsymmetric {R n} M {_}. (** The zero matrix is skew-symmetric. *)
R: Ring
n: nat

IsSkewSymmetric (matrix_zero R n n)
R: Ring
n: nat

IsSkewSymmetric (matrix_zero R n n)
R: Ring
n: nat

matrix_transpose (matrix_zero R n n) = matrix_negate (matrix_zero R n n)
R: Ring
n: nat

matrix_zero R n n = matrix_negate (matrix_zero R n n)
R: Ring
n: nat

matrix_negate (matrix_zero R n n) = matrix_zero R n n
napply (rng_negate_zero (A:=matrix_ring R n)). Defined. (** The negation of a skew-symmetric matrix is skew-symmetric. *)
R: Ring
n: nat
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

IsSkewSymmetric (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

IsSkewSymmetric (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

matrix_transpose (matrix_negate M) = matrix_negate (matrix_negate M)
R: Ring
n: nat
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

matrix_negate (matrix_transpose M) = matrix_negate (matrix_negate M)
f_ap. Defined. (** A scalar multiple of a skew-symmetric matrix is skew-symmetric. *)
R: Ring
n: nat
r: R
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

IsSkewSymmetric (matrix_lact r M)
R: Ring
n: nat
r: R
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

IsSkewSymmetric (matrix_lact r M)
R: Ring
n: nat
r: R
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

matrix_transpose (matrix_lact r M) = matrix_negate (matrix_lact r M)
R: Ring
n: nat
r: R
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

matrix_lact r (matrix_transpose M) = matrix_negate (matrix_lact r M)
R: Ring
n: nat
r: R
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

matrix_lact r (matrix_transpose M) = lact r (- M)
f_ap. Defined. (** The transpose of a skew-symmetric matrix is skew-symmetric. *)
R: Ring
n: nat
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

IsSkewSymmetric (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

IsSkewSymmetric (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

matrix_transpose (matrix_transpose M) = matrix_negate (matrix_transpose M)
R: Ring
n: nat
M: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M

matrix_transpose (matrix_transpose M) = matrix_transpose (matrix_negate M)
f_ap. Defined. (** The sum of two skew-symmetric matrices is skew-symmetric. *)
R: Ring
n: nat
M, N: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M
IsSkewSymmetric1: IsSkewSymmetric N

IsSkewSymmetric (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M
IsSkewSymmetric1: IsSkewSymmetric N

IsSkewSymmetric (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M
IsSkewSymmetric1: IsSkewSymmetric N

matrix_transpose (matrix_plus M N) = matrix_negate (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M
IsSkewSymmetric1: IsSkewSymmetric N

matrix_plus (matrix_transpose M) (matrix_transpose N) = matrix_negate (matrix_plus M N)
R: Ring
n: nat
M, N: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M
IsSkewSymmetric1: IsSkewSymmetric N

matrix_plus (matrix_transpose M) (matrix_transpose N) = sg_op (inv N) (inv M)
R: Ring
n: nat
M, N: Matrix R n n
IsSkewSymmetric0: IsSkewSymmetric M
IsSkewSymmetric1: IsSkewSymmetric N

matrix_plus (matrix_transpose M) (matrix_transpose N) = sg_op (inv M) (inv N)
f_ap. Defined. (** Skew-symmetric matrices degenerate to symmetric matrices in rings with characteristic 2. In odd characteristic the module of matrices can be decomposed into the direct sum of symmetric and skew-symmetric matrices. *) Section MatrixCat. (** The wild category [MatrixCat R] of [R]-valued matrices. This category has natural numbers as objects and m x n matrices as the arrows between [m] and [n]. *) Definition MatrixCat (R : Ring) := nat. #[export] Instance isgraph_matrixcat {R : Ring} : IsGraph (MatrixCat R) := {| Hom := Matrix R |}.
R: Ring

Is01Cat (MatrixCat R)
R: Ring

Is01Cat (MatrixCat R)
R: Ring

forall a : MatrixCat R, a $-> a
R: Ring
forall a b c : MatrixCat R, (b $-> c) -> (a $-> b) -> a $-> c
R: Ring

forall a : MatrixCat R, a $-> a
exact (identity_matrix R).
R: Ring

forall a b c : MatrixCat R, (b $-> c) -> (a $-> b) -> a $-> c
R: Ring
l, m, n: MatrixCat R
M: m $-> n
N: l $-> m

l $-> n
exact (matrix_mult N M). Defined. #[export] Instance is2graph_matrixcat {R : Ring} : Is2Graph (MatrixCat R) := is2graph_paths _. (** [MatrixCat R] forms a strong 1-category. *)
R: Ring

Is1Cat_Strong (MatrixCat R)
R: Ring

Is1Cat_Strong (MatrixCat R)
R: Ring

forall a b : MatrixCat R, Is01Cat (a $-> b)
R: Ring
forall a b : MatrixCat R, Is0Gpd (a $-> b)
R: Ring
forall (a b c : MatrixCat R) (g : b $-> c), Is0Functor (cat_postcomp a g)
R: Ring
forall (a b c : MatrixCat R) (f : a $-> b), Is0Functor (cat_precomp c f)
R: Ring
forall (a b c d : MatrixCat R) (f : a $-> b) (g : b $-> c) (h : c $-> d), h $o g $o f = h $o (g $o f)
R: Ring
forall (a b c d : MatrixCat R) (f : a $-> b) (g : b $-> c) (h : c $-> d), h $o (g $o f) = h $o g $o f
R: Ring
forall (a b : MatrixCat R) (f : a $-> b), Id b $o f = f
R: Ring
forall (a b : MatrixCat R) (f : a $-> b), f $o Id a = f
(* Most of the structure comes from typeclasses in WildCat.Paths. *)
R: Ring

forall (a b c d : MatrixCat R) (f : a $-> b) (g : b $-> c) (h : c $-> d), h $o g $o f = h $o (g $o f)
R: Ring
forall (a b c d : MatrixCat R) (f : a $-> b) (g : b $-> c) (h : c $-> d), h $o (g $o f) = h $o g $o f
R: Ring
forall (a b : MatrixCat R) (f : a $-> b), Id b $o f = f
R: Ring
forall (a b : MatrixCat R) (f : a $-> b), f $o Id a = f
R: Ring

forall (a b c d : MatrixCat R) (f : a $-> b) (g : b $-> c) (h : c $-> d), h $o g $o f = h $o (g $o f)
apply (associative_matrix_mult R).
R: Ring

forall (a b c d : MatrixCat R) (f : a $-> b) (g : b $-> c) (h : c $-> d), h $o (g $o f) = h $o g $o f
R: Ring
k, l, m, n: MatrixCat R
M: k $-> l
N: l $-> m
P: m $-> n

P $o (N $o M) = P $o N $o M
R: Ring
k, l, m, n: MatrixCat R
M: k $-> l
N: l $-> m
P: m $-> n

P $o N $o M = P $o (N $o M)
apply (associative_matrix_mult R).
R: Ring

forall (a b : MatrixCat R) (f : a $-> b), Id b $o f = f
apply right_identity_matrix_mult.
R: Ring

forall (a b : MatrixCat R) (f : a $-> b), f $o Id a = f
apply left_identity_matrix_mult. Defined. (** TODO: Define [HasEquivs] for [MatrixCat]. *) End MatrixCat.