l3lab/ntp-mathlib huggingface dataset:
theorem coeff_charpoly_mem_ideal_pow {I : Ideal R} (h : ∀ i j, M i j ∈ I) (k : ℕ) :
    M.charpoly.coeff k ∈ I ^ (Fintype.card n - k) := by
  delta charpoly
  rw [Matrix.det_apply, finset_sum_coeff]
  apply sum_mem
  rintro c -
  rw [coeff_smul, Submodule.smul_mem_iff']
  have : ∑ x : n, 1 = Fintype.card n := by rw [Finset.sum_const, card_univ, smul_eq_mul, mul_one]
  rw [← this]
  apply coeff_prod_mem_ideal_pow_tsub
  rintro i - (_ | k)
  · rw [Nat.zero_eq]  -- porting note: `rw [Nat.zero_eq]` was not present
    rw [tsub_zero, pow_one, charmatrix_apply, coeff_sub, ← smul_one_eq_diagonal, smul_apply,
      smul_eq_mul, coeff_X_mul_zero, coeff_C_zero, zero_sub]
    

Proof state:
case h.h.zero
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
I : Ideal R
h : ∀ (i j : n), M i j ∈ I
k : ℕ
c : Equiv.Perm n
this : ∑ x : n, 1 = Fintype.card n
i : n
⊢ -M (c i) i ∈ I

Next tactic:
apply neg_mem
theorem coeff_charpoly_mem_ideal_pow {I : Ideal R} (h : ∀ i j, M i j ∈ I) (k : ℕ) :
    M.charpoly.coeff k ∈ I ^ (Fintype.card n - k) := by
  delta charpoly
  rw [Matrix.det_apply, finset_sum_coeff]
  apply sum_mem
  rintro c -
  rw [coeff_smul, Submodule.smul_mem_iff']
  have : ∑ x : n, 1 = Fintype.card n := by rw [Finset.sum_const, card_univ, smul_eq_mul, mul_one]
  rw [← this]
  apply coeff_prod_mem_ideal_pow_tsub
  rintro i - (_ | k)
  · rw [Nat.zero_eq]  -- porting note: `rw [Nat.zero_eq]` was not present
    rw [tsub_zero, pow_one, charmatrix_apply, coeff_sub, ← smul_one_eq_diagonal, smul_apply,
      smul_eq_mul, coeff_X_mul_zero, coeff_C_zero, zero_sub]
    apply neg_mem  -- porting note: was `rw [neg_mem_iff]`, but Lean could not synth `NegMemClass`
    

Proof state:
case h.h.zero.a
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
I : Ideal R
h : ∀ (i j : n), M i j ∈ I
k : ℕ
c : Equiv.Perm n
this : ∑ x : n, 1 = Fintype.card n
i : n
⊢ M (c i) i ∈ I

Next tactic:
exact h (c i) i
theorem coeff_charpoly_mem_ideal_pow {I : Ideal R} (h : ∀ i j, M i j ∈ I) (k : ℕ) :
    M.charpoly.coeff k ∈ I ^ (Fintype.card n - k) := by
  delta charpoly
  rw [Matrix.det_apply, finset_sum_coeff]
  apply sum_mem
  rintro c -
  rw [coeff_smul, Submodule.smul_mem_iff']
  have : ∑ x : n, 1 = Fintype.card n := by rw [Finset.sum_const, card_univ, smul_eq_mul, mul_one]
  rw [← this]
  apply coeff_prod_mem_ideal_pow_tsub
  rintro i - (_ | k)
  · rw [Nat.zero_eq]  -- porting note: `rw [Nat.zero_eq]` was not present
    rw [tsub_zero, pow_one, charmatrix_apply, coeff_sub, ← smul_one_eq_diagonal, smul_apply,
      smul_eq_mul, coeff_X_mul_zero, coeff_C_zero, zero_sub]
    apply neg_mem  -- porting note: was `rw [neg_mem_iff]`, but Lean could not synth `NegMemClass`
    exact h (c i) i
  · 

Proof state:
case h.h.succ
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
I : Ideal R
h : ∀ (i j : n), M i j ∈ I
k✝ : ℕ
c : Equiv.Perm n
this : ∑ x : n, 1 = Fintype.card n
i : n
k : ℕ
⊢ coeff (charmatrix M (c i) i) (Nat.succ k) ∈ I ^ (1 - Nat.succ k)

Next tactic:
rw [Nat.succ_eq_one_add, tsub_self_add, pow_zero, Ideal.one_eq_top]
theorem coeff_charpoly_mem_ideal_pow {I : Ideal R} (h : ∀ i j, M i j ∈ I) (k : ℕ) :
    M.charpoly.coeff k ∈ I ^ (Fintype.card n - k) := by
  delta charpoly
  rw [Matrix.det_apply, finset_sum_coeff]
  apply sum_mem
  rintro c -
  rw [coeff_smul, Submodule.smul_mem_iff']
  have : ∑ x : n, 1 = Fintype.card n := by rw [Finset.sum_const, card_univ, smul_eq_mul, mul_one]
  rw [← this]
  apply coeff_prod_mem_ideal_pow_tsub
  rintro i - (_ | k)
  · rw [Nat.zero_eq]  -- porting note: `rw [Nat.zero_eq]` was not present
    rw [tsub_zero, pow_one, charmatrix_apply, coeff_sub, ← smul_one_eq_diagonal, smul_apply,
      smul_eq_mul, coeff_X_mul_zero, coeff_C_zero, zero_sub]
    apply neg_mem  -- porting note: was `rw [neg_mem_iff]`, but Lean could not synth `NegMemClass`
    exact h (c i) i
  · rw [Nat.succ_eq_one_add, tsub_self_add, pow_zero, Ideal.one_eq_top]
    

Proof state:
case h.h.succ
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
I : Ideal R
h : ∀ (i j : n), M i j ∈ I
k✝ : ℕ
c : Equiv.Perm n
this : ∑ x : n, 1 = Fintype.card n
i : n
k : ℕ
⊢ coeff (charmatrix M (c i) i) (1 + k) ∈ ⊤

Next tactic:
exact Submodule.mem_top
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
M : Matrix n n R
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
nontriviality R
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
M : Matrix n n R
✝ : Nontrivial R
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
let t : R[T;T⁻¹] := T 1
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
let t_inv : R[T;T⁻¹] := T (-1)
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by 

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
⊢ t_inv * t = 1

Next tactic:
rw [← T_add, add_left_neg, T_zero]
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
have hp : toLaurentAlg M.charpoly = p := by
    simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  have hp : toLaurentAlg M.charpoly = p := by
    

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
⊢ toLaurentAlg (charpoly M) = p

Next tactic:
simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  have hp : toLaurentAlg M.charpoly = p := by
    simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
hp : toLaurentAlg (charpoly M) = p
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
have hq : toLaurentAlg M.charpolyRev = q := by
    simp [charpolyRev, AlgHom.map_det, map_sub, map_smul', smul_eq_diagonal_mul]
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  have hp : toLaurentAlg M.charpoly = p := by
    simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
  have hq : toLaurentAlg M.charpolyRev = q := by
    

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
hp : toLaurentAlg (charpoly M) = p
⊢ toLaurentAlg (charpolyRev M) = q

Next tactic:
simp [charpolyRev, AlgHom.map_det, map_sub, map_smul', smul_eq_diagonal_mul]
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  have hp : toLaurentAlg M.charpoly = p := by
    simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
  have hq : toLaurentAlg M.charpolyRev = q := by
    simp [charpolyRev, AlgHom.map_det, map_sub, map_smul', smul_eq_diagonal_mul]
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
hp : toLaurentAlg (charpoly M) = p
hq : toLaurentAlg (charpolyRev M) = q
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
suffices : t_inv ^ Fintype.card n * p = invert q
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  have hp : toLaurentAlg M.charpoly = p := by
    simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
  have hq : toLaurentAlg M.charpolyRev = q := by
    simp [charpolyRev, AlgHom.map_det, map_sub, map_smul', smul_eq_diagonal_mul]
  suffices : t_inv ^ Fintype.card n * p = invert q
  · 

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
hp : toLaurentAlg (charpoly M) = p
hq : toLaurentAlg (charpolyRev M) = q
this : t_inv ^ Fintype.card n * p = invert q
⊢ reverse (charpoly M) = charpolyRev M

Next tactic:
apply toLaurent_injective
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  have hp : toLaurentAlg M.charpoly = p := by
    simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
  have hq : toLaurentAlg M.charpolyRev = q := by
    simp [charpolyRev, AlgHom.map_det, map_sub, map_smul', smul_eq_diagonal_mul]
  suffices : t_inv ^ Fintype.card n * p = invert q
  · apply toLaurent_injective
    

Proof state:
case a
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
hp : toLaurentAlg (charpoly M) = p
hq : toLaurentAlg (charpolyRev M) = q
this : t_inv ^ Fintype.card n * p = invert q
⊢ toLaurent (reverse (charpoly M)) = toLaurent (charpolyRev M)

Next tactic:
rwa [toLaurent_reverse, ← coe_toLaurentAlg, hp, hq, ← involutive_invert.injective.eq_iff,
      invert.map_mul, involutive_invert p, charpoly_natDegree_eq_dim,
      ← mul_one (Fintype.card n : ℤ), ← T_pow, invert.map_pow, invert_T, mul_comm]
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  have hp : toLaurentAlg M.charpoly = p := by
    simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
  have hq : toLaurentAlg M.charpolyRev = q := by
    simp [charpolyRev, AlgHom.map_det, map_sub, map_smul', smul_eq_diagonal_mul]
  suffices : t_inv ^ Fintype.card n * p = invert q
  · apply toLaurent_injective
    rwa [toLaurent_reverse, ← coe_toLaurentAlg, hp, hq, ← involutive_invert.injective.eq_iff,
      invert.map_mul, involutive_invert p, charpoly_natDegree_eq_dim,
      ← mul_one (Fintype.card n : ℤ), ← T_pow, invert.map_pow, invert_T, mul_comm]
  

Proof state:
case this
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
hp : toLaurentAlg (charpoly M) = p
hq : toLaurentAlg (charpolyRev M) = q
⊢ t_inv ^ Fintype.card n * p = invert q

Next tactic:
rw [← det_smul, smul_sub, scalar_apply, ← diagonal_smul, Pi.smul_def, smul_eq_mul, ht,
    diagonal_one, invert.map_det]
lemma reverse_charpoly (M : Matrix n n R) :
    M.charpoly.reverse = M.charpolyRev := by
  nontriviality R
  let t : R[T;T⁻¹] := T 1
  let t_inv : R[T;T⁻¹] := T (-1)
  let p : R[T;T⁻¹] := det (scalar n t - M.map LaurentPolynomial.C)
  let q : R[T;T⁻¹] := det (1 - scalar n t * M.map LaurentPolynomial.C)
  have ht : t_inv * t = 1 := by rw [← T_add, add_left_neg, T_zero]
  have hp : toLaurentAlg M.charpoly = p := by
    simp [charpoly, charmatrix, AlgHom.map_det, map_sub, map_smul']
  have hq : toLaurentAlg M.charpolyRev = q := by
    simp [charpolyRev, AlgHom.map_det, map_sub, map_smul', smul_eq_diagonal_mul]
  suffices : t_inv ^ Fintype.card n * p = invert q
  · apply toLaurent_injective
    rwa [toLaurent_reverse, ← coe_toLaurentAlg, hp, hq, ← involutive_invert.injective.eq_iff,
      invert.map_mul, involutive_invert p, charpoly_natDegree_eq_dim,
      ← mul_one (Fintype.card n : ℤ), ← T_pow, invert.map_pow, invert_T, mul_comm]
  rw [← det_smul, smul_sub, scalar_apply, ← diagonal_smul, Pi.smul_def, smul_eq_mul, ht,
    diagonal_one, invert.map_det]
  

Proof state:
case this
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
M : Matrix n n R
✝ : Nontrivial R
t : R[T;T⁻¹] := T 1
t_inv : R[T;T⁻¹] := T (-1)
p : R[T;T⁻¹] := det ((scalar n) t - map M ⇑LaurentPolynomial.C)
q : R[T;T⁻¹] := det (1 - (scalar n) t * map M ⇑LaurentPolynomial.C)
ht : t_inv * t = 1
hp : toLaurentAlg (charpoly M) = p
hq : toLaurentAlg (charpolyRev M) = q
⊢ det (1 - t_inv • map M ⇑LaurentPolynomial.C) =
    det ((AlgEquiv.mapMatrix invert) (1 - (scalar n) t * map M ⇑LaurentPolynomial.C))

Next tactic:
simp [map_smul', smul_eq_diagonal_mul]
@[simp] lemma eval_charpolyRev :
    eval 0 M.charpolyRev = 1 := by
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ eval 0 (charpolyRev M) = 1

Next tactic:
rw [charpolyRev, ← coe_evalRingHom, RingHom.map_det, ← det_one (R := R) (n := n)]
@[simp] lemma eval_charpolyRev :
    eval 0 M.charpolyRev = 1 := by
  rw [charpolyRev, ← coe_evalRingHom, RingHom.map_det, ← det_one (R := R) (n := n)]
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ det ((RingHom.mapMatrix (evalRingHom 0)) (1 - X • map M ⇑C)) = det 1

Next tactic:
have : (1 - (X : R[X]) • M.map C).map (eval 0) = 1 := by
    ext i j; rcases eq_or_ne i j with hij | hij <;> simp [hij]
@[simp] lemma eval_charpolyRev :
    eval 0 M.charpolyRev = 1 := by
  rw [charpolyRev, ← coe_evalRingHom, RingHom.map_det, ← det_one (R := R) (n := n)]
  have : (1 - (X : R[X]) • M.map C).map (eval 0) = 1 := by
    

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ map (1 - X • map M ⇑C) (eval 0) = 1

Next tactic:
ext i j
@[simp] lemma eval_charpolyRev :
    eval 0 M.charpolyRev = 1 := by
  rw [charpolyRev, ← coe_evalRingHom, RingHom.map_det, ← det_one (R := R) (n := n)]
  have : (1 - (X : R[X]) • M.map C).map (eval 0) = 1 := by
    ext i j; 

Proof state:
case a.h
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
i j : n
⊢ map (1 - X • map M ⇑C) (eval 0) i j = OfNat.ofNat 1 i j

Next tactic:
rcases eq_or_ne i j with hij | hij
@[simp] lemma eval_charpolyRev :
    eval 0 M.charpolyRev = 1 := by
  rw [charpolyRev, ← coe_evalRingHom, RingHom.map_det, ← det_one (R := R) (n := n)]
  have : (1 - (X : R[X]) • M.map C).map (eval 0) = 1 := by
    ext i j; rcases eq_or_ne i j with hij | hij <;> 

Proof state:
case a.h.inl
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
i j : n
hij : i = j
⊢ map (1 - X • map M ⇑C) (eval 0) i j = OfNat.ofNat 1 i j

Next tactic:
simp [hij]
@[simp] lemma eval_charpolyRev :
    eval 0 M.charpolyRev = 1 := by
  rw [charpolyRev, ← coe_evalRingHom, RingHom.map_det, ← det_one (R := R) (n := n)]
  have : (1 - (X : R[X]) • M.map C).map (eval 0) = 1 := by
    ext i j; rcases eq_or_ne i j with hij | hij <;> 

Proof state:
case a.h.inr
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
i j : n
hij : i ≠ j
⊢ map (1 - X • map M ⇑C) (eval 0) i j = OfNat.ofNat 1 i j

Next tactic:
simp [hij]
@[simp] lemma eval_charpolyRev :
    eval 0 M.charpolyRev = 1 := by
  rw [charpolyRev, ← coe_evalRingHom, RingHom.map_det, ← det_one (R := R) (n := n)]
  have : (1 - (X : R[X]) • M.map C).map (eval 0) = 1 := by
    ext i j; rcases eq_or_ne i j with hij | hij <;> simp [hij]
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
this : map (1 - X • map M ⇑C) (eval 0) = 1
⊢ det ((RingHom.mapMatrix (evalRingHom 0)) (1 - X • map M ⇑C)) = det 1

Next tactic:
congr
@[simp] lemma coeff_charpolyRev_eq_neg_trace (M : Matrix n n R) :
    coeff M.charpolyRev 1 = - trace M := by
  

Proof state:
R : Type u
inst✝⁴ : CommRing R
n G : Type v
inst✝³ : DecidableEq n
inst✝² : Fintype n
α β : Type v
inst✝¹ : DecidableEq α
M✝ : Matrix n n R
p : ℕ
inst✝ : Fact (Nat.Prime p)
M : Matrix n n R
⊢ coeff (charpolyRev M) 1 = -trace M

Next tactic:
nontriviality R