Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit e62a406

Browse files
paulvanwamelenpaulvanwamelen
andcommitted
feat(linear_algebra/determinant): determinant of a block triangular matrix (#6050)
Add lemmas for determinants of block triangular matrices. Co-authored-by: paulvanwamelen <30371019+paulvanwamelen@users.noreply.github.com>
1 parent 664feed commit e62a406

File tree

6 files changed

+392
-5
lines changed

6 files changed

+392
-5
lines changed

src/data/equiv/basic.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,12 +1289,20 @@ def subtype_subtype_equiv_subtype_exists {α : Type u} (p : α → Prop) (q : su
12891289
λ⟨a, ha⟩, ⟨⟨a, ha.cases_on $ assume h _, h⟩, by { cases ha, exact ha_h }⟩,
12901290
assume ⟨⟨a, ha⟩, h⟩, rfl, assume ⟨a, h₁, h₂⟩, rfl⟩
12911291

1292+
@[simp] lemma subtype_subtype_equiv_subtype_exists_apply {α : Type u} (p : α → Prop)
1293+
(q : subtype p → Prop) (a) : (subtype_subtype_equiv_subtype_exists p q a : α) = a :=
1294+
by { cases a, cases a_val, refl }
1295+
12921296
/-- A subtype of a subtype is equivalent to the subtype of elements satisfying both predicates. -/
12931297
def subtype_subtype_equiv_subtype_inter {α : Type u} (p q : α → Prop) :
12941298
{x : subtype p // q x.1} ≃ subtype (λ x, p x ∧ q x) :=
12951299
(subtype_subtype_equiv_subtype_exists p _).trans $
12961300
subtype_equiv_right $ λ x, exists_prop
12971301

1302+
@[simp] lemma subtype_subtype_equiv_subtype_inter_apply {α : Type u} (p q : α → Prop) (a) :
1303+
(subtype_subtype_equiv_subtype_inter p q a : α) = a :=
1304+
by { cases a, cases a_val, refl }
1305+
12981306
/-- If the outer subtype has more restrictive predicate than the inner one,
12991307
then we can drop the latter. -/
13001308
def subtype_subtype_equiv_subtype {α : Type u} {p q : α → Prop} (h : ∀ {x}, q x → p x) :
@@ -1304,6 +1312,11 @@ subtype_equiv_right $
13041312
assume x,
13051313
⟨and.right, λ h₁, ⟨h h₁, h₁⟩⟩
13061314

1315+
@[simp] lemma subtype_subtype_equiv_subtype_apply {α : Type u} {p q : α → Prop} (h : ∀ x, q x → p x)
1316+
(a : {x : subtype p // q x.1}) :
1317+
(subtype_subtype_equiv_subtype h a : α) = a :=
1318+
by { cases a, cases a_val, refl }
1319+
13071320
/-- If a proposition holds for all elements, then the subtype is
13081321
equivalent to the original type. -/
13091322
def subtype_univ_equiv {α : Type u} {p : α → Prop} (h : ∀ x, p x) :

src/data/matrix/basic.lean

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -985,22 +985,22 @@ rfl
985985
from_blocks A B C D (sum.inr i) (sum.inr j) = D i j :=
986986
rfl
987987

988-
/-- Given a matrix whose row and column indexes are sum types, we can extract the correspnding
988+
/-- Given a matrix whose row and column indexes are sum types, we can extract the corresponding
989989
"top left" submatrix. -/
990990
def to_blocks₁₁ (M : matrix (n ⊕ o) (l ⊕ m) α) : matrix n l α :=
991991
λ i j, M (sum.inl i) (sum.inl j)
992992

993-
/-- Given a matrix whose row and column indexes are sum types, we can extract the correspnding
993+
/-- Given a matrix whose row and column indexes are sum types, we can extract the corresponding
994994
"top right" submatrix. -/
995995
def to_blocks₁₂ (M : matrix (n ⊕ o) (l ⊕ m) α) : matrix n m α :=
996996
λ i j, M (sum.inl i) (sum.inr j)
997997

998-
/-- Given a matrix whose row and column indexes are sum types, we can extract the correspnding
998+
/-- Given a matrix whose row and column indexes are sum types, we can extract the corresponding
999999
"bottom left" submatrix. -/
10001000
def to_blocks₂₁ (M : matrix (n ⊕ o) (l ⊕ m) α) : matrix o l α :=
10011001
λ i j, M (sum.inr i) (sum.inl j)
10021002

1003-
/-- Given a matrix whose row and column indexes are sum types, we can extract the correspnding
1003+
/-- Given a matrix whose row and column indexes are sum types, we can extract the corresponding
10041004
"bottom right" submatrix. -/
10051005
def to_blocks₂₂ (M : matrix (n ⊕ o) (l ⊕ m) α) : matrix o m α :=
10061006
λ i j, M (sum.inr i) (sum.inr j)
@@ -1038,6 +1038,39 @@ begin
10381038
ext i j, rcases i; rcases j; simp [from_blocks],
10391039
end
10401040

1041+
/-- Let `p` pick out certain rows and `q` pick out certain columns of a matrix `M`. Then
1042+
`to_block M p q` is the corresponding block matrix. -/
1043+
def to_block (M : matrix m n α) (p : m → Prop) [decidable_pred p]
1044+
(q : n → Prop) [decidable_pred q] : matrix {a // p a} {a // q a} α := M.minor coe coe
1045+
1046+
@[simp] lemma to_block_apply (M : matrix m n α) (p : m → Prop) [decidable_pred p]
1047+
(q : n → Prop) [decidable_pred q] (i : {a // p a}) (j : {a // q a}) :
1048+
to_block M p q i j = M ↑i ↑j := rfl
1049+
1050+
/-- Let `b` map rows and columns of a square matrix `M` to blocks. Then
1051+
`to_square_block M b k` is the block `k` matrix. -/
1052+
def to_square_block (M : matrix m m α) {n : nat} (b : m → fin n) (k : fin n) :
1053+
matrix {a // b a = k} {a // b a = k} α := M.minor coe coe
1054+
1055+
@[simp] lemma to_square_block_def (M : matrix m m α) {n : nat} (b : m → fin n) (k : fin n) :
1056+
to_square_block M b k = λ i j, M ↑i ↑j := rfl
1057+
1058+
/-- Alternate version with `b : m → nat`. Let `b` map rows and columns of a square matrix `M` to
1059+
blocks. Then `to_square_block' M b k` is the block `k` matrix. -/
1060+
def to_square_block' (M : matrix m m α) (b : m → nat) (k : nat) :
1061+
matrix {a // b a = k} {a // b a = k} α := M.minor coe coe
1062+
1063+
@[simp] lemma to_square_block_def' (M : matrix m m α) (b : m → nat) (k : nat) :
1064+
to_square_block' M b k = λ i j, M ↑i ↑j := rfl
1065+
1066+
/-- Let `p` pick out certain rows and columns of a square matrix `M`. Then
1067+
`to_square_block_prop M p` is the corresponding block matrix. -/
1068+
def to_square_block_prop (M : matrix m m α) (p : m → Prop) [decidable_pred p] :
1069+
matrix {a // p a} {a // p a} α := M.minor coe coe
1070+
1071+
@[simp] lemma to_square_block_prop_def (M : matrix m m α) (p : m → Prop) [decidable_pred p] :
1072+
to_square_block_prop M p = λ i j, M ↑i ↑j := rfl
1073+
10411074
variables [semiring α]
10421075

10431076
lemma from_blocks_smul

src/group_theory/perm/basic.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ else by simp [h, of_subtype_apply_of_not_mem f h]
240240
equiv.ext $ λ ⟨x, hx⟩, by { dsimp [subtype_perm, of_subtype],
241241
simp only [show p x, from hx, dif_pos, subtype.coe_eta] }
242242

243+
instance perm_unique {n : Type*} [unique n] : unique (equiv.perm n) :=
244+
{ default := 1,
245+
uniq := λ σ, equiv.ext (λ i, subsingleton.elim _ _) }
246+
247+
@[simp] lemma default_perm {n : Type*} : default (equiv.perm n) = 1 := rfl
248+
243249
end perm
244250

245251
section swap

src/group_theory/perm/sign.lean

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,37 @@ f.subtype_perm (λ x, ⟨h x, λ h₂, f.inv_apply_self x ▸ perm_inv_on_of_per
8686
(h : ∀ x, p x → p ((1 : perm α) x)) : @subtype_perm_of_fintype α 1 p _ h = 1 :=
8787
equiv.ext $ λ ⟨_, _⟩, rfl
8888

89+
lemma perm_maps_to_inl_iff_maps_to_inr {m n : Type*} [fintype m] [fintype n]
90+
(σ : equiv.perm (m ⊕ n)) :
91+
set.maps_to σ (set.range sum.inl) (set.range sum.inl) ↔
92+
set.maps_to σ (set.range sum.inr) (set.range sum.inr) :=
93+
begin
94+
split; id {
95+
intros h,
96+
classical,
97+
rw ←perm_inv_maps_to_iff_maps_to at h,
98+
intro x,
99+
cases hx : σ x with l r, },
100+
{ rintros ⟨a, rfl⟩,
101+
obtain ⟨y, hy⟩ := h ⟨l, rfl⟩,
102+
rw [←hx, σ.inv_apply_self] at hy,
103+
exact absurd hy sum.inl_ne_inr},
104+
{ rintros ⟨a, ha⟩, exact ⟨r, rfl⟩, },
105+
{ rintros ⟨a, ha⟩, exact ⟨l, rfl⟩, },
106+
{ rintros ⟨a, rfl⟩,
107+
obtain ⟨y, hy⟩ := h ⟨r, rfl⟩,
108+
rw [←hx, σ.inv_apply_self] at hy,
109+
exact absurd hy sum.inr_ne_inl},
110+
end
111+
112+
lemma perm_on_inl_iff_perm_on_inr {m n : Type*} [fintype m] [fintype n] (σ : equiv.perm (m ⊕ n)) :
113+
(∀ a1, ∃ a2, sum.inl a2 = σ (sum.inl a1)) ↔ ∀ b1, ∃ b2, sum.inr b2 = σ (sum.inr b1) :=
114+
begin
115+
have := perm_maps_to_inl_iff_maps_to_inr σ,
116+
rw [set.maps_range_to, set.maps_range_to] at this,
117+
convert this; simp
118+
end
119+
89120
/-- Two permutations `f` and `g` are `disjoint` if their supports are disjoint, i.e.,
90121
every element is fixed either by `f`, or by `g`. -/
91122
def disjoint (f g : perm α) := ∀ x, f x = x ∨ g x = x

src/linear_algebra/determinant.lean

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ open equiv equiv.perm finset function
4040
namespace matrix
4141
open_locale matrix big_operators
4242

43-
variables {n : Type u} [decidable_eq n] [fintype n] {R : Type v} [comm_ring R]
43+
variables {m n : Type u} [decidable_eq n] [fintype n] [decidable_eq m] [fintype m]
44+
variables {R : Type v} [comm_ring R]
4445

4546
local notation ` σ:max := ((sign σ : ℤ ) : R)
4647

@@ -75,6 +76,24 @@ begin
7576
simp [det, card_eq_zero.mp h, perm_eq],
7677
end
7778

79+
/-- If `n` has only one element, the determinant of an `n` by `n` matrix is just that element.
80+
Although `unique` implies `decidable_eq` and `fintype`, the instances might
81+
not be syntactically equal. Thus, we need to fill in the args explicitly. -/
82+
@[simp]
83+
lemma det_unique {n : Type*} [unique n] [decidable_eq n] [fintype n] (A : matrix n n R) :
84+
det A = A (default n) (default n) :=
85+
by simp [det, univ_unique]
86+
87+
lemma det_eq_elem_of_card_eq_one {A : matrix n n R} (h : fintype.card n = 1) (k : n) :
88+
det A = A k k :=
89+
begin
90+
have h1 : (univ : finset (perm n)) = {1},
91+
{ apply univ_eq_singleton_of_card_one (1 : perm n),
92+
simp [card_univ, fintype.card_perm, h] },
93+
have h2 := univ_eq_singleton_of_card_one k h,
94+
simp [det, h1, h2],
95+
end
96+
7897
lemma det_mul_aux {M N : matrix n n R} {p : n → n} (H : ¬bijective p) :
7998
∑ σ : perm n, (ε σ) * ∏ x, (M (σ x) (p x) * N (p x) x) = 0 :=
8099
begin
@@ -344,4 +363,78 @@ begin
344363
exact hkx }
345364
end
346365

366+
/-- The determinant of a 2x2 block matrix with the lower-left block equal to zero is the product of
367+
the determinants of the diagonal blocks. For the generalization to any number of blocks, see
368+
`matrix.upper_block_triangular_det`. -/
369+
lemma upper_two_block_triangular_det (A : matrix m m R) (B : matrix m n R) (D : matrix n n R) :
370+
(matrix.from_blocks A B 0 D).det = A.det * D.det :=
371+
begin
372+
unfold det,
373+
rw sum_mul_sum,
374+
let preserving_A : finset (perm (m ⊕ n)) :=
375+
univ.filter (λ σ, ∀ x, ∃ y, sum.inl y = (σ (sum.inl x))),
376+
simp_rw univ_product_univ,
377+
have mem_preserving_A : ∀ {σ : perm (m ⊕ n)},
378+
σ ∈ preserving_A ↔ ∀ x, ∃ y, sum.inl y = σ (sum.inl x) :=
379+
λ σ, mem_filter.trans ⟨λ h, h.2, λ h, ⟨mem_univ _, h⟩⟩,
380+
rw ← sum_subset (subset_univ preserving_A) _,
381+
rw (sum_bij (λ (σ : perm m × perm n) _, equiv.sum_congr σ.fst σ.snd) _ _ _ _).symm,
382+
{ intros a ha,
383+
rw mem_preserving_A,
384+
intro x,
385+
use a.fst x,
386+
simp },
387+
{ simp only [forall_prop_of_true, prod.forall, mem_univ],
388+
intros σ₁ σ₂,
389+
rw fintype.prod_sum_type,
390+
simp_rw [equiv.sum_congr_apply, sum.map_inr, sum.map_inl, from_blocks_apply₁₁,
391+
from_blocks_apply₂₂],
392+
have hr : ∀ (a b c d : R), (a * b) * (c * d) = a * c * (b * d), { intros, ac_refl },
393+
rw hr,
394+
congr,
395+
norm_cast,
396+
rw sign_sum_congr },
397+
{ intros σ₁ σ₂ h₁ h₂,
398+
dsimp only [],
399+
intro h,
400+
have h2 : ∀ x, perm.sum_congr σ₁.fst σ₁.snd x = perm.sum_congr σ₂.fst σ₂.snd x,
401+
{ intro x, exact congr_fun (congr_arg to_fun h) x },
402+
simp only [sum.map_inr, sum.map_inl, perm.sum_congr_apply, sum.forall] at h2,
403+
ext,
404+
{ exact h2.left x },
405+
{ exact h2.right x }},
406+
{ intros σ hσ,
407+
have h1 : ∀ (x : m ⊕ n), (∃ (a : m), sum.inl a = x) → (∃ (a : m), sum.inl a = σ x),
408+
{ rintros x ⟨a, ha⟩,
409+
rw ← ha,
410+
exact (@mem_preserving_A σ).mp hσ a },
411+
have h2 : ∀ (x : m ⊕ n), (∃ (b : n), sum.inr b = x) → (∃ (b : n), sum.inr b = σ x),
412+
{ rintros x ⟨b, hb⟩,
413+
rw ← hb,
414+
exact (perm_on_inl_iff_perm_on_inr σ).mp ((@mem_preserving_A σ).mp hσ) b },
415+
let σ₁' := subtype_perm_of_fintype σ h1,
416+
let σ₂' := subtype_perm_of_fintype σ h2,
417+
let σ₁ := perm_congr (equiv.set.range (@sum.inl m n) sum.injective_inl).symm σ₁',
418+
let σ₂ := perm_congr (equiv.set.range (@sum.inr m n) sum.injective_inr).symm σ₂',
419+
use [⟨σ₁, σ₂⟩, finset.mem_univ _],
420+
ext,
421+
cases x with a b,
422+
{ rw [equiv.sum_congr_apply, sum.map_inl, perm_congr_apply, equiv.symm_symm,
423+
set.apply_range_symm (@sum.inl m n)],
424+
erw subtype_perm_apply,
425+
rw [set.range_apply, subtype.coe_mk, subtype.coe_mk] },
426+
{ rw [equiv.sum_congr_apply, sum.map_inr, perm_congr_apply, equiv.symm_symm,
427+
set.apply_range_symm (@sum.inr m n)],
428+
erw subtype_perm_apply,
429+
rw [set.range_apply, subtype.coe_mk, subtype.coe_mk] }},
430+
{ intros σ h0 hσ,
431+
obtain ⟨a, ha⟩ := not_forall.mp ((not_congr (@mem_preserving_A σ)).mp hσ),
432+
generalize hx : σ (sum.inl a) = x,
433+
cases x with a2 b,
434+
{ have hn := (not_exists.mp ha) a2,
435+
exact absurd hx.symm hn },
436+
{ rw [finset.prod_eq_zero (finset.mem_univ (sum.inl a)), mul_zero],
437+
rw [hx, from_blocks_apply₂₁], refl }}
438+
end
439+
347440
end matrix

0 commit comments

Comments
 (0)