-- Mathlib/LinearAlgebra/Matrix/Block.lean
theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a ∈ univ.image b, (M.toSquareBlock b a).det

Proof state:
case H.inr
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
h✝ : Nonempty m
k : α := (image b univ).max' ⋯
this : image b univ = insert k ((image b univ).erase k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : (M.toSquareBlockProp fun i => b i ≠ k).BlockTriangular b'
hb' : image b' univ = (image b univ).erase k
⊢ ∏ a ∈ (image b univ).erase ((image b univ).max' ⋯), ((M.toSquareBlockProp fun i => b i ≠ k).toSquareBlock b' a).det =
    ∏ x ∈ (image b univ).erase k, (M.toSquareBlock b x).det

Tactic:
refine Finset.prod_congr rfl fun l hl => ?_

Result:
case H.inr
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
h✝ : Nonempty m
k : α := (image b univ).max' ⋯
this : image b univ = insert k ((image b univ).erase k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : (M.toSquareBlockProp fun i => b i ≠ k).BlockTriangular b'
hb' : image b' univ = (image b univ).erase k
l : α
hl : l ∈ (image b univ).erase k
⊢ ((M.toSquareBlockProp fun i => b i ≠ k).toSquareBlock b' l).det = (M.toSquareBlock b l).det

Proof state:
case H.inr
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
h✝ : Nonempty m
k : α := (image b univ).max' ⋯
i : m
hi : b i = k
j : m
hj : ¬b j = k
⊢ M i j = 0

Tactic:
apply hM

Result:
case H.inr.a
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
h✝ : Nonempty m
k : α := (image b univ).max' ⋯
i : m
hi : b i = k
j : m
hj : ¬b j = k
⊢ b j < b i

Proof state:
case H
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
hs : image b univ = s
⊢ M.det = ∏ a ∈ s, (M.toSquareBlock b a).det

Tactic:
subst hs

Result:
case H
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
⊢ M.det = ∏ a ∈ image b univ, (M.toSquareBlock b a).det

Proof state:
case H.inr
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
h✝ : Nonempty m
k : α := (image b univ).max' ⋯
this : image b univ = insert k ((image b univ).erase k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : (M.toSquareBlockProp fun i => b i ≠ k).BlockTriangular b'
⊢ (M.toSquareBlockProp fun i => ¬b i = k).det = ∏ x ∈ (image b univ).erase k, (M.toSquareBlock b x).det

Tactic:
have hb' : image b' univ = (image b univ).erase k := by
  convert image_subtype_ne_univ_eq_image_erase k b

Result:
case H.inr
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
h✝ : Nonempty m
k : α := (image b univ).max' ⋯
this : image b univ = insert k ((image b univ).erase k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : (M.toSquareBlockProp fun i => b i ≠ k).BlockTriangular b'
hb' : image b' univ = (image b univ).erase k
⊢ (M.toSquareBlockProp fun i => ¬b i = k).det = ∏ x ∈ (image b univ).erase k, (M.toSquareBlock b x).det

Proof state:
case H.inr
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
h✝ : Nonempty m
k : α := (image b univ).max' ⋯
this : image b univ = insert k ((image b univ).erase k)
⊢ (M.toSquareBlockProp fun i => b i = k).det * (M.toSquareBlockProp fun i => ¬b i = k).det =
    ∏ a ∈ image b univ, (M.toSquareBlock b a).det

Tactic:
rw [this, prod_insert (not_mem_erase _ _)]

Result:
case H.inr
α : Type u_1
R : Type v
inst✝⁴ : CommRing R
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : M.BlockTriangular b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      M.BlockTriangular b → image b univ = t → M.det = ∏ a ∈ t, (M.toSquareBlock b a).det
h✝ : Nonempty m
k : α := (image b univ).max' ⋯
this : image b univ = insert k ((image b univ).erase k)
⊢ (M.toSquareBlockProp fun i => b i = k).det * (M.toSquareBlockProp fun i => ¬b i = k).det =
    (M.toSquareBlock b k).det * ∏ x ∈ (image b univ).erase k, (M.toSquareBlock b x).det