l3lab/ntp-mathlib huggingface dataset:
theorem ChainClosure.succ_fixpoint (hc₁ : ChainClosure r c₁) (hc₂ : ChainClosure r c₂)
    (hc : SuccChain r c₂ = c₂) : c₁ ⊆ c₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
hc₁ : ChainClosure r c₁
hc₂ : ChainClosure r c₂
hc : SuccChain r c₂ = c₂
⊢ c₁ ⊆ c₂

Next tactic:
induction hc₁
theorem ChainClosure.succ_fixpoint (hc₁ : ChainClosure r c₁) (hc₂ : ChainClosure r c₂)
    (hc : SuccChain r c₂ = c₂) : c₁ ⊆ c₂ := by
  induction hc₁
  

Proof state:
case succ
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
hc₂ : ChainClosure r c₂
hc : SuccChain r c₂ = c₂
s✝ : Set α
a✝ : ChainClosure r s✝
a_ih✝ : s✝ ⊆ c₂
⊢ SuccChain r s✝ ⊆ c₂
case union
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
hc₂ : ChainClosure r c₂
hc : SuccChain r c₂ = c₂
s✝ : Set (Set α)
a✝ : ∀ a ∈ s✝, ChainClosure r a
a_ih✝ : ∀ a ∈ s✝, a ⊆ c₂
⊢ ⋃₀ s✝ ⊆ c₂

Next tactic:
case succ s₁ hc₁ h => exact (chainClosure_succ_total hc₁ hc₂ h).elim (fun h => h ▸ hc.subset) id
theorem ChainClosure.succ_fixpoint (hc₁ : ChainClosure r c₁) (hc₂ : ChainClosure r c₂)
    (hc : SuccChain r c₂ = c₂) : c₁ ⊆ c₂ := by
  induction hc₁
  

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
hc₂ : ChainClosure r c₂
hc : SuccChain r c₂ = c₂
s₁ : Set α
hc₁ : ChainClosure r s₁
h : s₁ ⊆ c₂
⊢ SuccChain r s₁ ⊆ c₂

Next tactic:
case succ s₁ hc₁ h => exact (chainClosure_succ_total hc₁ hc₂ h).elim (fun h => h ▸ hc.subset) id
theorem ChainClosure.succ_fixpoint (hc₁ : ChainClosure r c₁) (hc₂ : ChainClosure r c₂)
    (hc : SuccChain r c₂ = c₂) : c₁ ⊆ c₂ := by
  induction hc₁
  case succ s₁ hc₁ h => 

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
hc₂ : ChainClosure r c₂
hc : SuccChain r c₂ = c₂
s₁ : Set α
hc₁ : ChainClosure r s₁
h : s₁ ⊆ c₂
⊢ SuccChain r s₁ ⊆ c₂

Next tactic:
exact (chainClosure_succ_total hc₁ hc₂ h).elim (fun h => h ▸ hc.subset) id
theorem ChainClosure.succ_fixpoint (hc₁ : ChainClosure r c₁) (hc₂ : ChainClosure r c₂)
    (hc : SuccChain r c₂ = c₂) : c₁ ⊆ c₂ := by
  induction hc₁
  case succ s₁ hc₁ h => exact (chainClosure_succ_total hc₁ hc₂ h).elim (fun h => h ▸ hc.subset) id
  

Proof state:
case union
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
hc₂ : ChainClosure r c₂
hc : SuccChain r c₂ = c₂
s✝ : Set (Set α)
a✝ : ∀ a ∈ s✝, ChainClosure r a
a_ih✝ : ∀ a ∈ s✝, a ⊆ c₂
⊢ ⋃₀ s✝ ⊆ c₂

Next tactic:
case union s _ ih => exact sUnion_subset ih
theorem ChainClosure.succ_fixpoint (hc₁ : ChainClosure r c₁) (hc₂ : ChainClosure r c₂)
    (hc : SuccChain r c₂ = c₂) : c₁ ⊆ c₂ := by
  induction hc₁
  case succ s₁ hc₁ h => exact (chainClosure_succ_total hc₁ hc₂ h).elim (fun h => h ▸ hc.subset) id
  

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s✝ t : Set α
a b x y : α
hc₂ : ChainClosure r c₂
hc : SuccChain r c₂ = c₂
s : Set (Set α)
a✝ : ∀ a ∈ s, ChainClosure r a
ih : ∀ a ∈ s, a ⊆ c₂
⊢ ⋃₀ s ⊆ c₂

