l3lab/ntp-mathlib huggingface dataset:
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
    have key :=
      roots_map (IsScalarTower.toAlgHom F p.SplittingField E : p.SplittingField →+* E)
        ((splits_id_iff_splits _).mpr (IsSplittingField.splits p.SplittingField p))
    

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)
key :
  roots (map (↑(IsScalarTower.toAlgHom F (SplittingField p) E)) (map (algebraMap F (SplittingField p)) p)) =
    Multiset.map (⇑↑(IsScalarTower.toAlgHom F (SplittingField p) E)) (roots (map (algebraMap F (SplittingField p)) p))
⊢ ∃ a, mapRoots p E a = y

Next tactic:
rw [map_map, AlgHom.comp_algebraMap] at key
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
    have key :=
      roots_map (IsScalarTower.toAlgHom F p.SplittingField E : p.SplittingField →+* E)
        ((splits_id_iff_splits _).mpr (IsSplittingField.splits p.SplittingField p))
    rw [map_map, AlgHom.comp_algebraMap] at key
    

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)
key :
  roots (map (algebraMap F E) p) =
    Multiset.map (⇑↑(IsScalarTower.toAlgHom F (SplittingField p) E)) (roots (map (algebraMap F (SplittingField p)) p))
⊢ ∃ a, mapRoots p E a = y

Next tactic:
have hy := Subtype.mem 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
    have key :=
      roots_map (IsScalarTower.toAlgHom F p.SplittingField E : p.SplittingField →+* E)
        ((splits_id_iff_splits _).mpr (IsSplittingField.splits p.SplittingField p))
    rw [map_map, AlgHom.comp_algebraMap] at key
    have hy := Subtype.mem y
    

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)
key :
  roots (map (algebraMap F E) p) =
    Multiset.map (⇑↑(IsScalarTower.toAlgHom F (SplittingField p) E)) (roots (map (algebraMap F (SplittingField p)) p))
hy : ↑y ∈ rootSet p E
⊢ ∃ a, mapRoots p E a = y

Next tactic:
simp only [rootSet, Finset.mem_coe, (Multiset.mem_toFinset), key, Multiset.mem_map] at hy
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
    have key :=
      roots_map (IsScalarTower.toAlgHom F p.SplittingField E : p.SplittingField →+* E)
        ((splits_id_iff_splits _).mpr (IsSplittingField.splits p.SplittingField p))
    rw [map_map, AlgHom.comp_algebraMap] at key
    have hy := Subtype.mem y
    simp only [rootSet, Finset.mem_coe, (Multiset.mem_toFinset), key, Multiset.mem_map] at hy
    

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)
key :
  roots (map (algebraMap F E) p) =
    Multiset.map (⇑↑(IsScalarTower.toAlgHom F (SplittingField p) E)) (roots (map (algebraMap F (SplittingField p)) p))
hy : ∃ a ∈ roots (map (algebraMap F (SplittingField p)) p), ↑(IsScalarTower.toAlgHom F (SplittingField p) E) a = ↑y
⊢ ∃ a, mapRoots p E a = y

Next tactic:
rcases hy with ⟨x, hx1, hx2⟩
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
    have key :=
      roots_map (IsScalarTower.toAlgHom F p.SplittingField E : p.SplittingField →+* E)
        ((splits_id_iff_splits _).mpr (IsSplittingField.splits p.SplittingField p))
    rw [map_map, AlgHom.comp_algebraMap] at key
    have hy := Subtype.mem y
    simp only [rootSet, Finset.mem_coe, (Multiset.mem_toFinset), key, Multiset.mem_map] at hy
    rcases hy with ⟨x, hx1, hx2⟩
    

Proof state:
case right.intro.intro
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)
key :
  roots (map (algebraMap F E) p) =
    Multiset.map (⇑↑(IsScalarTower.toAlgHom F (SplittingField p) E)) (roots (map (algebraMap F (SplittingField p)) p))
x : SplittingField p
hx1 : x ∈ roots (map (algebraMap F (SplittingField p)) p)
hx2 : ↑(IsScalarTower.toAlgHom F (SplittingField p) E) x = ↑y
⊢ ∃ a, mapRoots p E a = y

