-- Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det

Proof state:
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
σ : n × o ≃ n × o
hσ : ∀ (x : n × o), (σ x).2 = x.2
x : n × o
⊢ (σ⁻¹ x).2 = x.2

Tactic:
conv_rhs => rw [← Perm.apply_inv_self σ x, hσ]

Result:
no goals

Proof state:
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
⊢ ∑ x ∈ preserving_snd, ↑↑(sign x) * ∏ i : n × o, blockDiagonal M (x i) i =
    ∑ x : (a : o) → a ∈ univ → Perm n, ∏ x_1 : o, ↑↑(sign (x x_1 ⋯)) * ∏ x_2 : n, M x_1 ((x x_1 ⋯) x_2) x_2

Tactic:
refine (Finset.sum_bij (fun σ _ => prodCongrLeft fun k ↦ σ k (mem_univ k)) ?_ ?_ ?_ ?_).symm

Result:
case refine_1
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
⊢ ∀ (a : (a : o) → a ∈ univ → Perm n) (ha : a ∈ univ), (fun σ x => prodCongrLeft fun k => σ k ⋯) a ha ∈ preserving_snd

case refine_2
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
⊢ ∀ (a₁ : (a : o) → a ∈ univ → Perm n) (ha₁ : a₁ ∈ univ) (a₂ : (a : o) → a ∈ univ → Perm n) (ha₂ : a₂ ∈ univ),
    (fun σ x => prodCongrLeft fun k => σ k ⋯) a₁ ha₁ = (fun σ x => prodCongrLeft fun k => σ k ⋯) a₂ ha₂ → a₁ = a₂

case refine_3
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
⊢ ∀ b ∈ preserving_snd, ∃ a, ∃ (ha : a ∈ univ), (fun σ x => prodCongrLeft fun k => σ k ⋯) a ha = b

case refine_4
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
⊢ ∀ (a : (a : o) → a ∈ univ → Perm n) (ha : a ∈ univ),
    ∏ x : o, ↑↑(sign (a x ⋯)) * ∏ x_1 : n, M x ((a x ⋯) x_1) x_1 =
      ↑↑(sign ((fun σ x => prodCongrLeft fun k => σ k ⋯) a ha)) *
        ∏ i : n × o, blockDiagonal M (((fun σ x => prodCongrLeft fun k => σ k ⋯) a ha) i) i

Proof state:
case refine_4
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
σ : (a : o) → a ∈ univ → Perm n
ha✝ : σ ∈ univ
⊢ ∏ x : o, ↑↑(sign (σ x ⋯)) * ∏ x_1 : n, M x ((σ x ⋯) x_1) x_1 =
    ↑↑(sign ((fun σ x => prodCongrLeft fun k => σ k ⋯) σ ha✝)) *
      ∏ i : n × o, blockDiagonal M (((fun σ x => prodCongrLeft fun k => σ k ⋯) σ ha✝) i) i

Tactic:
rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]

Result:
case refine_4
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
σ : (a : o) → a ∈ univ → Perm n
ha✝ : σ ∈ univ
⊢ (∏ x : o, ↑↑(sign (σ x ⋯))) * ∏ x : o, ∏ x_1 : n, M x ((σ x ⋯) x_1) x_1 =
    ↑↑(sign ((fun σ x => prodCongrLeft fun k => σ k ⋯) σ ha✝)) *
      ∏ y : o, ∏ x : n, blockDiagonal M (((fun σ x => prodCongrLeft fun k => σ k ⋯) σ ha✝) (x, y)) (x, y)

Proof state:
case refine_3
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
σ : n × o ≃ n × o
hσ : ∀ (x : n × o), (σ x).2 = x.2
⊢ ∃ a, ∃ (ha : a ∈ univ), (fun σ x => prodCongrLeft fun k => σ k ⋯) a ha = σ

Tactic:
have hσ' : ∀ x, (σ⁻¹ x).snd = x.snd := by
  intro x
  conv_rhs => rw [← Perm.apply_inv_self σ x, hσ]

Result:
case refine_3
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
σ : n × o ≃ n × o
hσ : ∀ (x : n × o), (σ x).2 = x.2
hσ' : ∀ (x : n × o), (σ⁻¹ x).2 = x.2
⊢ ∃ a, ∃ (ha : a ∈ univ), (fun σ x => prodCongrLeft fun k => σ k ⋯) a ha = σ

Proof state:
case refine_3.refine_4.H.mk.fst
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
σ : n × o ≃ n × o
hσ : ∀ (x : n × o), (σ x).2 = x.2
hσ' : ∀ (x : n × o), (σ⁻¹ x).2 = x.2
mk_apply_eq : ∀ (k : o) (x : n), ((σ (x, k)).1, k) = σ (x, k)
mk_inv_apply_eq : ∀ (k : o) (x : n), ((σ⁻¹ (x, k)).1, k) = σ⁻¹ (x, k)
k : n
x : o
⊢ (((fun σ x => prodCongrLeft fun k => σ k ⋯)
          (fun k x =>
            { toFun := fun x => (σ (x, k)).1, invFun := fun x => (σ⁻¹ (x, k)).1, left_inv := ⋯, right_inv := ⋯ })
          ⋯)
        (k, x)).1 =
    (σ (k, x)).1

Tactic:
simp only [coe_fn_mk, prodCongrLeft_apply]

Result:
no goals

Proof state:
case refine_2.h.h.H
n : Type u_2
inst✝⁴ : DecidableEq n
inst✝³ : Fintype n
R : Type v
inst✝² : CommRing R
o : Type u_3
inst✝¹ : Fintype o
inst✝ : DecidableEq o
M : o → Matrix n n R
preserving_snd : Finset (Perm (n × o)) := filter (fun σ => ∀ (x : n × o), (σ x).2 = x.2) univ
mem_preserving_snd : ∀ {σ : Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ (x : n × o), (σ x).2 = x.2
σ : (a : o) → a ∈ univ → Perm n
ha₁✝ : σ ∈ univ
σ' : (a : o) → a ∈ univ → Perm n
ha₂✝ : σ' ∈ univ
eq : (prodCongrLeft fun k => σ k ⋯) = prodCongrLeft fun k => σ' k ⋯
x : o
hx : x ∈ univ
k : n
this : ∀ (k : n) (x : o), (σ x ⋯) k = (σ' x ⋯) k ∧ True
⊢ (σ x hx) k = (σ' x hx) k

Tactic:
exact (this k x).1

Result:
no goals