l3lab/ntp-mathlib huggingface dataset:
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> 

Proof state:
case mpr
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
⊢ (∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂) →
    ∀ (n₁ n₂ : ℕ) (a₁ a₂ : α), (⇑f)^[n₁ + n₂] (a₁ ⊔ a₂) ≤ (⇑f)^[n₁] a₁ ⊔ (⇑f)^[n₂] a₂

Next tactic:
intro h
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · 

Proof state:
case mp
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (n₁ n₂ : ℕ) (a₁ a₂ : α), (⇑f)^[n₁ + n₂] (a₁ ⊔ a₂) ≤ (⇑f)^[n₁] a₁ ⊔ (⇑f)^[n₂] a₂
⊢ ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂

Next tactic:
exact h 1 0
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · 

Proof state:
case mpr
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
⊢ ∀ (n₁ n₂ : ℕ) (a₁ a₂ : α), (⇑f)^[n₁ + n₂] (a₁ ⊔ a₂) ≤ (⇑f)^[n₁] a₁ ⊔ (⇑f)^[n₂] a₂

Next tactic:
intro n₁ n₂ a₁ a₂
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    

Proof state:
case mpr
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁ a₂ : α
⊢ (⇑f)^[n₁ + n₂] (a₁ ⊔ a₂) ≤ (⇑f)^[n₁] a₁ ⊔ (⇑f)^[n₂] a₂

Next tactic:
have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> intro a₁ a₂
      · rfl
      · calc
          f^[n + 1] (a₁ ⊔ a₂) = f^[n] (f (a₁ ⊔ a₂)) := Function.iterate_succ_apply f n _
          _ ≤ f^[n] (f a₁ ⊔ a₂) := f.mono.iterate n (h a₁ a₂)
          _ ≤ f^[n] (f a₁) ⊔ a₂ := ih _ _
          _ = f^[n + 1] a₁ ⊔ a₂ := by rw [← Function.iterate_succ_apply]
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      

Proof state:
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁ a₂ : α
⊢ ∀ (n : ℕ) (a₁ a₂ : α), (⇑f)^[n] (a₁ ⊔ a₂) ≤ (⇑f)^[n] a₁ ⊔ a₂

Next tactic:
intro n
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      

Proof state:
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁ a₂ : α
n : ℕ
⊢ ∀ (a₁ a₂ : α), (⇑f)^[n] (a₁ ⊔ a₂) ≤ (⇑f)^[n] a₁ ⊔ a₂

Next tactic:
induction' n with n ih
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> 

Proof state:
case zero
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁ a₂ : α
⊢ ∀ (a₁ a₂ : α), (⇑f)^[Nat.zero] (a₁ ⊔ a₂) ≤ (⇑f)^[Nat.zero] a₁ ⊔ a₂

Next tactic:
intro a₁ a₂
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> 

Proof state:
case succ
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁ a₂ : α
n : ℕ
ih : ∀ (a₁ a₂ : α), (⇑f)^[n] (a₁ ⊔ a₂) ≤ (⇑f)^[n] a₁ ⊔ a₂
⊢ ∀ (a₁ a₂ : α), (⇑f)^[Nat.succ n] (a₁ ⊔ a₂) ≤ (⇑f)^[Nat.succ n] a₁ ⊔ a₂

Next tactic:
intro a₁ a₂
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> intro a₁ a₂
      · 

Proof state:
case zero
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁✝ a₂✝ a₁ a₂ : α
⊢ (⇑f)^[Nat.zero] (a₁ ⊔ a₂) ≤ (⇑f)^[Nat.zero] a₁ ⊔ a₂

Next tactic:
rfl
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> intro a₁ a₂
      · rfl
      · 

Proof state:
case succ
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁✝ a₂✝ : α
n : ℕ
ih : ∀ (a₁ a₂ : α), (⇑f)^[n] (a₁ ⊔ a₂) ≤ (⇑f)^[n] a₁ ⊔ a₂
a₁ a₂ : α
⊢ (⇑f)^[Nat.succ n] (a₁ ⊔ a₂) ≤ (⇑f)^[Nat.succ n] a₁ ⊔ a₂