Next tactic:
exact ⟨⟨x, (@Multiset.mem_toFinset _ (Classical.decEq _) _ _).mpr hx1⟩, Subtype.ext hx2⟩
instance galActionAux : MulAction p.Gal (rootSet p p.SplittingField) where
  smul ϕ := Set.MapsTo.restrict ϕ _ _ <| rootSet_mapsTo ϕ.toAlgHom
  one_smul _ := 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
x✝ : ↑(rootSet p (SplittingField p))
⊢ 1 • x✝ = x✝

Next tactic:
ext
instance galActionAux : MulAction p.Gal (rootSet p p.SplittingField) where
  smul ϕ := Set.MapsTo.restrict ϕ _ _ <| rootSet_mapsTo ϕ.toAlgHom
  one_smul _ := by ext; 

Proof state:
case a
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
x✝ : ↑(rootSet p (SplittingField p))
⊢ ↑(1 • x✝) = ↑x✝

Next tactic:
rfl
instance galActionAux : MulAction p.Gal (rootSet p p.SplittingField) where
  smul ϕ := Set.MapsTo.restrict ϕ _ _ <| rootSet_mapsTo ϕ.toAlgHom
  one_smul _ := by ext; rfl
  mul_smul _ _ _ := 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
x✝² x✝¹ : Gal p
x✝ : ↑(rootSet p (SplittingField p))
⊢ (x✝² * x✝¹) • x✝ = x✝² • x✝¹ • x✝

Next tactic:
ext
instance galActionAux : MulAction p.Gal (rootSet p p.SplittingField) where
  smul ϕ := Set.MapsTo.restrict ϕ _ _ <| rootSet_mapsTo ϕ.toAlgHom
  one_smul _ := by ext; rfl
  mul_smul _ _ _ := by ext; 

Proof state:
case a
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
x✝² x✝¹ : Gal p
x✝ : ↑(rootSet p (SplittingField p))
⊢ ↑((x✝² * x✝¹) • x✝) = ↑(x✝² • x✝¹ • x✝)

Next tactic:
rfl
/-- The action of `gal p` on the roots of `p` in `E`. -/
instance galAction [Fact (p.Splits (algebraMap F E))] : MulAction p.Gal (rootSet p E) where
  one_smul _ := 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
inst✝ : Fact (Splits (algebraMap F E) p)
x✝ : ↑(rootSet p E)
⊢ 1 • x✝ = x✝

Next tactic:
simp only [smul_def, Equiv.apply_symm_apply, one_smul]
/-- The action of `gal p` on the roots of `p` in `E`. -/
instance galAction [Fact (p.Splits (algebraMap F E))] : MulAction p.Gal (rootSet p E) where
  one_smul _ := by simp only [smul_def, Equiv.apply_symm_apply, one_smul]
  mul_smul _ _ _ := 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
inst✝ : Fact (Splits (algebraMap F E) p)
x✝² x✝¹ : Gal p
x✝ : ↑(rootSet p E)
⊢ (x✝² * x✝¹) • x✝ = x✝² • x✝¹ • x✝

Next tactic:
simp only [smul_def, Equiv.apply_symm_apply, Equiv.symm_apply_apply, mul_smul]
/-- `Polynomial.Gal.restrict p E` is compatible with `Polynomial.Gal.galAction p E`. -/
@[simp]
theorem restrict_smul [Fact (p.Splits (algebraMap F E))] (ϕ : E ≃ₐ[F] E) (x : rootSet p E) :
    ↑(restrict p E ϕ • 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
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : E ≃ₐ[F] E
x : ↑(rootSet p E)
⊢ ↑((restrict p E) ϕ • x) = ϕ ↑x

Next tactic:
let ψ := AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F p.SplittingField E)
/-- `Polynomial.Gal.restrict p E` is compatible with `Polynomial.Gal.galAction p E`. -/
@[simp]
theorem restrict_smul [Fact (p.Splits (algebraMap F E))] (ϕ : E ≃ₐ[F] E) (x : rootSet p E) :
    ↑(restrict p E ϕ • x) = ϕ x := by
  let ψ := AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F p.SplittingField E)
  