Next tactic:
case union s _ ih => exact sUnion_subset ih
theorem ChainClosure.succ_fixpoint (hc₁ : ChainClosure r c₁) (hc₂ : ChainClosure r c₂)
    (hc : SuccChain r c₂ = c₂) : c₁ ⊆ c₂ := by
  induction hc₁
  case succ s₁ hc₁ h => exact (chainClosure_succ_total hc₁ hc₂ h).elim (fun h => h ▸ hc.subset) id
  case union s _ ih => 

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s✝ t : Set α
a b x y : α
hc₂ : ChainClosure r c₂
hc : SuccChain r c₂ = c₂
s : Set (Set α)
a✝ : ∀ a ∈ s, ChainClosure r a
ih : ∀ a ∈ s, a ⊆ c₂
⊢ ⋃₀ s ⊆ c₂

Next tactic:
exact sUnion_subset ih
theorem ChainClosure.isChain (hc : ChainClosure r c) : IsChain r c := by
  

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
hc : ChainClosure r c
⊢ IsChain r c

Next tactic:
induction hc
theorem ChainClosure.isChain (hc : ChainClosure r c) : IsChain r c := by
  induction hc
  

Proof state:
case succ
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
s✝ : Set α
a✝ : ChainClosure r s✝
a_ih✝ : IsChain r s✝
⊢ IsChain r (SuccChain r s✝)
case union
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
s✝ : Set (Set α)
a✝ : ∀ a ∈ s✝, ChainClosure r a
a_ih✝ : ∀ a ∈ s✝, IsChain r a
⊢ IsChain r (⋃₀ s✝)

Next tactic:
case succ c _ h => exact h.succ
theorem ChainClosure.isChain (hc : ChainClosure r c) : IsChain r c := by
  induction hc
  

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c✝ c₁ c₂ c₃ s t : Set α
a b x y : α
c : Set α
a✝ : ChainClosure r c
h : IsChain r c
⊢ IsChain r (SuccChain r c)

Next tactic:
case succ c _ h => exact h.succ
theorem ChainClosure.isChain (hc : ChainClosure r c) : IsChain r c := by
  induction hc
  case succ c _ h => 

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c✝ c₁ c₂ c₃ s t : Set α
a b x y : α
c : Set α
a✝ : ChainClosure r c
h : IsChain r c
⊢ IsChain r (SuccChain r c)

Next tactic:
exact h.succ
theorem ChainClosure.isChain (hc : ChainClosure r c) : IsChain r c := by
  induction hc
  case succ c _ h => exact h.succ
  

Proof state:
case union
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s t : Set α
a b x y : α
s✝ : Set (Set α)
a✝ : ∀ a ∈ s✝, ChainClosure r a
a_ih✝ : ∀ a ∈ s✝, IsChain r a
⊢ IsChain r (⋃₀ s✝)

Next tactic:
case union s hs h =>
    exact fun c₁ ⟨t₁, ht₁, (hc₁ : c₁ ∈ t₁)⟩ c₂ ⟨t₂, ht₂, (hc₂ : c₂ ∈ t₂)⟩ hneq =>
      ((hs _ ht₁).total <| hs _ ht₂).elim (fun ht => h t₂ ht₂ (ht hc₁) hc₂ hneq) fun ht =>
        h t₁ ht₁ hc₁ (ht hc₂) hneq
theorem ChainClosure.isChain (hc : ChainClosure r c) : IsChain r c := by
  induction hc
  case succ c _ h => exact h.succ
  

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s✝ t : Set α
a b x y : α
s : Set (Set α)
hs : ∀ a ∈ s, ChainClosure r a
h : ∀ a ∈ s, IsChain r a
⊢ IsChain r (⋃₀ s)

Next tactic:
case union s hs h =>
    exact fun c₁ ⟨t₁, ht₁, (hc₁ : c₁ ∈ t₁)⟩ c₂ ⟨t₂, ht₂, (hc₂ : c₂ ∈ t₂)⟩ hneq =>
      ((hs _ ht₁).total <| hs _ ht₂).elim (fun ht => h t₂ ht₂ (ht hc₁) hc₂ hneq) fun ht =>
        h t₁ ht₁ hc₁ (ht hc₂) hneq
theorem ChainClosure.isChain (hc : ChainClosure r c) : IsChain r c := by
  induction hc
  case succ c _ h => exact h.succ
  case union s hs h =>
    

Proof state:
α : Type u_1
β : Type u_2
r : α → α → Prop
c c₁ c₂ c₃ s✝ t : Set α
a b x y : α
s : Set (Set α)
hs : ∀ a ∈ s, ChainClosure r a
h : ∀ a ∈ s, IsChain r a
⊢ IsChain r (⋃₀ s)

