-- Mathlib/LinearAlgebra/PID.lean
/-- If a linear endomorphism of a (finite, free) module `M` takes values in a submodule `p ⊆ M`,
then the trace of its restriction to `p` is equal to its trace on `M`. -/
lemma trace_restrict_eq_of_forall_mem [IsDomain R] [IsPrincipalIdealRing R]
    (p : Submodule R M) (f : M →ₗ[R] M)
    (hf : ∀ x, f x ∈ p) (hf' : ∀ x ∈ p, f x ∈ p := fun x _ ↦ hf x) :
    trace R p (f.restrict hf') = trace R M f

Proof state:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
⊢ ((toMatrix snf.bN snf.bN) (f.restrict hf')).trace = ((toMatrix snf.bM snf.bM) f).trace

Tactic:
set A : Matrix (Fin n) (Fin n) R := toMatrix snf.bN snf.bN (f.restrict hf')

Result:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
A : Matrix (Fin n) (Fin n) R := (toMatrix snf.bN snf.bN) (f.restrict hf')
⊢ A.trace = ((toMatrix snf.bM snf.bM) f).trace

Proof state:
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
⊢ (trace R ↥p) (f.restrict hf') = (trace R M) f

Tactic:
let ι := Module.Free.ChooseBasisIndex R M

Result:
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
⊢ (trace R ↥p) (f.restrict hf') = (trace R M) f

Proof state:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
A : Matrix (Fin n) (Fin n) R := (toMatrix snf.bN snf.bN) (f.restrict hf')
B : Matrix ι ι R := (toMatrix snf.bM snf.bM) f
⊢ A.trace = B.trace

Tactic:
have aux : ∀ i, B i i ≠ 0 → i ∈ Set.range snf.f := fun i hi ↦ by
  contrapose! hi; exact snf.repr_eq_zero_of_nmem_range ⟨_, (hf _)⟩ hi

Result:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
A : Matrix (Fin n) (Fin n) R := (toMatrix snf.bN snf.bN) (f.restrict hf')
B : Matrix ι ι R := (toMatrix snf.bM snf.bM) f
aux : ∀ (i : ι), B i i ≠ 0 → i ∈ Set.range ⇑snf.f
⊢ A.trace = B.trace

Proof state:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
A : Matrix (Fin n) (Fin n) R := (toMatrix snf.bN snf.bN) (f.restrict hf')
B : Matrix ι ι R := (toMatrix snf.bM snf.bM) f
aux : ∀ (i : ι), B i i ≠ 0 → i ∈ Set.range ⇑snf.f
⊢ ∑ i : Fin n, A i i = ∑ x ∈ Finset.filter (fun x => x ∈ Set.range ⇑snf.f) Finset.univ, B x x

Tactic:
simp [A, B]

Result:
no goals

Proof state:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
⊢ (trace R ↥p) (f.restrict hf') = (trace R M) f

Tactic:
rw [trace_eq_matrix_trace R snf.bM, trace_eq_matrix_trace R snf.bN]

Result:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
⊢ ((toMatrix snf.bN snf.bN) (f.restrict hf')).trace = ((toMatrix snf.bM snf.bM) f).trace

Proof state:
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
⊢ (trace R ↥p) (f.restrict hf') = (trace R M) f

Tactic:
obtain ⟨n, snf : Basis.SmithNormalForm p ι n⟩ := p.smithNormalForm (Module.Free.chooseBasis R M)

Result:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
⊢ (trace R ↥p) (f.restrict hf') = (trace R M) f

Proof state:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
A : Matrix (Fin n) (Fin n) R := (toMatrix snf.bN snf.bN) (f.restrict hf')
B : Matrix ι ι R := (toMatrix snf.bM snf.bM) f
aux : ∀ (i : ι), B i i ≠ 0 → i ∈ Set.range ⇑snf.f
⊢ A.trace = B.trace

Tactic:
change ∑ i, A i i = ∑ i, B i i

Result:
case mk
R : Type u_1
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : Module.Finite R M
inst✝² : Module.Free R M
inst✝¹ : IsDomain R
inst✝ : IsPrincipalIdealRing R
p : Submodule R M
f : M →ₗ[R] M
hf : ∀ (x : M), f x ∈ p
hf' : optParam (∀ x ∈ p, f x ∈ p) ⋯
ι : Type u_2 := Module.Free.ChooseBasisIndex R M
n : ℕ
snf : Basis.SmithNormalForm p ι n
A : Matrix (Fin n) (Fin n) R := (toMatrix snf.bN snf.bN) (f.restrict hf')
B : Matrix ι ι R := (toMatrix snf.bM snf.bM) f
aux : ∀ (i : ι), B i i ≠ 0 → i ∈ Set.range ⇑snf.f
⊢ ∑ i : Fin n, A i i = ∑ i : ι, B i i