Next tactic:
calc
          f^[n + 1] (a₁ ⊔ a₂) = f^[n] (f (a₁ ⊔ a₂)) := Function.iterate_succ_apply f n _
          _ ≤ f^[n] (f a₁ ⊔ a₂) := f.mono.iterate n (h a₁ a₂)
          _ ≤ f^[n] (f a₁) ⊔ a₂ := ih _ _
          _ = f^[n + 1] a₁ ⊔ a₂ := by rw [← Function.iterate_succ_apply]
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> intro a₁ a₂
      · rfl
      · calc
          f^[n + 1] (a₁ ⊔ a₂) = f^[n] (f (a₁ ⊔ a₂)) := Function.iterate_succ_apply f n _
          _ ≤ f^[n] (f a₁ ⊔ a₂) := f.mono.iterate n (h a₁ a₂)
          _ ≤ f^[n] (f a₁) ⊔ a₂ := ih _ _
          _ = f^[n + 1] a₁ ⊔ a₂ := by 

Proof state:
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁✝ a₂✝ : α
n : ℕ
ih : ∀ (a₁ a₂ : α), (⇑f)^[n] (a₁ ⊔ a₂) ≤ (⇑f)^[n] a₁ ⊔ a₂
a₁ a₂ : α
⊢ (⇑f)^[n] (f a₁) ⊔ a₂ = (⇑f)^[n + 1] a₁ ⊔ a₂

Next tactic:
rw [← Function.iterate_succ_apply]
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> intro a₁ a₂
      · rfl
      · calc
          f^[n + 1] (a₁ ⊔ a₂) = f^[n] (f (a₁ ⊔ a₂)) := Function.iterate_succ_apply f n _
          _ ≤ f^[n] (f a₁ ⊔ a₂) := f.mono.iterate n (h a₁ a₂)
          _ ≤ f^[n] (f a₁) ⊔ a₂ := ih _ _
          _ = f^[n + 1] a₁ ⊔ a₂ := by rw [← Function.iterate_succ_apply]
    

Proof state:
case mpr
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁ a₂ : α
h' : ∀ (n : ℕ) (a₁ a₂ : α), (⇑f)^[n] (a₁ ⊔ a₂) ≤ (⇑f)^[n] a₁ ⊔ a₂
⊢ (⇑f)^[n₁ + n₂] (a₁ ⊔ a₂) ≤ (⇑f)^[n₁] a₁ ⊔ (⇑f)^[n₂] a₂