Next tactic:
exact fun c₁ ⟨t₁, ht₁, (hc₁ : c₁ ∈ t₁)⟩ c₂ ⟨t₂, ht₂, (hc₂ : c₂ ∈ t₂)⟩ hneq =>
      ((hs _ ht₁).total <| hs _ ht₂).elim (fun ht => h t₂ ht₂ (ht hc₁) hc₂ hneq) fun ht =>
        h t₁ ht₁ hc₁ (ht hc₂) hneq
instance : SetLike (Flag α) α where
  coe := carrier
  coe_injective' s t h := by
    

Proof state:
α : Type u_1
β : Type u_2
inst✝ : LE α
s✝ t✝ : Flag α
a : α
s t : Flag α
h : s.carrier = t.carrier
⊢ s = t

Next tactic:
cases s
instance : SetLike (Flag α) α where
  coe := carrier
  coe_injective' s t h := by
    cases s
    

Proof state:
case mk
α : Type u_1
β : Type u_2
inst✝ : LE α
s t✝ : Flag α
a : α
t : Flag α
carrier✝ : Set α
Chain'✝ : IsChain (fun x x_1 => x ≤ x_1) carrier✝
max_chain'✝ : ∀ ⦃s : Set α⦄, IsChain (fun x x_1 => x ≤ x_1) s → carrier✝ ⊆ s → carrier✝ = s
h : { carrier := carrier✝, Chain' := Chain'✝, max_chain' := max_chain'✝ }.carrier = t.carrier
⊢ { carrier := carrier✝, Chain' := Chain'✝, max_chain' := max_chain'✝ } = t

Next tactic:
cases t
instance : SetLike (Flag α) α where
  coe := carrier
  coe_injective' s t h := by
    cases s
    cases t
    

Proof state:
case mk.mk
α : Type u_1
β : Type u_2
inst✝ : LE α
s t : Flag α
a : α
carrier✝¹ : Set α
Chain'✝¹ : IsChain (fun x x_1 => x ≤ x_1) carrier✝¹
max_chain'✝¹ : ∀ ⦃s : Set α⦄, IsChain (fun x x_1 => x ≤ x_1) s → carrier✝¹ ⊆ s → carrier✝¹ = s
carrier✝ : Set α
Chain'✝ : IsChain (fun x x_1 => x ≤ x_1) carrier✝
max_chain'✝ : ∀ ⦃s : Set α⦄, IsChain (fun x x_1 => x ≤ x_1) s → carrier✝ ⊆ s → carrier✝ = s
h :
  { carrier := carrier✝¹, Chain' := Chain'✝¹, max_chain' := max_chain'✝¹ }.carrier =
    { carrier := carrier✝, Chain' := Chain'✝, max_chain' := max_chain'✝ }.carrier
⊢ { carrier := carrier✝¹, Chain' := Chain'✝¹, max_chain' := max_chain'✝¹ } =
    { carrier := carrier✝, Chain' := Chain'✝, max_chain' := max_chain'✝ }

Next tactic:
congr
protected theorem add_pow_prime_pow_eq (hp : p.Prime) (h : Commute x y) (n : ℕ) :
    (x + y) ^ p ^ n =
      x ^ p ^ n + y ^ p ^ n +
        p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑((p ^ n).choose k / p) := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
p : ℕ
x y : R
hp : Nat.Prime p
h : Commute x y
n : ℕ
⊢ (x + y) ^ p ^ n =
    x ^ p ^ n + y ^ p ^ n + ↑p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑(Nat.choose (p ^ n) k / p)

Next tactic:
trans x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * (p ^ n).choose k
protected theorem add_pow_prime_pow_eq (hp : p.Prime) (h : Commute x y) (n : ℕ) :
    (x + y) ^ p ^ n =
      x ^ p ^ n + y ^ p ^ n +
        p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑((p ^ n).choose k / p) := by
  trans x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * (p ^ n).choose k
  · 

Proof state:
R : Type u_1
inst✝ : Semiring R
p : ℕ
x y : R
hp : Nat.Prime p
h : Commute x y
n : ℕ
⊢ (x + y) ^ p ^ n = x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑(Nat.choose (p ^ n) k)

Next tactic:
simp_rw [h.add_pow, ← Nat.Ico_zero_eq_range, Nat.Ico_succ_right, Icc_eq_cons_Ico (zero_le _),
      Finset.sum_cons, Ico_eq_cons_Ioo (pow_pos hp.pos _), Finset.sum_cons, tsub_self, tsub_zero,
      pow_zero, Nat.choose_zero_right, Nat.choose_self, Nat.cast_one, mul_one, one_mul, ← add_assoc]
