l3lab/ntp-mathlib huggingface dataset:
/-- Pullback a `StrictOrderedRing` under an injective map. -/
@[reducible]
protected def strictOrderedRing [StrictOrderedRing α] [Zero β] [One β] [Add β] [Mul β] [Neg β]
    [Sub β] [SMul ℕ β] [SMul ℤ β] [Pow β ℕ] [NatCast β] [IntCast β] (f : β → α)
    (hf : Injective f) (zero : f 0 = 0) (one : f 1 = 1) (add : ∀ x y, f (x + y) = f x + f y)
    (mul : ∀ x y, f (x * y) = f x * f y) (neg : ∀ x, f (-x) = -f x)
    (sub : ∀ x y, f (x - y) = f x - f y) (nsmul : ∀ (x) (n : ℕ), f (n • x) = n • f x)
    (zsmul : ∀ (x) (n : ℤ), f (n • x) = n • f x) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n)
    (nat_cast : ∀ n : ℕ, f n = n) (int_cast : ∀ n : ℤ, f n = n) : StrictOrderedRing β :=
  { hf.strictOrderedSemiring f zero one add mul nsmul npow nat_cast,
    hf.ring f zero one add mul neg sub nsmul zsmul npow nat_cast int_cast with
    mul_pos := fun a b a0 b0 =>
      show f 0 < f (a * b) by
        rw [zero, mul]
        

Proof state:
α : Type u
β : Type u_1
inst✝¹¹ : StrictOrderedRing α
inst✝¹⁰ : Zero β
inst✝⁹ : One β
inst✝⁸ : Add β
inst✝⁷ : Mul β
inst✝⁶ : Neg β
inst✝⁵ : Sub β
inst✝⁴ : SMul ℕ β
inst✝³ : SMul ℤ β
inst✝² : Pow β ℕ
inst✝¹ : NatCast β
inst✝ : IntCast β
f : β → α
hf : Injective f
zero : f 0 = 0
one : f 1 = 1
add : ∀ (x y : β), f (x + y) = f x + f y
mul : ∀ (x y : β), f (x * y) = f x * f y
neg : ∀ (x : β), f (-x) = -f x
sub : ∀ (x y : β), f (x - y) = f x - f y
nsmul : ∀ (x : β) (n : ℕ), f (n • x) = n • f x
zsmul : ∀ (x : β) (n : ℤ), f (n • x) = n • f x
npow : ∀ (x : β) (n : ℕ), f (x ^ n) = f x ^ n
nat_cast : ∀ (n : ℕ), f ↑n = ↑n
int_cast : ∀ (n : ℤ), f ↑n = ↑n
src✝¹ : StrictOrderedSemiring β := Injective.strictOrderedSemiring f hf zero one add mul nsmul npow nat_cast
src✝ : Ring β := Injective.ring f hf zero one add mul neg sub nsmul zsmul npow nat_cast int_cast
a b : β
a0 : 0 < a
b0 : 0 < b
⊢ 0 < f a * f b

Next tactic:
apply mul_pos
/-- Pullback a `StrictOrderedRing` under an injective map. -/
@[reducible]
protected def strictOrderedRing [StrictOrderedRing α] [Zero β] [One β] [Add β] [Mul β] [Neg β]
    [Sub β] [SMul ℕ β] [SMul ℤ β] [Pow β ℕ] [NatCast β] [IntCast β] (f : β → α)
    (hf : Injective f) (zero : f 0 = 0) (one : f 1 = 1) (add : ∀ x y, f (x + y) = f x + f y)
    (mul : ∀ x y, f (x * y) = f x * f y) (neg : ∀ x, f (-x) = -f x)
    (sub : ∀ x y, f (x - y) = f x - f y) (nsmul : ∀ (x) (n : ℕ), f (n • x) = n • f x)
    (zsmul : ∀ (x) (n : ℤ), f (n • x) = n • f x) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n)
    (nat_cast : ∀ n : ℕ, f n = n) (int_cast : ∀ n : ℤ, f n = n) : StrictOrderedRing β :=
  { hf.strictOrderedSemiring f zero one add mul nsmul npow nat_cast,
    hf.ring f zero one add mul neg sub nsmul zsmul npow nat_cast int_cast with
    mul_pos := fun a b a0 b0 =>
      show f 0 < f (a * b) by
        rw [zero, mul]
        apply mul_pos <;> 

Proof state:
case ha
α : Type u
β : Type u_1
inst✝¹¹ : StrictOrderedRing α
inst✝¹⁰ : Zero β
inst✝⁹ : One β
inst✝⁸ : Add β
inst✝⁷ : Mul β
inst✝⁶ : Neg β
inst✝⁵ : Sub β
inst✝⁴ : SMul ℕ β
inst✝³ : SMul ℤ β
inst✝² : Pow β ℕ
inst✝¹ : NatCast β
inst✝ : IntCast β
f : β → α
hf : Injective f
zero : f 0 = 0
one : f 1 = 1
add : ∀ (x y : β), f (x + y) = f x + f y
mul : ∀ (x y : β), f (x * y) = f x * f y
neg : ∀ (x : β), f (-x) = -f x
sub : ∀ (x y : β), f (x - y) = f x - f y
nsmul : ∀ (x : β) (n : ℕ), f (n • x) = n • f x
zsmul : ∀ (x : β) (n : ℤ), f (n • x) = n • f x
npow : ∀ (x : β) (n : ℕ), f (x ^ n) = f x ^ n
nat_cast : ∀ (n : ℕ), f ↑n = ↑n
int_cast : ∀ (n : ℤ), f ↑n = ↑n
src✝¹ : StrictOrderedSemiring β := Injective.strictOrderedSemiring f hf zero one add mul nsmul npow nat_cast
src✝ : Ring β := Injective.ring f hf zero one add mul neg sub nsmul zsmul npow nat_cast int_cast
a b : β
a0 : 0 < a
b0 : 0 < b
⊢ 0 < f a

Next tactic:
rwa [← zero]
/-- Pullback a `StrictOrderedRing` under an injective map. -/
@[reducible]
protected def strictOrderedRing [StrictOrderedRing α] [Zero β] [One β] [Add β] [Mul β] [Neg β]
    [Sub β] [SMul ℕ β] [SMul ℤ β] [Pow β ℕ] [NatCast β] [IntCast β] (f : β → α)
    (hf : Injective f) (zero : f 0 = 0) (one : f 1 = 1) (add : ∀ x y, f (x + y) = f x + f y)
    (mul : ∀ x y, f (x * y) = f x * f y) (neg : ∀ x, f (-x) = -f x)
    (sub : ∀ x y, f (x - y) = f x - f y) (nsmul : ∀ (x) (n : ℕ), f (n • x) = n • f x)
    (zsmul : ∀ (x) (n : ℤ), f (n • x) = n • f x) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n)
    (nat_cast : ∀ n : ℕ, f n = n) (int_cast : ∀ n : ℤ, f n = n) : StrictOrderedRing β :=
  { hf.strictOrderedSemiring f zero one add mul nsmul npow nat_cast,
    hf.ring f zero one add mul neg sub nsmul zsmul npow nat_cast int_cast with
    mul_pos := fun a b a0 b0 =>
      show f 0 < f (a * b) by
        rw [zero, mul]
        apply mul_pos <;> 

Proof state:
case hb
α : Type u
β : Type u_1
inst✝¹¹ : StrictOrderedRing α
inst✝¹⁰ : Zero β
inst✝⁹ : One β
inst✝⁸ : Add β
inst✝⁷ : Mul β
inst✝⁶ : Neg β
inst✝⁵ : Sub β
inst✝⁴ : SMul ℕ β
inst✝³ : SMul ℤ β
inst✝² : Pow β ℕ
inst✝¹ : NatCast β
inst✝ : IntCast β
f : β → α
hf : Injective f
zero : f 0 = 0
one : f 1 = 1
add : ∀ (x y : β), f (x + y) = f x + f y
mul : ∀ (x y : β), f (x * y) = f x * f y
neg : ∀ (x : β), f (-x) = -f x
sub : ∀ (x y : β), f (x - y) = f x - f y
nsmul : ∀ (x : β) (n : ℕ), f (n • x) = n • f x
zsmul : ∀ (x : β) (n : ℤ), f (n • x) = n • f x
npow : ∀ (x : β) (n : ℕ), f (x ^ n) = f x ^ n
nat_cast : ∀ (n : ℕ), f ↑n = ↑n
int_cast : ∀ (n : ℤ), f ↑n = ↑n
src✝¹ : StrictOrderedSemiring β := Injective.strictOrderedSemiring f hf zero one add mul nsmul npow nat_cast
src✝ : Ring β := Injective.ring f hf zero one add mul neg sub nsmul zsmul npow nat_cast int_cast
a b : β
a0 : 0 < a
b0 : 0 < b
⊢ 0 < f b

Next tactic:
rwa [← zero]
theorem mul_matrix_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α)
    (i j) : (f.toMatrix * M :) i j = Option.casesOn (f i) 0 fun fi => M fi j := by
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : l ≃. m
M : Matrix m n α
i : l
j : n
⊢ (toMatrix f * M) i j = Option.casesOn (f i) 0 fun fi => M fi j

