l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    

Proof state:
case h.h.H
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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
σ σ' : (k : o) → k ∈ univ → Perm n
ha₁✝ : σ ∈ univ
ha₂✝ : σ' ∈ univ
eq :
  (fun σ x => prodCongrLeft fun k => σ k (_ : k ∈ univ)) σ ha₁✝ =
    (fun σ x => prodCongrLeft fun k => σ k (_ : k ∈ univ)) σ' ha₂✝
x : o
hx : x ∈ univ
k : n
⊢ (σ x hx) k = (σ' x hx) k

Next tactic:
simp only at eq
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    

Proof state:
case h.h.H
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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
σ σ' : (k : o) → k ∈ univ → Perm n
ha₁✝ : σ ∈ univ
ha₂✝ : σ' ∈ univ
eq : (prodCongrLeft fun k => σ k (_ : k ∈ univ)) = prodCongrLeft fun k => σ' k (_ : k ∈ univ)
x : o
hx : x ∈ univ
k : n
⊢ (σ x hx) k = (σ' x hx) k

Next tactic:
have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by rw [eq]
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by 

Proof state:
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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
σ σ' : (k : o) → k ∈ univ → Perm n
ha₁✝ : σ ∈ univ
ha₂✝ : σ' ∈ univ
eq : (prodCongrLeft fun k => σ k (_ : k ∈ univ)) = prodCongrLeft fun k => σ' k (_ : k ∈ univ)
x✝ : o
hx : x✝ ∈ univ
k✝ k : n
x : o
⊢ (prodCongrLeft fun k => σ k (_ : k ∈ univ)) (k, x) = (prodCongrLeft fun k => σ' k (_ : k ∈ univ)) (k, x)

Next tactic:
rw [eq]
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by rw [eq]
    

Proof state:
case h.h.H
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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
σ σ' : (k : o) → k ∈ univ → Perm n
ha₁✝ : σ ∈ univ
ha₂✝ : σ' ∈ univ
eq : (prodCongrLeft fun k => σ k (_ : k ∈ univ)) = prodCongrLeft fun k => σ' k (_ : k ∈ univ)
x : o
hx : x ∈ univ
k : n
this :
  ∀ (k : n) (x : o),
    (prodCongrLeft fun k => σ k (_ : k ∈ univ)) (k, x) = (prodCongrLeft fun k => σ' k (_ : k ∈ univ)) (k, x)
⊢ (σ x hx) k = (σ' x hx) k

Next tactic:
simp only [prodCongrLeft_apply, Prod.mk.inj_iff] at this
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by rw [eq]
    simp only [prodCongrLeft_apply, Prod.mk.inj_iff] at this
    

Proof state:
case h.h.H
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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
σ σ' : (k : o) → k ∈ univ → Perm n
ha₁✝ : σ ∈ univ
ha₂✝ : σ' ∈ univ
eq : (prodCongrLeft fun k => σ k (_ : k ∈ univ)) = prodCongrLeft fun k => σ' k (_ : k ∈ univ)
x : o
hx : x ∈ univ
k : n
this : ∀ (k : n) (x : o), (σ x (_ : x ∈ univ)) k = (σ' x (_ : x ∈ univ)) k ∧ True
⊢ (σ x hx) k = (σ' x hx) k

Next tactic:
exact (this k x).1
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by rw [eq]
    simp only [prodCongrLeft_apply, Prod.mk.inj_iff] at this
    exact (this k x).1
  · 

Proof state:
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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), b = (fun σ x => prodCongrLeft fun k => σ k (_ : k ∈ univ)) a ha

Next tactic:
intro σ hσ
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by rw [eq]
    simp only [prodCongrLeft_apply, Prod.mk.inj_iff] at this
    exact (this k x).1
  · intro σ hσ
    

Proof state:
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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σ : σ ∈ preserving_snd
⊢ ∃ a, ∃ (ha : a ∈ univ), σ = (fun σ x => prodCongrLeft fun k => σ k (_ : k ∈ univ)) a ha

Next tactic:
rw [mem_preserving_snd] at hσ
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by rw [eq]
    simp only [prodCongrLeft_apply, Prod.mk.inj_iff] at this
    exact (this k x).1
  · intro σ hσ
    rw [mem_preserving_snd] at hσ
    

Proof state:
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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 (_ : k ∈ univ)) a ha

Next tactic:
have hσ' : ∀ x, (σ⁻¹ x).snd = x.snd := by
      intro x
      conv_rhs => rw [← Perm.apply_inv_self σ x, hσ]
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by rw [eq]
    simp only [prodCongrLeft_apply, Prod.mk.inj_iff] at this
    exact (this k x).1
  · intro σ hσ
    rw [mem_preserving_snd] at hσ
    have hσ' : ∀ x, (σ⁻¹ x).snd = x.snd := by
      

Proof state:
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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

Next tactic:
intro x
@[simp]
theorem det_blockDiagonal {o : Type*} [Fintype o] [DecidableEq o] (M : o → Matrix n n R) :
    (blockDiagonal M).det = ∏ k, (M k).det := by
  -- Rewrite the determinants as a sum over permutations.
  simp_rw [det_apply']
  -- The right hand side is a product of sums, rewrite it as a sum of products.
  rw [Finset.prod_sum]
  simp_rw [Finset.prod_attach_univ, Finset.univ_pi_univ]
  -- We claim that the only permutations contributing to the sum are those that
  -- preserve their second component.
  let preserving_snd : Finset (Equiv.Perm (n × o)) :=
    Finset.univ.filter fun σ => ∀ x, (σ x).snd = x.snd
  have mem_preserving_snd :
    ∀ {σ : Equiv.Perm (n × o)}, σ ∈ preserving_snd ↔ ∀ x, (σ x).snd = x.snd := fun {σ} =>
    Finset.mem_filter.trans ⟨fun h => h.2, fun h => ⟨Finset.mem_univ _, h⟩⟩
  rw [← Finset.sum_subset (Finset.subset_univ preserving_snd) _]
  -- And that these are in bijection with `o → Equiv.Perm m`.
  rw [(Finset.sum_bij
        (fun (σ : ∀ k : o, k ∈ Finset.univ → Equiv.Perm n) _ =>
          prodCongrLeft fun k => σ k (Finset.mem_univ k))
        _ _ _ _).symm]
  · intro σ _
    rw [mem_preserving_snd]
    rintro ⟨-, x⟩
    simp only [prodCongrLeft_apply]
  · intro σ _
    rw [Finset.prod_mul_distrib, ← Finset.univ_product_univ, Finset.prod_product_right]
    simp only [sign_prodCongrLeft, Units.coe_prod, Int.cast_prod, blockDiagonal_apply_eq,
      prodCongrLeft_apply]
  · intro σ σ' _ _ eq
    ext x hx k
    simp only at eq
    have :
      ∀ k x,
        prodCongrLeft (fun k => σ k (Finset.mem_univ _)) (k, x) =
          prodCongrLeft (fun k => σ' k (Finset.mem_univ _)) (k, x) :=
      fun k x => by rw [eq]
    simp only [prodCongrLeft_apply, Prod.mk.inj_iff] at this
    exact (this k x).1
  · intro σ hσ
    rw [mem_preserving_snd] at hσ
    have hσ' : ∀ x, (σ⁻¹ x).snd = x.snd := by
      intro x
      

Proof state:
m : Type u_1
n : Type u_2
inst✝⁶ : DecidableEq n
inst✝⁵ : Fintype n
inst✝⁴ : DecidableEq m
inst✝³ : Fintype m
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

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