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

Commit 802c5b5

Browse files
committed
feat(linear_algebra/determinant): various operations preserve the determinant (#7115)
These are a couple of helper lemmas for computing the determinant of a Vandermonde matrix. Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>
1 parent 6c61779 commit 802c5b5

File tree

2 files changed

+172
-0
lines changed

2 files changed

+172
-0
lines changed

src/data/matrix/basic.lean

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,16 @@ begin
10961096
refl
10971097
end
10981098

1099+
@[simp] lemma update_row_eq_self [decidable_eq m]
1100+
(A : matrix m n α) {i : m} :
1101+
A.update_row i (A i) = A :=
1102+
function.update_eq_self i A
1103+
1104+
@[simp] lemma update_column_eq_self [decidable_eq n]
1105+
(A : matrix m n α) {i : n} :
1106+
A.update_column i (λ j, A j i) = A :=
1107+
funext $ λ j, function.update_eq_self i (A j)
1108+
10991109
end update
11001110

11011111
section block_matrices

src/linear_algebra/determinant.lean

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,19 @@ calc det (c • A) = det (matrix.mul (diagonal (λ _, c)) A) : by rw [smul_eq_di
226226
... = det (diagonal (λ _, c)) * det A : det_mul _ _
227227
... = c ^ fintype.card n * det A : by simp [card_univ]
228228

229+
/-- Multiplying each row by a fixed `v i` multiplies the determinant by
230+
the product of the `v`s. -/
231+
lemma det_mul_row (v : n → R) (A : matrix n n R) :
232+
det (λ i j, v j * A i j) = (∏ i, v i) * det A :=
233+
calc det (λ i j, v j * A i j) = det (A ⬝ diagonal v) : congr_arg det $ by { ext, simp [mul_comm] }
234+
... = (∏ i, v i) * det A : by rw [det_mul, det_diagonal, mul_comm]
235+
236+
/-- Multiplying each column by a fixed `v j` multiplies the determinant by
237+
the product of the `v`s. -/
238+
lemma det_mul_column (v : n → R) (A : matrix n n R) :
239+
det (λ i j, v i * A i j) = (∏ i, v i) * det A :=
240+
multilinear_map.map_smul_univ _ v A
241+
229242
section hom_map
230243

231244
variables {S : Type w} [comm_ring S]
@@ -260,6 +273,10 @@ variables {M : matrix n n R} {i j : n}
260273
theorem det_zero_of_row_eq (i_ne_j : i ≠ j) (hij : M i = M j) : M.det = 0 :=
261274
(det_row_multilinear : alternating_map R (n → R) R n).map_eq_zero_of_eq M hij i_ne_j
262275

276+
/-- If a matrix has a repeated column, the determinant will be zero. -/
277+
theorem det_zero_of_column_eq (i_ne_j : i ≠ j) (hij : ∀ k, M k i = M k j) : M.det = 0 :=
278+
by { rw [← det_transpose, det_zero_of_row_eq i_ne_j], exact funext hij }
279+
263280
end det_zero
264281

265282
lemma det_update_row_add (M : matrix n n R) (j : n) (u v : n → R) :
@@ -284,6 +301,151 @@ begin
284301
simp [update_row_transpose, det_transpose]
285302
end
286303

304+
section det_eq
305+
306+
/-! ### `det_eq` section
307+
308+
Lemmas showing the determinant is invariant under a variety of operations.
309+
-/
310+
lemma det_eq_of_eq_mul_det_one {A B : matrix n n R}
311+
(C : matrix n n R) (hC : det C = 1) (hA : A = B ⬝ C) : det A = det B :=
312+
calc det A = det (B ⬝ C) : congr_arg _ hA
313+
... = det B * det C : det_mul _ _
314+
... = det B : by rw [hC, mul_one]
315+
316+
lemma det_eq_of_eq_det_one_mul {A B : matrix n n R}
317+
(C : matrix n n R) (hC : det C = 1) (hA : A = C ⬝ B) : det A = det B :=
318+
calc det A = det (C ⬝ B) : congr_arg _ hA
319+
... = det C * det B : det_mul _ _
320+
... = det B : by rw [hC, one_mul]
321+
322+
lemma det_update_row_add_self (A : matrix n n R) {i j : n} (hij : i ≠ j) :
323+
det (update_row A i (A i + A j)) = det A :=
324+
by simp [det_update_row_add,
325+
det_zero_of_row_eq hij ((update_row_self).trans (update_row_ne hij.symm).symm)]
326+
327+
lemma det_update_column_add_self (A : matrix n n R) {i j : n} (hij : i ≠ j) :
328+
det (update_column A i (λ k, A k i + A k j)) = det A :=
329+
by { rw [← det_transpose, ← update_row_transpose, ← det_transpose A],
330+
exact det_update_row_add_self Aᵀ hij }
331+
332+
lemma det_update_row_add_smul_self (A : matrix n n R) {i j : n} (hij : i ≠ j) (c : R) :
333+
det (update_row A i (A i + c • A j)) = det A :=
334+
by simp [det_update_row_add, det_update_row_smul,
335+
det_zero_of_row_eq hij ((update_row_self).trans (update_row_ne hij.symm).symm)]
336+
337+
lemma det_update_column_add_smul_self (A : matrix n n R) {i j : n} (hij : i ≠ j) (c : R) :
338+
det (update_column A i (λ k, A k i + c • A k j)) = det A :=
339+
by { rw [← det_transpose, ← update_row_transpose, ← det_transpose A],
340+
exact det_update_row_add_smul_self Aᵀ hij c }
341+
342+
lemma det_eq_of_forall_row_eq_smul_add_const_aux
343+
{A B : matrix n n R} {s : finset n} : ∀ (c : n → R) (hs : ∀ i, i ∉ s → c i = 0)
344+
(k : n) (hk : k ∉ s) (A_eq : ∀ i j, A i j = B i j + c i * B k j),
345+
det A = det B :=
346+
begin
347+
revert B,
348+
refine s.induction_on _ _,
349+
{ intros A c hs k hk A_eq,
350+
have : ∀ i, c i = 0,
351+
{ intros i,
352+
specialize hs i,
353+
contrapose! hs,
354+
simp [hs] },
355+
congr,
356+
ext i j,
357+
rw [A_eq, this, zero_mul, add_zero], },
358+
{ intros i s hi ih B c hs k hk A_eq,
359+
have hAi : A i = B i + c i • B k := funext (A_eq i),
360+
rw [@ih (update_row B i (A i)) (function.update c i 0), hAi,
361+
det_update_row_add_smul_self],
362+
{ exact mt (λ h, show k ∈ insert i s, from h ▸ finset.mem_insert_self _ _) hk },
363+
{ intros i' hi',
364+
rw function.update_apply,
365+
split_ifs with hi'i, { refl },
366+
{ exact hs i' (λ h, hi' ((finset.mem_insert.mp h).resolve_left hi'i)) } },
367+
{ exact λ h, hk (finset.mem_insert_of_mem h) },
368+
{ intros i' j',
369+
rw [update_row_apply, function.update_apply],
370+
split_ifs with hi'i,
371+
{ simp [hi'i] },
372+
rw [A_eq, update_row_ne (λ (h : k = i), hk $ h ▸ finset.mem_insert_self k s)] } }
373+
end
374+
375+
/-- If you add multiples of row `B k` to other rows, the determinant doesn't change. -/
376+
lemma det_eq_of_forall_row_eq_smul_add_const
377+
{A B : matrix n n R} (c : n → R) (k : n) (hk : c k = 0)
378+
(A_eq : ∀ i j, A i j = B i j + c i * B k j) :
379+
det A = det B :=
380+
det_eq_of_forall_row_eq_smul_add_const_aux c
381+
(λ i, not_imp_comm.mp $ λ hi, finset.mem_erase.mpr
382+
⟨mt (λ (h : i = k), show c i = 0, from h.symm ▸ hk) hi, finset.mem_univ i⟩)
383+
k (finset.not_mem_erase k finset.univ) A_eq
384+
385+
lemma det_eq_of_forall_row_eq_smul_add_pred_aux {n : ℕ} (k : fin (n + 1)) :
386+
∀ (c : fin n → R) (hc : ∀ (i : fin n), k < i.succ → c i = 0)
387+
{M N : matrix (fin n.succ) (fin n.succ) R}
388+
(h0 : ∀ j, M 0 j = N 0 j)
389+
(hsucc : ∀ (i : fin n) j, M i.succ j = N i.succ j + c i * M i.cast_succ j),
390+
det M = det N :=
391+
begin
392+
refine fin.induction _ (λ k ih, _) k;
393+
intros c hc M N h0 hsucc,
394+
{ congr,
395+
ext i j,
396+
refine fin.cases (h0 j) (λ i, _) i,
397+
rw [hsucc, hc i (fin.succ_pos _), zero_mul, add_zero] },
398+
399+
set M' := update_row M k.succ (N k.succ) with hM',
400+
have hM : M = update_row M' k.succ (M' k.succ + c k • M k.cast_succ),
401+
{ ext i j,
402+
by_cases hi : i = k.succ,
403+
{ simp [hi, hM', hsucc, update_row_self] },
404+
rw [update_row_ne hi, hM', update_row_ne hi] },
405+
406+
have k_ne_succ : k.cast_succ ≠ k.succ := (fin.cast_succ_lt_succ k).ne,
407+
have M_k : M k.cast_succ = M' k.cast_succ := (update_row_ne k_ne_succ).symm,
408+
409+
rw [hM, M_k, det_update_row_add_smul_self M' k_ne_succ.symm, ih (function.update c k 0)],
410+
{ intros i hi,
411+
rw [fin.lt_iff_coe_lt_coe, fin.coe_cast_succ, fin.coe_succ, nat.lt_succ_iff] at hi,
412+
rw function.update_apply,
413+
split_ifs with hik, { refl },
414+
exact hc _ (fin.succ_lt_succ_iff.mpr (lt_of_le_of_ne hi (ne.symm hik))) },
415+
{ rwa [hM', update_row_ne (fin.succ_ne_zero _).symm] },
416+
intros i j,
417+
rw function.update_apply,
418+
split_ifs with hik,
419+
{ rw [zero_mul, add_zero, hM', hik, update_row_self] },
420+
rw [hM', update_row_ne ((fin.succ_injective _).ne hik), hsucc],
421+
by_cases hik2 : k < i,
422+
{ simp [hc i (fin.succ_lt_succ_iff.mpr hik2)] },
423+
rw update_row_ne,
424+
apply ne_of_lt,
425+
rwa [fin.lt_iff_coe_lt_coe, fin.coe_cast_succ, fin.coe_succ, nat.lt_succ_iff, ← not_lt]
426+
end
427+
428+
/-- If you add multiples of previous rows to the next row, the determinant doesn't change. -/
429+
lemma det_eq_of_forall_row_eq_smul_add_pred {n : ℕ}
430+
{A B : matrix (fin (n + 1)) (fin (n + 1)) R} (c : fin n → R)
431+
(A_zero : ∀ j, A 0 j = B 0 j)
432+
(A_succ : ∀ (i : fin n) j, A i.succ j = B i.succ j + c i * A i.cast_succ j) :
433+
det A = det B :=
434+
det_eq_of_forall_row_eq_smul_add_pred_aux (fin.last _) c
435+
(λ i hi, absurd hi (not_lt_of_ge (fin.le_last _)))
436+
A_zero A_succ
437+
438+
/-- If you add multiples of previous columns to the next columns, the determinant doesn't change. -/
439+
lemma det_eq_of_forall_col_eq_smul_add_pred {n : ℕ}
440+
{A B : matrix (fin (n + 1)) (fin (n + 1)) R} (c : fin n → R)
441+
(A_zero : ∀ i, A i 0 = B i 0)
442+
(A_succ : ∀ i (j : fin n), A i j.succ = B i j.succ + c j * A i j.cast_succ) :
443+
det A = det B :=
444+
by { rw [← det_transpose A, ← det_transpose B],
445+
exact det_eq_of_forall_row_eq_smul_add_pred c A_zero (λ i j, A_succ j i) }
446+
447+
end det_eq
448+
287449
@[simp] lemma det_block_diagonal {o : Type*} [fintype o] [decidable_eq o] (M : o → matrix n n R) :
288450
(block_diagonal M).det = ∏ k, (M k).det :=
289451
begin

0 commit comments

Comments
 (0)