protected theorem add_pow_prime_pow_eq (hp : p.Prime) (h : Commute x y) (n : ℕ) :
    (x + y) ^ p ^ n =
      x ^ p ^ n + y ^ p ^ n +
        p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑((p ^ n).choose k / p) := by
  trans x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * (p ^ n).choose k
  · simp_rw [h.add_pow, ← Nat.Ico_zero_eq_range, Nat.Ico_succ_right, Icc_eq_cons_Ico (zero_le _),
      Finset.sum_cons, Ico_eq_cons_Ioo (pow_pos hp.pos _), Finset.sum_cons, tsub_self, tsub_zero,
      pow_zero, Nat.choose_zero_right, Nat.choose_self, Nat.cast_one, mul_one, one_mul, ← add_assoc]
  · 

Proof state:
R : Type u_1
inst✝ : Semiring R
p : ℕ
x y : R
hp : Nat.Prime p
h : Commute x y
n : ℕ
⊢ x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑(Nat.choose (p ^ n) k) =
    x ^ p ^ n + y ^ p ^ n + ↑p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑(Nat.choose (p ^ n) k / p)

Next tactic:
congr 1
protected theorem add_pow_prime_pow_eq (hp : p.Prime) (h : Commute x y) (n : ℕ) :
    (x + y) ^ p ^ n =
      x ^ p ^ n + y ^ p ^ n +
        p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑((p ^ n).choose k / p) := by
  trans x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * (p ^ n).choose k
  · simp_rw [h.add_pow, ← Nat.Ico_zero_eq_range, Nat.Ico_succ_right, Icc_eq_cons_Ico (zero_le _),
      Finset.sum_cons, Ico_eq_cons_Ioo (pow_pos hp.pos _), Finset.sum_cons, tsub_self, tsub_zero,
      pow_zero, Nat.choose_zero_right, Nat.choose_self, Nat.cast_one, mul_one, one_mul, ← add_assoc]
  · congr 1
    

Proof state:
case e_a
R : Type u_1
inst✝ : Semiring R
p : ℕ
x y : R
hp : Nat.Prime p
h : Commute x y
n : ℕ
⊢ ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑(Nat.choose (p ^ n) k) =
    ↑p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑(Nat.choose (p ^ n) k / p)

Next tactic:
simp_rw [Finset.mul_sum, Nat.cast_comm, mul_assoc _ _ (p : R), ← Nat.cast_mul]
protected theorem add_pow_prime_pow_eq (hp : p.Prime) (h : Commute x y) (n : ℕ) :
    (x + y) ^ p ^ n =
      x ^ p ^ n + y ^ p ^ n +
        p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑((p ^ n).choose k / p) := by
  trans x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * (p ^ n).choose k
  · simp_rw [h.add_pow, ← Nat.Ico_zero_eq_range, Nat.Ico_succ_right, Icc_eq_cons_Ico (zero_le _),
      Finset.sum_cons, Ico_eq_cons_Ioo (pow_pos hp.pos _), Finset.sum_cons, tsub_self, tsub_zero,
      pow_zero, Nat.choose_zero_right, Nat.choose_self, Nat.cast_one, mul_one, one_mul, ← add_assoc]
  · congr 1
    simp_rw [Finset.mul_sum, Nat.cast_comm, mul_assoc _ _ (p : R), ← Nat.cast_mul]
    

Proof state:
case e_a
R : Type u_1
inst✝ : Semiring R
p : ℕ
x y : R
hp : Nat.Prime p
h : Commute x y
n : ℕ
⊢ ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑(Nat.choose (p ^ n) k) =
    ∑ x_1 in Ioo 0 (p ^ n), x ^ x_1 * y ^ (p ^ n - x_1) * ↑(Nat.choose (p ^ n) x_1 / p * p)

Next tactic:
refine' Finset.sum_congr rfl fun i hi => _
protected theorem add_pow_prime_pow_eq (hp : p.Prime) (h : Commute x y) (n : ℕ) :
    (x + y) ^ p ^ n =
      x ^ p ^ n + y ^ p ^ n +
        p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑((p ^ n).choose k / p) := by
  trans x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * (p ^ n).choose k
  · simp_rw [h.add_pow, ← Nat.Ico_zero_eq_range, Nat.Ico_succ_right, Icc_eq_cons_Ico (zero_le _),
      Finset.sum_cons, Ico_eq_cons_Ioo (pow_pos hp.pos _), Finset.sum_cons, tsub_self, tsub_zero,
      pow_zero, Nat.choose_zero_right, Nat.choose_self, Nat.cast_one, mul_one, one_mul, ← add_assoc]
  · congr 1
    simp_rw [Finset.mul_sum, Nat.cast_comm, mul_assoc _ _ (p : R), ← Nat.cast_mul]
    refine' Finset.sum_congr rfl fun i hi => _
    

