l3lab/ntp-mathlib huggingface dataset:
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  

Proof state:
case pos
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
⊢ (kroneckerMap (fun x x_1 => x * x_1) A B)⁻¹ = kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹

Next tactic:
by_cases hB : IsUnit B.det
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; 

Proof state:
case pos
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : IsUnit (det B)
⊢ (kroneckerMap (fun x x_1 => x * x_1) A B)⁻¹ = kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹
case neg
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : ¬IsUnit (det B)
⊢ (kroneckerMap (fun x x_1 => x * x_1) A B)⁻¹ = kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹

Next tactic:
swap
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · 

Proof state:
case neg
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : ¬IsUnit (det B)
⊢ (kroneckerMap (fun x x_1 => x * x_1) A B)⁻¹ = kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹

Next tactic:
cases isEmpty_or_nonempty m
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · cases isEmpty_or_nonempty m
    · 

Proof state:
case neg.inl
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : ¬IsUnit (det B)
h✝ : IsEmpty m
⊢ (kroneckerMap (fun x x_1 => x * x_1) A B)⁻¹ = kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹

Next tactic:
exact Subsingleton.elim _ _
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · cases isEmpty_or_nonempty m
    · exact Subsingleton.elim _ _
    

Proof state:
case neg.inr
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : ¬IsUnit (det B)
h✝ : Nonempty m
⊢ (kroneckerMap (fun x x_1 => x * x_1) A B)⁻¹ = kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹

Next tactic:
have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hB
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_right hAB)
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · cases isEmpty_or_nonempty m
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := 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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : ¬IsUnit (det B)
h✝ : Nonempty m
⊢ ¬IsUnit (det (kroneckerMap (fun x x_1 => x * x_1) A B))

Next tactic:
refine' mt (fun hAB => _) hB
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · cases isEmpty_or_nonempty m
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hB
      

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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : ¬IsUnit (det B)
h✝ : Nonempty m
hAB : IsUnit (det (kroneckerMap (fun x x_1 => x * x_1) A B))
⊢ IsUnit (det B)

Next tactic:
rw [det_kronecker] at hAB
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · cases isEmpty_or_nonempty m
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hB
      rw [det_kronecker] at hAB
      

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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : ¬IsUnit (det B)
h✝ : Nonempty m
hAB : IsUnit (det A ^ Fintype.card n * det B ^ Fintype.card m)
⊢ IsUnit (det B)

Next tactic:
exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_right hAB)
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · cases isEmpty_or_nonempty m
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hB
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_right hAB)
    

Proof state:
case neg.inr
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : ¬IsUnit (det B)
h✝ : Nonempty m
hAB : ¬IsUnit (det (kroneckerMap (fun x x_1 => x * x_1) A B))
⊢ (kroneckerMap (fun x x_1 => x * x_1) A B)⁻¹ = kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹

Next tactic:
rw [nonsing_inv_apply_not_isUnit _ hB, kronecker_zero, nonsing_inv_apply_not_isUnit _ hAB]
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · cases isEmpty_or_nonempty m
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hB
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_right hAB)
    rw [nonsing_inv_apply_not_isUnit _ hB, kronecker_zero, nonsing_inv_apply_not_isUnit _ hAB]
  -- otherwise follows trivially from `mul_kronecker_mul`
  · 

Proof state:
case pos
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : IsUnit (det B)
⊢ (kroneckerMap (fun x x_1 => x * x_1) A B)⁻¹ = kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹

Next tactic:
apply inv_eq_right_inv
theorem inv_kronecker [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing R]
    (A : Matrix m m R) (B : Matrix n n R) : (A ⊗ₖ B)⁻¹ = A⁻¹ ⊗ₖ B⁻¹ := by
  -- handle the special cases where either matrix is not invertible
  by_cases hA : IsUnit A.det;
  swap
  · cases isEmpty_or_nonempty n
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hA
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_left hAB)
    rw [nonsing_inv_apply_not_isUnit _ hA, zero_kronecker, nonsing_inv_apply_not_isUnit _ hAB]
  by_cases hB : IsUnit B.det; swap
  · cases isEmpty_or_nonempty m
    · exact Subsingleton.elim _ _
    have hAB : ¬IsUnit (A ⊗ₖ B).det := by
      refine' mt (fun hAB => _) hB
      rw [det_kronecker] at hAB
      exact (isUnit_pow_iff Fintype.card_ne_zero).mp (isUnit_of_mul_isUnit_right hAB)
    rw [nonsing_inv_apply_not_isUnit _ hB, kronecker_zero, nonsing_inv_apply_not_isUnit _ hAB]
  -- otherwise follows trivially from `mul_kronecker_mul`
  · apply inv_eq_right_inv
    

