-- Mathlib/FieldTheory/PolynomialGaloisGroup.lean
theorem restrictProd_injective : Function.Injective (restrictProd p q)

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

Tactic:
have : Unique (p * q).Gal := by rw [hpq]; infer_instance

Result:
case pos
F : Type u_1
inst✝ : Field F
p q : F[X]
hpq : p * q = 0
this : Unique (p * q).Gal
⊢ Function.Injective ⇑(restrictProd p q)

Proof state:
case neg.h.inl
F : Type u_1
inst✝ : Field F
p q : F[X]
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

Result:
case neg.h.inl
F : Type u_1
inst✝ : Field F
p q : F[X]
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

Proof state:
case neg.h.inr
F : Type u_1
inst✝ : Field F
p q : F[X]
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 _)

Result:
no goals

Proof state:
case neg.h.inl
F : Type u_1
inst✝ : Field F
p q : F[X]
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 _)

Result:
no goals

Proof state:
F : Type u_1
inst✝ : Field F
p q : F[X]
⊢ Function.Injective ⇑(restrictProd p q)

Tactic:
by_cases hpq : p * q = 0

Result:
case pos
F : Type u_1
inst✝ : Field F
p q : F[X]
hpq : p * q = 0
⊢ Function.Injective ⇑(restrictProd p q)

case neg
F : Type u_1
inst✝ : Field F
p q : F[X]
hpq : ¬p * q = 0
⊢ Function.Injective ⇑(restrictProd p q)

Proof state:
case neg.h.inr
F : Type u_1
inst✝ : Field F
p q : F[X]
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]

Result:
case neg.h.inr
F : Type u_1
inst✝ : Field F
p q : F[X]
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, ⋯⟩))

Proof state:
F : Type u_1
inst✝ : Field F
p q : F[X]
hpq : p * q = 0
⊢ Unique (p * q).Gal

Tactic:
rw [hpq]

Result:
F : Type u_1
inst✝ : Field F
p q : F[X]
hpq : p * q = 0
⊢ Unique (Gal 0)

Proof state:
case neg.h.inr
F : Type u_1
inst✝ : Field F
p q : F[X]
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 (q.Splits (algebraMap F (p * q).SplittingField)) :=
  ⟨splits_of_splits_of_dvd _ hpq (SplittingField.splits (p * q)) (dvd_mul_left q p)⟩

Result:
case neg.h.inr
F : Type u_1
inst✝ : Field F
p q : F[X]
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