l3lab/ntp-mathlib huggingface dataset:
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; rw [num_den'] at ha
  generalize hc : c /. d = x; cases' x with n₂ d₂ h₂ c₂; 

Proof state:
case mk'.mk'
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
c₁ : Nat.Coprime (Int.natAbs n₁) d₁
ha : a /. b = n₁ /. ↑d₁
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
c₂ : Nat.Coprime (Int.natAbs n₂) d₂
hc : c /. d = mk' n₂ d₂
⊢ f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ a b c d /. f₂ a b c d

Next tactic:
rw [num_den'] at hc
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; rw [num_den'] at ha
  generalize hc : c /. d = x; cases' x with n₂ d₂ h₂ c₂; rw [num_den'] at hc
  

Proof state:
case mk'.mk'
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
c₁ : Nat.Coprime (Int.natAbs n₁) d₁
ha : a /. b = n₁ /. ↑d₁
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
c₂ : Nat.Coprime (Int.natAbs n₂) d₂
hc : c /. d = n₂ /. ↑d₂
⊢ f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ a b c d /. f₂ a b c d

Next tactic:
rw [fv]
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; rw [num_den'] at ha
  generalize hc : c /. d = x; cases' x with n₂ d₂ h₂ c₂; rw [num_den'] at hc
  rw [fv]
  

Proof state:
case mk'.mk'
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
c₁ : Nat.Coprime (Int.natAbs n₁) d₁
ha : a /. b = n₁ /. ↑d₁
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
c₂ : Nat.Coprime (Int.natAbs n₂) d₂
hc : c /. d = n₂ /. ↑d₂
⊢ f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂ = f₁ a b c d /. f₂ a b c d

Next tactic:
have d₁0 := ne_of_gt (Int.ofNat_lt.2 $ Nat.pos_of_ne_zero h₁)
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; rw [num_den'] at ha
  generalize hc : c /. d = x; cases' x with n₂ d₂ h₂ c₂; rw [num_den'] at hc
  rw [fv]
  have d₁0 := ne_of_gt (Int.ofNat_lt.2 $ Nat.pos_of_ne_zero h₁)
  

Proof state:
case mk'.mk'
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
c₁ : Nat.Coprime (Int.natAbs n₁) d₁
ha : a /. b = n₁ /. ↑d₁
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
c₂ : Nat.Coprime (Int.natAbs n₂) d₂
hc : c /. d = n₂ /. ↑d₂
d₁0 : ↑d₁ ≠ ↑0
⊢ f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂ = f₁ a b c d /. f₂ a b c d

Next tactic:
have d₂0 := ne_of_gt (Int.ofNat_lt.2 $ Nat.pos_of_ne_zero h₂)
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; rw [num_den'] at ha
  generalize hc : c /. d = x; cases' x with n₂ d₂ h₂ c₂; rw [num_den'] at hc
  rw [fv]
  have d₁0 := ne_of_gt (Int.ofNat_lt.2 $ Nat.pos_of_ne_zero h₁)
  have d₂0 := ne_of_gt (Int.ofNat_lt.2 $ Nat.pos_of_ne_zero h₂)
  

Proof state:
case mk'.mk'
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
c₁ : Nat.Coprime (Int.natAbs n₁) d₁
ha : a /. b = n₁ /. ↑d₁
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
c₂ : Nat.Coprime (Int.natAbs n₂) d₂
hc : c /. d = n₂ /. ↑d₂
d₁0 : ↑d₁ ≠ ↑0
d₂0 : ↑d₂ ≠ ↑0
⊢ f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂ = f₁ a b c d /. f₂ a b c d

Next tactic:
exact (divInt_eq_iff (f0 d₁0 d₂0) (f0 b0 d0)).2
    (H ((divInt_eq_iff b0 d₁0).1 ha) ((divInt_eq_iff d0 d₂0).1 hc))
protected theorem add_zero : a + 0 = a :=
  numDenCasesOn' a fun n d h => by
    

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ n /. ↑d + 0 = n /. ↑d

Next tactic:
rw [← zero_divInt d, add_def'', zero_mul, add_zero, divInt_mul_right]
protected theorem add_zero : a + 0 = a :=
  numDenCasesOn' a fun n d h => by
    rw [← zero_divInt d, add_def'', zero_mul, add_zero, divInt_mul_right] <;> 

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ ↑d ≠ 0

Next tactic:
simp [h]
protected theorem add_zero : a + 0 = a :=
  numDenCasesOn' a fun n d h => by
    rw [← zero_divInt d, add_def'', zero_mul, add_zero, divInt_mul_right] <;> 

Proof state:
case b0
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ ↑d ≠ 0

Next tactic:
simp [h]
protected theorem add_zero : a + 0 = a :=
  numDenCasesOn' a fun n d h => by
    rw [← zero_divInt d, add_def'', zero_mul, add_zero, divInt_mul_right] <;> 

Proof state:
case d0
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ ↑d ≠ 0

Next tactic:
simp [h]
protected theorem zero_add : 0 + a = a :=
  numDenCasesOn' a fun n d h => by
    

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ 0 + n /. ↑d = n /. ↑d

Next tactic:
rw [← zero_divInt d, add_def'', zero_mul, zero_add, divInt_mul_right]
protected theorem zero_add : 0 + a = a :=
  numDenCasesOn' a fun n d h => by
    rw [← zero_divInt d, add_def'', zero_mul, zero_add, divInt_mul_right] <;> 

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ ↑d ≠ 0

Next tactic:
simp [h]
protected theorem zero_add : 0 + a = a :=
  numDenCasesOn' a fun n d h => by
    rw [← zero_divInt d, add_def'', zero_mul, zero_add, divInt_mul_right] <;> 

Proof state:
case b0
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ ↑d ≠ 0

Next tactic:
simp [h]
protected theorem zero_add : 0 + a = a :=
  numDenCasesOn' a fun n d h => by
    rw [← zero_divInt d, add_def'', zero_mul, zero_add, divInt_mul_right] <;> 

Proof state:
case d0
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ ↑d ≠ 0

Next tactic:
simp [h]
protected theorem add_comm : a + b = b + a :=
  numDenCasesOn' a fun n₁ d₁ h₁ => numDenCasesOn' b fun n₂ d₂ h₂ => by
    

Proof state:
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
⊢ n₁ /. ↑d₁ + n₂ /. ↑d₂ = n₂ /. ↑d₂ + n₁ /. ↑d₁

Next tactic:
simp [h₁, h₂, add_comm, mul_comm]
protected theorem add_assoc : a + b + c = a + (b + c) :=
  numDenCasesOn' a fun n₁ d₁ h₁ =>
    numDenCasesOn' b fun n₂ d₂ h₂ =>
      numDenCasesOn' c fun n₃ d₃ h₃ => by
        

Proof state:
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
n₃ : ℤ
d₃ : ℕ
h₃ : d₃ ≠ 0
⊢ n₁ /. ↑d₁ + n₂ /. ↑d₂ + n₃ /. ↑d₃ = n₁ /. ↑d₁ + (n₂ /. ↑d₂ + n₃ /. ↑d₃)

Next tactic:
simp only [ne_eq, Nat.cast_eq_zero, h₁, not_false_eq_true, h₂, add_def'', mul_eq_zero,
          or_self, h₃]
protected theorem add_assoc : a + b + c = a + (b + c) :=
  numDenCasesOn' a fun n₁ d₁ h₁ =>
    numDenCasesOn' b fun n₂ d₂ h₂ =>
      numDenCasesOn' c fun n₃ d₃ h₃ => by
        simp only [ne_eq, Nat.cast_eq_zero, h₁, not_false_eq_true, h₂, add_def'', mul_eq_zero,
          or_self, h₃]
        

Proof state:
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
n₃ : ℤ
d₃ : ℕ
h₃ : d₃ ≠ 0
⊢ ((n₁ * ↑d₂ + n₂ * ↑d₁) * ↑d₃ + n₃ * (↑d₁ * ↑d₂)) /. (↑d₁ * ↑d₂ * ↑d₃) =
    (n₁ * (↑d₂ * ↑d₃) + (n₂ * ↑d₃ + n₃ * ↑d₂) * ↑d₁) /. (↑d₁ * (↑d₂ * ↑d₃))

Next tactic:
rw [mul_assoc, add_mul, add_mul, mul_assoc, add_assoc]
protected theorem add_assoc : a + b + c = a + (b + c) :=
  numDenCasesOn' a fun n₁ d₁ h₁ =>
    numDenCasesOn' b fun n₂ d₂ h₂ =>
      numDenCasesOn' c fun n₃ d₃ h₃ => by
        simp only [ne_eq, Nat.cast_eq_zero, h₁, not_false_eq_true, h₂, add_def'', mul_eq_zero,
          or_self, h₃]
        rw [mul_assoc, add_mul, add_mul, mul_assoc, add_assoc]
        

Proof state:
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
n₃ : ℤ
d₃ : ℕ
h₃ : d₃ ≠ 0
⊢ (n₁ * (↑d₂ * ↑d₃) + (n₂ * ↑d₁ * ↑d₃ + n₃ * (↑d₁ * ↑d₂))) /. (↑d₁ * (↑d₂ * ↑d₃)) =
    (n₁ * (↑d₂ * ↑d₃) + (n₂ * ↑d₃ * ↑d₁ + n₃ * ↑d₂ * ↑d₁)) /. (↑d₁ * (↑d₂ * ↑d₃))

Next tactic:
congr 2
protected theorem add_assoc : a + b + c = a + (b + c) :=
  numDenCasesOn' a fun n₁ d₁ h₁ =>
    numDenCasesOn' b fun n₂ d₂ h₂ =>
      numDenCasesOn' c fun n₃ d₃ h₃ => by
        simp only [ne_eq, Nat.cast_eq_zero, h₁, not_false_eq_true, h₂, add_def'', mul_eq_zero,
          or_self, h₃]
        rw [mul_assoc, add_mul, add_mul, mul_assoc, add_assoc]
        congr 2
        

Proof state:
case e_a.e_a
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
n₃ : ℤ
d₃ : ℕ
h₃ : d₃ ≠ 0
⊢ n₂ * ↑d₁ * ↑d₃ + n₃ * (↑d₁ * ↑d₂) = n₂ * ↑d₃ * ↑d₁ + n₃ * ↑d₂ * ↑d₁

Next tactic:
ac_rfl
protected theorem add_left_neg : -a + a = 0 :=
  numDenCasesOn' a fun n d h => by 

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
⊢ -(n /. ↑d) + n /. ↑d = 0

Next tactic:
simp [h, mkRat_add_mkRat]
theorem divInt_zero_one : 0 /. 1 = 0 :=
  show divInt _ _ = _ by
    

Proof state:
a b c : ℚ
⊢ 0 /. 1 = 0

Next tactic:
rw [divInt]
theorem divInt_zero_one : 0 /. 1 = 0 :=
  show divInt _ _ = _ by
    rw [divInt]
    

Proof state:
a b c : ℚ
⊢ (match 0, 1 with
    | n, Int.ofNat d => inline (mkRat n d)
    | n, Int.negSucc d => normalize (-n) (Nat.succ d)) =
    0

Next tactic:
simp
@[simp]
theorem divInt_one_one : 1 /. 1 = 1 :=
  show divInt _ _ = _ by
    

Proof state:
a b c : ℚ
⊢ 1 /. 1 = 1

Next tactic:
rw [divInt]
@[simp]
theorem divInt_one_one : 1 /. 1 = 1 :=
  show divInt _ _ = _ by
    rw [divInt]
    

Proof state:
a b c : ℚ
⊢ (match 1, 1 with
    | n, Int.ofNat d => inline (mkRat n d)
    | n, Int.negSucc d => normalize (-n) (Nat.succ d)) =
    1

Next tactic:
simp [mkRat, normalize]
@[simp]
theorem divInt_one_one : 1 /. 1 = 1 :=
  show divInt _ _ = _ by
    rw [divInt]
    simp [mkRat, normalize]
    

Proof state:
a b c : ℚ
⊢ mk' 1 1 = 1

Next tactic:
rfl
@[simp]
theorem divInt_neg_one_one : -1 /. 1 = -1 :=
  show divInt _ _ = _ by
    

Proof state:
a b c : ℚ
⊢ -1 /. 1 = -1

Next tactic:
rw [divInt]
@[simp]
theorem divInt_neg_one_one : -1 /. 1 = -1 :=
  show divInt _ _ = _ by
    rw [divInt]
    

Proof state:
a b c : ℚ
⊢ (match -1, 1 with
    | n, Int.ofNat d => inline (mkRat n d)
    | n, Int.negSucc d => normalize (-n) (Nat.succ d)) =
    -1

Next tactic:
simp [mkRat, normalize]
@[simp]
theorem divInt_neg_one_one : -1 /. 1 = -1 :=
  show divInt _ _ = _ by
    rw [divInt]
    simp [mkRat, normalize]
    

Proof state:
a b c : ℚ
⊢ mk' (-1) 1 = -1

Next tactic:
rfl
theorem divInt_one (n : ℤ) : n /. 1 = n :=
  show divInt _ _ = _ by
    

Proof state:
a b c : ℚ
n : ℤ
⊢ n /. 1 = ↑n

Next tactic:
rw [divInt]
theorem divInt_one (n : ℤ) : n /. 1 = n :=
  show divInt _ _ = _ by
    rw [divInt]
    

Proof state:
a b c : ℚ
n : ℤ
⊢ (match n, 1 with
    | n, Int.ofNat d => inline (mkRat n d)
    | n, Int.negSucc d => normalize (-n) (Nat.succ d)) =
    ↑n

Next tactic:
simp [mkRat, normalize]
theorem divInt_one (n : ℤ) : n /. 1 = n :=
  show divInt _ _ = _ by
    rw [divInt]
    simp [mkRat, normalize]
    

Proof state:
a b c : ℚ
n : ℤ
⊢ mk' n 1 = ↑n

Next tactic:
rfl
theorem mkRat_one {n : ℤ} : mkRat n 1 = n := by
  

Proof state:
a b c : ℚ
n : ℤ
⊢ mkRat n 1 = ↑n

Next tactic:
simp [Rat.mkRat_eq, Rat.divInt_one]
protected theorem mul_assoc : a * b * c = a * (b * c) :=
  numDenCasesOn' a fun n₁ d₁ h₁ =>
    numDenCasesOn' b fun n₂ d₂ h₂ =>
      numDenCasesOn' c fun n₃ d₃ h₃ => by
        

Proof state:
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
n₃ : ℤ
d₃ : ℕ
h₃ : d₃ ≠ 0
⊢ n₁ /. ↑d₁ * (n₂ /. ↑d₂) * (n₃ /. ↑d₃) = n₁ /. ↑d₁ * (n₂ /. ↑d₂ * (n₃ /. ↑d₃))

Next tactic:
simp [h₁, h₂, h₃, mul_ne_zero, mul_comm, mul_assoc, mul_left_comm]
protected theorem add_mul : (a + b) * c = a * c + b * c :=
  numDenCasesOn' a fun n₁ d₁ h₁ =>
    numDenCasesOn' b fun n₂ d₂ h₂ =>
      numDenCasesOn' c fun n₃ d₃ h₃ => by
        

Proof state:
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
n₃ : ℤ
d₃ : ℕ
h₃ : d₃ ≠ 0
⊢ (n₁ /. ↑d₁ + n₂ /. ↑d₂) * (n₃ /. ↑d₃) = n₁ /. ↑d₁ * (n₃ /. ↑d₃) + n₂ /. ↑d₂ * (n₃ /. ↑d₃)

Next tactic:
simp only [ne_eq, Nat.cast_eq_zero, h₁, not_false_eq_true, h₂, add_def'', mul_eq_zero,
          or_self, h₃, mul_def']
protected theorem add_mul : (a + b) * c = a * c + b * c :=
  numDenCasesOn' a fun n₁ d₁ h₁ =>
    numDenCasesOn' b fun n₂ d₂ h₂ =>
      numDenCasesOn' c fun n₃ d₃ h₃ => by
        simp only [ne_eq, Nat.cast_eq_zero, h₁, not_false_eq_true, h₂, add_def'', mul_eq_zero,
          or_self, h₃, mul_def']
        

Proof state:
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
n₃ : ℤ
d₃ : ℕ
h₃ : d₃ ≠ 0
⊢ (n₁ * ↑d₂ + n₂ * ↑d₁) * n₃ /. (↑d₁ * ↑d₂ * ↑d₃) =
    (n₁ * n₃ * (↑d₂ * ↑d₃) + n₂ * n₃ * (↑d₁ * ↑d₃)) /. (↑d₁ * ↑d₃ * (↑d₂ * ↑d₃))

Next tactic:
rw [← divInt_mul_right (Int.coe_nat_ne_zero.2 h₃), add_mul, add_mul]
protected theorem add_mul : (a + b) * c = a * c + b * c :=
  numDenCasesOn' a fun n₁ d₁ h₁ =>
    numDenCasesOn' b fun n₂ d₂ h₂ =>
      numDenCasesOn' c fun n₃ d₃ h₃ => by
        simp only [ne_eq, Nat.cast_eq_zero, h₁, not_false_eq_true, h₂, add_def'', mul_eq_zero,
          or_self, h₃, mul_def']
        rw [← divInt_mul_right (Int.coe_nat_ne_zero.2 h₃), add_mul, add_mul]
        

Proof state:
a b c : ℚ
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
n₂ : ℤ
d₂ : ℕ
h₂ : d₂ ≠ 0
n₃ : ℤ
d₃ : ℕ
h₃ : d₃ ≠ 0
⊢ (n₁ * ↑d₂ * n₃ * ↑d₃ + n₂ * ↑d₁ * n₃ * ↑d₃) /. (↑d₁ * ↑d₂ * ↑d₃ * ↑d₃) =
    (n₁ * n₃ * (↑d₂ * ↑d₃) + n₂ * n₃ * (↑d₁ * ↑d₃)) /. (↑d₁ * ↑d₃ * (↑d₂ * ↑d₃))

Next tactic:
ac_rfl
protected theorem mul_add : a * (b + c) = a * b + a * c := by
  

Proof state:
a b c : ℚ
⊢ a * (b + c) = a * b + a * c

Next tactic:
rw [Rat.mul_comm, Rat.add_mul, Rat.mul_comm, Rat.mul_comm c a]
protected theorem zero_ne_one : 0 ≠ (1 : ℚ) := by
  

Proof state:
a b c : ℚ
⊢ 0 ≠ 1

Next tactic:
rw [ne_comm, ← divInt_one_one, divInt_ne_zero one_ne_zero]
protected theorem zero_ne_one : 0 ≠ (1 : ℚ) := by
  rw [ne_comm, ← divInt_one_one, divInt_ne_zero one_ne_zero]
  

Proof state:
a b c : ℚ
⊢ 1 ≠ 0

Next tactic:
exact one_ne_zero
protected theorem mul_inv_cancel : a ≠ 0 → a * a⁻¹ = 1 :=
  numDenCasesOn' a fun n d h a0 => by
    

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
a0 : n /. ↑d ≠ 0
⊢ n /. ↑d * (n /. ↑d)⁻¹ = 1

Next tactic:
have n0 : n ≠ 0 := mt (by rintro rfl; simp) a0
protected theorem mul_inv_cancel : a ≠ 0 → a * a⁻¹ = 1 :=
  numDenCasesOn' a fun n d h a0 => by
    have n0 : n ≠ 0 := mt (by 

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
a0 : n /. ↑d ≠ 0
⊢ n = 0 → n /. ↑d = 0

Next tactic:
rintro rfl
protected theorem mul_inv_cancel : a ≠ 0 → a * a⁻¹ = 1 :=
  numDenCasesOn' a fun n d h a0 => by
    have n0 : n ≠ 0 := mt (by rintro rfl; 

Proof state:
a b c : ℚ
d : ℕ
h : d ≠ 0
a0 : 0 /. ↑d ≠ 0
⊢ 0 /. ↑d = 0

Next tactic:
simp
protected theorem mul_inv_cancel : a ≠ 0 → a * a⁻¹ = 1 :=
  numDenCasesOn' a fun n d h a0 => by
    have n0 : n ≠ 0 := mt (by rintro rfl; simp) a0
    

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
a0 : n /. ↑d ≠ 0
n0 : n ≠ 0
⊢ n /. ↑d * (n /. ↑d)⁻¹ = 1

Next tactic:
simpa [h, n0, mul_comm] using @divInt_mul_right 1 1 (n * d) (by simp [h, n0])
protected theorem mul_inv_cancel : a ≠ 0 → a * a⁻¹ = 1 :=
  numDenCasesOn' a fun n d h a0 => by
    have n0 : n ≠ 0 := mt (by rintro rfl; simp) a0
    simpa [h, n0, mul_comm] using @divInt_mul_right 1 1 (n * d) (by 

Proof state:
a b c : ℚ
n : ℤ
d : ℕ
h : d ≠ 0
a0 : n /. ↑d ≠ 0
n0 : n ≠ 0
⊢ n * ↑d ≠ 0

Next tactic:
simp [h, n0]
instance commRing : CommRing ℚ where
  zero := 0
  add := (· + ·)
  neg := Neg.neg
  one := 1
  mul := (· * ·)
  zero_add := Rat.zero_add
  add_zero := Rat.add_zero
  add_comm := Rat.add_comm
  add_assoc := Rat.add_assoc
  add_left_neg := Rat.add_left_neg
  mul_one := Rat.mul_one
  one_mul := Rat.one_mul
  mul_comm := Rat.mul_comm
  mul_assoc := Rat.mul_assoc
  zero_mul := Rat.zero_mul
  mul_zero := Rat.mul_zero
  left_distrib := Rat.mul_add
  right_distrib := Rat.add_mul
  sub_eq_add_neg := Rat.sub_eq_add_neg
  intCast := fun n => n
  natCast n := Int.cast n
  natCast_zero := rfl
  natCast_succ n := by
    

Proof state:
a b c : ℚ
n : ℕ
⊢ NatCast.natCast (n + 1) = NatCast.natCast n + 1

Next tactic:
simp only [coe_int_eq_divInt, add_def'' one_ne_zero one_ne_zero,
      ← divInt_one_one, Nat.cast_add, Nat.cast_one, mul_one]
instance commGroupWithZero : CommGroupWithZero ℚ :=
  { exists_pair_ne := ⟨0, 1, Rat.zero_ne_one⟩
    inv_zero := by
      

Proof state:
a b c : ℚ
⊢ 0⁻¹ = 0

Next tactic:
change Rat.inv 0 = 0
instance commGroupWithZero : CommGroupWithZero ℚ :=
  { exists_pair_ne := ⟨0, 1, Rat.zero_ne_one⟩
    inv_zero := by
      change Rat.inv 0 = 0
      

Proof state:
a b c : ℚ
⊢ Rat.inv 0 = 0

Next tactic:
rw [Rat.inv_def]
instance commGroupWithZero : CommGroupWithZero ℚ :=
  { exists_pair_ne := ⟨0, 1, Rat.zero_ne_one⟩
    inv_zero := by
      change Rat.inv 0 = 0
      rw [Rat.inv_def]
      

Proof state:
a b c : ℚ
⊢ ↑0.den /. 0.num = 0

Next tactic:
rfl
instance nontrivial : Nontrivial ℚ := by 

Proof state:
a b c : ℚ
⊢ Nontrivial ℚ

Next tactic:
infer_instance
instance commSemiring : CommSemiring ℚ := by 

Proof state:
a b c : ℚ
⊢ CommSemiring ℚ

Next tactic:
infer_instance
instance semiring : Semiring ℚ := by 

Proof state:
a b c : ℚ
⊢ Semiring ℚ

Next tactic:
infer_instance
instance addCommGroup : AddCommGroup ℚ := by 

Proof state:
a b c : ℚ
⊢ AddCommGroup ℚ

Next tactic:
infer_instance
instance addGroup : AddGroup ℚ := by 

Proof state:
a b c : ℚ
⊢ AddGroup ℚ

Next tactic:
infer_instance
instance addCommMonoid : AddCommMonoid ℚ := by 

Proof state:
a b c : ℚ
⊢ AddCommMonoid ℚ

Next tactic:
infer_instance
instance addMonoid : AddMonoid ℚ := by 

Proof state:
a b c : ℚ
⊢ AddMonoid ℚ

Next tactic:
infer_instance
instance addLeftCancelSemigroup : AddLeftCancelSemigroup ℚ := by 

Proof state:
a b c : ℚ
⊢ AddLeftCancelSemigroup ℚ

Next tactic:
infer_instance
instance addRightCancelSemigroup : AddRightCancelSemigroup ℚ := by 

Proof state:
a b c : ℚ
⊢ AddRightCancelSemigroup ℚ

Next tactic:
infer_instance
instance addCommSemigroup : AddCommSemigroup ℚ := by 

Proof state:
a b c : ℚ
⊢ AddCommSemigroup ℚ

Next tactic:
infer_instance
instance addSemigroup : AddSemigroup ℚ := by 

Proof state:
a b c : ℚ
⊢ AddSemigroup ℚ

Next tactic:
infer_instance
instance commMonoid : CommMonoid ℚ := by 

Proof state:
a b c : ℚ
⊢ CommMonoid ℚ

Next tactic:
infer_instance
instance monoid : Monoid ℚ := by 

Proof state:
a b c : ℚ
⊢ Monoid ℚ

Next tactic:
infer_instance
instance commSemigroup : CommSemigroup ℚ := by 

Proof state:
a b c : ℚ
⊢ CommSemigroup ℚ

Next tactic:
infer_instance
instance semigroup : Semigroup ℚ := by 

Proof state:
a b c : ℚ
⊢ Semigroup ℚ

Next tactic:
infer_instance
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  

Proof state:
a b c p q : ℚ
⊢ p = q ↔ p.num * ↑q.den = q.num * ↑p.den

Next tactic:
conv =>
    lhs
    rw [← @num_den p, ← @num_den q]
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  conv =>
    

Proof state:
a b c p q : ℚ
| p = q ↔ p.num * ↑q.den = q.num * ↑p.den

Next tactic:
lhs
    rw [← @num_den p, ← @num_den q]
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  conv =>
    

Proof state:
a b c p q : ℚ
| p = q ↔ p.num * ↑q.den = q.num * ↑p.den

Next tactic:
lhs
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  conv =>
    lhs
    

Proof state:
a b c p q : ℚ
| p = q

Next tactic:
rw [← @num_den p, ← @num_den q]
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  conv =>
    lhs
    rw [← @num_den p, ← @num_den q]
  

Proof state:
a b c p q : ℚ
⊢ p.num /. ↑p.den = q.num /. ↑q.den ↔ p.num * ↑q.den = q.num * ↑p.den

Next tactic:
apply Rat.divInt_eq_iff
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  conv =>
    lhs
    rw [← @num_den p, ← @num_den q]
  apply Rat.divInt_eq_iff <;>
    · 

Proof state:
case z₁
a b c p q : ℚ
⊢ ↑p.den ≠ 0

Next tactic:
rw [← Nat.cast_zero, Ne, Int.ofNat_inj]
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  conv =>
    lhs
    rw [← @num_den p, ← @num_den q]
  apply Rat.divInt_eq_iff <;>
    · rw [← Nat.cast_zero, Ne, Int.ofNat_inj]
      

Proof state:
case z₁
a b c p q : ℚ
⊢ ¬p.den = 0

Next tactic:
apply den_nz
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  conv =>
    lhs
    rw [← @num_den p, ← @num_den q]
  apply Rat.divInt_eq_iff <;>
    · 

Proof state:
case z₂
a b c p q : ℚ
⊢ ↑q.den ≠ 0

Next tactic:
rw [← Nat.cast_zero, Ne, Int.ofNat_inj]
theorem eq_iff_mul_eq_mul {p q : ℚ} : p = q ↔ p.num * q.den = q.num * p.den := by
  conv =>
    lhs
    rw [← @num_den p, ← @num_den q]
  apply Rat.divInt_eq_iff <;>
    · rw [← Nat.cast_zero, Ne, Int.ofNat_inj]
      

Proof state:
case z₂
a b c p q : ℚ
⊢ ¬q.den = 0

Next tactic:
apply den_nz