Next tactic:
dsimp [toMatrix, Matrix.mul_apply]
theorem mul_matrix_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α)
    (i j) : (f.toMatrix * M :) i j = Option.casesOn (f i) 0 fun fi => M fi j := by
  dsimp [toMatrix, Matrix.mul_apply]
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : l ≃. m
M : Matrix m n α
i : l
j : n
⊢ (Finset.sum Finset.univ fun j_1 => (if j_1 ∈ f i then 1 else 0) * M j_1 j) = Option.rec 0 (fun val => M val j) (f i)

Next tactic:
cases' h : f i with fi
theorem mul_matrix_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α)
    (i j) : (f.toMatrix * M :) i j = Option.casesOn (f i) 0 fun fi => M fi j := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f i with fi
  · 

Proof state:
case none
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : l ≃. m
M : Matrix m n α
i : l
j : n
h : f i = none
⊢ (Finset.sum Finset.univ fun j_1 => (if j_1 ∈ none then 1 else 0) * M j_1 j) = Option.rec 0 (fun val => M val j) none

Next tactic:
simp [h]
theorem mul_matrix_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α)
    (i j) : (f.toMatrix * M :) i j = Option.casesOn (f i) 0 fun fi => M fi j := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f i with fi
  · simp [h]
  · 

