Theorem: Polynomial.Gal.restrictProd_injective
File: Mathlib/FieldTheory/PolynomialGaloisGroup.lean

tactic: by_cases hpq : p * q = 0
state_before: 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)
state_after: 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)

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)

tactic: intro f g hfg
state_before: 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)
state_after: 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
f g : (p * q).Gal
hfg : (restrictProd p q) f = (restrictProd p q) g
⊢ f = g

tactic: have : Unique (p * q).Gal := by rw [hpq]; infer_instance
state_before: 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)
state_after: 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 (p * q).Gal
⊢ Function.Injective ⇑(restrictProd p q)

tactic: exact fun f g _ => Eq.trans (Unique.eq_default f) (Unique.eq_default g).symm
state_before: 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 (p * q).Gal
⊢ Function.Injective ⇑(restrictProd p q)
state_after: no goals

tactic: rw [hpq]
state_before: 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 (p * q).Gal
state_after: 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)

tactic: infer_instance
state_before: 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)
state_after: no goals

tactic: simp only [restrictProd, restrictDvd_def] at hfg
state_before: 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
f g : (p * q).Gal
hfg : (restrictProd p q) f = (restrictProd p q) g
⊢ f = g
state_after: 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
f g : (p * q).Gal
hfg :
  ((if hq : p * q = 0 then 1 else restrict p (p * q).SplittingField).prod
        (if hq : p * q = 0 then 1 else restrict q (p * q).SplittingField))
      f =
    ((if hq : p * q = 0 then 1 else restrict p (p * q).SplittingField).prod
        (if hq : p * q = 0 then 1 else restrict q (p * q).SplittingField))
      g
⊢ f = g

tactic: simp only [dif_neg hpq, MonoidHom.prod_apply, Prod.mk.inj_iff] at hfg
state_before: 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
f g : (p * q).Gal
hfg :
  ((if hq : p * q = 0 then 1 else restrict p (p * q).SplittingField).prod
        (if hq : p * q = 0 then 1 else restrict q (p * q).SplittingField))
      f =
    ((if hq : p * q = 0 then 1 else restrict p (p * q).SplittingField).prod
        (if hq : p * q = 0 then 1 else restrict q (p * q).SplittingField))
      g
⊢ f = g
state_after: 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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
⊢ f = g

tactic: ext (x hx)
state_before: 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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
⊢ f = g
state_after: case neg.h
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ (p * q).rootSet (p * q).SplittingField
⊢ f x = g x

tactic: rw [rootSet_def, aroots_mul hpq] at hx
state_before: case neg.h
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ (p * q).rootSet (p * q).SplittingField
⊢ f x = g x
state_after: case neg.h
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
⊢ f x = g x

tactic: cases' Multiset.mem_add.mp (Multiset.mem_toFinset.mp hx) with h h
state_before: case neg.h
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
⊢ f x = g x
state_after: case neg.h.inl
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ p.aroots (p * q).SplittingField
⊢ f x = g x

case neg.h.inr
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ q.aroots (p * q).SplittingField
⊢ f x = g x

tactic: haveI : Fact (p.Splits (algebraMap F (p * q).SplittingField)) :=
  ⟨splits_of_splits_of_dvd _ hpq (SplittingField.splits (p * q)) (dvd_mul_right p q)⟩
state_before: case neg.h.inl
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ p.aroots (p * q).SplittingField
⊢ f x = g x
state_after: case neg.h.inl
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ p.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) p)
⊢ f x = g x

tactic: have key :
  x =
    algebraMap p.SplittingField (p * q).SplittingField
      ((rootsEquivRoots p _).invFun
        ⟨x, (@Multiset.mem_toFinset _ (Classical.decEq _) _ _).mpr h⟩) :=
  Subtype.ext_iff.mp (Equiv.apply_symm_apply (rootsEquivRoots p _) ⟨x, _⟩).symm
state_before: case neg.h.inl
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ p.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) p)
⊢ f x = g x
state_after: case neg.h.inl
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ p.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) p)
key :
  x = (algebraMap p.SplittingField (p * q).SplittingField) ↑((rootsEquivRoots p (p * q).SplittingField).invFun ⟨x, ⋯⟩)
⊢ f x = g x

tactic: rw [key, ← AlgEquiv.restrictNormal_commutes, ← AlgEquiv.restrictNormal_commutes]
state_before: case neg.h.inl
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ p.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) p)
key :
  x = (algebraMap p.SplittingField (p * q).SplittingField) ↑((rootsEquivRoots p (p * q).SplittingField).invFun ⟨x, ⋯⟩)
⊢ f x = g x
state_after: case neg.h.inl
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ p.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) p)
key :
  x = (algebraMap p.SplittingField (p * q).SplittingField) ↑((rootsEquivRoots p (p * q).SplittingField).invFun ⟨x, ⋯⟩)