Proof state:
case pos.h
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✝⁴ : Fintype m
inst✝³ : Fintype n
inst✝² : DecidableEq m
inst✝¹ : DecidableEq n
inst✝ : CommRing R
A : Matrix m m R
B : Matrix n n R
hA : IsUnit (det A)
hB : IsUnit (det B)
⊢ kroneckerMap (fun x x_1 => x * x_1) A B * kroneckerMap (fun x x_1 => x * x_1) A⁻¹ B⁻¹ = 1

Next tactic:
rw [← mul_kronecker_mul, ← one_kronecker_one, mul_nonsing_inv _ hA, mul_nonsing_inv _ hB]
theorem det_kroneckerTMul [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n]
    (A : Matrix m m α) (B : Matrix n n β) :
    det (A ⊗ₖₜ[R] B) = (det A ^ Fintype.card n) ⊗ₜ[R] (det B ^ Fintype.card m) := 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✝⁸ : CommRing R
inst✝⁷ : CommRing α
inst✝⁶ : CommRing β
inst✝⁵ : Algebra R α
inst✝⁴ : Algebra R β
inst✝³ : Fintype m
inst✝² : Fintype n
inst✝¹ : DecidableEq m
inst✝ : DecidableEq n
A : Matrix m m α
B : Matrix n n β
⊢ det (kroneckerMap (tmul R) A B) = (det A ^ Fintype.card n) ⊗ₜ[R] (det B ^ Fintype.card m)

Next tactic:
refine' (det_kroneckerMapBilinear (TensorProduct.mk R α β) tmul_mul_tmul _ _).trans _
theorem det_kroneckerTMul [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n]
    (A : Matrix m m α) (B : Matrix n n β) :
    det (A ⊗ₖₜ[R] B) = (det A ^ Fintype.card n) ⊗ₜ[R] (det B ^ Fintype.card m) := by
  refine' (det_kroneckerMapBilinear (TensorProduct.mk R α β) tmul_mul_tmul _ _).trans _
  

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✝⁸ : CommRing R
inst✝⁷ : CommRing α
inst✝⁶ : CommRing β
inst✝⁵ : Algebra R α
inst✝⁴ : Algebra R β
inst✝³ : Fintype m
inst✝² : Fintype n
inst✝¹ : DecidableEq m
inst✝ : DecidableEq n
A : Matrix m m α
B : Matrix n n β
⊢ det (map A fun a => ((mk R α β) a) 1) ^ Fintype.card n * det (map B fun b => ((mk R α β) 1) b) ^ Fintype.card m =
    (det A ^ Fintype.card n) ⊗ₜ[R] (det B ^ Fintype.card m)

Next tactic:
simp (config := { eta := false }) only [mk_apply, ← includeLeft_apply (S := R),
    ← includeRight_apply]
theorem det_kroneckerTMul [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n]
    (A : Matrix m m α) (B : Matrix n n β) :
    det (A ⊗ₖₜ[R] B) = (det A ^ Fintype.card n) ⊗ₜ[R] (det B ^ Fintype.card m) := by
  refine' (det_kroneckerMapBilinear (TensorProduct.mk R α β) tmul_mul_tmul _ _).trans _
  simp (config := { eta := false }) only [mk_apply, ← includeLeft_apply (S := R),
    ← includeRight_apply]
  

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✝⁸ : CommRing R
inst✝⁷ : CommRing α
inst✝⁶ : CommRing β
inst✝⁵ : Algebra R α
inst✝⁴ : Algebra R β
inst✝³ : Fintype m
inst✝² : Fintype n
inst✝¹ : DecidableEq m
inst✝ : DecidableEq n
A : Matrix m m α
B : Matrix n n β
⊢ det (map A fun a => includeLeft a) ^ Fintype.card n * det (map B fun b => includeRight b) ^ Fintype.card m =
    (det A ^ Fintype.card n) ⊗ₜ[R] (det B ^ Fintype.card m)

Next tactic:
simp only [← AlgHom.mapMatrix_apply, ← AlgHom.map_det]
theorem det_kroneckerTMul [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n]
    (A : Matrix m m α) (B : Matrix n n β) :
    det (A ⊗ₖₜ[R] B) = (det A ^ Fintype.card n) ⊗ₜ[R] (det B ^ Fintype.card m) := by
  refine' (det_kroneckerMapBilinear (TensorProduct.mk R α β) tmul_mul_tmul _ _).trans _
  simp (config := { eta := false }) only [mk_apply, ← includeLeft_apply (S := R),
    ← includeRight_apply]
  simp only [← AlgHom.mapMatrix_apply, ← AlgHom.map_det]
  

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✝⁸ : CommRing R
inst✝⁷ : CommRing α
inst✝⁶ : CommRing β
inst✝⁵ : Algebra R α
inst✝⁴ : Algebra R β
inst✝³ : Fintype m
inst✝² : Fintype n
inst✝¹ : DecidableEq m
inst✝ : DecidableEq n
A : Matrix m m α
B : Matrix n n β
⊢ includeLeft (det A) ^ Fintype.card n * includeRight (det B) ^ Fintype.card m =
    (det A ^ Fintype.card n) ⊗ₜ[R] (det B ^ Fintype.card m)

