l3lab/ntp-mathlib huggingface dataset:
theorem conjugatesOf_subset {t : Set G} (ht : IsNormalSubgroup t) {a : G} (h : a ∈ t) :
    conjugatesOf a ⊆ t := fun x hc => by
  obtain ⟨c, w⟩ := isConj_iff.1 hc
  

Proof state:
case intro
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c✝ : G
s : Set G
inst✝ : Group G
t : Set G
ht : IsNormalSubgroup t
a : G
h : a ∈ t
x : G
hc : x ∈ conjugatesOf a
c : G
w : c * a * c⁻¹ = x
⊢ x ∈ t

Next tactic:
have H := IsNormalSubgroup.normal ht a h c
theorem conjugatesOf_subset {t : Set G} (ht : IsNormalSubgroup t) {a : G} (h : a ∈ t) :
    conjugatesOf a ⊆ t := fun x hc => by
  obtain ⟨c, w⟩ := isConj_iff.1 hc
  have H := IsNormalSubgroup.normal ht a h c
  

Proof state:
case intro
G : Type u_1
H✝ : Type u_2
A : Type u_3
a✝ a₁ a₂ b c✝ : G
s : Set G
inst✝ : Group G
t : Set G
ht : IsNormalSubgroup t
a : G
h : a ∈ t
x : G
hc : x ∈ conjugatesOf a
c : G
w : c * a * c⁻¹ = x
H : c * a * c⁻¹ ∈ t
⊢ x ∈ t

