l3lab/ntp-mathlib huggingface dataset:
/-- A sequentially compact set in a uniform set with countably generated uniformity filter
is complete. -/
protected theorem IsSeqCompact.isComplete (hs : IsSeqCompact s) : IsComplete s := fun l hl hls => by
  have := hl.1
  rcases exists_antitone_basis (𝓤 X) with ⟨V, hV⟩
  choose W hW hWV using fun n => comp_mem_uniformity_sets (hV.mem n)
  have hWV' : ∀ n, W n ⊆ V n := fun n ⟨x, y⟩ hx =>
    @hWV n (x, y) ⟨x, refl_mem_uniformity <| hW _, hx⟩
  obtain ⟨t, ht_anti, htl, htW, hts⟩ :
      ∃ t : ℕ → Set X, Antitone t ∧ (∀ n, t n ∈ l) ∧ (∀ n, t n ×ˢ t n ⊆ W n) ∧ ∀ n, t n ⊆ s := by
    have : ∀ n, ∃ t ∈ l, t ×ˢ t ⊆ W n ∧ t ⊆ s := by
      rw [le_principal_iff] at hls
      have : ∀ n, W n ∩ s ×ˢ s ∈ l ×ˢ l := fun n => inter_mem (hl.2 (hW n)) (prod_mem_prod hls hls)
      simpa only [l.basis_sets.prod_self.mem_iff, true_imp_iff, subset_inter_iff,
        prod_self_subset_prod_self, and_assoc] using this
    choose t htl htW hts using this
    have : ∀ n : ℕ, ⋂ k ≤ n, t k ⊆ t n := fun n => by apply iInter₂_subset; rfl
    exact ⟨fun n => ⋂ k ≤ n, t k, fun m n h =>
      biInter_subset_biInter_left fun k (hk : k ≤ m) => hk.trans h, fun n =>
      (biInter_mem (finite_le_nat n)).2 fun k _ => htl k, fun n =>
      (prod_mono (this n) (this n)).trans (htW n), fun n => (this n).trans (hts n)⟩
  choose u hu using fun n => Filter.nonempty_of_mem (htl n)
  have huc : CauchySeq u := hV.toHasBasis.cauchySeq_iff.2 fun N _ =>
      ⟨N, fun m hm n hn => hWV' _ <| @htW N (_, _) ⟨ht_anti hm (hu _), ht_anti hn (hu _)⟩⟩
  rcases hs.exists_tendsto (fun n => hts n (hu n)) huc with ⟨x, hxs, hx⟩
  refine ⟨x, hxs, (nhds_basis_uniformity' hV.toHasBasis).ge_iff.2 fun N _ => ?_⟩
  obtain ⟨n, hNn, hn⟩ : ∃ n, N ≤ n ∧ u n ∈ ball x (W N)
  · exact ((eventually_ge_atTop N).and (hx <| ball_mem_nhds x (hW N))).exists
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro
X : Type u_1
Y : Type u_2
inst✝¹ : UniformSpace X
s : Set X
inst✝ : IsCountablyGenerated (𝓤 X)
hs : IsSeqCompact s
l : Filter X
hl : Cauchy l
hls : l ≤ 𝓟 s
this : NeBot l
V : ℕ → Set (X × X)
hV : HasAntitoneBasis (𝓤 X) V
W : ℕ → Set (X × X)
hW : ∀ (n : ℕ), W n ∈ 𝓤 X
hWV : ∀ (n : ℕ), W n ○ W n ⊆ V n
hWV' : ∀ (n : ℕ), W n ⊆ V n
t : ℕ → Set X
ht_anti : Antitone t
htl : ∀ (n : ℕ), t n ∈ l
htW : ∀ (n : ℕ), t n ×ˢ t n ⊆ W n
hts : ∀ (n : ℕ), t n ⊆ s
u : ℕ → X
hu : ∀ (n : ℕ), u n ∈ t n
huc : CauchySeq u
x : X
hxs : x ∈ s
hx : Tendsto (fun n => u n) atTop (𝓝 x)
N : ℕ
x✝ : True
n : ℕ
hNn : N ≤ n
hn : u n ∈ ball x (W N)
⊢ ball x (V N) ∈ l

Next tactic:
refine mem_of_superset (htl n) fun y hy => hWV N ⟨u n, hn, htW N ?_⟩
/-- A sequentially compact set in a uniform set with countably generated uniformity filter
is complete. -/
protected theorem IsSeqCompact.isComplete (hs : IsSeqCompact s) : IsComplete s := fun l hl hls => by
  have := hl.1
  rcases exists_antitone_basis (𝓤 X) with ⟨V, hV⟩
  choose W hW hWV using fun n => comp_mem_uniformity_sets (hV.mem n)
  have hWV' : ∀ n, W n ⊆ V n := fun n ⟨x, y⟩ hx =>
    @hWV n (x, y) ⟨x, refl_mem_uniformity <| hW _, hx⟩
  obtain ⟨t, ht_anti, htl, htW, hts⟩ :
      ∃ t : ℕ → Set X, Antitone t ∧ (∀ n, t n ∈ l) ∧ (∀ n, t n ×ˢ t n ⊆ W n) ∧ ∀ n, t n ⊆ s := by
    have : ∀ n, ∃ t ∈ l, t ×ˢ t ⊆ W n ∧ t ⊆ s := by
      rw [le_principal_iff] at hls
      have : ∀ n, W n ∩ s ×ˢ s ∈ l ×ˢ l := fun n => inter_mem (hl.2 (hW n)) (prod_mem_prod hls hls)
      simpa only [l.basis_sets.prod_self.mem_iff, true_imp_iff, subset_inter_iff,
        prod_self_subset_prod_self, and_assoc] using this
    choose t htl htW hts using this
    have : ∀ n : ℕ, ⋂ k ≤ n, t k ⊆ t n := fun n => by apply iInter₂_subset; rfl
    exact ⟨fun n => ⋂ k ≤ n, t k, fun m n h =>
      biInter_subset_biInter_left fun k (hk : k ≤ m) => hk.trans h, fun n =>
      (biInter_mem (finite_le_nat n)).2 fun k _ => htl k, fun n =>
      (prod_mono (this n) (this n)).trans (htW n), fun n => (this n).trans (hts n)⟩
  choose u hu using fun n => Filter.nonempty_of_mem (htl n)
  have huc : CauchySeq u := hV.toHasBasis.cauchySeq_iff.2 fun N _ =>
      ⟨N, fun m hm n hn => hWV' _ <| @htW N (_, _) ⟨ht_anti hm (hu _), ht_anti hn (hu _)⟩⟩
  rcases hs.exists_tendsto (fun n => hts n (hu n)) huc with ⟨x, hxs, hx⟩
  refine ⟨x, hxs, (nhds_basis_uniformity' hV.toHasBasis).ge_iff.2 fun N _ => ?_⟩
  obtain ⟨n, hNn, hn⟩ : ∃ n, N ≤ n ∧ u n ∈ ball x (W N)
  · exact ((eventually_ge_atTop N).and (hx <| ball_mem_nhds x (hW N))).exists
  refine mem_of_superset (htl n) fun y hy => hWV N ⟨u n, hn, htW N ?_⟩
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro
X : Type u_1
Y : Type u_2
inst✝¹ : UniformSpace X
s : Set X
inst✝ : IsCountablyGenerated (𝓤 X)
hs : IsSeqCompact s
l : Filter X
hl : Cauchy l
hls : l ≤ 𝓟 s
this : NeBot l
V : ℕ → Set (X × X)
hV : HasAntitoneBasis (𝓤 X) V
W : ℕ → Set (X × X)
hW : ∀ (n : ℕ), W n ∈ 𝓤 X
hWV : ∀ (n : ℕ), W n ○ W n ⊆ V n
hWV' : ∀ (n : ℕ), W n ⊆ V n
t : ℕ → Set X
ht_anti : Antitone t
htl : ∀ (n : ℕ), t n ∈ l
htW : ∀ (n : ℕ), t n ×ˢ t n ⊆ W n
hts : ∀ (n : ℕ), t n ⊆ s
u : ℕ → X
hu : ∀ (n : ℕ), u n ∈ t n
huc : CauchySeq u
x : X
hxs : x ∈ s
hx : Tendsto (fun n => u n) atTop (𝓝 x)
N : ℕ
x✝ : True
n : ℕ
hNn : N ≤ n
hn : u n ∈ ball x (W N)
y : X
hy : y ∈ t n
⊢ (u n, (x, y).2) ∈ t N ×ˢ t N

Next tactic:
exact ⟨ht_anti hNn (hu n), ht_anti hNn hy⟩
theorem UniformSpace.compactSpace_iff_seqCompactSpace : CompactSpace X ↔ SeqCompactSpace X := by
  

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : UniformSpace X
s : Set X
inst✝ : IsCountablyGenerated (𝓤 X)
⊢ CompactSpace X ↔ SeqCompactSpace X

Next tactic:
simp only [← isCompact_univ_iff, seqCompactSpace_iff, UniformSpace.isCompact_iff_isSeqCompact]
theorem kroneckerMap_diagonal_diagonal [Zero α] [Zero β] [Zero γ] [DecidableEq m] [DecidableEq n]
    (f : α → β → γ) (hf₁ : ∀ b, f 0 b = 0) (hf₂ : ∀ a, f a 0 = 0) (a : m → α) (b : n → β) :
    kroneckerMap f (diagonal a) (diagonal b) = diagonal fun mn => f (a mn.1) (b mn.2) := by
  

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝⁴ : Zero α
inst✝³ : Zero β
inst✝² : Zero γ
inst✝¹ : DecidableEq m
inst✝ : DecidableEq n
f : α → β → γ
hf₁ : ∀ (b : β), f 0 b = 0
hf₂ : ∀ (a : α), f a 0 = 0
a : m → α
b : n → β
⊢ kroneckerMap f (diagonal a) (diagonal b) = diagonal fun mn => f (a mn.1) (b mn.2)

Next tactic:
ext ⟨i₁, i₂⟩ ⟨j₁, j₂⟩
theorem kroneckerMap_diagonal_diagonal [Zero α] [Zero β] [Zero γ] [DecidableEq m] [DecidableEq n]
    (f : α → β → γ) (hf₁ : ∀ b, f 0 b = 0) (hf₂ : ∀ a, f a 0 = 0) (a : m → α) (b : n → β) :
    kroneckerMap f (diagonal a) (diagonal b) = diagonal fun mn => f (a mn.1) (b mn.2) := by
  ext ⟨i₁, i₂⟩ ⟨j₁, j₂⟩
  

Proof state:
case a.mk.h.mk
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝⁴ : Zero α
inst✝³ : Zero β
inst✝² : Zero γ
inst✝¹ : DecidableEq m
inst✝ : DecidableEq n
f : α → β → γ
hf₁ : ∀ (b : β), f 0 b = 0
hf₂ : ∀ (a : α), f a 0 = 0
a : m → α
b : n → β
i₁ : m
i₂ : n
j₁ : m
j₂ : n
⊢ kroneckerMap f (diagonal a) (diagonal b) (i₁, i₂) (j₁, j₂) =
    diagonal (fun mn => f (a mn.1) (b mn.2)) (i₁, i₂) (j₁, j₂)

Next tactic:
simp [diagonal, apply_ite f, ite_and, ite_apply, apply_ite (f (a i₁)), hf₁, hf₂]
theorem kroneckerMap_diagonal_right [Zero β] [Zero γ] [DecidableEq n] (f : α → β → γ)
    (hf : ∀ a, f a 0 = 0) (A : Matrix l m α) (b : n → β) :
    kroneckerMap f A (diagonal b) = blockDiagonal fun i => A.map fun a => f a (b i) := by
  

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝² : Zero β
inst✝¹ : Zero γ
inst✝ : DecidableEq n
f : α → β → γ
hf : ∀ (a : α), f a 0 = 0
A : Matrix l m α
b : n → β
⊢ kroneckerMap f A (diagonal b) = blockDiagonal fun i => map A fun a => f a (b i)

Next tactic:
ext ⟨i₁, i₂⟩ ⟨j₁, j₂⟩
theorem kroneckerMap_diagonal_right [Zero β] [Zero γ] [DecidableEq n] (f : α → β → γ)
    (hf : ∀ a, f a 0 = 0) (A : Matrix l m α) (b : n → β) :
    kroneckerMap f A (diagonal b) = blockDiagonal fun i => A.map fun a => f a (b i) := by
  ext ⟨i₁, i₂⟩ ⟨j₁, j₂⟩
  

Proof state:
case a.mk.h.mk
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝² : Zero β
inst✝¹ : Zero γ
inst✝ : DecidableEq n
f : α → β → γ
hf : ∀ (a : α), f a 0 = 0
A : Matrix l m α
b : n → β
i₁ : l
i₂ : n
j₁ : m
j₂ : n
⊢ kroneckerMap f A (diagonal b) (i₁, i₂) (j₁, j₂) = blockDiagonal (fun i => map A fun a => f a (b i)) (i₁, i₂) (j₁, j₂)

Next tactic:
simp [diagonal, blockDiagonal, apply_ite (f (A i₁ j₁)), hf]
theorem kroneckerMap_diagonal_left [Zero α] [Zero γ] [DecidableEq l] (f : α → β → γ)
    (hf : ∀ b, f 0 b = 0) (a : l → α) (B : Matrix m n β) :
    kroneckerMap f (diagonal a) B =
      Matrix.reindex (Equiv.prodComm _ _) (Equiv.prodComm _ _)
        (blockDiagonal fun i => B.map fun b => f (a i) b) := by
  

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝² : Zero α
inst✝¹ : Zero γ
inst✝ : DecidableEq l
f : α → β → γ
hf : ∀ (b : β), f 0 b = 0
a : l → α
B : Matrix m n β
⊢ kroneckerMap f (diagonal a) B =
    (reindex (Equiv.prodComm m l) (Equiv.prodComm n l)) (blockDiagonal fun i => map B fun b => f (a i) b)

Next tactic:
ext ⟨i₁, i₂⟩ ⟨j₁, j₂⟩
theorem kroneckerMap_diagonal_left [Zero α] [Zero γ] [DecidableEq l] (f : α → β → γ)
    (hf : ∀ b, f 0 b = 0) (a : l → α) (B : Matrix m n β) :
    kroneckerMap f (diagonal a) B =
      Matrix.reindex (Equiv.prodComm _ _) (Equiv.prodComm _ _)
        (blockDiagonal fun i => B.map fun b => f (a i) b) := by
  ext ⟨i₁, i₂⟩ ⟨j₁, j₂⟩
  

Proof state:
case a.mk.h.mk
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝² : Zero α
inst✝¹ : Zero γ
inst✝ : DecidableEq l
f : α → β → γ
hf : ∀ (b : β), f 0 b = 0
a : l → α
B : Matrix m n β
i₁ : l
i₂ : m
j₁ : l
j₂ : n
⊢ kroneckerMap f (diagonal a) B (i₁, i₂) (j₁, j₂) =
    (reindex (Equiv.prodComm m l) (Equiv.prodComm n l)) (blockDiagonal fun i => map B fun b => f (a i) b) (i₁, i₂)
      (j₁, j₂)

Next tactic:
simp [diagonal, blockDiagonal, apply_ite f, ite_apply, hf]
@[simp]
theorem kroneckerMap_one_one [Zero α] [Zero β] [Zero γ] [One α] [One β] [One γ] [DecidableEq m]
    [DecidableEq n] (f : α → β → γ) (hf₁ : ∀ b, f 0 b = 0) (hf₂ : ∀ a, f a 0 = 0)
    (hf₃ : f 1 1 = 1) : kroneckerMap f (1 : Matrix m m α) (1 : Matrix n n β) = 1 :=
  (kroneckerMap_diagonal_diagonal _ hf₁ hf₂ _ _).trans <| by 

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝⁷ : Zero α
inst✝⁶ : Zero β
inst✝⁵ : Zero γ
inst✝⁴ : One α
inst✝³ : One β
inst✝² : One γ
inst✝¹ : DecidableEq m
inst✝ : DecidableEq n
f : α → β → γ
hf₁ : ∀ (b : β), f 0 b = 0
hf₂ : ∀ (a : α), f a 0 = 0
hf₃ : f 1 1 = 1
⊢ (diagonal fun mn => f 1 1) = 1

Next tactic:
simp only [hf₃, diagonal_one]
theorem kroneckerMap_reindex (f : α → β → γ) (el : l ≃ l') (em : m ≃ m') (en : n ≃ n') (ep : p ≃ p')
    (M : Matrix l m α) (N : Matrix n p β) :
    kroneckerMap f (reindex el em M) (reindex en ep N) =
      reindex (el.prodCongr en) (em.prodCongr ep) (kroneckerMap f M N) := by
  

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
f : α → β → γ
el : l ≃ l'
em : m ≃ m'
en : n ≃ n'
ep : p ≃ p'
M : Matrix l m α
N : Matrix n p β
⊢ kroneckerMap f ((reindex el em) M) ((reindex en ep) N) =
    (reindex (Equiv.prodCongr el en) (Equiv.prodCongr em ep)) (kroneckerMap f M N)

Next tactic:
ext ⟨i, i'⟩ ⟨j, j'⟩
theorem kroneckerMap_reindex (f : α → β → γ) (el : l ≃ l') (em : m ≃ m') (en : n ≃ n') (ep : p ≃ p')
    (M : Matrix l m α) (N : Matrix n p β) :
    kroneckerMap f (reindex el em M) (reindex en ep N) =
      reindex (el.prodCongr en) (em.prodCongr ep) (kroneckerMap f M N) := by
  ext ⟨i, i'⟩ ⟨j, j'⟩
  

Proof state:
case a.mk.h.mk
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
f : α → β → γ
el : l ≃ l'
em : m ≃ m'
en : n ≃ n'
ep : p ≃ p'
M : Matrix l m α
N : Matrix n p β
i : l'
i' : n'
j : m'
j' : p'
⊢ kroneckerMap f ((reindex el em) M) ((reindex en ep) N) (i, i') (j, j') =
    (reindex (Equiv.prodCongr el en) (Equiv.prodCongr em ep)) (kroneckerMap f M N) (i, i') (j, j')

Next tactic:
rfl
/-- `Matrix.kroneckerMapBilinear` commutes with `*` if `f` does.

This is primarily used with `R = ℕ` to prove `Matrix.mul_kronecker_mul`. -/
theorem kroneckerMapBilinear_mul_mul [CommSemiring R] [Fintype m] [Fintype m']
    [NonUnitalNonAssocSemiring α] [NonUnitalNonAssocSemiring β] [NonUnitalNonAssocSemiring γ]
    [Module R α] [Module R β] [Module R γ] (f : α →ₗ[R] β →ₗ[R] γ)
    (h_comm : ∀ a b a' b', f (a * b) (a' * b') = f a a' * f b b') (A : Matrix l m α)
    (B : Matrix m n α) (A' : Matrix l' m' β) (B' : Matrix m' n' β) :
    kroneckerMapBilinear f (A * B) (A' * B') =
      kroneckerMapBilinear f A A' * kroneckerMapBilinear f B B' := by
  

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝⁸ : CommSemiring R
inst✝⁷ : Fintype m
inst✝⁶ : Fintype m'
inst✝⁵ : NonUnitalNonAssocSemiring α
inst✝⁴ : NonUnitalNonAssocSemiring β
inst✝³ : NonUnitalNonAssocSemiring γ
inst✝² : Module R α
inst✝¹ : Module R β
inst✝ : Module R γ
f : α →ₗ[R] β →ₗ[R] γ
h_comm : ∀ (a b : α) (a' b' : β), (f (a * b)) (a' * b') = (f a) a' * (f b) b'
A : Matrix l m α
B : Matrix m n α
A' : Matrix l' m' β
B' : Matrix m' n' β
⊢ ((kroneckerMapBilinear f) (A * B)) (A' * B') = ((kroneckerMapBilinear f) A) A' * ((kroneckerMapBilinear f) B) B'

Next tactic:
ext ⟨i, i'⟩ ⟨j, j'⟩
/-- `Matrix.kroneckerMapBilinear` commutes with `*` if `f` does.

This is primarily used with `R = ℕ` to prove `Matrix.mul_kronecker_mul`. -/
theorem kroneckerMapBilinear_mul_mul [CommSemiring R] [Fintype m] [Fintype m']
    [NonUnitalNonAssocSemiring α] [NonUnitalNonAssocSemiring β] [NonUnitalNonAssocSemiring γ]
    [Module R α] [Module R β] [Module R γ] (f : α →ₗ[R] β →ₗ[R] γ)
    (h_comm : ∀ a b a' b', f (a * b) (a' * b') = f a a' * f b b') (A : Matrix l m α)
    (B : Matrix m n α) (A' : Matrix l' m' β) (B' : Matrix m' n' β) :
    kroneckerMapBilinear f (A * B) (A' * B') =
      kroneckerMapBilinear f A A' * kroneckerMapBilinear f B B' := by
  ext ⟨i, i'⟩ ⟨j, j'⟩
  

Proof state:
case a.mk.h.mk
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝⁸ : CommSemiring R
inst✝⁷ : Fintype m
inst✝⁶ : Fintype m'
inst✝⁵ : NonUnitalNonAssocSemiring α
inst✝⁴ : NonUnitalNonAssocSemiring β
inst✝³ : NonUnitalNonAssocSemiring γ
inst✝² : Module R α
inst✝¹ : Module R β
inst✝ : Module R γ
f : α →ₗ[R] β →ₗ[R] γ
h_comm : ∀ (a b : α) (a' b' : β), (f (a * b)) (a' * b') = (f a) a' * (f b) b'
A : Matrix l m α
B : Matrix m n α
A' : Matrix l' m' β
B' : Matrix m' n' β
i : l
i' : l'
j : n
j' : n'
⊢ ((kroneckerMapBilinear f) (A * B)) (A' * B') (i, i') (j, j') =
    (((kroneckerMapBilinear f) A) A' * ((kroneckerMapBilinear f) B) B') (i, i') (j, j')

Next tactic:
simp only [kroneckerMapBilinear_apply_apply, mul_apply, ← Finset.univ_product_univ,
    Finset.sum_product, kroneckerMap_apply]
/-- `Matrix.kroneckerMapBilinear` commutes with `*` if `f` does.

This is primarily used with `R = ℕ` to prove `Matrix.mul_kronecker_mul`. -/
theorem kroneckerMapBilinear_mul_mul [CommSemiring R] [Fintype m] [Fintype m']
    [NonUnitalNonAssocSemiring α] [NonUnitalNonAssocSemiring β] [NonUnitalNonAssocSemiring γ]
    [Module R α] [Module R β] [Module R γ] (f : α →ₗ[R] β →ₗ[R] γ)
    (h_comm : ∀ a b a' b', f (a * b) (a' * b') = f a a' * f b b') (A : Matrix l m α)
    (B : Matrix m n α) (A' : Matrix l' m' β) (B' : Matrix m' n' β) :
    kroneckerMapBilinear f (A * B) (A' * B') =
      kroneckerMapBilinear f A A' * kroneckerMapBilinear f B B' := by
  ext ⟨i, i'⟩ ⟨j, j'⟩
  simp only [kroneckerMapBilinear_apply_apply, mul_apply, ← Finset.univ_product_univ,
    Finset.sum_product, kroneckerMap_apply]
  

Proof state:
case a.mk.h.mk
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝⁸ : CommSemiring R
inst✝⁷ : Fintype m
inst✝⁶ : Fintype m'
inst✝⁵ : NonUnitalNonAssocSemiring α
inst✝⁴ : NonUnitalNonAssocSemiring β
inst✝³ : NonUnitalNonAssocSemiring γ
inst✝² : Module R α
inst✝¹ : Module R β
inst✝ : Module R γ
f : α →ₗ[R] β →ₗ[R] γ
h_comm : ∀ (a b : α) (a' b' : β), (f (a * b)) (a' * b') = (f a) a' * (f b) b'
A : Matrix l m α
B : Matrix m n α
A' : Matrix l' m' β
B' : Matrix m' n' β
i : l
i' : l'
j : n
j' : n'
⊢ (f (Finset.sum Finset.univ fun j_1 => A i j_1 * B j_1 j)) (Finset.sum Finset.univ fun j => A' i' j * B' j j') =
    Finset.sum Finset.univ fun x => Finset.sum Finset.univ fun x_1 => (f (A i x)) (A' i' x_1) * (f (B x j)) (B' x_1 j')

Next tactic:
simp_rw [map_sum f, LinearMap.sum_apply, map_sum, h_comm]
/-- `trace` distributes over `Matrix.kroneckerMapBilinear`.

This is primarily used with `R = ℕ` to prove `Matrix.trace_kronecker`. -/
theorem trace_kroneckerMapBilinear [CommSemiring R] [Fintype m] [Fintype n] [AddCommMonoid α]
    [AddCommMonoid β] [AddCommMonoid γ] [Module R α] [Module R β] [Module R γ]
    (f : α →ₗ[R] β →ₗ[R] γ) (A : Matrix m m α) (B : Matrix n n β) :
    trace (kroneckerMapBilinear f A B) = f (trace A) (trace B) := by
  

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝⁸ : CommSemiring R
inst✝⁷ : Fintype m
inst✝⁶ : Fintype n
inst✝⁵ : AddCommMonoid α
inst✝⁴ : AddCommMonoid β
inst✝³ : AddCommMonoid γ
inst✝² : Module R α
inst✝¹ : Module R β
inst✝ : Module R γ
f : α →ₗ[R] β →ₗ[R] γ
A : Matrix m m α
B : Matrix n n β
⊢ trace (((kroneckerMapBilinear f) A) B) = (f (trace A)) (trace B)

Next tactic:
simp_rw [Matrix.trace, Matrix.diag, kroneckerMapBilinear_apply_apply, LinearMap.map_sum₂,
    map_sum, ← Finset.univ_product_univ, Finset.sum_product, kroneckerMap_apply]
/-- `determinant` of `Matrix.kroneckerMapBilinear`.

This is primarily used with `R = ℕ` to prove `Matrix.det_kronecker`. -/
theorem det_kroneckerMapBilinear [CommSemiring R] [Fintype m] [Fintype n] [DecidableEq m]
    [DecidableEq n] [CommRing α] [CommRing β] [CommRing γ] [Module R α] [Module R β] [Module R γ]
    (f : α →ₗ[R] β →ₗ[R] γ) (h_comm : ∀ a b a' b', f (a * b) (a' * b') = f a a' * f b b')
    (A : Matrix m m α) (B : Matrix n n β) :
    det (kroneckerMapBilinear f A B) =
      det (A.map fun a => f a 1) ^ Fintype.card n * det (B.map fun b => f 1 b) ^ Fintype.card m :=
  calc
    det (kroneckerMapBilinear f A B) =
        det (kroneckerMapBilinear f A 1 * kroneckerMapBilinear f 1 B) :=
      by 

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝¹⁰ : CommSemiring R
inst✝⁹ : Fintype m
inst✝⁸ : Fintype n
inst✝⁷ : DecidableEq m
inst✝⁶ : DecidableEq n
inst✝⁵ : CommRing α
inst✝⁴ : CommRing β
inst✝³ : CommRing γ
inst✝² : Module R α
inst✝¹ : Module R β
inst✝ : Module R γ
f : α →ₗ[R] β →ₗ[R] γ
h_comm : ∀ (a b : α) (a' b' : β), (f (a * b)) (a' * b') = (f a) a' * (f b) b'
A : Matrix m m α
B : Matrix n n β
⊢ det (((kroneckerMapBilinear f) A) B) = det (((kroneckerMapBilinear f) A) 1 * ((kroneckerMapBilinear f) 1) B)

Next tactic:
rw [← kroneckerMapBilinear_mul_mul f h_comm, Matrix.mul_one, Matrix.one_mul]
/-- `determinant` of `Matrix.kroneckerMapBilinear`.

This is primarily used with `R = ℕ` to prove `Matrix.det_kronecker`. -/
theorem det_kroneckerMapBilinear [CommSemiring R] [Fintype m] [Fintype n] [DecidableEq m]
    [DecidableEq n] [CommRing α] [CommRing β] [CommRing γ] [Module R α] [Module R β] [Module R γ]
    (f : α →ₗ[R] β →ₗ[R] γ) (h_comm : ∀ a b a' b', f (a * b) (a' * b') = f a a' * f b b')
    (A : Matrix m m α) (B : Matrix n n β) :
    det (kroneckerMapBilinear f A B) =
      det (A.map fun a => f a 1) ^ Fintype.card n * det (B.map fun b => f 1 b) ^ Fintype.card m :=
  calc
    det (kroneckerMapBilinear f A B) =
        det (kroneckerMapBilinear f A 1 * kroneckerMapBilinear f 1 B) :=
      by rw [← kroneckerMapBilinear_mul_mul f h_comm, Matrix.mul_one, Matrix.one_mul]
    _ = det (blockDiagonal fun _ => A.map fun a => f a 1) *
        det (blockDiagonal fun _ => B.map fun b => f 1 b) := by
      

Proof state:
R : Type u_1
α : Type u_2
α' : Type u_3
β : Type u_4
β' : Type u_5
γ : Type u_6
γ' : Type u_7
l : Type u_8
m : Type u_9
n : Type u_10
p : Type u_11
q : Type u_12
r : Type u_13
l' : Type u_14
m' : Type u_15
n' : Type u_16
p' : Type u_17
inst✝¹⁰ : CommSemiring R
inst✝⁹ : Fintype m
inst✝⁸ : Fintype n
inst✝⁷ : DecidableEq m
inst✝⁶ : DecidableEq n
inst✝⁵ : CommRing α
inst✝⁴ : CommRing β
inst✝³ : CommRing γ
inst✝² : Module R α
inst✝¹ : Module R β
inst✝ : Module R γ
f : α →ₗ[R] β →ₗ[R] γ
h_comm : ∀ (a b : α) (a' b' : β), (f (a * b)) (a' * b') = (f a) a' * (f b) b'
A : Matrix m m α
B : Matrix n n β
⊢ det (((kroneckerMapBilinear f) A) 1 * ((kroneckerMapBilinear f) 1) B) =
    det (blockDiagonal fun x => map A fun a => (f a) 1) * det (blockDiagonal fun x => map B fun b => (f 1) b)

Next tactic:
rw [det_mul, ← diagonal_one, ← diagonal_one, kroneckerMapBilinear_apply_apply,
        kroneckerMap_diagonal_right _ fun _ => _, kroneckerMapBilinear_apply_apply,
        kroneckerMap_diagonal_left _ fun _ => _, det_reindex_self]