Proof state:
case some
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : l ≃. m
M : Matrix m n α
i : l
j : n
fi : m
h : f i = some fi
⊢ (Finset.sum Finset.univ fun j_1 => (if j_1 ∈ some fi then 1 else 0) * M j_1 j) =
    Option.rec 0 (fun val => M val j) (some fi)

Next tactic:
rw [Finset.sum_eq_single fi]
theorem mul_matrix_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α)
    (i j) : (f.toMatrix * M :) i j = Option.casesOn (f i) 0 fun fi => M fi j := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f i with fi
  · simp [h]
  · rw [Finset.sum_eq_single fi] <;> 

Proof state:
case some
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : l ≃. m
M : Matrix m n α
i : l
j : n
fi : m
h : f i = some fi
⊢ (if fi ∈ some fi then 1 else 0) * M fi j = Option.rec 0 (fun val => M val j) (some fi)

Next tactic:
simp (config := { contextual := true }) [h, eq_comm]
theorem mul_matrix_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α)
    (i j) : (f.toMatrix * M :) i j = Option.casesOn (f i) 0 fun fi => M fi j := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f i with fi
  · simp [h]
  · rw [Finset.sum_eq_single fi] <;> 

Proof state:
case some.h₀
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : l ≃. m
M : Matrix m n α
i : l
j : n
fi : m
h : f i = some fi
⊢ ∀ b ∈ Finset.univ, b ≠ fi → (if b ∈ some fi then 1 else 0) * M b j = 0

