l3lab/ntp-mathlib huggingface dataset:
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    

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

Next tactic:
rw [this, prod_insert (not_mem_erase _ _)]
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    

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

Next tactic:
refine' congr_arg _ _
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    

Proof state:
case H.inr
α : Type u_1
β : Type u_2
n : Type u_4
o : Type u_5
m' : α → Type u_6
n' : α → Type u_7
R : Type v
inst✝⁶ : CommRing R
inst✝⁵ : DecidableEq n
inst✝⁴ : Fintype n
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : BlockTriangular M b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      BlockTriangular M b → image b univ = t → det M = ∏ a in t, det (toSquareBlock M b a)
h✝ : Nonempty m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
this : image b univ = insert k (erase (image b univ) k)
⊢ det (toSquareBlockProp M fun i => ¬b i = k) = ∏ x in erase (image b univ) k, det (toSquareBlock M b x)

Next tactic:
let b' := fun i : { a // b a ≠ k } => b ↑i
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    

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

Next tactic:
have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
    

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

Next tactic:
have hb' : image b' univ = (image b univ).erase k := by
      convert image_subtype_ne_univ_eq_image_erase k b
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
    have hb' : image b' univ = (image b univ).erase k := by
      

Proof state:
α : Type u_1
β : Type u_2
n : Type u_4
o : Type u_5
m' : α → Type u_6
n' : α → Type u_7
R : Type v
inst✝⁶ : CommRing R
inst✝⁵ : DecidableEq n
inst✝⁴ : Fintype n
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : BlockTriangular M b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      BlockTriangular M b → image b univ = t → det M = ∏ a in t, det (toSquareBlock M b a)
h✝ : Nonempty m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
this : image b univ = insert k (erase (image b univ) k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : BlockTriangular (toSquareBlockProp M fun i => b i ≠ k) b'
⊢ image b' univ = erase (image b univ) k

Next tactic:
convert image_subtype_ne_univ_eq_image_erase k b
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
    have hb' : image b' univ = (image b univ).erase k := by
      convert image_subtype_ne_univ_eq_image_erase k b
    

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

Next tactic:
rw [ih _ (erase_ssubset <| max'_mem _ _) h' hb']
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
    have hb' : image b' univ = (image b univ).erase k := by
      convert image_subtype_ne_univ_eq_image_erase k b
    rw [ih _ (erase_ssubset <| max'_mem _ _) h' hb']
    

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

Next tactic:
refine' Finset.prod_congr rfl fun l hl => _
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
    have hb' : image b' univ = (image b univ).erase k := by
      convert image_subtype_ne_univ_eq_image_erase k b
    rw [ih _ (erase_ssubset <| max'_mem _ _) h' hb']
    refine' Finset.prod_congr rfl fun l hl => _
    

Proof state:
case H.inr
α : Type u_1
β : Type u_2
n : Type u_4
o : Type u_5
m' : α → Type u_6
n' : α → Type u_7
R : Type v
inst✝⁶ : CommRing R
inst✝⁵ : DecidableEq n
inst✝⁴ : Fintype n
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : BlockTriangular M b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      BlockTriangular M b → image b univ = t → det M = ∏ a in t, det (toSquareBlock M b a)
h✝ : Nonempty m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
this : image b univ = insert k (erase (image b univ) k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : BlockTriangular (toSquareBlockProp M fun i => b i ≠ k) b'
hb' : image b' univ = erase (image b univ) k
l : α
hl : l ∈ erase (image b univ) k
⊢ det (toSquareBlock (toSquareBlockProp M fun i => b i ≠ k) b' l) = det (toSquareBlock M b l)

Next tactic:
let he : { a // b' a = l } ≃ { a // b a = l } :=
      haveI hc : ∀ i, b i = l → b i ≠ k := fun i hi => ne_of_eq_of_ne hi (ne_of_mem_erase hl)
      Equiv.subtypeSubtypeEquivSubtype @(hc)
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
    have hb' : image b' univ = (image b univ).erase k := by
      convert image_subtype_ne_univ_eq_image_erase k b
    rw [ih _ (erase_ssubset <| max'_mem _ _) h' hb']
    refine' Finset.prod_congr rfl fun l hl => _
    let he : { a // b' a = l } ≃ { a // b a = l } :=
      haveI hc : ∀ i, b i = l → b i ≠ k := fun i hi => ne_of_eq_of_ne hi (ne_of_mem_erase hl)
      Equiv.subtypeSubtypeEquivSubtype @(hc)
    

Proof state:
case H.inr
α : Type u_1
β : Type u_2
n : Type u_4
o : Type u_5
m' : α → Type u_6
n' : α → Type u_7
R : Type v
inst✝⁶ : CommRing R
inst✝⁵ : DecidableEq n
inst✝⁴ : Fintype n
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : BlockTriangular M b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      BlockTriangular M b → image b univ = t → det M = ∏ a in t, det (toSquareBlock M b a)
h✝ : Nonempty m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
this : image b univ = insert k (erase (image b univ) k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : BlockTriangular (toSquareBlockProp M fun i => b i ≠ k) b'
hb' : image b' univ = erase (image b univ) k
l : α
hl : l ∈ erase (image b univ) k
he : { a // b' a = l } ≃ { a // b a = l } := Equiv.subtypeSubtypeEquivSubtype (_ : ∀ (i : m), b i = l → b i ≠ k)
⊢ det (toSquareBlock (toSquareBlockProp M fun i => b i ≠ k) b' l) = det (toSquareBlock M b l)

Next tactic:
simp only [toSquareBlock_def]
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
    have hb' : image b' univ = (image b univ).erase k := by
      convert image_subtype_ne_univ_eq_image_erase k b
    rw [ih _ (erase_ssubset <| max'_mem _ _) h' hb']
    refine' Finset.prod_congr rfl fun l hl => _
    let he : { a // b' a = l } ≃ { a // b a = l } :=
      haveI hc : ∀ i, b i = l → b i ≠ k := fun i hi => ne_of_eq_of_ne hi (ne_of_mem_erase hl)
      Equiv.subtypeSubtypeEquivSubtype @(hc)
    simp only [toSquareBlock_def]
    

Proof state:
case H.inr
α : Type u_1
β : Type u_2
n : Type u_4
o : Type u_5
m' : α → Type u_6
n' : α → Type u_7
R : Type v
inst✝⁶ : CommRing R
inst✝⁵ : DecidableEq n
inst✝⁴ : Fintype n
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : BlockTriangular M b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      BlockTriangular M b → image b univ = t → det M = ∏ a in t, det (toSquareBlock M b a)
h✝ : Nonempty m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
this : image b univ = insert k (erase (image b univ) k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : BlockTriangular (toSquareBlockProp M fun i => b i ≠ k) b'
hb' : image b' univ = erase (image b univ) k
l : α
hl : l ∈ erase (image b univ) k
he : { a // b' a = l } ≃ { a // b a = l } := Equiv.subtypeSubtypeEquivSubtype (_ : ∀ (i : m), b i = l → b i ≠ k)
⊢ det
      (of fun i j =>
        toSquareBlockProp M (fun i => b i ≠ max' (image b univ) (_ : Finset.Nonempty (image b univ))) ↑i ↑j) =
    det (of fun i j => M ↑i ↑j)

Next tactic:
erw [← Matrix.det_reindex_self he.symm fun i j : { a // b a = l } => M ↑i ↑j]
protected theorem BlockTriangular.det [DecidableEq α] [LinearOrder α] (hM : BlockTriangular M b) :
    M.det = ∏ a in univ.image b, (M.toSquareBlock b a).det := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  cases isEmpty_or_nonempty m
  · simp
  let k := (univ.image b).max' (univ_nonempty.image _)
  rw [twoBlockTriangular_det' M fun i => b i = k]
  · have : univ.image b = insert k ((univ.image b).erase k) := by
      rw [insert_erase]
      apply max'_mem
    rw [this, prod_insert (not_mem_erase _ _)]
    refine' congr_arg _ _
    let b' := fun i : { a // b a ≠ k } => b ↑i
    have h' : BlockTriangular (M.toSquareBlockProp fun i => b i ≠ k) b' := hM.submatrix
    have hb' : image b' univ = (image b univ).erase k := by
      convert image_subtype_ne_univ_eq_image_erase k b
    rw [ih _ (erase_ssubset <| max'_mem _ _) h' hb']
    refine' Finset.prod_congr rfl fun l hl => _
    let he : { a // b' a = l } ≃ { a // b a = l } :=
      haveI hc : ∀ i, b i = l → b i ≠ k := fun i hi => ne_of_eq_of_ne hi (ne_of_mem_erase hl)
      Equiv.subtypeSubtypeEquivSubtype @(hc)
    simp only [toSquareBlock_def]
    erw [← Matrix.det_reindex_self he.symm fun i j : { a // b a = l } => M ↑i ↑j]
    

Proof state:
case H.inr
α : Type u_1
β : Type u_2
n : Type u_4
o : Type u_5
m' : α → Type u_6
n' : α → Type u_7
R : Type v
inst✝⁶ : CommRing R
inst✝⁵ : DecidableEq n
inst✝⁴ : Fintype n
inst✝³ : DecidableEq α
inst✝² : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝¹ : DecidableEq m
inst✝ : Fintype m
hM : BlockTriangular M b
ih :
  ∀ t ⊂ image b univ,
    ∀ {m : Type u_3} {M : Matrix m m R} {b : m → α} [inst : DecidableEq m] [inst_1 : Fintype m],
      BlockTriangular M b → image b univ = t → det M = ∏ a in t, det (toSquareBlock M b a)
h✝ : Nonempty m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
this : image b univ = insert k (erase (image b univ) k)
b' : { a // b a ≠ k } → α := fun i => b ↑i
h' : BlockTriangular (toSquareBlockProp M fun i => b i ≠ k) b'
hb' : image b' univ = erase (image b univ) k
l : α
hl : l ∈ erase (image b univ) k
he : { a // b' a = l } ≃ { a // b a = l } := Equiv.subtypeSubtypeEquivSubtype (_ : ∀ (i : m), b i = l → b i ≠ k)
⊢ det
      (of fun i j =>
        toSquareBlockProp M (fun i => b i ≠ max' (image b univ) (_ : Finset.Nonempty (image b univ))) ↑i ↑j) =
    det ((reindex he.symm he.symm) fun i j => M ↑i ↑j)

Next tactic:
rfl