⊢ (algebraMap p.SplittingField (p * q).SplittingField)
      ((AlgEquiv.restrictNormal f p.SplittingField) ↑((rootsEquivRoots p (p * q).SplittingField).invFun ⟨x, ⋯⟩)) =
    (algebraMap p.SplittingField (p * q).SplittingField)
      ((AlgEquiv.restrictNormal g p.SplittingField) ↑((rootsEquivRoots p (p * q).SplittingField).invFun ⟨x, ⋯⟩))

tactic: exact congr_arg _ (AlgEquiv.ext_iff.mp hfg.1 _)
state_before: case neg.h.inl
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ p.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) p)
key :
  x = (algebraMap p.SplittingField (p * q).SplittingField) ↑((rootsEquivRoots p (p * q).SplittingField).invFun ⟨x, ⋯⟩)
⊢ (algebraMap p.SplittingField (p * q).SplittingField)
      ((AlgEquiv.restrictNormal f p.SplittingField) ↑((rootsEquivRoots p (p * q).SplittingField).invFun ⟨x, ⋯⟩)) =
    (algebraMap p.SplittingField (p * q).SplittingField)
      ((AlgEquiv.restrictNormal g p.SplittingField) ↑((rootsEquivRoots p (p * q).SplittingField).invFun ⟨x, ⋯⟩))
state_after: no goals

tactic: haveI : Fact (q.Splits (algebraMap F (p * q).SplittingField)) :=
  ⟨splits_of_splits_of_dvd _ hpq (SplittingField.splits (p * q)) (dvd_mul_left q p)⟩
state_before: case neg.h.inr
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ q.aroots (p * q).SplittingField
⊢ f x = g x
state_after: case neg.h.inr
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ q.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) q)
⊢ f x = g x

tactic: have key :
  x =
    algebraMap q.SplittingField (p * q).SplittingField
      ((rootsEquivRoots q _).invFun
        ⟨x, (@Multiset.mem_toFinset _ (Classical.decEq _) _ _).mpr h⟩) :=
  Subtype.ext_iff.mp (Equiv.apply_symm_apply (rootsEquivRoots q _) ⟨x, _⟩).symm
state_before: case neg.h.inr
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ q.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) q)
⊢ f x = g x
state_after: case neg.h.inr
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ q.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) q)
key :
  x = (algebraMap q.SplittingField (p * q).SplittingField) ↑((rootsEquivRoots q (p * q).SplittingField).invFun ⟨x, ⋯⟩)
⊢ f x = g x

tactic: rw [key, ← AlgEquiv.restrictNormal_commutes, ← AlgEquiv.restrictNormal_commutes]
state_before: case neg.h.inr
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ q.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) q)
key :
  x = (algebraMap q.SplittingField (p * q).SplittingField) ↑((rootsEquivRoots q (p * q).SplittingField).invFun ⟨x, ⋯⟩)
⊢ f x = g x
state_after: case neg.h.inr
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ q.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) q)
key :
  x = (algebraMap q.SplittingField (p * q).SplittingField) ↑((rootsEquivRoots q (p * q).SplittingField).invFun ⟨x, ⋯⟩)
⊢ (algebraMap q.SplittingField (p * q).SplittingField)
      ((AlgEquiv.restrictNormal f q.SplittingField) ↑((rootsEquivRoots q (p * q).SplittingField).invFun ⟨x, ⋯⟩)) =
    (algebraMap q.SplittingField (p * q).SplittingField)
      ((AlgEquiv.restrictNormal g q.SplittingField) ↑((rootsEquivRoots q (p * q).SplittingField).invFun ⟨x, ⋯⟩))

tactic: exact congr_arg _ (AlgEquiv.ext_iff.mp hfg.2 _)
state_before: case neg.h.inr
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
f g : (p * q).Gal
hfg :
  (restrict p (p * q).SplittingField) f = (restrict p (p * q).SplittingField) g ∧
    (restrict q (p * q).SplittingField) f = (restrict q (p * q).SplittingField) g
x : (p * q).SplittingField
hx : x ∈ ↑(p.aroots (p * q).SplittingField + q.aroots (p * q).SplittingField).toFinset
h : x ∈ q.aroots (p * q).SplittingField
this : Fact (Splits (algebraMap F (p * q).SplittingField) q)
key :
  x = (algebraMap q.SplittingField (p * q).SplittingField) ↑((rootsEquivRoots q (p * q).SplittingField).invFun ⟨x, ⋯⟩)
⊢ (algebraMap q.SplittingField (p * q).SplittingField)
      ((AlgEquiv.restrictNormal f q.SplittingField) ↑((rootsEquivRoots q (p * q).SplittingField).invFun ⟨x, ⋯⟩)) =
    (algebraMap q.SplittingField (p * q).SplittingField)
      ((AlgEquiv.restrictNormal g q.SplittingField) ↑((rootsEquivRoots q (p * q).SplittingField).invFun ⟨x, ⋯⟩))
state_after: no goals