Next tactic:
simp (config := { contextual := true }) [h, eq_comm]
theorem mul_matrix_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α)
    (i j) : (f.toMatrix * M :) i j = Option.casesOn (f i) 0 fun fi => M fi j := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f i with fi
  · simp [h]
  · rw [Finset.sum_eq_single fi] <;> 

Proof state:
case some.h₁
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : l ≃. m
M : Matrix m n α
i : l
j : n
fi : m
h : f i = some fi
⊢ fi ∉ Finset.univ → (if fi ∈ some fi then 1 else 0) * M fi j = 0

Next tactic:
simp (config := { contextual := true }) [h, eq_comm]
theorem toMatrix_symm [DecidableEq m] [DecidableEq n] [Zero α] [One α] (f : m ≃. n) :
    (f.symm.toMatrix : Matrix n m α) = f.toMatrixᵀ := by
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : DecidableEq m
inst✝² : DecidableEq n
inst✝¹ : Zero α
inst✝ : One α
f : m ≃. n
⊢ toMatrix (PEquiv.symm f) = (toMatrix f)ᵀ

Next tactic:
ext
theorem toMatrix_symm [DecidableEq m] [DecidableEq n] [Zero α] [One α] (f : m ≃. n) :
    (f.symm.toMatrix : Matrix n m α) = f.toMatrixᵀ := by
  ext
  

Proof state:
case a.h
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : DecidableEq m
inst✝² : DecidableEq n
inst✝¹ : Zero α
inst✝ : One α
f : m ≃. n
i✝ : n
x✝ : m
⊢ toMatrix (PEquiv.symm f) i✝ x✝ = (toMatrix f)ᵀ i✝ x✝

Next tactic:
simp only [transpose, mem_iff_mem f, toMatrix_apply]
theorem toMatrix_symm [DecidableEq m] [DecidableEq n] [Zero α] [One α] (f : m ≃. n) :
    (f.symm.toMatrix : Matrix n m α) = f.toMatrixᵀ := by
  ext
  simp only [transpose, mem_iff_mem f, toMatrix_apply]
  

Proof state:
case a.h
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : DecidableEq m
inst✝² : DecidableEq n
inst✝¹ : Zero α
inst✝ : One α
f : m ≃. n
i✝ : n
x✝ : m
⊢ (if i✝ ∈ f x✝ then 1 else 0) = of (fun x y => if x ∈ f y then 1 else 0) i✝ x✝

Next tactic:
congr
@[simp]
theorem toMatrix_refl [DecidableEq n] [Zero α] [One α] :
    ((PEquiv.refl n).toMatrix : Matrix n n α) = 1 := by
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : DecidableEq n
inst✝¹ : Zero α
inst✝ : One α
⊢ toMatrix (PEquiv.refl n) = 1

Next tactic:
ext
@[simp]
theorem toMatrix_refl [DecidableEq n] [Zero α] [One α] :
    ((PEquiv.refl n).toMatrix : Matrix n n α) = 1 := by
  ext
  

Proof state:
case a.h
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : DecidableEq n
inst✝¹ : Zero α
inst✝ : One α
i✝ x✝ : n
⊢ toMatrix (PEquiv.refl n) i✝ x✝ = OfNat.ofNat 1 i✝ x✝