Next tactic:
rwa [← w]
/-- The normal closure of s is a normal subgroup. -/
theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) :=
  { normalClosure.isSubgroup _ with
    normal := fun n h g => by
      

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
s : Set G
inst✝ : Group G
src✝ : IsSubgroup (normalClosure s) := isSubgroup s
n : G
h : n ∈ normalClosure s
g : G
⊢ g * n * g⁻¹ ∈ normalClosure s

Next tactic:
induction' h with x hx x hx ihx x y hx hy ihx ihy
/-- The normal closure of s is a normal subgroup. -/
theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) :=
  { normalClosure.isSubgroup _ with
    normal := fun n h g => by
      induction' h with x hx x hx ihx x y hx hy ihx ihy
      · 

Proof state:
case basic
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
s : Set G
inst✝ : Group G
src✝ : IsSubgroup (normalClosure s) := isSubgroup s
n g x : G
hx : x ∈ conjugatesOfSet s
⊢ g * x * g⁻¹ ∈ normalClosure s

Next tactic:
exact conjugatesOfSet_subset_normalClosure (conj_mem_conjugatesOfSet hx)
/-- The normal closure of s is a normal subgroup. -/
theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) :=
  { normalClosure.isSubgroup _ with
    normal := fun n h g => by
      induction' h with x hx x hx ihx x y hx hy ihx ihy
      · exact conjugatesOfSet_subset_normalClosure (conj_mem_conjugatesOfSet hx)
      · 

Proof state:
case one
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
s : Set G
inst✝ : Group G
src✝ : IsSubgroup (normalClosure s) := isSubgroup s
n g : G
⊢ g * 1 * g⁻¹ ∈ normalClosure s

Next tactic:
simpa using (normalClosure.isSubgroup s).one_mem
/-- The normal closure of s is a normal subgroup. -/
theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) :=
  { normalClosure.isSubgroup _ with
    normal := fun n h g => by
      induction' h with x hx x hx ihx x y hx hy ihx ihy
      · exact conjugatesOfSet_subset_normalClosure (conj_mem_conjugatesOfSet hx)
      · simpa using (normalClosure.isSubgroup s).one_mem
      · 

Proof state:
case inv
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
s : Set G
inst✝ : Group G
src✝ : IsSubgroup (normalClosure s) := isSubgroup s
n g x : G
hx : InClosure (conjugatesOfSet s) x
ihx : g * x * g⁻¹ ∈ normalClosure s
⊢ g * x⁻¹ * g⁻¹ ∈ normalClosure s

Next tactic:
rw [← conj_inv]
/-- The normal closure of s is a normal subgroup. -/
theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) :=
  { normalClosure.isSubgroup _ with
    normal := fun n h g => by
      induction' h with x hx x hx ihx x y hx hy ihx ihy
      · exact conjugatesOfSet_subset_normalClosure (conj_mem_conjugatesOfSet hx)
      · simpa using (normalClosure.isSubgroup s).one_mem
      · rw [← conj_inv]
        

Proof state:
case inv
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
s : Set G
inst✝ : Group G
src✝ : IsSubgroup (normalClosure s) := isSubgroup s
n g x : G
hx : InClosure (conjugatesOfSet s) x
ihx : g * x * g⁻¹ ∈ normalClosure s
⊢ (g * x * g⁻¹)⁻¹ ∈ normalClosure s

Next tactic:
exact (normalClosure.isSubgroup _).inv_mem ihx
/-- The normal closure of s is a normal subgroup. -/
theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) :=
  { normalClosure.isSubgroup _ with
    normal := fun n h g => by
      induction' h with x hx x hx ihx x y hx hy ihx ihy
      · exact conjugatesOfSet_subset_normalClosure (conj_mem_conjugatesOfSet hx)
      · simpa using (normalClosure.isSubgroup s).one_mem
      · rw [← conj_inv]
        exact (normalClosure.isSubgroup _).inv_mem ihx
      · 

Proof state:
case mul
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
s : Set G
inst✝ : Group G
src✝ : IsSubgroup (normalClosure s) := isSubgroup s
n g x y : G
hx : InClosure (conjugatesOfSet s) x
hy : InClosure (conjugatesOfSet s) y
ihx : g * x * g⁻¹ ∈ normalClosure s
ihy : g * y * g⁻¹ ∈ normalClosure s
⊢ g * (x * y) * g⁻¹ ∈ normalClosure s

Next tactic:
rw [← conj_mul]
/-- The normal closure of s is a normal subgroup. -/
theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) :=
  { normalClosure.isSubgroup _ with
    normal := fun n h g => by
      induction' h with x hx x hx ihx x y hx hy ihx ihy
      · exact conjugatesOfSet_subset_normalClosure (conj_mem_conjugatesOfSet hx)
      · simpa using (normalClosure.isSubgroup s).one_mem
      · rw [← conj_inv]
        exact (normalClosure.isSubgroup _).inv_mem ihx
      · rw [← conj_mul]
        

Proof state:
case mul
G : Type u_1
H : Type u_2
A : Type u_3
a a₁ a₂ b c : G
s : Set G
inst✝ : Group G
src✝ : IsSubgroup (normalClosure s) := isSubgroup s
n g x y : G
hx : InClosure (conjugatesOfSet s) x
hy : InClosure (conjugatesOfSet s) y
ihx : g * x * g⁻¹ ∈ normalClosure s
ihy : g * y * g⁻¹ ∈ normalClosure s
⊢ g * x * g⁻¹ * (g * y * g⁻¹) ∈ normalClosure s

Next tactic:
exact (normalClosure.isSubgroup _).toIsSubmonoid.mul_mem ihx ihy
/-- The normal closure of s is the smallest normal subgroup containing s. -/
theorem normalClosure_subset {s t : Set G} (ht : IsNormalSubgroup t) (h : s ⊆ t) :
    normalClosure s ⊆ t := fun a w => by
  

Proof state:
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
s✝ : Set G
inst✝ : Group G
s t : Set G
ht : IsNormalSubgroup t
h : s ⊆ t
a : G
w : a ∈ normalClosure s
⊢ a ∈ t

Next tactic:
induction' w with x hx x _ ihx x y _ _ ihx ihy
/-- The normal closure of s is the smallest normal subgroup containing s. -/
theorem normalClosure_subset {s t : Set G} (ht : IsNormalSubgroup t) (h : s ⊆ t) :
    normalClosure s ⊆ t := fun a w => by
  induction' w with x hx x _ ihx x y _ _ ihx ihy
  · 

Proof state:
case basic
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
s✝ : Set G
inst✝ : Group G
s t : Set G
ht : IsNormalSubgroup t
h : s ⊆ t
a x : G
hx : x ∈ conjugatesOfSet s
⊢ x ∈ t

Next tactic:
exact conjugatesOfSet_subset' ht h <| hx
/-- The normal closure of s is the smallest normal subgroup containing s. -/
theorem normalClosure_subset {s t : Set G} (ht : IsNormalSubgroup t) (h : s ⊆ t) :
    normalClosure s ⊆ t := fun a w => by
  induction' w with x hx x _ ihx x y _ _ ihx ihy
  · exact conjugatesOfSet_subset' ht h <| hx
  · 

Proof state:
case one
G : Type u_1
H : Type u_2
A : Type u_3
a✝ a₁ a₂ b c : G
s✝ : Set G
inst✝ : Group G
s t : Set G
ht : IsNormalSubgroup t
h : s ⊆ t
a : G
⊢ 1 ∈ t

Next tactic:
exact ht.toIsSubgroup.toIsSubmonoid.one_mem
/-- The normal closure of s is the smallest normal subgroup containing s. -/
theorem normalClosure_subset {s t : Set G} (ht : IsNormalSubgroup t) (h : s ⊆ t) :
    normalClosure s ⊆ t := fun a w => by
  induction' w with x hx x _ ihx x y _ _ ihx ihy
  · exact conjugatesOfSet_subset' ht h <| hx
  · exact ht.toIsSubgroup.toIsSubmonoid.one_mem
  · 

Proof state:
case inv
G : Type u_1
H : Type u_2
A : Type u_3
a✝¹ a₁ a₂ b c : G
s✝ : Set G
inst✝ : Group G
s t : Set G
ht : IsNormalSubgroup t
h : s ⊆ t
a x : G
a✝ : InClosure (conjugatesOfSet s) x
ihx : x ∈ t
⊢ x⁻¹ ∈ t

Next tactic:
exact ht.toIsSubgroup.inv_mem ihx
/-- The normal closure of s is the smallest normal subgroup containing s. -/
theorem normalClosure_subset {s t : Set G} (ht : IsNormalSubgroup t) (h : s ⊆ t) :
    normalClosure s ⊆ t := fun a w => by
  induction' w with x hx x _ ihx x y _ _ ihx ihy
  · exact conjugatesOfSet_subset' ht h <| hx
  · exact ht.toIsSubgroup.toIsSubmonoid.one_mem
  · exact ht.toIsSubgroup.inv_mem ihx
  · 

Proof state:
case mul
G : Type u_1
H : Type u_2
A : Type u_3
a✝² a₁ a₂ b c : G
s✝ : Set G
inst✝ : Group G
s t : Set G
ht : IsNormalSubgroup t
h : s ⊆ t
a x y : G
a✝¹ : InClosure (conjugatesOfSet s) x
a✝ : InClosure (conjugatesOfSet s) y
ihx : x ∈ t
ihy : y ∈ t
⊢ x * y ∈ t

Next tactic:
exact ht.toIsSubgroup.toIsSubmonoid.mul_mem ihx ihy
/-- A random bijection between `Field.Emb F E` and `Field.Emb F K` when `E` and `K` are isomorphic
as `F`-algebras. -/
def embEquivOfEquiv (i : E ≃ₐ[F] K) :
    Emb F E ≃ Emb F K := AlgEquiv.arrowCongr i <| AlgEquiv.symm <| by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
⊢ AlgebraicClosure K ≃ₐ[F] AlgebraicClosure E

Next tactic:
letI : Algebra E K := i.toAlgHom.toRingHom.toAlgebra
/-- A random bijection between `Field.Emb F E` and `Field.Emb F K` when `E` and `K` are isomorphic
as `F`-algebras. -/
def embEquivOfEquiv (i : E ≃ₐ[F] K) :
    Emb F E ≃ Emb F K := AlgEquiv.arrowCongr i <| AlgEquiv.symm <| by
  letI : Algebra E K := i.toAlgHom.toRingHom.toAlgebra
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
this : Algebra E K := RingHom.toAlgebra ↑↑i
⊢ AlgebraicClosure K ≃ₐ[F] AlgebraicClosure E

Next tactic:
apply AlgEquiv.restrictScalars (R := F) (S := E)
/-- A random bijection between `Field.Emb F E` and `Field.Emb F K` when `E` and `K` are isomorphic
as `F`-algebras. -/
def embEquivOfEquiv (i : E ≃ₐ[F] K) :
    Emb F E ≃ Emb F K := AlgEquiv.arrowCongr i <| AlgEquiv.symm <| by
  letI : Algebra E K := i.toAlgHom.toRingHom.toAlgebra
  apply AlgEquiv.restrictScalars (R := F) (S := E)
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
this : Algebra E K := RingHom.toAlgebra ↑↑i
⊢ AlgebraicClosure K ≃ₐ[E] AlgebraicClosure E

Next tactic:
apply IsAlgClosure.equivOfAlgebraic E K (AlgebraicClosure K) (AlgebraicClosure E)
/-- A random bijection between `Field.Emb F E` and `Field.Emb F K` when `E` and `K` are isomorphic
as `F`-algebras. -/
def embEquivOfEquiv (i : E ≃ₐ[F] K) :
    Emb F E ≃ Emb F K := AlgEquiv.arrowCongr i <| AlgEquiv.symm <| by
  letI : Algebra E K := i.toAlgHom.toRingHom.toAlgebra
  apply AlgEquiv.restrictScalars (R := F) (S := E)
  apply IsAlgClosure.equivOfAlgebraic E K (AlgebraicClosure K) (AlgebraicClosure E)
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
this : Algebra E K := RingHom.toAlgebra ↑↑i
⊢ Algebra.IsAlgebraic E K

Next tactic:
intro x
/-- A random bijection between `Field.Emb F E` and `Field.Emb F K` when `E` and `K` are isomorphic
as `F`-algebras. -/
def embEquivOfEquiv (i : E ≃ₐ[F] K) :
    Emb F E ≃ Emb F K := AlgEquiv.arrowCongr i <| AlgEquiv.symm <| by
  letI : Algebra E K := i.toAlgHom.toRingHom.toAlgebra
  apply AlgEquiv.restrictScalars (R := F) (S := E)
  apply IsAlgClosure.equivOfAlgebraic E K (AlgebraicClosure K) (AlgebraicClosure E)
  intro x
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
this : Algebra E K := RingHom.toAlgebra ↑↑i
x : K
⊢ IsAlgebraic E x

Next tactic:
have h := isAlgebraic_algebraMap (R := E) (A := K) (i.symm.toAlgHom x)
/-- A random bijection between `Field.Emb F E` and `Field.Emb F K` when `E` and `K` are isomorphic
as `F`-algebras. -/
def embEquivOfEquiv (i : E ≃ₐ[F] K) :
    Emb F E ≃ Emb F K := AlgEquiv.arrowCongr i <| AlgEquiv.symm <| by
  letI : Algebra E K := i.toAlgHom.toRingHom.toAlgebra
  apply AlgEquiv.restrictScalars (R := F) (S := E)
  apply IsAlgClosure.equivOfAlgebraic E K (AlgebraicClosure K) (AlgebraicClosure E)
  intro x
  have h := isAlgebraic_algebraMap (R := E) (A := K) (i.symm.toAlgHom x)
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
this : Algebra E K := RingHom.toAlgebra ↑↑i
x : K
h : IsAlgebraic E ((algebraMap E K) (↑(AlgEquiv.symm i) x))
⊢ IsAlgebraic E x

Next tactic:
rw [show ∀ y : E, (algebraMap E K) y = i.toAlgHom y from fun y ↦ rfl] at h
/-- A random bijection between `Field.Emb F E` and `Field.Emb F K` when `E` and `K` are isomorphic
as `F`-algebras. -/
def embEquivOfEquiv (i : E ≃ₐ[F] K) :
    Emb F E ≃ Emb F K := AlgEquiv.arrowCongr i <| AlgEquiv.symm <| by
  letI : Algebra E K := i.toAlgHom.toRingHom.toAlgebra
  apply AlgEquiv.restrictScalars (R := F) (S := E)
  apply IsAlgClosure.equivOfAlgebraic E K (AlgebraicClosure K) (AlgebraicClosure E)
  intro x
  have h := isAlgebraic_algebraMap (R := E) (A := K) (i.symm.toAlgHom x)
  rw [show ∀ y : E, (algebraMap E K) y = i.toAlgHom y from fun y ↦ rfl] at h
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
this : Algebra E K := RingHom.toAlgebra ↑↑i
x : K
h : IsAlgebraic E (↑i (↑(AlgEquiv.symm i) x))
⊢ IsAlgebraic E x

Next tactic:
simpa only [AlgEquiv.toAlgHom_eq_coe, AlgHom.coe_coe, AlgEquiv.apply_symm_apply] using h
/-- If `E` and `K` are isomorphic as `F`-algebras, then they have the same separable degree
over `F`. -/
theorem sepDegree_eq_of_equiv (i : E ≃ₐ[F] K) :
    Cardinal.lift.{w} (sepDegree F E) = Cardinal.lift.{v} (sepDegree F K) := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
⊢ Cardinal.lift.{w, v} (sepDegree F E) = Cardinal.lift.{v, w} (sepDegree F K)

Next tactic:
have := (Equiv.ulift.{w} (α := Emb F E)).trans
    (embEquivOfEquiv F E K i) |>.trans
      (Equiv.ulift.{v} (α := Emb F K)).symm |>.cardinal_eq
/-- If `E` and `K` are isomorphic as `F`-algebras, then they have the same separable degree
over `F`. -/
theorem sepDegree_eq_of_equiv (i : E ≃ₐ[F] K) :
    Cardinal.lift.{w} (sepDegree F E) = Cardinal.lift.{v} (sepDegree F K) := by
  have := (Equiv.ulift.{w} (α := Emb F E)).trans
    (embEquivOfEquiv F E K i) |>.trans
      (Equiv.ulift.{v} (α := Emb F K)).symm |>.cardinal_eq
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
this : Cardinal.mk (ULift.{w, v} (Emb F E)) = Cardinal.mk (ULift.{v, w} (Emb F K))
⊢ Cardinal.lift.{w, v} (sepDegree F E) = Cardinal.lift.{v, w} (sepDegree F K)

Next tactic:
simpa only [Cardinal.mk_uLift] using this
/-- If `E` and `K` are isomorphic as `F`-algebras, then they have the same `Field.finSepDegree`
over `F`. -/
theorem finSepDegree_eq_of_equiv (i : E ≃ₐ[F] K) :
    finSepDegree F E = finSepDegree F K := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
i : E ≃ₐ[F] K
⊢ finSepDegree F E = finSepDegree F K

Next tactic:
simpa only [Cardinal.toNat_lift] using congr_arg Cardinal.toNat
    (sepDegree_eq_of_equiv F E K i)
@[simp]
theorem finSepDegree_self : finSepDegree F F = 1 := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
⊢ finSepDegree F F = 1

Next tactic:
simp only [finSepDegree, sepDegree_self, Cardinal.one_toNat]
@[simp]
theorem sepDegree_bot : sepDegree F (⊥ : IntermediateField F E) = 1 := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
⊢ sepDegree F ↥⊥ = 1

Next tactic:
have := sepDegree_eq_of_equiv _ _ _ (botEquiv F E)
@[simp]
theorem sepDegree_bot : sepDegree F (⊥ : IntermediateField F E) = 1 := by
  have := sepDegree_eq_of_equiv _ _ _ (botEquiv F E)
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
this : Cardinal.lift.{u, v} (sepDegree F ↥⊥) = Cardinal.lift.{v, u} (sepDegree F F)
⊢ sepDegree F ↥⊥ = 1

Next tactic:
rwa [sepDegree_self, Cardinal.lift_one, ← Cardinal.lift_one.{u, v}, Cardinal.lift_inj] at this
@[simp]
theorem finSepDegree_bot : finSepDegree F (⊥ : IntermediateField F E) = 1 := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
⊢ finSepDegree F ↥⊥ = 1

Next tactic:
simp only [finSepDegree, sepDegree_bot, Cardinal.one_toNat]
@[simp]
theorem sepDegree_top : sepDegree F (⊤ : IntermediateField F E) = sepDegree F E := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
⊢ sepDegree F ↥⊤ = sepDegree F E

Next tactic:
simpa only [Cardinal.lift_id] using sepDegree_eq_of_equiv F _ E topEquiv
@[simp]
theorem finSepDegree_top : finSepDegree F (⊤ : IntermediateField F E) = finSepDegree F E := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
⊢ finSepDegree F ↥⊤ = finSepDegree F E

Next tactic:
simp only [finSepDegree, sepDegree_top]
@[simp]
theorem sepDegree_bot'' (K : Type v) [Field K] [Algebra F K] [Algebra E K] [IsScalarTower F E K] :
    sepDegree F (⊥ : IntermediateField E K) = sepDegree F E := by
  

Proof state:
F : Type u
E : Type v
inst✝¹⁰ : Field F
inst✝⁹ : Field E
inst✝⁸ : Algebra F E
K✝ : Type w
inst✝⁷ : Field K✝
inst✝⁶ : Algebra F K✝
inst✝⁵ : Algebra E K✝
inst✝⁴ : IsScalarTower F E K✝
K : Type v
inst✝³ : Field K
inst✝² : Algebra F K
inst✝¹ : Algebra E K
inst✝ : IsScalarTower F E K
⊢ sepDegree F ↥⊥ = sepDegree F E

Next tactic:
simpa only [Cardinal.lift_id] using sepDegree_bot' F E K
@[simp]
theorem finSepDegree_bot' : finSepDegree F (⊥ : IntermediateField E K) = finSepDegree F E := by
  

Proof state:
F : Type u
E : Type v
inst✝⁶ : Field F
inst✝⁵ : Field E
inst✝⁴ : Algebra F E
K : Type w
inst✝³ : Field K
inst✝² : Algebra F K
inst✝¹ : Algebra E K
inst✝ : IsScalarTower F E K
⊢ finSepDegree F ↥⊥ = finSepDegree F E

Next tactic:
simpa only [Cardinal.toNat_lift] using congr_arg Cardinal.toNat (sepDegree_bot' F E K)
@[simp]
theorem sepDegree_top' : sepDegree F (⊤ : IntermediateField E K) = sepDegree F K := by
  

Proof state:
F : Type u
E : Type v
inst✝⁶ : Field F
inst✝⁵ : Field E
inst✝⁴ : Algebra F E
K : Type w
inst✝³ : Field K
inst✝² : Algebra F K
inst✝¹ : Algebra E K
inst✝ : IsScalarTower F E K
⊢ sepDegree F ↥⊤ = sepDegree F K

Next tactic:
simpa only [Cardinal.lift_id] using sepDegree_eq_of_equiv _ _ _
    ((topEquiv (F := E) (E := K)).restrictScalars F)
@[simp]
theorem finSepDegree_top' : finSepDegree F (⊤ : IntermediateField E K) = finSepDegree F K := by
  

Proof state:
F : Type u
E : Type v
inst✝⁶ : Field F
inst✝⁵ : Field E
inst✝⁴ : Algebra F E
K : Type w
inst✝³ : Field K
inst✝² : Algebra F K
inst✝¹ : Algebra E K
inst✝ : IsScalarTower F E K
⊢ finSepDegree F ↥⊤ = finSepDegree F K

Next tactic:
simp only [finSepDegree, sepDegree_top']
/-- The separable degree of `E / F` is equal to the cardinality of `E →ₐ[F] K`
if `E = F(S)` such that every element
`s` of `S` is integral (= algebraic) over `F` and whose minimal polynomial splits in `K`. -/
theorem sepDegree_eq_of_adjoin_splits {S : Set E} (hS : adjoin F S = ⊤)
    (hK : ∀ s ∈ S, IsIntegral F s ∧ Splits (algebraMap F K) (minpoly F s)) :
    Cardinal.lift.{w} (sepDegree F E) = Cardinal.mk (E →ₐ[F] K) := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
S : Set E
hS : adjoin F S = ⊤
hK : ∀ s ∈ S, IsIntegral F s ∧ Splits (algebraMap F K) (minpoly F s)
⊢ Cardinal.lift.{w, v} (sepDegree F E) = Cardinal.mk (E →ₐ[F] K)

Next tactic:
simpa only [Cardinal.mk_uLift] using (Equiv.ulift.{w} (α := Emb F E)).trans
    (embEquivOfAdjoinSplits F E K hS hK) |>.cardinal_eq
/-- The `Field.finSepDegree F E` is equal to the cardinality of `E →ₐ[F] K`
if `E = F(S)` such that every element
`s` of `S` is integral (= algebraic) over `F` and whose minimal polynomial splits in `K`. -/
theorem finSepDegree_eq_of_adjoin_splits {S : Set E} (hS : adjoin F S = ⊤)
    (hK : ∀ s ∈ S, IsIntegral F s ∧ Splits (algebraMap F K) (minpoly F s)) :
    finSepDegree F E = Cardinal.toNat (Cardinal.mk (E →ₐ[F] K)) := by
  

Proof state:
F : Type u
E : Type v
inst✝⁴ : Field F
inst✝³ : Field E
inst✝² : Algebra F E
K : Type w
inst✝¹ : Field K
inst✝ : Algebra F K
S : Set E
hS : adjoin F S = ⊤
hK : ∀ s ∈ S, IsIntegral F s ∧ Splits (algebraMap F K) (minpoly F s)
⊢ finSepDegree F E = Cardinal.toNat (Cardinal.mk (E →ₐ[F] K))

Next tactic:
simpa only [Cardinal.toNat_lift] using congr_arg Cardinal.toNat
    (sepDegree_eq_of_adjoin_splits F E K hS hK)
/-- The separable degree of `E / F` is equal to the cardinality of `E →ₐ[F] K` when `E / F`
is algebraic and `K / F` is algebraically closed. -/
theorem sepDegree_eq_of_isAlgClosed (halg : Algebra.IsAlgebraic F E) [IsAlgClosed K] :
    Cardinal.lift.{w} (sepDegree F E) = Cardinal.mk (E →ₐ[F] K) := by
  

Proof state:
F : Type u
E : Type v
inst✝⁵ : Field F
inst✝⁴ : Field E
inst✝³ : Algebra F E
K : Type w
inst✝² : Field K
inst✝¹ : Algebra F K
halg : Algebra.IsAlgebraic F E
inst✝ : IsAlgClosed K
⊢ Cardinal.lift.{w, v} (sepDegree F E) = Cardinal.mk (E →ₐ[F] K)

Next tactic:
simpa only [Cardinal.mk_uLift] using (Equiv.ulift.{w} (α := Emb F E)).trans
    (embEquivOfIsAlgClosed F E K halg) |>.cardinal_eq
/-- The `Field.finSepDegree F E` is equal to the cardinality of `E →ₐ[F] K` as a natural number,
when `E / F` is algebraic and `K / F` is algebraically closed. -/
theorem finSepDegree_eq_of_isAlgClosed (halg : Algebra.IsAlgebraic F E) [IsAlgClosed K] :
    finSepDegree F E = Cardinal.toNat (Cardinal.mk (E →ₐ[F] K)) := by
  

Proof state:
F : Type u
E : Type v
inst✝⁵ : Field F
inst✝⁴ : Field E
inst✝³ : Algebra F E
K : Type w
inst✝² : Field K
inst✝¹ : Algebra F K
halg : Algebra.IsAlgebraic F E
inst✝ : IsAlgClosed K
⊢ finSepDegree F E = Cardinal.toNat (Cardinal.mk (E →ₐ[F] K))

Next tactic:
simpa only [Cardinal.toNat_lift] using congr_arg Cardinal.toNat
    (sepDegree_eq_of_isAlgClosed F E K halg)
/-- If `K / E / F` is a field extension tower, such that `K / E` is algebraic, then
$[E:F]_s [K:E]_s = [K:F]_s$. See also `lift_rank_mul_lift_rank`. -/
theorem lift_sepDegree_mul_lift_sepDegree_of_isAlgebraic
    [Algebra E K] [IsScalarTower F E K] (halg : Algebra.IsAlgebraic E K) :
    Cardinal.lift.{w} (sepDegree F E) * Cardinal.lift.{v} (sepDegree E K) =
      Cardinal.lift.{v} (sepDegree F K) := by
  

Proof state:
F : Type u
E : Type v
inst✝⁶ : Field F
inst✝⁵ : Field E
inst✝⁴ : Algebra F E
K : Type w
inst✝³ : Field K
inst✝² : Algebra F K
inst✝¹ : Algebra E K
inst✝ : IsScalarTower F E K
halg : Algebra.IsAlgebraic E K
⊢ Cardinal.lift.{w, v} (sepDegree F E) * Cardinal.lift.{v, w} (sepDegree E K) = Cardinal.lift.{v, w} (sepDegree F K)

Next tactic:
have := (embProdEmbOfIsAlgebraic F E K halg).trans
    (Equiv.ulift.{v} (α := Emb F K)).symm |>.cardinal_eq