Proof state:
case e_a
R : Type u_1
inst✝ : Semiring R
p : ℕ
x y : R
hp : Nat.Prime p
h : Commute x y
n i : ℕ
hi : i ∈ Ioo 0 (p ^ n)
⊢ x ^ i * y ^ (p ^ n - i) * ↑(Nat.choose (p ^ n) i) = x ^ i * y ^ (p ^ n - i) * ↑(Nat.choose (p ^ n) i / p * p)

Next tactic:
rw [mem_Ioo] at hi
protected theorem add_pow_prime_pow_eq (hp : p.Prime) (h : Commute x y) (n : ℕ) :
    (x + y) ^ p ^ n =
      x ^ p ^ n + y ^ p ^ n +
        p * ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * ↑((p ^ n).choose k / p) := by
  trans x ^ p ^ n + y ^ p ^ n + ∑ k in Ioo 0 (p ^ n), x ^ k * y ^ (p ^ n - k) * (p ^ n).choose k
  · simp_rw [h.add_pow, ← Nat.Ico_zero_eq_range, Nat.Ico_succ_right, Icc_eq_cons_Ico (zero_le _),
      Finset.sum_cons, Ico_eq_cons_Ioo (pow_pos hp.pos _), Finset.sum_cons, tsub_self, tsub_zero,
      pow_zero, Nat.choose_zero_right, Nat.choose_self, Nat.cast_one, mul_one, one_mul, ← add_assoc]
  · congr 1
    simp_rw [Finset.mul_sum, Nat.cast_comm, mul_assoc _ _ (p : R), ← Nat.cast_mul]
    refine' Finset.sum_congr rfl fun i hi => _
    rw [mem_Ioo] at hi
    

Proof state:
case e_a
R : Type u_1
inst✝ : Semiring R
p : ℕ
x y : R
hp : Nat.Prime p
h : Commute x y
n i : ℕ
hi : 0 < i ∧ i < p ^ n
⊢ x ^ i * y ^ (p ^ n - i) * ↑(Nat.choose (p ^ n) i) = x ^ i * y ^ (p ^ n - i) * ↑(Nat.choose (p ^ n) i / p * p)