Next tactic:
simp [toMatrix_apply, one_apply]
theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n)
    (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : Semiring α
inst✝ : DecidableEq n
M : Matrix l m α
f : m ≃. n
i : l
j : n
⊢ (M * toMatrix f) i j = Option.casesOn ((PEquiv.symm f) j) 0 fun fj => M i fj

Next tactic:
dsimp [toMatrix, Matrix.mul_apply]
theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n)
    (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by
  dsimp [toMatrix, Matrix.mul_apply]
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : Semiring α
inst✝ : DecidableEq n
M : Matrix l m α
f : m ≃. n
i : l
j : n
⊢ (Finset.sum Finset.univ fun j_1 => M i j_1 * if j ∈ f j_1 then 1 else 0) =
    Option.rec 0 (fun val => M i val) ((PEquiv.symm f) j)

Next tactic:
cases' h : f.symm j with fj
theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n)
    (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f.symm j with fj
  · 

Proof state:
case none
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : Semiring α
inst✝ : DecidableEq n
M : Matrix l m α
f : m ≃. n
i : l
j : n
h : (PEquiv.symm f) j = none
⊢ (Finset.sum Finset.univ fun j_1 => M i j_1 * if j ∈ f j_1 then 1 else 0) = Option.rec 0 (fun val => M i val) none

Next tactic:
simp [h, ← f.eq_some_iff]
theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n)
    (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f.symm j with fj
  · simp [h, ← f.eq_some_iff]
  · 

Proof state:
case some
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : Semiring α
inst✝ : DecidableEq n
M : Matrix l m α
f : m ≃. n
i : l
j : n
fj : m
h : (PEquiv.symm f) j = some fj
⊢ (Finset.sum Finset.univ fun j_1 => M i j_1 * if j ∈ f j_1 then 1 else 0) = Option.rec 0 (fun val => M i val) (some fj)

Next tactic:
rw [Finset.sum_eq_single fj]
theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n)
    (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f.symm j with fj
  · simp [h, ← f.eq_some_iff]
  · rw [Finset.sum_eq_single fj]
    · 

Proof state:
case some
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : Semiring α
inst✝ : DecidableEq n
M : Matrix l m α
f : m ≃. n
i : l
j : n
fj : m
h : (PEquiv.symm f) j = some fj
⊢ (M i fj * if j ∈ f fj then 1 else 0) = Option.rec 0 (fun val => M i val) (some fj)

Next tactic:
simp [h, ← f.eq_some_iff]
theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n)
    (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f.symm j with fj
  · simp [h, ← f.eq_some_iff]
  · rw [Finset.sum_eq_single fj]
    · simp [h, ← f.eq_some_iff]
    · 

Proof state:
case some.h₀
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : Semiring α
inst✝ : DecidableEq n
M : Matrix l m α
f : m ≃. n
i : l
j : n
fj : m
h : (PEquiv.symm f) j = some fj
⊢ ∀ b ∈ Finset.univ, b ≠ fj → (M i b * if j ∈ f b then 1 else 0) = 0

Next tactic:
rintro b - n
theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n)
    (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f.symm j with fj
  · simp [h, ← f.eq_some_iff]
  · rw [Finset.sum_eq_single fj]
    · simp [h, ← f.eq_some_iff]
    · rintro b - n
      

Proof state:
case some.h₀
k : Type u_1
l : Type u_2
m : Type u_3
n✝ : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : Semiring α
inst✝ : DecidableEq n✝
M : Matrix l m α
f : m ≃. n✝
i : l
j : n✝
fj : m
h : (PEquiv.symm f) j = some fj
b : m
n : b ≠ fj
⊢ (M i b * if j ∈ f b then 1 else 0) = 0

Next tactic:
simp [h, ← f.eq_some_iff, n.symm]
theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n)
    (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by
  dsimp [toMatrix, Matrix.mul_apply]
  cases' h : f.symm j with fj
  · simp [h, ← f.eq_some_iff]
  · rw [Finset.sum_eq_single fj]
    · simp [h, ← f.eq_some_iff]
    · rintro b - n
      simp [h, ← f.eq_some_iff, n.symm]
    · 

Proof state:
case some.h₁
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : Semiring α
inst✝ : DecidableEq n
M : Matrix l m α
f : m ≃. n
i : l
j : n
fj : m
h : (PEquiv.symm f) j = some fj
⊢ fj ∉ Finset.univ → (M i fj * if j ∈ f fj then 1 else 0) = 0

Next tactic:
simp
theorem toPEquiv_mul_matrix [Fintype m] [DecidableEq m] [Semiring α] (f : m ≃ m)
    (M : Matrix m n α) : f.toPEquiv.toMatrix * M = fun i => M (f i) := by
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : m ≃ m
M : Matrix m n α
⊢ toMatrix (Equiv.toPEquiv f) * M = fun i => M (f i)

Next tactic:
ext i j
theorem toPEquiv_mul_matrix [Fintype m] [DecidableEq m] [Semiring α] (f : m ≃ m)
    (M : Matrix m n α) : f.toPEquiv.toMatrix * M = fun i => M (f i) := by
  ext i j
  

Proof state:
case h.h
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : Fintype m
inst✝¹ : DecidableEq m
inst✝ : Semiring α
f : m ≃ m
M : Matrix m n α
i : m
j : n
⊢ (toMatrix (Equiv.toPEquiv f) * M) i j = M (f i) j

Next tactic:
rw [mul_matrix_apply, Equiv.toPEquiv_apply]
theorem mul_toPEquiv_toMatrix {m n α : Type*} [Fintype n] [DecidableEq n] [Semiring α] (f : n ≃ n)
    (M : Matrix m n α) : M * f.toPEquiv.toMatrix = M.submatrix id f.symm :=
  Matrix.ext fun i j => by
    

Proof state:
k : Type u_1
l : Type u_2
m✝ : Type u_3
n✝ : Type u_4
α✝ : Type v
m : Type u_5
n : Type u_6
α : Type u_7
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : Semiring α
f : n ≃ n
M : Matrix m n α
i : m
j : n
⊢ (M * toMatrix (Equiv.toPEquiv f)) i j = submatrix M id (⇑f.symm) i j

Next tactic:
rw [PEquiv.matrix_mul_apply, ← Equiv.toPEquiv_symm, Equiv.toPEquiv_apply,
      Matrix.submatrix_apply, id.def]
theorem toMatrix_trans [Fintype m] [DecidableEq m] [DecidableEq n] [Semiring α] (f : l ≃. m)
    (g : m ≃. n) : ((f.trans g).toMatrix : Matrix l n α) = f.toMatrix * g.toMatrix := by
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : Semiring α
f : l ≃. m
g : m ≃. n
⊢ toMatrix (PEquiv.trans f g) = toMatrix f * toMatrix g

Next tactic:
ext i j
theorem toMatrix_trans [Fintype m] [DecidableEq m] [DecidableEq n] [Semiring α] (f : l ≃. m)
    (g : m ≃. n) : ((f.trans g).toMatrix : Matrix l n α) = f.toMatrix * g.toMatrix := by
  ext i j
  

Proof state:
case a.h
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : Semiring α
f : l ≃. m
g : m ≃. n
i : l
j : n
⊢ toMatrix (PEquiv.trans f g) i j = (toMatrix f * toMatrix g) i j

Next tactic:
rw [mul_matrix_apply]
theorem toMatrix_trans [Fintype m] [DecidableEq m] [DecidableEq n] [Semiring α] (f : l ≃. m)
    (g : m ≃. n) : ((f.trans g).toMatrix : Matrix l n α) = f.toMatrix * g.toMatrix := by
  ext i j
  rw [mul_matrix_apply]
  

Proof state:
case a.h
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : Semiring α
f : l ≃. m
g : m ≃. n
i : l
j : n
⊢ toMatrix (PEquiv.trans f g) i j = Option.casesOn (f i) 0 fun fi => toMatrix g fi j

Next tactic:
dsimp [toMatrix, PEquiv.trans]
theorem toMatrix_trans [Fintype m] [DecidableEq m] [DecidableEq n] [Semiring α] (f : l ≃. m)
    (g : m ≃. n) : ((f.trans g).toMatrix : Matrix l n α) = f.toMatrix * g.toMatrix := by
  ext i j
  rw [mul_matrix_apply]
  dsimp [toMatrix, PEquiv.trans]
  

Proof state:
case a.h
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : Semiring α
f : l ≃. m
g : m ≃. n
i : l
j : n
⊢ (if j ∈ Option.bind (f i) ⇑g then 1 else 0) = Option.rec 0 (fun val => if j ∈ g val then 1 else 0) (f i)

Next tactic:
cases f i
theorem toMatrix_trans [Fintype m] [DecidableEq m] [DecidableEq n] [Semiring α] (f : l ≃. m)
    (g : m ≃. n) : ((f.trans g).toMatrix : Matrix l n α) = f.toMatrix * g.toMatrix := by
  ext i j
  rw [mul_matrix_apply]
  dsimp [toMatrix, PEquiv.trans]
  cases f i <;> 

Proof state:
case a.h.none
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : Semiring α
f : l ≃. m
g : m ≃. n
i : l
j : n
⊢ (if j ∈ Option.bind none ⇑g then 1 else 0) = Option.rec 0 (fun val => if j ∈ g val then 1 else 0) none

Next tactic:
simp
theorem toMatrix_trans [Fintype m] [DecidableEq m] [DecidableEq n] [Semiring α] (f : l ≃. m)
    (g : m ≃. n) : ((f.trans g).toMatrix : Matrix l n α) = f.toMatrix * g.toMatrix := by
  ext i j
  rw [mul_matrix_apply]
  dsimp [toMatrix, PEquiv.trans]
  cases f i <;> 

Proof state:
case a.h.some
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝³ : Fintype m
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : Semiring α
f : l ≃. m
g : m ≃. n
i : l
j : n
val✝ : m
⊢ (if j ∈ Option.bind (some val✝) ⇑g then 1 else 0) = Option.rec 0 (fun val => if j ∈ g val then 1 else 0) (some val✝)

Next tactic:
simp
theorem toMatrix_injective [DecidableEq n] [MonoidWithZero α] [Nontrivial α] :
    Function.Injective (@toMatrix m n α _ _ _) := by
  

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : DecidableEq n
inst✝¹ : MonoidWithZero α
inst✝ : Nontrivial α
⊢ Function.Injective toMatrix

Next tactic:
classical
    intro f g
    refine' not_imp_not.1 _
    simp only [Matrix.ext_iff.symm, toMatrix_apply, PEquiv.ext_iff, not_forall, exists_imp]
    intro i hi
    use i
    cases' hf : f i with fi
    · cases' hg : g i with gi
      -- Porting note: was `cc`
      · rw [hf, hg] at hi
        exact (hi rfl).elim
      · use gi
        simp
    · use fi
      simp [hf.symm, Ne.symm hi]
theorem toMatrix_injective [DecidableEq n] [MonoidWithZero α] [Nontrivial α] :
    Function.Injective (@toMatrix m n α _ _ _) := by
  classical
    

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : DecidableEq n
inst✝¹ : MonoidWithZero α
inst✝ : Nontrivial α
⊢ Function.Injective toMatrix

Next tactic:
intro f g
theorem toMatrix_injective [DecidableEq n] [MonoidWithZero α] [Nontrivial α] :
    Function.Injective (@toMatrix m n α _ _ _) := by
  classical
    intro f g
    

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : DecidableEq n
inst✝¹ : MonoidWithZero α
inst✝ : Nontrivial α
f g : m ≃. n
⊢ toMatrix f = toMatrix g → f = g

Next tactic:
refine' not_imp_not.1 _
theorem toMatrix_injective [DecidableEq n] [MonoidWithZero α] [Nontrivial α] :
    Function.Injective (@toMatrix m n α _ _ _) := by
  classical
    intro f g
    refine' not_imp_not.1 _
    

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : DecidableEq n
inst✝¹ : MonoidWithZero α
inst✝ : Nontrivial α
f g : m ≃. n
⊢ ¬f = g → ¬toMatrix f = toMatrix g

Next tactic:
simp only [Matrix.ext_iff.symm, toMatrix_apply, PEquiv.ext_iff, not_forall, exists_imp]
theorem toMatrix_injective [DecidableEq n] [MonoidWithZero α] [Nontrivial α] :
    Function.Injective (@toMatrix m n α _ _ _) := by
  classical
    intro f g
    refine' not_imp_not.1 _
    simp only [Matrix.ext_iff.symm, toMatrix_apply, PEquiv.ext_iff, not_forall, exists_imp]
    

Proof state:
k : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type v
inst✝² : DecidableEq n
inst✝¹ : MonoidWithZero α
inst✝ : Nontrivial α
f g : m ≃. n
⊢ ∀ (x : m), ¬f x = g x → ∃ x x_1, ¬(if x_1 ∈ f x then 1 else 0) = if x_1 ∈ g x then 1 else 0

Next tactic:
intro i hi