-- Mathlib/NumberTheory/Padics/Hensel.lean
theorem a_soln_is_unique (ha : F.eval a = 0) (z' : ℤ_[p]) (hz' : F.eval z' = 0)
    (hnormz' : ‖z' - a‖ < ‖F.derivative.eval a‖) : z' = a :=
  let h := z' - a
  let ⟨q, hq⟩ := F.binomExpansion a h
  have : (F.derivative.eval a + q * h) * h = 0 :=
    Eq.symm
      (calc
        0 = F.eval (a + h) := show 0 = F.eval (a + (z' - a)) by rw [add_comm]; simp [hz']
        _ = F.derivative.eval a * h + q * h ^ 2

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
⊢ 0 = Polynomial.eval (z' - a + a) F

Tactic:
simp [hz']

Result:
no goals

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
this✝¹ : (Polynomial.eval a (Polynomial.derivative F) + q * h) * h = 0
hne : ¬h = 0
this✝ : Polynomial.eval a (Polynomial.derivative F) + q * h = 0
this : Polynomial.eval a (Polynomial.derivative F) = -q * h
⊢ ‖q‖ * ‖h‖ ≤ 1 * ‖h‖

Tactic:
gcongr

Result:
case h
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
this✝¹ : (Polynomial.eval a (Polynomial.derivative F) + q * h) * h = 0
hne : ¬h = 0
this✝ : Polynomial.eval a (Polynomial.derivative F) + q * h = 0
this : Polynomial.eval a (Polynomial.derivative F) = -q * h
⊢ ‖q‖ ≤ 1

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
this✝¹ : (Polynomial.eval a (Polynomial.derivative F) + q * h) * h = 0
hne : ¬h = 0
this✝ : Polynomial.eval a (Polynomial.derivative F) + q * h = 0
this : Polynomial.eval a (Polynomial.derivative F) = -q * h
⊢ 1 * ‖h‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖

Tactic:
simpa

Result:
no goals

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
this✝ : (Polynomial.eval a (Polynomial.derivative F) + q * h) * h = 0
this : h = 0
⊢ z' - a = 0

Tactic:
rw [← this]

Result:
no goals

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
⊢ Polynomial.eval (a + h) F = Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2

Tactic:
rw [hq, ha, zero_add]

Result:
no goals

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
⊢ Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2 =
    (Polynomial.eval a (Polynomial.derivative F) + q * h) * h

Tactic:
rw [sq, right_distrib, mul_assoc]

Result:
no goals

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
this✝¹ : (Polynomial.eval a (Polynomial.derivative F) + q * h) * h = 0
hne : ¬h = 0
this✝ : Polynomial.eval a (Polynomial.derivative F) + q * h = 0
this : Polynomial.eval a (Polynomial.derivative F) = -q * h
⊢ ‖Polynomial.eval a (Polynomial.derivative F)‖ = ‖q‖ * ‖h‖

Tactic:
simp [this]

Result:
no goals

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
this✝ : (Polynomial.eval a (Polynomial.derivative F) + q * h) * h = 0
hne : ¬h = 0
this : Polynomial.eval a (Polynomial.derivative F) + q * h = 0
⊢ Polynomial.eval a (Polynomial.derivative F) = -q * h

Tactic:
simpa using eq_neg_of_add_eq_zero_left this

Result:
no goals

Proof state:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
⊢ 0 = Polynomial.eval (a + (z' - a)) F

Tactic:
rw [add_comm]

Result:
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
⊢ 0 = Polynomial.eval (z' - a + a) F

Proof state:
case h
p : ℕ
inst✝ : Fact (Nat.Prime p)
F : Polynomial ℤ_[p]
a : ℤ_[p]
ha : Polynomial.eval a F = 0
z' : ℤ_[p]
hz' : Polynomial.eval z' F = 0
hnormz' : ‖z' - a‖ < ‖Polynomial.eval a (Polynomial.derivative F)‖
h : ℤ_[p] := z' - a
q : ℤ_[p]
hq : Polynomial.eval (a + h) F = Polynomial.eval a F + Polynomial.eval a (Polynomial.derivative F) * h + q * h ^ 2
this✝¹ : (Polynomial.eval a (Polynomial.derivative F) + q * h) * h = 0
hne : ¬h = 0
this✝ : Polynomial.eval a (Polynomial.derivative F) + q * h = 0
this : Polynomial.eval a (Polynomial.derivative F) = -q * h
⊢ ‖q‖ ≤ 1

Tactic:
apply PadicInt.norm_le_one

Result:
no goals