Next tactic:
simp only [includeLeft_apply, includeRight_apply, tmul_pow, tmul_mul_tmul, one_pow,
    _root_.mul_one, _root_.one_mul]
@[ext]
theorem ext {σ τ : p.Gal} (h : ∀ x ∈ p.rootSet p.SplittingField, σ x = τ x) : σ = τ := by
  

Proof state:
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
σ τ : Gal p
h : ∀ x ∈ rootSet p (SplittingField p), σ x = τ x
⊢ σ = τ

Next tactic:
refine'
    AlgEquiv.ext fun x =>
      (AlgHom.mem_equalizer σ.toAlgHom τ.toAlgHom x).mp
        ((SetLike.ext_iff.mp _ x).mpr Algebra.mem_top)
@[ext]
theorem ext {σ τ : p.Gal} (h : ∀ x ∈ p.rootSet p.SplittingField, σ x = τ x) : σ = τ := by
  refine'
    AlgEquiv.ext fun x =>
      (AlgHom.mem_equalizer σ.toAlgHom τ.toAlgHom x).mp
        ((SetLike.ext_iff.mp _ x).mpr Algebra.mem_top)
  

Proof state:
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
σ τ : Gal p
h : ∀ x ∈ rootSet p (SplittingField p), σ x = τ x
x : SplittingField p
⊢ AlgHom.equalizer ↑σ ↑τ = ⊤

Next tactic:
rwa [eq_top_iff, ← SplittingField.adjoin_rootSet, Algebra.adjoin_le_iff]
/-- If `p` splits in `F` then the `p.gal` is trivial. -/
def uniqueGalOfSplits (h : p.Splits (RingHom.id F)) : Unique p.Gal where
  default := 1
  uniq f :=
    AlgEquiv.ext fun x => by
      

Proof state:
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
h : Splits (RingHom.id F) p
f : Gal p
x : SplittingField p
⊢ f x = default x

Next tactic:
obtain ⟨y, rfl⟩ :=
        Algebra.mem_bot.mp
          ((SetLike.ext_iff.mp ((IsSplittingField.splits_iff _ p).mp h) x).mp Algebra.mem_top)
/-- If `p` splits in `F` then the `p.gal` is trivial. -/
def uniqueGalOfSplits (h : p.Splits (RingHom.id F)) : Unique p.Gal where
  default := 1
  uniq f :=
    AlgEquiv.ext fun x => by
      obtain ⟨y, rfl⟩ :=
        Algebra.mem_bot.mp
          ((SetLike.ext_iff.mp ((IsSplittingField.splits_iff _ p).mp h) x).mp Algebra.mem_top)
      

Proof state:
case intro
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
h : Splits (RingHom.id F) p
f : Gal p
y : F
⊢ f ((algebraMap F (SplittingField p)) y) = default ((algebraMap F (SplittingField p)) y)

Next tactic:
rw [AlgEquiv.commutes, AlgEquiv.commutes]
theorem mapRoots_bijective [h : Fact (p.Splits (algebraMap F E))] :
    Function.Bijective (mapRoots p E) := by
  

Proof state:
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
h : Fact (Splits (algebraMap F E) p)
⊢ Function.Bijective (mapRoots p E)

Next tactic:
constructor
theorem mapRoots_bijective [h : Fact (p.Splits (algebraMap F E))] :
    Function.Bijective (mapRoots p E) := by
  constructor
  · 

Proof state:
case left
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
h : Fact (Splits (algebraMap F E) p)
⊢ Function.Injective (mapRoots p E)

Next tactic:
exact fun _ _ h => Subtype.ext (RingHom.injective _ (Subtype.ext_iff.mp h))
theorem mapRoots_bijective [h : Fact (p.Splits (algebraMap F E))] :
    Function.Bijective (mapRoots p E) := by
  constructor
  · exact fun _ _ h => Subtype.ext (RingHom.injective _ (Subtype.ext_iff.mp h))
  · 

Proof state:
case right
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
h : Fact (Splits (algebraMap F E) p)
⊢ Function.Surjective (mapRoots p E)

Next tactic:
intro y
theorem mapRoots_bijective [h : Fact (p.Splits (algebraMap F E))] :
    Function.Bijective (mapRoots p E) := by
  constructor
  · exact fun _ _ h => Subtype.ext (RingHom.injective _ (Subtype.ext_iff.mp h))
  · intro y
    -- this is just an equality of two different ways to write the roots of `p` as an `E`-polynomial
    

Proof state:
case right
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
h : Fact (Splits (algebraMap F E) p)
y : ↑(rootSet p E)
⊢ ∃ a, mapRoots p E a = y

Next tactic:
have key :=
      roots_map (IsScalarTower.toAlgHom F p.SplittingField E : p.SplittingField →+* E)
        ((splits_id_iff_splits _).mpr (IsSplittingField.splits p.SplittingField p))