Proof state:
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : E ≃ₐ[F] E
x : ↑(rootSet p E)
ψ : SplittingField p ≃ₐ[F] ↥(AlgHom.range (IsScalarTower.toAlgHom F (SplittingField p) E)) :=
  AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F (SplittingField p) E)
⊢ ↑((restrict p E) ϕ • x) = ϕ ↑x

Next tactic:
change ↑(ψ (ψ.symm _)) = ϕ x
/-- `Polynomial.Gal.restrict p E` is compatible with `Polynomial.Gal.galAction p E`. -/
@[simp]
theorem restrict_smul [Fact (p.Splits (algebraMap F E))] (ϕ : E ≃ₐ[F] E) (x : rootSet p E) :
    ↑(restrict p E ϕ • x) = ϕ x := by
  let ψ := AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F p.SplittingField E)
  change ↑(ψ (ψ.symm _)) = ϕ x
  

Proof state:
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : E ≃ₐ[F] E
x : ↑(rootSet p E)
ψ : SplittingField p ≃ₐ[F] ↥(AlgHom.range (IsScalarTower.toAlgHom F (SplittingField p) E)) :=
  AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F (SplittingField p) E)
⊢ ↑(ψ
        ((AlgEquiv.symm ψ)
          (↑(AlgHom.restrictNormalAux (↑ϕ) (SplittingField p))
            (↑↑(AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F (SplittingField p) E))
              ↑((rootsEquivRoots p E).symm x))))) =
    ϕ ↑x

Next tactic:
rw [AlgEquiv.apply_symm_apply ψ]
/-- `Polynomial.Gal.restrict p E` is compatible with `Polynomial.Gal.galAction p E`. -/
@[simp]
theorem restrict_smul [Fact (p.Splits (algebraMap F E))] (ϕ : E ≃ₐ[F] E) (x : rootSet p E) :
    ↑(restrict p E ϕ • x) = ϕ x := by
  let ψ := AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F p.SplittingField E)
  change ↑(ψ (ψ.symm _)) = ϕ x
  rw [AlgEquiv.apply_symm_apply ψ]
  

Proof state:
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : E ≃ₐ[F] E
x : ↑(rootSet p E)
ψ : SplittingField p ≃ₐ[F] ↥(AlgHom.range (IsScalarTower.toAlgHom F (SplittingField p) E)) :=
  AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F (SplittingField p) E)
⊢ ↑(↑(AlgHom.restrictNormalAux (↑ϕ) (SplittingField p))
        (↑↑(AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F (SplittingField p) E))
          ↑((rootsEquivRoots p E).symm x))) =
    ϕ ↑x

Next tactic:
change ϕ (rootsEquivRoots p E ((rootsEquivRoots p E).symm x)) = ϕ x
/-- `Polynomial.Gal.restrict p E` is compatible with `Polynomial.Gal.galAction p E`. -/
@[simp]
theorem restrict_smul [Fact (p.Splits (algebraMap F E))] (ϕ : E ≃ₐ[F] E) (x : rootSet p E) :
    ↑(restrict p E ϕ • x) = ϕ x := by
  let ψ := AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F p.SplittingField E)
  change ↑(ψ (ψ.symm _)) = ϕ x
  rw [AlgEquiv.apply_symm_apply ψ]
  change ϕ (rootsEquivRoots p E ((rootsEquivRoots p E).symm x)) = ϕ x
  

Proof state:
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : E ≃ₐ[F] E
x : ↑(rootSet p E)
ψ : SplittingField p ≃ₐ[F] ↥(AlgHom.range (IsScalarTower.toAlgHom F (SplittingField p) E)) :=
  AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F (SplittingField p) E)
⊢ ϕ ↑((rootsEquivRoots p E) ((rootsEquivRoots p E).symm x)) = ϕ ↑x