Next tactic:
calc
      f^[n₁ + n₂] (a₁ ⊔ a₂) = f^[n₁] (f^[n₂] (a₁ ⊔ a₂)) :=
        Function.iterate_add_apply f n₁ n₂ _
      _ = f^[n₁] (f^[n₂] (a₂ ⊔ a₁)) := by rw [sup_comm]
      _ ≤ f^[n₁] (f^[n₂] a₂ ⊔ a₁) := f.mono.iterate n₁ (h' n₂ _ _)
      _ = f^[n₁] (a₁ ⊔ f^[n₂] a₂) := by rw [sup_comm]
      _ ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂ := h' n₁ a₁ _
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> intro a₁ a₂
      · rfl
      · calc
          f^[n + 1] (a₁ ⊔ a₂) = f^[n] (f (a₁ ⊔ a₂)) := Function.iterate_succ_apply f n _
          _ ≤ f^[n] (f a₁ ⊔ a₂) := f.mono.iterate n (h a₁ a₂)
          _ ≤ f^[n] (f a₁) ⊔ a₂ := ih _ _
          _ = f^[n + 1] a₁ ⊔ a₂ := by rw [← Function.iterate_succ_apply]
    calc
      f^[n₁ + n₂] (a₁ ⊔ a₂) = f^[n₁] (f^[n₂] (a₁ ⊔ a₂)) :=
        Function.iterate_add_apply f n₁ n₂ _
      _ = f^[n₁] (f^[n₂] (a₂ ⊔ a₁)) := by 

Proof state:
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁ a₂ : α
h' : ∀ (n : ℕ) (a₁ a₂ : α), (⇑f)^[n] (a₁ ⊔ a₂) ≤ (⇑f)^[n] a₁ ⊔ a₂
⊢ (⇑f)^[n₁] ((⇑f)^[n₂] (a₁ ⊔ a₂)) = (⇑f)^[n₁] ((⇑f)^[n₂] (a₂ ⊔ a₁))

Next tactic:
rw [sup_comm]
theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) :
    (∀ n₁ n₂ a₁ a₂, f^[n₁ + n₂] (a₁ ⊔ a₂) ≤ f^[n₁] a₁ ⊔ f^[n₂] a₂) ↔
      ∀ a₁ a₂, f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂ := by
  constructor <;> intro h
  · exact h 1 0
  · intro n₁ n₂ a₁ a₂
    have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by
      intro n
      induction' n with n ih <;> intro a₁ a₂
      · rfl
      · calc
          f^[n + 1] (a₁ ⊔ a₂) = f^[n] (f (a₁ ⊔ a₂)) := Function.iterate_succ_apply f n _
          _ ≤ f^[n] (f a₁ ⊔ a₂) := f.mono.iterate n (h a₁ a₂)
          _ ≤ f^[n] (f a₁) ⊔ a₂ := ih _ _
          _ = f^[n + 1] a₁ ⊔ a₂ := by rw [← Function.iterate_succ_apply]
    calc
      f^[n₁ + n₂] (a₁ ⊔ a₂) = f^[n₁] (f^[n₂] (a₁ ⊔ a₂)) :=
        Function.iterate_add_apply f n₁ n₂ _
      _ = f^[n₁] (f^[n₂] (a₂ ⊔ a₁)) := by rw [sup_comm]
      _ ≤ f^[n₁] (f^[n₂] a₂ ⊔ a₁) := f.mono.iterate n₁ (h' n₂ _ _)
      _ = f^[n₁] (a₁ ⊔ f^[n₂] a₂) := by 

Proof state:
α✝ : Type u_1
β : Type u_2
inst✝¹ : Preorder α✝
α : Type u_3
inst✝ : SemilatticeSup α
f : α →o α
h : ∀ (a₁ a₂ : α), f (a₁ ⊔ a₂) ≤ f a₁ ⊔ a₂
n₁ n₂ : ℕ
a₁ a₂ : α
h' : ∀ (n : ℕ) (a₁ a₂ : α), (⇑f)^[n] (a₁ ⊔ a₂) ≤ (⇑f)^[n] a₁ ⊔ a₂
⊢ (⇑f)^[n₁] ((⇑f)^[n₂] a₂ ⊔ a₁) = (⇑f)^[n₁] (a₁ ⊔ (⇑f)^[n₂] a₂)

Next tactic:
rw [sup_comm]
@[refl, simp]
theorem modEq_refl (a : α) : a ≡ a [PMOD p] :=
  ⟨0, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a✝ a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
a : α
⊢ a - a = 0 • p

Next tactic:
simp
theorem modEq_comm : a ≡ b [PMOD p] ↔ b ≡ a [PMOD p] :=
  (Equiv.neg _).exists_congr_left.trans <| by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ (∃ b_1, b - a = (Equiv.neg ℤ).symm b_1 • p) ↔ b ≡ a [PMOD p]

Next tactic:
simp [ModEq, ← neg_eq_iff_eq_neg]
@[trans]
theorem ModEq.trans : a ≡ b [PMOD p] → b ≡ c [PMOD p] → a ≡ c [PMOD p] := fun ⟨m, hm⟩ ⟨n, hn⟩ =>
  ⟨m + n, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n✝ : ℕ
z : ℤ
x✝¹ : a ≡ b [PMOD p]
x✝ : b ≡ c [PMOD p]
m : ℤ
hm : b - a = m • p
n : ℤ
hn : c - b = n • p
⊢ c - a = (m + n) • p

Next tactic:
simp [add_smul, ← hm, ← hn]
@[simp]
theorem neg_modEq_neg : -a ≡ -b [PMOD p] ↔ a ≡ b [PMOD p] :=
  modEq_comm.trans <| by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ -b ≡ -a [PMOD p] ↔ a ≡ b [PMOD p]

Next tactic:
simp [ModEq, neg_add_eq_sub]
@[simp]
theorem modEq_neg : a ≡ b [PMOD -p] ↔ a ≡ b [PMOD p] :=
  modEq_comm.trans <| by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ b ≡ a [PMOD -p] ↔ a ≡ b [PMOD p]

Next tactic:
simp [ModEq, ← neg_eq_iff_eq_neg]
@[simp]
theorem modEq_zero : a ≡ b [PMOD 0] ↔ a = b := by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ a ≡ b [PMOD 0] ↔ a = b

Next tactic:
simp [ModEq, sub_eq_zero, eq_comm]
@[simp]
theorem self_modEq_zero : p ≡ 0 [PMOD p] :=
  ⟨-1, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ 0 - p = -1 • p

Next tactic:
simp
@[simp]
theorem zsmul_modEq_zero (z : ℤ) : z • p ≡ 0 [PMOD p] :=
  ⟨-z, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z✝ z : ℤ
⊢ 0 - z • p = -z • p

Next tactic:
simp
theorem add_zsmul_modEq (z : ℤ) : a + z • p ≡ a [PMOD p] :=
  ⟨-z, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z✝ z : ℤ
⊢ a - (a + z • p) = -z • p

Next tactic:
simp
theorem zsmul_add_modEq (z : ℤ) : z • p + a ≡ a [PMOD p] :=
  ⟨-z, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z✝ z : ℤ
⊢ a - (z • p + a) = -z • p

Next tactic:
simp [← sub_sub]
theorem add_nsmul_modEq (n : ℕ) : a + n • p ≡ a [PMOD p] :=
  ⟨-n, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n✝ : ℕ
z : ℤ
n : ℕ
⊢ a - (a + n • p) = -↑n • p

Next tactic:
simp
theorem nsmul_add_modEq (n : ℕ) : n • p + a ≡ a [PMOD p] :=
  ⟨-n, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n✝ : ℕ
z : ℤ
n : ℕ
⊢ a - (n • p + a) = -↑n • p

Next tactic:
simp [← sub_sub]
protected theorem of_zsmul : a ≡ b [PMOD z • p] → a ≡ b [PMOD p] := fun ⟨m, hm⟩ =>
  ⟨m * z, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
x✝ : a ≡ b [PMOD z • p]
m : ℤ
hm : b - a = m • z • p
⊢ b - a = (m * z) • p

Next tactic:
rwa [mul_smul]
protected theorem of_nsmul : a ≡ b [PMOD n • p] → a ≡ b [PMOD p] := fun ⟨m, hm⟩ =>
  ⟨m * n, by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
x✝ : a ≡ b [PMOD n • p]
m : ℤ
hm : b - a = m • n • p
⊢ b - a = (m * ↑n) • p

Next tactic:
rwa [mul_smul, coe_nat_zsmul]
protected theorem zsmul : a ≡ b [PMOD p] → z • a ≡ z • b [PMOD z • p] :=
  Exists.imp fun m hm => by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z m : ℤ
hm : b - a = m • p
⊢ z • b - z • a = m • z • p

Next tactic:
rw [← smul_sub, hm, smul_comm]
protected theorem nsmul : a ≡ b [PMOD p] → n • a ≡ n • b [PMOD n • p] :=
  Exists.imp fun m hm => by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z m : ℤ
hm : b - a = m • p
⊢ n • b - n • a = m • n • p

Next tactic:
rw [← smul_sub, hm, smul_comm]
@[simp]
theorem zsmul_modEq_zsmul [NoZeroSMulDivisors ℤ α] (hn : z ≠ 0) :
    z • a ≡ z • b [PMOD z • p] ↔ a ≡ b [PMOD p] :=
  exists_congr fun m => by 

Proof state:
α : Type u_1
inst✝¹ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
inst✝ : NoZeroSMulDivisors ℤ α
hn : z ≠ 0
m : ℤ
⊢ z • b - z • a = m • z • p ↔ b - a = m • p

Next tactic:
rw [← smul_sub, smul_comm, smul_right_inj hn]
@[simp]
theorem nsmul_modEq_nsmul [NoZeroSMulDivisors ℕ α] (hn : n ≠ 0) :
    n • a ≡ n • b [PMOD n • p] ↔ a ≡ b [PMOD p] :=
  exists_congr fun m => by 

Proof state:
α : Type u_1
inst✝¹ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
inst✝ : NoZeroSMulDivisors ℕ α
hn : n ≠ 0
m : ℤ
⊢ n • b - n • a = m • n • p ↔ b - a = m • p

Next tactic:
rw [← smul_sub, smul_comm, smul_right_inj hn]
@[simp]
protected theorem add_iff_left :
    a₁ ≡ b₁ [PMOD p] → (a₁ + a₂ ≡ b₁ + b₂ [PMOD p] ↔ a₂ ≡ b₂ [PMOD p]) := fun ⟨m, hm⟩ =>
  (Equiv.addLeft m).symm.exists_congr_left.trans <| by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
x✝ : a₁ ≡ b₁ [PMOD p]
m : ℤ
hm : b₁ - a₁ = m • p
⊢ (∃ b, b₁ + b₂ - (a₁ + a₂) = (Equiv.addLeft m).symm.symm b • p) ↔ a₂ ≡ b₂ [PMOD p]

Next tactic:
simp [add_sub_add_comm, hm, add_smul, ModEq]
@[simp]
protected theorem add_iff_right :
    a₂ ≡ b₂ [PMOD p] → (a₁ + a₂ ≡ b₁ + b₂ [PMOD p] ↔ a₁ ≡ b₁ [PMOD p]) := fun ⟨m, hm⟩ =>
  (Equiv.addRight m).symm.exists_congr_left.trans <| by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
x✝ : a₂ ≡ b₂ [PMOD p]
m : ℤ
hm : b₂ - a₂ = m • p
⊢ (∃ b, b₁ + b₂ - (a₁ + a₂) = (Equiv.addRight m).symm.symm b • p) ↔ a₁ ≡ b₁ [PMOD p]

Next tactic:
simp [add_sub_add_comm, hm, add_smul, ModEq]
@[simp]
protected theorem sub_iff_left :
    a₁ ≡ b₁ [PMOD p] → (a₁ - a₂ ≡ b₁ - b₂ [PMOD p] ↔ a₂ ≡ b₂ [PMOD p]) := fun ⟨m, hm⟩ =>
  (Equiv.subLeft m).symm.exists_congr_left.trans <| by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
x✝ : a₁ ≡ b₁ [PMOD p]
m : ℤ
hm : b₁ - a₁ = m • p
⊢ (∃ b, b₁ - b₂ - (a₁ - a₂) = (Equiv.subLeft m).symm.symm b • p) ↔ a₂ ≡ b₂ [PMOD p]

Next tactic:
simp [sub_sub_sub_comm, hm, sub_smul, ModEq]
@[simp]
protected theorem sub_iff_right :
    a₂ ≡ b₂ [PMOD p] → (a₁ - a₂ ≡ b₁ - b₂ [PMOD p] ↔ a₁ ≡ b₁ [PMOD p]) := fun ⟨m, hm⟩ =>
  (Equiv.subRight m).symm.exists_congr_left.trans <| by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
x✝ : a₂ ≡ b₂ [PMOD p]
m : ℤ
hm : b₂ - a₂ = m • p
⊢ (∃ b, b₁ - b₂ - (a₁ - a₂) = (Equiv.subRight m).symm.symm b • p) ↔ a₁ ≡ b₁ [PMOD p]

Next tactic:
simp [sub_sub_sub_comm, hm, sub_smul, ModEq]
theorem modEq_sub_iff_add_modEq' : a ≡ b - c [PMOD p] ↔ c + a ≡ b [PMOD p] := by
  

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ a ≡ b - c [PMOD p] ↔ c + a ≡ b [PMOD p]

Next tactic:
simp [ModEq, sub_sub]
theorem modEq_sub_iff_add_modEq : a ≡ b - c [PMOD p] ↔ a + c ≡ b [PMOD p] :=
  modEq_sub_iff_add_modEq'.trans <| by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ c + a ≡ b [PMOD p] ↔ a + c ≡ b [PMOD p]

Next tactic:
rw [add_comm]
@[simp]
theorem sub_modEq_zero : a - b ≡ 0 [PMOD p] ↔ a ≡ b [PMOD p] := by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ a - b ≡ 0 [PMOD p] ↔ a ≡ b [PMOD p]

Next tactic:
simp [sub_modEq_iff_modEq_add]
@[simp]
theorem add_modEq_left : a + b ≡ a [PMOD p] ↔ b ≡ 0 [PMOD p] := by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ a + b ≡ a [PMOD p] ↔ b ≡ 0 [PMOD p]

Next tactic:
simp [← modEq_sub_iff_add_modEq']
@[simp]
theorem add_modEq_right : a + b ≡ b [PMOD p] ↔ a ≡ 0 [PMOD p] := by 

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ a + b ≡ b [PMOD p] ↔ a ≡ 0 [PMOD p]

Next tactic:
simp [← modEq_sub_iff_add_modEq]
theorem modEq_iff_eq_add_zsmul : a ≡ b [PMOD p] ↔ ∃ z : ℤ, b = a + z • p := by
  

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ a ≡ b [PMOD p] ↔ ∃ z, b = a + z • p

Next tactic:
simp_rw [ModEq, sub_eq_iff_eq_add']
theorem not_modEq_iff_ne_add_zsmul : ¬a ≡ b [PMOD p] ↔ ∀ z : ℤ, b ≠ a + z • p := by
  

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ ¬a ≡ b [PMOD p] ↔ ∀ (z : ℤ), b ≠ a + z • p

Next tactic:
rw [modEq_iff_eq_add_zsmul, not_exists]
theorem modEq_iff_eq_mod_zmultiples : a ≡ b [PMOD p] ↔ (b : α ⧸ AddSubgroup.zmultiples p) = a := by
  

Proof state:
α : Type u_1
inst✝ : AddCommGroup α
p a a₁ a₂ b b₁ b₂ c : α
n : ℕ
z : ℤ
⊢ a ≡ b [PMOD p] ↔ ↑b = ↑a

Next tactic:
simp_rw [modEq_iff_eq_add_zsmul, QuotientAddGroup.eq_iff_sub_mem, AddSubgroup.mem_zmultiples_iff,
    eq_sub_iff_add_eq', eq_comm]
@[simp]
theorem modEq_iff_int_modEq {a b z : ℤ} : a ≡ b [PMOD z] ↔ a ≡ b [ZMOD z] := by
  

Proof state:
α : Type u_1
a b z : ℤ
⊢ a ≡ b [PMOD z] ↔ a ≡ b [ZMOD z]

Next tactic:
simp [ModEq, dvd_iff_exists_eq_mul_left, Int.modEq_iff_dvd]
@[simp, norm_cast]
theorem int_cast_modEq_int_cast {a b z : ℤ} : a ≡ b [PMOD (z : α)] ↔ a ≡ b [PMOD z] := by
  

Proof state:
α : Type u_1
inst✝¹ : AddCommGroupWithOne α
inst✝ : CharZero α
a b z : ℤ
⊢ ↑a ≡ ↑b [PMOD ↑z] ↔ a ≡ b [PMOD z]

Next tactic:
simp_rw [ModEq, ← Int.cast_mul_eq_zsmul_cast]
@[simp, norm_cast]
theorem int_cast_modEq_int_cast {a b z : ℤ} : a ≡ b [PMOD (z : α)] ↔ a ≡ b [PMOD z] := by
  simp_rw [ModEq, ← Int.cast_mul_eq_zsmul_cast]
  

Proof state:
α : Type u_1
inst✝¹ : AddCommGroupWithOne α
inst✝ : CharZero α
a b z : ℤ
⊢ (∃ z_1, ↑b - ↑a = ↑(z_1 * z)) ↔ ∃ z_1, b - a = z_1 • z

Next tactic:
norm_cast
@[simp, norm_cast]
theorem nat_cast_modEq_nat_cast {a b n : ℕ} : a ≡ b [PMOD (n : α)] ↔ a ≡ b [MOD n] := by
  

Proof state:
α : Type u_1
inst✝¹ : AddCommGroupWithOne α
inst✝ : CharZero α
a b n : ℕ
⊢ ↑a ≡ ↑b [PMOD ↑n] ↔ a ≡ b [MOD n]

Next tactic:
simp_rw [← Int.coe_nat_modEq_iff, ← modEq_iff_int_modEq, ← @int_cast_modEq_int_cast α,
    Int.cast_ofNat]
@[simp]
theorem add_self : a + a = 0 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
⊢ a + a = 0

Next tactic:
have : a + a = a + a + (a + a) :=
    calc
      a + a = (a + a) * (a + a) := by rw [mul_self]
      _ = a * a + a * a + (a * a + a * a) := by rw [add_mul, mul_add]
      _ = a + a + (a + a) := by rw [mul_self]
@[simp]
theorem add_self : a + a = 0 := by
  have : a + a = a + a + (a + a) :=
    calc
      a + a = (a + a) * (a + a) := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
⊢ a + a = (a + a) * (a + a)

Next tactic:
rw [mul_self]
@[simp]
theorem add_self : a + a = 0 := by
  have : a + a = a + a + (a + a) :=
    calc
      a + a = (a + a) * (a + a) := by rw [mul_self]
      _ = a * a + a * a + (a * a + a * a) := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
⊢ (a + a) * (a + a) = a * a + a * a + (a * a + a * a)

Next tactic:
rw [add_mul, mul_add]
@[simp]
theorem add_self : a + a = 0 := by
  have : a + a = a + a + (a + a) :=
    calc
      a + a = (a + a) * (a + a) := by rw [mul_self]
      _ = a * a + a * a + (a * a + a * a) := by rw [add_mul, mul_add]
      _ = a + a + (a + a) := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
⊢ a * a + a * a + (a * a + a * a) = a + a + (a + a)

Next tactic:
rw [mul_self]
@[simp]
theorem add_self : a + a = 0 := by
  have : a + a = a + a + (a + a) :=
    calc
      a + a = (a + a) * (a + a) := by rw [mul_self]
      _ = a * a + a * a + (a * a + a * a) := by rw [add_mul, mul_add]
      _ = a + a + (a + a) := by rw [mul_self]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
this : a + a = a + a + (a + a)
⊢ a + a = 0

Next tactic:
rwa [self_eq_add_left] at this
@[simp]
theorem neg_eq : -a = a :=
  calc
    -a = -a + 0 := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
⊢ -a = -a + 0

Next tactic:
rw [add_zero]
@[simp]
theorem neg_eq : -a = a :=
  calc
    -a = -a + 0 := by rw [add_zero]
    _ = -a + -a + a := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
⊢ -a + 0 = -a + -a + a

Next tactic:
rw [← neg_add_self, add_assoc]
@[simp]
theorem neg_eq : -a = a :=
  calc
    -a = -a + 0 := by rw [add_zero]
    _ = -a + -a + a := by rw [← neg_add_self, add_assoc]
    _ = a := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
⊢ -a + -a + a = a

Next tactic:
rw [add_self, zero_add]
theorem add_eq_zero' : a + b = 0 ↔ a = b :=
  calc
    a + b = 0 ↔ a = -b := add_eq_zero_iff_eq_neg
    _ ↔ a = b := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : BooleanRing α
a b : α
⊢ a = -b ↔ a = b

Next tactic:
rw [neg_eq]