Next tactic:
rw [Nat.div_mul_cancel (hp.dvd_choose_pow hi.1.ne' hi.2.ne)]
protected theorem add_pow_prime_eq (hp : p.Prime) (h : Commute x y) :
    (x + y) ^ p =
      x ^ p + y ^ p + p * ∑ k in Finset.Ioo 0 p, x ^ k * y ^ (p - k) * ↑(p.choose k / p) :=
  by 

Proof state:
R : Type u_1
inst✝ : Semiring R
p : ℕ
x y : R
hp : Nat.Prime p
h : Commute x y
⊢ (x + y) ^ p = x ^ p + y ^ p + ↑p * ∑ k in Ioo 0 p, x ^ k * y ^ (p - k) * ↑(Nat.choose p k / p)

Next tactic:
simpa using h.add_pow_prime_pow_eq hp 1
@[simp]
theorem CharP.cast_card_eq_zero [AddGroupWithOne R] [Fintype R] : (Fintype.card R : R) = 0 := by
  

Proof state:
R : Type u_1
inst✝¹ : AddGroupWithOne R
inst✝ : Fintype R
⊢ ↑(Fintype.card R) = 0

Next tactic:
rw [← nsmul_one, card_nsmul_eq_zero]
theorem CharP.addOrderOf_one (R) [Semiring R] : CharP R (addOrderOf (1 : R)) :=
  ⟨fun n => by 

Proof state:
R✝ : Type u_1
R : Type u_2
inst✝ : Semiring R
n : ℕ
⊢ ↑n = 0 ↔ addOrderOf 1 ∣ n

Next tactic:
rw [← Nat.smul_one_eq_coe, addOrderOf_dvd_iff_nsmul_eq_zero]
theorem CharP.int_cast_eq_zero_iff [AddGroupWithOne R] (p : ℕ) [CharP R p] (a : ℤ) :
    (a : R) = 0 ↔ (p : ℤ) ∣ a := by
  

Proof state:
R : Type u_1
inst✝¹ : AddGroupWithOne R
p : ℕ
inst✝ : CharP R p
a : ℤ
⊢ ↑a = 0 ↔ ↑p ∣ a

Next tactic:
rcases lt_trichotomy a 0 with (h | rfl | h)
theorem CharP.int_cast_eq_zero_iff [AddGroupWithOne R] (p : ℕ) [CharP R p] (a : ℤ) :
    (a : R) = 0 ↔ (p : ℤ) ∣ a := by
  rcases lt_trichotomy a 0 with (h | rfl | h)
  · 

Proof state:
case inl
R : Type u_1
inst✝¹ : AddGroupWithOne R
p : ℕ
inst✝ : CharP R p
a : ℤ
h : a < 0
⊢ ↑a = 0 ↔ ↑p ∣ a

Next tactic:
rw [← neg_eq_zero, ← Int.cast_neg, ← dvd_neg]
theorem CharP.int_cast_eq_zero_iff [AddGroupWithOne R] (p : ℕ) [CharP R p] (a : ℤ) :
    (a : R) = 0 ↔ (p : ℤ) ∣ a := by
  rcases lt_trichotomy a 0 with (h | rfl | h)
  · rw [← neg_eq_zero, ← Int.cast_neg, ← dvd_neg]
    

Proof state:
case inl
R : Type u_1
inst✝¹ : AddGroupWithOne R
p : ℕ
inst✝ : CharP R p
a : ℤ
h : a < 0
⊢ ↑(-a) = 0 ↔ ↑p ∣ -a

Next tactic:
lift -a to ℕ using neg_nonneg.mpr (le_of_lt h) with b
theorem CharP.int_cast_eq_zero_iff [AddGroupWithOne R] (p : ℕ) [CharP R p] (a : ℤ) :
    (a : R) = 0 ↔ (p : ℤ) ∣ a := by
  rcases lt_trichotomy a 0 with (h | rfl | h)
  · rw [← neg_eq_zero, ← Int.cast_neg, ← dvd_neg]
    lift -a to ℕ using neg_nonneg.mpr (le_of_lt h) with b
    

Proof state:
case inl.intro
R : Type u_1
inst✝¹ : AddGroupWithOne R
p : ℕ
inst✝ : CharP R p
a : ℤ
h : a < 0
b : ℕ
⊢ ↑↑b = 0 ↔ ↑p ∣ ↑b

Next tactic:
rw [Int.cast_ofNat, CharP.cast_eq_zero_iff R p, Int.coe_nat_dvd]
theorem CharP.int_cast_eq_zero_iff [AddGroupWithOne R] (p : ℕ) [CharP R p] (a : ℤ) :
    (a : R) = 0 ↔ (p : ℤ) ∣ a := by
  rcases lt_trichotomy a 0 with (h | rfl | h)
  · rw [← neg_eq_zero, ← Int.cast_neg, ← dvd_neg]
    lift -a to ℕ using neg_nonneg.mpr (le_of_lt h) with b
    rw [Int.cast_ofNat, CharP.cast_eq_zero_iff R p, Int.coe_nat_dvd]
  · 

Proof state:
case inr.inl
R : Type u_1
inst✝¹ : AddGroupWithOne R
p : ℕ
inst✝ : CharP R p
⊢ ↑0 = 0 ↔ ↑p ∣ 0

Next tactic:
simp only [Int.cast_zero, eq_self_iff_true, dvd_zero]
theorem CharP.int_cast_eq_zero_iff [AddGroupWithOne R] (p : ℕ) [CharP R p] (a : ℤ) :
    (a : R) = 0 ↔ (p : ℤ) ∣ a := by
  rcases lt_trichotomy a 0 with (h | rfl | h)
  · rw [← neg_eq_zero, ← Int.cast_neg, ← dvd_neg]
    lift -a to ℕ using neg_nonneg.mpr (le_of_lt h) with b
    rw [Int.cast_ofNat, CharP.cast_eq_zero_iff R p, Int.coe_nat_dvd]
  · simp only [Int.cast_zero, eq_self_iff_true, dvd_zero]
  · 

Proof state:
case inr.inr
R : Type u_1
inst✝¹ : AddGroupWithOne R
p : ℕ
inst✝ : CharP R p
a : ℤ
h : 0 < a
⊢ ↑a = 0 ↔ ↑p ∣ a

Next tactic:
lift a to ℕ using le_of_lt h with b
theorem CharP.int_cast_eq_zero_iff [AddGroupWithOne R] (p : ℕ) [CharP R p] (a : ℤ) :
    (a : R) = 0 ↔ (p : ℤ) ∣ a := by
  rcases lt_trichotomy a 0 with (h | rfl | h)
  · rw [← neg_eq_zero, ← Int.cast_neg, ← dvd_neg]
    lift -a to ℕ using neg_nonneg.mpr (le_of_lt h) with b
    rw [Int.cast_ofNat, CharP.cast_eq_zero_iff R p, Int.coe_nat_dvd]
  · simp only [Int.cast_zero, eq_self_iff_true, dvd_zero]
  · lift a to ℕ using le_of_lt h with b
    

Proof state:
case inr.inr.intro
R : Type u_1
inst✝¹ : AddGroupWithOne R
p : ℕ
inst✝ : CharP R p
a : ℤ
b : ℕ
h✝ h : 0 < ↑b
⊢ ↑↑b = 0 ↔ ↑p ∣ ↑b

Next tactic:
rw [Int.cast_ofNat, CharP.cast_eq_zero_iff R p, Int.coe_nat_dvd]
theorem CharP.intCast_eq_intCast [AddGroupWithOne R] (p : ℕ) [CharP R p] {a b : ℤ} :
    (a : R) = b ↔ a ≡ b [ZMOD p] := by
  

Proof state:
R : Type u_1
inst✝¹ : AddGroupWithOne R
p : ℕ
inst✝ : CharP R p
a b : ℤ
⊢ ↑a = ↑b ↔ a ≡ b [ZMOD ↑p]

Next tactic:
rw [eq_comm, ← sub_eq_zero, ← Int.cast_sub, CharP.int_cast_eq_zero_iff R p, Int.modEq_iff_dvd]
theorem CharP.natCast_eq_natCast' [AddMonoidWithOne R] (p : ℕ) [CharP R p] {a b : ℕ}
    (h : a ≡ b [MOD p]) : (a : R) = b := by
  

Proof state:
R : Type u_1
inst✝¹ : AddMonoidWithOne R
p : ℕ
inst✝ : CharP R p
a b : ℕ
h : a ≡ b [MOD p]
⊢ ↑a = ↑b

Next tactic:
wlog hle : a ≤ b
theorem CharP.natCast_eq_natCast' [AddMonoidWithOne R] (p : ℕ) [CharP R p] {a b : ℕ}
    (h : a ≡ b [MOD p]) : (a : R) = b := by
  wlog hle : a ≤ b
  · 

Proof state:
case inr
R : Type u_1
inst✝¹ : AddMonoidWithOne R
p : ℕ
inst✝ : CharP R p
a b : ℕ
h : a ≡ b [MOD p]
this :
  ∀ (R : Type u_1) [inst : AddMonoidWithOne R] (p : ℕ) [inst_1 : CharP R p] {a b : ℕ}, a ≡ b [MOD p] → a ≤ b → ↑a = ↑b
hle : ¬a ≤ b
⊢ ↑a = ↑b

Next tactic:
exact (this R p h.symm (le_of_not_le hle)).symm
theorem CharP.natCast_eq_natCast' [AddMonoidWithOne R] (p : ℕ) [CharP R p] {a b : ℕ}
    (h : a ≡ b [MOD p]) : (a : R) = b := by
  wlog hle : a ≤ b
  · exact (this R p h.symm (le_of_not_le hle)).symm
  

Proof state:
R✝ R : Type u_1
inst✝¹ : AddMonoidWithOne R
p : ℕ
inst✝ : CharP R p
a b : ℕ
h : a ≡ b [MOD p]
hle : a ≤ b
⊢ ↑a = ↑b

Next tactic:
rw [Nat.modEq_iff_dvd' hle] at h
theorem CharP.natCast_eq_natCast' [AddMonoidWithOne R] (p : ℕ) [CharP R p] {a b : ℕ}
    (h : a ≡ b [MOD p]) : (a : R) = b := by
  wlog hle : a ≤ b
  · exact (this R p h.symm (le_of_not_le hle)).symm
  rw [Nat.modEq_iff_dvd' hle] at h
  

Proof state:
R✝ R : Type u_1
inst✝¹ : AddMonoidWithOne R
p : ℕ
inst✝ : CharP R p
a b : ℕ
h : p ∣ b - a
hle : a ≤ b
⊢ ↑a = ↑b

Next tactic:
rw [← Nat.sub_add_cancel hle, Nat.cast_add, (CharP.cast_eq_zero_iff R p _).mpr h, zero_add]
theorem CharP.natCast_eq_natCast [AddMonoidWithOne R] [IsRightCancelAdd R] (p : ℕ) [CharP R p]
    {a b : ℕ} : (a : R) = b ↔ a ≡ b [MOD p] := by
  

Proof state:
R : Type u_1
inst✝² : AddMonoidWithOne R
inst✝¹ : IsRightCancelAdd R
p : ℕ
inst✝ : CharP R p
a b : ℕ
⊢ ↑a = ↑b ↔ a ≡ b [MOD p]

Next tactic:
wlog hle : a ≤ b
theorem CharP.natCast_eq_natCast [AddMonoidWithOne R] [IsRightCancelAdd R] (p : ℕ) [CharP R p]
    {a b : ℕ} : (a : R) = b ↔ a ≡ b [MOD p] := by
  wlog hle : a ≤ b
  · 

Proof state:
case inr
R : Type u_1
inst✝² : AddMonoidWithOne R
inst✝¹ : IsRightCancelAdd R
p : ℕ
inst✝ : CharP R p
a b : ℕ
this :
  ∀ (R : Type u_1) [inst : AddMonoidWithOne R] [inst_1 : IsRightCancelAdd R] (p : ℕ) [inst_2 : CharP R p] {a b : ℕ},
    a ≤ b → (↑a = ↑b ↔ a ≡ b [MOD p])
hle : ¬a ≤ b
⊢ ↑a = ↑b ↔ a ≡ b [MOD p]

Next tactic:
rw [eq_comm, this R p (le_of_not_le hle), Nat.ModEq.comm]
theorem CharP.natCast_eq_natCast [AddMonoidWithOne R] [IsRightCancelAdd R] (p : ℕ) [CharP R p]
    {a b : ℕ} : (a : R) = b ↔ a ≡ b [MOD p] := by
  wlog hle : a ≤ b
  · rw [eq_comm, this R p (le_of_not_le hle), Nat.ModEq.comm]
  

Proof state:
R✝ R : Type u_1
inst✝² : AddMonoidWithOne R
inst✝¹ : IsRightCancelAdd R
p : ℕ
inst✝ : CharP R p
a b : ℕ
hle : a ≤ b
⊢ ↑a = ↑b ↔ a ≡ b [MOD p]

Next tactic:
rw [Nat.modEq_iff_dvd' hle, ← CharP.cast_eq_zero_iff R p (b - a),
    ← add_right_cancel_iff (G := R) (a := a) (b := b - a), zero_add, ← Nat.cast_add,
    Nat.sub_add_cancel hle, eq_comm]
instance CharP.ofCharZero [AddMonoidWithOne R] [CharZero R] : CharP R 0 :=
  ⟨fun x => by 

Proof state:
R : Type u_1
inst✝¹ : AddMonoidWithOne R
inst✝ : CharZero R
x : ℕ
⊢ ↑x = 0 ↔ 0 ∣ x

Next tactic:
rw [zero_dvd_iff, ← Nat.cast_zero, Nat.cast_inj]
theorem CharP.exists [NonAssocSemiring R] : ∃ p, CharP R p :=
  letI := Classical.decEq R
  by_cases
    (fun H : ∀ p : ℕ, (p : R) = 0 → p = 0 =>
      ⟨0, ⟨fun x => by 

Proof state:
R : Type u_1
inst✝ : NonAssocSemiring R
this : DecidableEq R := Classical.decEq R
H : ∀ (p : ℕ), ↑p = 0 → p = 0
x : ℕ
⊢ ↑x = 0 ↔ 0 ∣ x

Next tactic:
rw [zero_dvd_iff]
theorem CharP.exists [NonAssocSemiring R] : ∃ p, CharP R p :=
  letI := Classical.decEq R
  by_cases
    (fun H : ∀ p : ℕ, (p : R) = 0 → p = 0 =>
      ⟨0, ⟨fun x => by rw [zero_dvd_iff]; 

Proof state:
R : Type u_1
inst✝ : NonAssocSemiring R
this : DecidableEq R := Classical.decEq R
H : ∀ (p : ℕ), ↑p = 0 → p = 0
x : ℕ
⊢ ↑x = 0 ↔ x = 0

Next tactic:
exact ⟨H x, by rintro rfl; simp⟩
theorem CharP.exists [NonAssocSemiring R] : ∃ p, CharP R p :=
  letI := Classical.decEq R
  by_cases
    (fun H : ∀ p : ℕ, (p : R) = 0 → p = 0 =>
      ⟨0, ⟨fun x => by rw [zero_dvd_iff]; exact ⟨H x, by 

Proof state:
R : Type u_1
inst✝ : NonAssocSemiring R
this : DecidableEq R := Classical.decEq R
H : ∀ (p : ℕ), ↑p = 0 → p = 0
x : ℕ
⊢ x = 0 → ↑x = 0

Next tactic:
rintro rfl
theorem CharP.exists [NonAssocSemiring R] : ∃ p, CharP R p :=
  letI := Classical.decEq R
  by_cases
    (fun H : ∀ p : ℕ, (p : R) = 0 → p = 0 =>
      ⟨0, ⟨fun x => by rw [zero_dvd_iff]; exact ⟨H x, by rintro rfl; 

Proof state:
R : Type u_1
inst✝ : NonAssocSemiring R
this : DecidableEq R := Classical.decEq R
H : ∀ (p : ℕ), ↑p = 0 → p = 0
⊢ ↑0 = 0

Next tactic:
simp