Next tactic:
rw [Equiv.apply_symm_apply (rootsEquivRoots p E)]
/-- `gal p` embeds as a subgroup of permutations of the roots of `p` in `E`. -/
theorem galActionHom_injective [Fact (p.Splits (algebraMap F E))] :
    Function.Injective (galActionHom 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
inst✝ : Fact (Splits (algebraMap F E) p)
⊢ Function.Injective ⇑(galActionHom p E)

Next tactic:
rw [injective_iff_map_eq_one]
/-- `gal p` embeds as a subgroup of permutations of the roots of `p` in `E`. -/
theorem galActionHom_injective [Fact (p.Splits (algebraMap F E))] :
    Function.Injective (galActionHom p E) := by
  rw [injective_iff_map_eq_one]
  

Proof state:
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
⊢ ∀ (a : Gal p), (galActionHom p E) a = 1 → a = 1

Next tactic:
intro ϕ hϕ
/-- `gal p` embeds as a subgroup of permutations of the roots of `p` in `E`. -/
theorem galActionHom_injective [Fact (p.Splits (algebraMap F E))] :
    Function.Injective (galActionHom p E) := by
  rw [injective_iff_map_eq_one]
  intro ϕ hϕ
  

Proof state:
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : Gal p
hϕ : (galActionHom p E) ϕ = 1
⊢ ϕ = 1

Next tactic:
ext (x hx)
/-- `gal p` embeds as a subgroup of permutations of the roots of `p` in `E`. -/
theorem galActionHom_injective [Fact (p.Splits (algebraMap F E))] :
    Function.Injective (galActionHom p E) := by
  rw [injective_iff_map_eq_one]
  intro ϕ hϕ
  ext (x hx)
  

Proof state:
case h
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : Gal p
hϕ : (galActionHom p E) ϕ = 1
x : SplittingField p
hx : x ∈ rootSet p (SplittingField p)
⊢ ϕ x = 1 x

Next tactic:
have key := Equiv.Perm.ext_iff.mp hϕ (rootsEquivRoots p E ⟨x, hx⟩)
/-- `gal p` embeds as a subgroup of permutations of the roots of `p` in `E`. -/
theorem galActionHom_injective [Fact (p.Splits (algebraMap F E))] :
    Function.Injective (galActionHom p E) := by
  rw [injective_iff_map_eq_one]
  intro ϕ hϕ
  ext (x hx)
  have key := Equiv.Perm.ext_iff.mp hϕ (rootsEquivRoots p E ⟨x, hx⟩)
  

Proof state:
case h
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : Gal p
hϕ : (galActionHom p E) ϕ = 1
x : SplittingField p
hx : x ∈ rootSet p (SplittingField p)
key :
  ((galActionHom p E) ϕ) ((rootsEquivRoots p E) { val := x, property := hx }) =
    1 ((rootsEquivRoots p E) { val := x, property := hx })
⊢ ϕ x = 1 x

Next tactic:
change
    rootsEquivRoots p E (ϕ • (rootsEquivRoots p E).symm (rootsEquivRoots p E ⟨x, hx⟩)) =
      rootsEquivRoots p E ⟨x, hx⟩
    at key
/-- `gal p` embeds as a subgroup of permutations of the roots of `p` in `E`. -/
theorem galActionHom_injective [Fact (p.Splits (algebraMap F E))] :
    Function.Injective (galActionHom p E) := by
  rw [injective_iff_map_eq_one]
  intro ϕ hϕ
  ext (x hx)
  have key := Equiv.Perm.ext_iff.mp hϕ (rootsEquivRoots p E ⟨x, hx⟩)
  change
    rootsEquivRoots p E (ϕ • (rootsEquivRoots p E).symm (rootsEquivRoots p E ⟨x, hx⟩)) =
      rootsEquivRoots p E ⟨x, hx⟩
    at key
  

Proof state:
case h
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : Gal p
hϕ : (galActionHom p E) ϕ = 1
x : SplittingField p
hx : x ∈ rootSet p (SplittingField p)
key :
  (rootsEquivRoots p E) (ϕ • (rootsEquivRoots p E).symm ((rootsEquivRoots p E) { val := x, property := hx })) =
    (rootsEquivRoots p E) { val := x, property := hx }
⊢ ϕ x = 1 x

Next tactic:
rw [Equiv.symm_apply_apply] at key
/-- `gal p` embeds as a subgroup of permutations of the roots of `p` in `E`. -/
theorem galActionHom_injective [Fact (p.Splits (algebraMap F E))] :
    Function.Injective (galActionHom p E) := by
  rw [injective_iff_map_eq_one]
  intro ϕ hϕ
  ext (x hx)
  have key := Equiv.Perm.ext_iff.mp hϕ (rootsEquivRoots p E ⟨x, hx⟩)
  change
    rootsEquivRoots p E (ϕ • (rootsEquivRoots p E).symm (rootsEquivRoots p E ⟨x, hx⟩)) =
      rootsEquivRoots p E ⟨x, hx⟩
    at key
  rw [Equiv.symm_apply_apply] at key
  

Proof state:
case h
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Fact (Splits (algebraMap F E) p)
ϕ : Gal p
hϕ : (galActionHom p E) ϕ = 1
x : SplittingField p
hx : x ∈ rootSet p (SplittingField p)
key : (rootsEquivRoots p E) (ϕ • { val := x, property := hx }) = (rootsEquivRoots p E) { val := x, property := hx }
⊢ ϕ x = 1 x

Next tactic:
exact Subtype.ext_iff.mp (Equiv.injective (rootsEquivRoots p E) key)
theorem restrictDvd_def [Decidable (q = 0)] (hpq : p ∣ q) :
    restrictDvd hpq =
      if hq : q = 0 then 1
      else
        @restrict F _ p _ _ _
          ⟨splits_of_splits_of_dvd (algebraMap F q.SplittingField) hq (SplittingField.splits q)
              hpq⟩ := by
  -- Porting note: added `unfold`
  

Proof state:
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Decidable (q = 0)
hpq : p ∣ q
⊢ restrictDvd hpq = if hq : q = 0 then 1 else restrict p (SplittingField q)

Next tactic:
unfold restrictDvd
theorem restrictDvd_def [Decidable (q = 0)] (hpq : p ∣ q) :
    restrictDvd hpq =
      if hq : q = 0 then 1
      else
        @restrict F _ p _ _ _
          ⟨splits_of_splits_of_dvd (algebraMap F q.SplittingField) hq (SplittingField.splits q)
              hpq⟩ := by
  -- Porting note: added `unfold`
  unfold restrictDvd
  

Proof state:
F : Type u_1
inst✝³ : Field F
p q : F[X]
E : Type u_2
inst✝² : Field E
inst✝¹ : Algebra F E
inst✝ : Decidable (q = 0)
hpq : p ∣ q
⊢ (if hq : q = 0 then 1 else restrict p (SplittingField q)) = if hq : q = 0 then 1 else restrict p (SplittingField q)

Next tactic:
convert rfl
theorem restrictDvd_surjective (hpq : p ∣ q) (hq : q ≠ 0) : Function.Surjective (restrictDvd hpq) :=
  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
hpq : p ∣ q
hq : q ≠ 0
⊢ Function.Surjective ⇑(restrictDvd hpq)

Next tactic:
classical
    -- Porting note: was `simp only [restrictDvd_def, dif_neg hq, restrict_surjective]`
    haveI := Fact.mk <|
      splits_of_splits_of_dvd (algebraMap F q.SplittingField) hq (SplittingField.splits q) hpq
    simp only [restrictDvd_def, dif_neg hq]
    exact restrict_surjective _ _
theorem restrictDvd_surjective (hpq : p ∣ q) (hq : q ≠ 0) : Function.Surjective (restrictDvd hpq) :=
  by classical
    -- Porting note: was `simp only [restrictDvd_def, dif_neg hq, restrict_surjective]`
    

Proof state:
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
hpq : p ∣ q
hq : q ≠ 0
⊢ Function.Surjective ⇑(restrictDvd hpq)

Next tactic:
haveI := Fact.mk <|
      splits_of_splits_of_dvd (algebraMap F q.SplittingField) hq (SplittingField.splits q) hpq
theorem restrictDvd_surjective (hpq : p ∣ q) (hq : q ≠ 0) : Function.Surjective (restrictDvd hpq) :=
  by classical
    -- Porting note: was `simp only [restrictDvd_def, dif_neg hq, restrict_surjective]`
    haveI := Fact.mk <|
      splits_of_splits_of_dvd (algebraMap F q.SplittingField) hq (SplittingField.splits q) hpq
    

Proof state:
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
hpq : p ∣ q
hq : q ≠ 0
this : Fact (Splits (algebraMap F (SplittingField q)) p)
⊢ Function.Surjective ⇑(restrictDvd hpq)

Next tactic:
simp only [restrictDvd_def, dif_neg hq]
theorem restrictDvd_surjective (hpq : p ∣ q) (hq : q ≠ 0) : Function.Surjective (restrictDvd hpq) :=
  by classical
    -- Porting note: was `simp only [restrictDvd_def, dif_neg hq, restrict_surjective]`
    haveI := Fact.mk <|
      splits_of_splits_of_dvd (algebraMap F q.SplittingField) hq (SplittingField.splits q) hpq
    simp only [restrictDvd_def, dif_neg hq]
    

Proof state:
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
hpq : p ∣ q
hq : q ≠ 0
this : Fact (Splits (algebraMap F (SplittingField q)) p)
⊢ Function.Surjective ⇑(restrict p (SplittingField q))

Next tactic:
exact restrict_surjective _ _
/-- `Polynomial.Gal.restrictProd` is actually a subgroup embedding. -/
theorem restrictProd_injective : Function.Injective (restrictProd p q) := 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
⊢ Function.Injective ⇑(restrictProd p q)

Next tactic:
by_cases hpq : p * q = 0
/-- `Polynomial.Gal.restrictProd` is actually a subgroup embedding. -/
theorem restrictProd_injective : Function.Injective (restrictProd p q) := by
  by_cases hpq : p * q = 0
  · 

Proof state:
case pos
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
hpq : p * q = 0
⊢ Function.Injective ⇑(restrictProd p q)

Next tactic:
have : Unique (p * q).Gal := by rw [hpq]; infer_instance
/-- `Polynomial.Gal.restrictProd` is actually a subgroup embedding. -/
theorem restrictProd_injective : Function.Injective (restrictProd p q) := by
  by_cases hpq : p * q = 0
  · have : Unique (p * q).Gal := 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
hpq : p * q = 0
⊢ Unique (Gal (p * q))

Next tactic:
rw [hpq]
/-- `Polynomial.Gal.restrictProd` is actually a subgroup embedding. -/
theorem restrictProd_injective : Function.Injective (restrictProd p q) := by
  by_cases hpq : p * q = 0
  · have : Unique (p * q).Gal := by rw [hpq]; 

Proof state:
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
hpq : p * q = 0
⊢ Unique (Gal 0)

Next tactic:
infer_instance
/-- `Polynomial.Gal.restrictProd` is actually a subgroup embedding. -/
theorem restrictProd_injective : Function.Injective (restrictProd p q) := by
  by_cases hpq : p * q = 0
  · have : Unique (p * q).Gal := by rw [hpq]; infer_instance
    

Proof state:
case pos
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
hpq : p * q = 0
this : Unique (Gal (p * q))
⊢ Function.Injective ⇑(restrictProd p q)

Next tactic:
exact fun f g _ => Eq.trans (Unique.eq_default f) (Unique.eq_default g).symm
/-- `Polynomial.Gal.restrictProd` is actually a subgroup embedding. -/
theorem restrictProd_injective : Function.Injective (restrictProd p q) := by
  by_cases hpq : p * q = 0
  · have : Unique (p * q).Gal := by rw [hpq]; infer_instance
    exact fun f g _ => Eq.trans (Unique.eq_default f) (Unique.eq_default g).symm
  

Proof state:
case neg
F : Type u_1
inst✝² : Field F
p q : F[X]
E : Type u_2
inst✝¹ : Field E
inst✝ : Algebra F E
hpq : ¬p * q = 0
⊢ Function.Injective ⇑(restrictProd p q)

Next tactic:
intro f g hfg