|
| 1 | +/- |
| 2 | +Copyright (c) 2020 Aaron Anderson, Jalex Stark. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Author: Aaron Anderson, Jalex Stark. |
| 5 | +-/ |
| 6 | + |
| 7 | +import linear_algebra.char_poly |
| 8 | +import linear_algebra.matrix |
| 9 | +import ring_theory.polynomial.basic |
| 10 | +import algebra.polynomial.big_operators |
| 11 | +import group_theory.perm.cycles |
| 12 | + |
| 13 | +/-! |
| 14 | +# Characteristic polynomials |
| 15 | +
|
| 16 | +We give methods for computing coefficients of the characteristic polynomial. |
| 17 | +
|
| 18 | +## Main definitions |
| 19 | +
|
| 20 | +- `char_poly_degree_eq_dim` proves that the degree of the characteristic polynomial |
| 21 | + over a nonzero ring is the dimension of the matrix |
| 22 | +- `det_eq_sign_char_poly_coeff` proves that the determinant is the constant term of the characteristic |
| 23 | + polynomial, up to sign. |
| 24 | +- `trace_eq_neg_char_poly_coeff` proves that the trace is the negative of the (d-1)th coefficient of the |
| 25 | + characteristic polynomial, where d is the dimension of the matrix. |
| 26 | + For a nonzero ring, this is the second-highest coefficient. |
| 27 | +
|
| 28 | +-/ |
| 29 | + |
| 30 | +noncomputable theory |
| 31 | + |
| 32 | +universes u v w z |
| 33 | + |
| 34 | +open polynomial matrix |
| 35 | +open_locale big_operators |
| 36 | + |
| 37 | +variables {R : Type u} [comm_ring R] |
| 38 | +variables {n G : Type v} [fintype n] [decidable_eq n] |
| 39 | +variables {α β : Type v} [decidable_eq α] |
| 40 | + |
| 41 | + |
| 42 | +open finset |
| 43 | +open polynomial |
| 44 | + |
| 45 | +variable {M : matrix n n R} |
| 46 | + |
| 47 | +lemma char_matrix_apply_nat_degree [nontrivial R] (i j : n) : |
| 48 | + (char_matrix M i j).nat_degree = ite (i = j) 1 0 := |
| 49 | +by { by_cases i = j; simp [h, ← degree_eq_iff_nat_degree_eq_of_pos (nat.succ_pos 0)], } |
| 50 | + |
| 51 | +lemma char_matrix_apply_nat_degree_le (i j : n) : |
| 52 | + (char_matrix M i j).nat_degree ≤ ite (i = j) 1 0 := |
| 53 | +by split_ifs; simp [h, nat_degree_X_sub_C_le] |
| 54 | + |
| 55 | +variable (M) |
| 56 | +lemma char_poly_sub_diagonal_degree_lt : |
| 57 | +(char_poly M - ∏ (i : n), (X - C (M i i))).degree < ↑(fintype.card n - 1) := |
| 58 | +begin |
| 59 | + rw [char_poly, det, ← insert_erase (mem_univ (equiv.refl n)), |
| 60 | + sum_insert (not_mem_erase (equiv.refl n) univ), add_comm], |
| 61 | + simp only [char_matrix_apply_eq, one_mul, equiv.perm.sign_refl, id.def, int.cast_one, |
| 62 | + units.coe_one, add_sub_cancel, equiv.coe_refl], |
| 63 | + rw ← mem_degree_lt, apply submodule.sum_mem (degree_lt R (fintype.card n - 1)), |
| 64 | + intros c hc, rw [← C_eq_int_cast, C_mul'], |
| 65 | + apply submodule.smul_mem (degree_lt R (fintype.card n - 1)) ↑↑(equiv.perm.sign c), |
| 66 | + rw mem_degree_lt, apply lt_of_le_of_lt degree_le_nat_degree _, rw with_bot.coe_lt_coe, |
| 67 | + apply lt_of_le_of_lt _ (equiv.perm.fixed_point_card_lt_of_ne_one (ne_of_mem_erase hc)), |
| 68 | + apply le_trans (polynomial.nat_degree_prod_le univ (λ i : n, (char_matrix M (c i) i))) _, |
| 69 | + rw card_eq_sum_ones, rw sum_filter, apply sum_le_sum, |
| 70 | + intros, apply char_matrix_apply_nat_degree_le, |
| 71 | +end |
| 72 | + |
| 73 | +lemma char_poly_coeff_eq_prod_coeff_of_le {k : ℕ} (h : fintype.card n - 1 ≤ k) : |
| 74 | + (char_poly M).coeff k = (∏ i : n, (X - C (M i i))).coeff k := |
| 75 | +begin |
| 76 | + apply eq_of_sub_eq_zero, rw ← coeff_sub, apply polynomial.coeff_eq_zero_of_degree_lt, |
| 77 | + apply lt_of_lt_of_le (char_poly_sub_diagonal_degree_lt M) _, rw with_bot.coe_le_coe, apply h, |
| 78 | +end |
| 79 | + |
| 80 | +lemma det_of_card_zero (h : fintype.card n = 0) (M : matrix n n R) : M.det = 1 := |
| 81 | +by { rw fintype.card_eq_zero_iff at h, suffices : M = 1, { simp [this] }, ext, tauto } |
| 82 | + |
| 83 | + |
| 84 | +theorem char_poly_degree_eq_dim [nontrivial R] (M : matrix n n R) : |
| 85 | +(char_poly M).degree = fintype.card n := |
| 86 | +begin |
| 87 | + by_cases fintype.card n = 0, rw h, unfold char_poly, rw det_of_card_zero, simpa, |
| 88 | + rw ← sub_add_cancel (char_poly M) (∏ (i : n), (X - C (M i i))), |
| 89 | + have h1 : (∏ (i : n), (X - C (M i i))).degree = fintype.card n, |
| 90 | + { rw degree_eq_iff_nat_degree_eq_of_pos, swap, apply nat.pos_of_ne_zero h, |
| 91 | + rw nat_degree_prod', simp_rw nat_degree_X_sub_C, unfold fintype.card, simp, |
| 92 | + simp_rw (monic_X_sub_C _).leading_coeff, simp, }, |
| 93 | + rw degree_add_eq_of_degree_lt, exact h1, rw h1, |
| 94 | + apply lt_trans (char_poly_sub_diagonal_degree_lt M), rw with_bot.coe_lt_coe, |
| 95 | + rw ← nat.pred_eq_sub_one, apply nat.pred_lt, apply h, |
| 96 | +end |
| 97 | + |
| 98 | +theorem char_poly_nat_degree_eq_dim [nontrivial R] (M : matrix n n R) : |
| 99 | + (char_poly M).nat_degree = fintype.card n := |
| 100 | +nat_degree_eq_of_degree_eq_some (char_poly_degree_eq_dim M) |
| 101 | + |
| 102 | +lemma char_poly_monic_of_nontrivial [nontrivial R] (M : matrix n n R) : |
| 103 | + monic (char_poly M) := |
| 104 | +begin |
| 105 | + by_cases fintype.card n = 0, rw [char_poly, det_of_card_zero h], apply monic_one, |
| 106 | + have mon : (∏ (i : n), (X - C (M i i))).monic, |
| 107 | + { apply monic_prod_of_monic univ (λ i : n, (X - C (M i i))), simp [monic_X_sub_C], }, |
| 108 | + rw ← sub_add_cancel (∏ (i : n), (X - C (M i i))) (char_poly M) at mon, |
| 109 | + rw monic at *, rw leading_coeff_add_of_degree_lt at mon, rw ← mon, |
| 110 | + rw char_poly_degree_eq_dim, rw ← neg_sub, rw degree_neg, |
| 111 | + apply lt_trans (char_poly_sub_diagonal_degree_lt M), rw with_bot.coe_lt_coe, |
| 112 | + rw ← nat.pred_eq_sub_one, apply nat.pred_lt, apply h, |
| 113 | +end |
| 114 | + |
| 115 | +lemma char_poly_monic (M : matrix n n R) : |
| 116 | + monic (char_poly M) := |
| 117 | +begin |
| 118 | + classical, by_cases h : nontrivial R, |
| 119 | + { letI := h, apply char_poly_monic_of_nontrivial, }, |
| 120 | + { rw nontrivial_iff at h, push_neg at h, apply h, } |
| 121 | +end |
| 122 | + |
| 123 | +theorem trace_eq_neg_char_poly_coeff [nonempty n] (M : matrix n n R) : |
| 124 | + (matrix.trace n R R) M = -(char_poly M).coeff (fintype.card n - 1) := |
| 125 | +begin |
| 126 | + by_cases nontrivial R; try { rw not_nontrivial_iff_subsingleton at h }; haveI := h, swap, |
| 127 | + { apply subsingleton.elim }, |
| 128 | + rw char_poly_coeff_eq_prod_coeff_of_le, swap, refl, |
| 129 | + rw [fintype.card, prod_X_sub_C_coeff_card_pred univ (λ i : n, M i i)], simp, |
| 130 | + rw [← fintype.card, fintype.card_pos_iff], apply_instance, |
| 131 | +end |
| 132 | + |
| 133 | +-- I feel like this should use polynomial.alg_hom_eval₂_algebra_map |
| 134 | +lemma mat_poly_equiv_eval (M : matrix n n (polynomial R)) (r : R) (i j : n) : |
| 135 | + (mat_poly_equiv M).eval ((scalar n) r) i j = (M i j).eval r := |
| 136 | +begin |
| 137 | + unfold polynomial.eval, unfold eval₂, |
| 138 | + transitivity finsupp.sum (mat_poly_equiv M) (λ (e : ℕ) (a : matrix n n R), |
| 139 | + (a * (scalar n) r ^ e) i j), |
| 140 | + { unfold finsupp.sum, rw sum_apply, rw sum_apply, dsimp, refl, }, |
| 141 | + { simp_rw ← (scalar n).map_pow, simp_rw ← (matrix.scalar.commute _ _).eq, |
| 142 | + simp only [coe_scalar, matrix.one_mul, ring_hom.id_apply, |
| 143 | + smul_val, mul_eq_mul, algebra.smul_mul_assoc], |
| 144 | + have h : ∀ x : ℕ, (λ (e : ℕ) (a : R), r ^ e * a) x 0 = 0 := by simp, |
| 145 | + symmetry, rw ← finsupp.sum_map_range_index h, swap, refl, |
| 146 | + refine congr (congr rfl _) (by {ext, rw mul_comm}), ext, rw finsupp.map_range_apply, |
| 147 | + simp [apply_eq_coeff], } |
| 148 | +end |
| 149 | + |
| 150 | +lemma eval_det (M : matrix n n (polynomial R)) (r : R) : |
| 151 | + polynomial.eval r M.det = (polynomial.eval (matrix.scalar n r) (mat_poly_equiv M)).det := |
| 152 | +begin |
| 153 | + rw [polynomial.eval, ← coe_eval₂_ring_hom, ring_hom.map_det], |
| 154 | + apply congr_arg det, ext, symmetry, convert mat_poly_equiv_eval _ _ _ _, |
| 155 | +end |
| 156 | + |
| 157 | +theorem det_eq_sign_char_poly_coeff (M : matrix n n R) : |
| 158 | + M.det = (-1)^(fintype.card n) * (char_poly M).coeff 0:= |
| 159 | +begin |
| 160 | + rw [coeff_zero_eq_eval_zero, char_poly, eval_det, mat_poly_equiv_char_matrix, ← det_smul], |
| 161 | + simp |
| 162 | +end |
0 commit comments