l3lab/ntp-mathlib huggingface dataset:
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  

Proof state:
case H
α : 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
⊢ BlockTriangular M⁻¹ b

Next tactic:
intro i j hij
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  

Proof state:
case H
α : 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
⊢ M⁻¹ i j = 0

Next tactic:
haveI : Inhabited m := ⟨i⟩
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  

Proof state:
case H
α : 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this : Inhabited m
⊢ M⁻¹ i j = 0

Next tactic:
let k := (univ.image b).max' (univ_nonempty.image _)
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  

Proof state:
case H
α : 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
⊢ M⁻¹ i j = 0

Next tactic:
let b' := fun i : { a // b a < k } => b ↑i
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  

Proof state:
case H
α : 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
⊢ M⁻¹ i j = 0

Next tactic:
let A := M.toBlock (fun i => b i < k) fun j => b j < k
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  

Proof state:
case H
α : 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
⊢ M⁻¹ i j = 0

Next tactic:
obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · 

Proof state:
case H.inl
α : 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hbi : b i = k
⊢ M⁻¹ i j = 0

Next tactic:
have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := by
      simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hbi : b i = k
⊢ toBlock M⁻¹ (fun i => k ≤ b i) (fun i => b i < k) { val := i, property := (_ : k ≤ b i) }
      { val := j, property := (_ : (fun i => b i < k) j) } =
    0

Next tactic:
simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := by
      simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
    

Proof state:
case H.inl
α : 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this✝ : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hbi : b i = k
this :
  toBlock M⁻¹ (fun i => k ≤ b i) (fun i => b i < k) { val := i, property := (_ : k ≤ b i) }
      { val := j, property := (_ : (fun i => b i < k) j) } =
    0
⊢ M⁻¹ i j = 0

Next tactic:
simp [this.symm]
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := by
      simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
    simp [this.symm]
  

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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hi : b i < max' (image b univ) (_ : ∃ x, x ∈ image b univ)
⊢ M⁻¹ i j = 0

Next tactic:
haveI : Invertible A := hM.invertibleToBlock _
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := by
      simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
    simp [this.symm]
  haveI : Invertible A := hM.invertibleToBlock _
  

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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this✝ : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hi : b i < max' (image b univ) (_ : ∃ x, x ∈ image b univ)
this : Invertible A
⊢ M⁻¹ i j = 0

Next tactic:
have hA : A.BlockTriangular b' := hM.submatrix
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := by
      simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
    simp [this.symm]
  haveI : Invertible A := hM.invertibleToBlock _
  have hA : A.BlockTriangular 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this✝ : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hi : b i < max' (image b univ) (_ : ∃ x, x ∈ image b univ)
this : Invertible A
hA : BlockTriangular A b'
⊢ M⁻¹ i j = 0

Next tactic:
have hb' : image b' univ ⊂ image b univ := by
    convert image_subtype_univ_ssubset_image_univ k b _ (fun a => a < k) (lt_irrefl _)
    convert max'_mem (α := α) _ _
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := by
      simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
    simp [this.symm]
  haveI : Invertible A := hM.invertibleToBlock _
  have hA : A.BlockTriangular b' := hM.submatrix
  have hb' : image b' univ ⊂ image b univ := 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this✝ : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hi : b i < max' (image b univ) (_ : ∃ x, x ∈ image b univ)
this : Invertible A
hA : BlockTriangular A b'
⊢ image b' univ ⊂ image b univ

Next tactic:
convert image_subtype_univ_ssubset_image_univ k b _ (fun a => a < k) (lt_irrefl _)
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := by
      simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
    simp [this.symm]
  haveI : Invertible A := hM.invertibleToBlock _
  have hA : A.BlockTriangular b' := hM.submatrix
  have hb' : image b' univ ⊂ image b univ := by
    convert image_subtype_univ_ssubset_image_univ k b _ (fun a => a < k) (lt_irrefl _)
    

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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this✝ : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hi : b i < max' (image b univ) (_ : ∃ x, x ∈ image b univ)
this : Invertible A
hA : BlockTriangular A b'
⊢ k ∈ image b univ

Next tactic:
convert max'_mem (α := α) _ _
/-- The inverse of a block-triangular matrix is block-triangular. -/
theorem blockTriangular_inv_of_blockTriangular [LinearOrder α] [Invertible M]
    (hM : BlockTriangular M b) : BlockTriangular M⁻¹ b := by
  clear N
  induction' hs : univ.image b using Finset.strongInduction with s ih generalizing m
  subst hs
  intro i j hij
  haveI : Inhabited m := ⟨i⟩
  let k := (univ.image b).max' (univ_nonempty.image _)
  let b' := fun i : { a // b a < k } => b ↑i
  let A := M.toBlock (fun i => b i < k) fun j => b j < k
  obtain hbi | hi : b i = k ∨ _ := (le_max' _ (b i) <| mem_image_of_mem _ <| mem_univ _).eq_or_lt
  · have : M⁻¹.toBlock (fun i => k ≤ b i) (fun i => b i < k) ⟨i, hbi.ge⟩ ⟨j, hbi ▸ hij⟩ = 0 := by
      simp only [toBlock_inverse_eq_zero hM k, Matrix.zero_apply]
    simp [this.symm]
  haveI : Invertible A := hM.invertibleToBlock _
  have hA : A.BlockTriangular b' := hM.submatrix
  have hb' : image b' univ ⊂ image b univ := by
    convert image_subtype_univ_ssubset_image_univ k b _ (fun a => a < k) (lt_irrefl _)
    convert 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✝³ : LinearOrder α
m : Type u_3
M : Matrix m m R
b : m → α
inst✝² : DecidableEq m
inst✝¹ : Fintype m
inst✝ : Invertible 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] [inst_2 : Invertible M],
      BlockTriangular M b → image b univ = t → BlockTriangular M⁻¹ b
i j : m
hij : b j < b i
this✝ : Inhabited m
k : α := max' (image b univ) (_ : Finset.Nonempty (image b univ))
b' : { a // b a < k } → α := fun i => b ↑i
A : Matrix { a // b a < k } { a // b a < k } R := toBlock M (fun i => b i < k) fun j => b j < k
hi : b i < max' (image b univ) (_ : ∃ x, x ∈ image b univ)
this : Invertible A
hA : BlockTriangular A b'
hb' : image b' univ ⊂ image b univ
⊢ M⁻¹ i j = 0

Next tactic:
have hij' : b' ⟨j, hij.trans hi⟩ < b' ⟨i, hi⟩ := by simp_rw [hij]