l3lab/ntp-mathlib huggingface dataset:
private theorem add'_comm (r₁ r₂ : R) (s₁ s₂ : S) :
    add' r₁ s₁ (r₂ /ₒ s₂) = add' r₂ s₂ (r₁ /ₒ s₁) := by
  -- Porting note: `assoc_rw` & `noncomm_ring` were not ported yet
  -- Porting note: `Quotient.mk'` required
  simp only [add', oreDiv, add'', Quotient.mk', Quotient.lift_mk]
  -- Porting note: `Quotient.eq` should be used in `rw` instead of `simp`
  rw [Quotient.eq]
  have hb := ore_eq (↑s₂) s₁
  -- Porting note: `set ... with h; rw [← h]; clear h`s aren't required anymore
  set rb := oreNum (↑s₂) s₁
  set sb := oreDenom (↑s₂) s₁
  have ha := ore_eq (↑s₁) s₂
  set ra := oreNum (↑s₁) s₂
  set sa := oreDenom (↑s₁) s₂
  rcases oreCondition ra sb with ⟨rc, sc, hc⟩
  -- r#, s#
  have : (s₁ : R) * (rb * rc) = s₁ * (sa * sc) := by
    rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← ha, mul_assoc]
  rcases ore_left_cancel _ _ s₁ this with ⟨sd, hd⟩
  -- s+
  use sc * sd
  use rc * sd
  dsimp
  

Proof state:
case h
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : ↥S
rb : R := oreNum (↑s₂) s₁
sb : ↥S := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : ↥S := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : ↥S
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : ↥S
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂) * (↑sc * ↑sd) =
      (r₂ * ↑(oreDenom (↑s₂) s₁) + r₁ * oreNum (↑s₂) s₁) * (rc * ↑sd) ∧
    ↑s₁ * ↑(oreDenom (↑s₁) s₂) * (↑sc * ↑sd) = ↑s₂ * ↑(oreDenom (↑s₂) s₁) * (rc * ↑sd)

Next tactic:
constructor
private theorem add'_comm (r₁ r₂ : R) (s₁ s₂ : S) :
    add' r₁ s₁ (r₂ /ₒ s₂) = add' r₂ s₂ (r₁ /ₒ s₁) := by
  -- Porting note: `assoc_rw` & `noncomm_ring` were not ported yet
  -- Porting note: `Quotient.mk'` required
  simp only [add', oreDiv, add'', Quotient.mk', Quotient.lift_mk]
  -- Porting note: `Quotient.eq` should be used in `rw` instead of `simp`
  rw [Quotient.eq]
  have hb := ore_eq (↑s₂) s₁
  -- Porting note: `set ... with h; rw [← h]; clear h`s aren't required anymore
  set rb := oreNum (↑s₂) s₁
  set sb := oreDenom (↑s₂) s₁
  have ha := ore_eq (↑s₁) s₂
  set ra := oreNum (↑s₁) s₂
  set sa := oreDenom (↑s₁) s₂
  rcases oreCondition ra sb with ⟨rc, sc, hc⟩
  -- r#, s#
  have : (s₁ : R) * (rb * rc) = s₁ * (sa * sc) := by
    rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← ha, mul_assoc]
  rcases ore_left_cancel _ _ s₁ this with ⟨sd, hd⟩
  -- s+
  use sc * sd
  use rc * sd
  dsimp
  constructor
  · 

Proof state:
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : ↥S
rb : R := oreNum (↑s₂) s₁
sb : ↥S := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : ↥S := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : ↥S
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : ↥S
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂) * (↑sc * ↑sd) =
    (r₂ * ↑(oreDenom (↑s₂) s₁) + r₁ * oreNum (↑s₂) s₁) * (rc * ↑sd)

Next tactic:
rw [add_mul, add_mul, add_comm, mul_assoc (a := r₁) (b := (sa : R)),
      ← mul_assoc (a := (sa : R)), ← hd, mul_assoc (a := r₂) (b := ra),
      ← mul_assoc (a := ra) (b := (sc : R)), hc]
private theorem add'_comm (r₁ r₂ : R) (s₁ s₂ : S) :
    add' r₁ s₁ (r₂ /ₒ s₂) = add' r₂ s₂ (r₁ /ₒ s₁) := by
  -- Porting note: `assoc_rw` & `noncomm_ring` were not ported yet
  -- Porting note: `Quotient.mk'` required
  simp only [add', oreDiv, add'', Quotient.mk', Quotient.lift_mk]
  -- Porting note: `Quotient.eq` should be used in `rw` instead of `simp`
  rw [Quotient.eq]
  have hb := ore_eq (↑s₂) s₁
  -- Porting note: `set ... with h; rw [← h]; clear h`s aren't required anymore
  set rb := oreNum (↑s₂) s₁
  set sb := oreDenom (↑s₂) s₁
  have ha := ore_eq (↑s₁) s₂
  set ra := oreNum (↑s₁) s₂
  set sa := oreDenom (↑s₁) s₂
  rcases oreCondition ra sb with ⟨rc, sc, hc⟩
  -- r#, s#
  have : (s₁ : R) * (rb * rc) = s₁ * (sa * sc) := by
    rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← ha, mul_assoc]
  rcases ore_left_cancel _ _ s₁ this with ⟨sd, hd⟩
  -- s+
  use sc * sd
  use rc * sd
  dsimp
  constructor
  · rw [add_mul, add_mul, add_comm, mul_assoc (a := r₁) (b := (sa : R)),
      ← mul_assoc (a := (sa : R)), ← hd, mul_assoc (a := r₂) (b := ra),
      ← mul_assoc (a := ra) (b := (sc : R)), hc]
    

Proof state:
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : ↥S
rb : R := oreNum (↑s₂) s₁
sb : ↥S := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : ↥S := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : ↥S
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : ↥S
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ r₂ * (↑sb * rc * ↑sd) + r₁ * (rb * rc * ↑sd) =
    r₂ * ↑(oreDenom (↑s₂) s₁) * (rc * ↑sd) + r₁ * oreNum (↑s₂) s₁ * (rc * ↑sd)

Next tactic:
simp only [mul_assoc]
private theorem add'_comm (r₁ r₂ : R) (s₁ s₂ : S) :
    add' r₁ s₁ (r₂ /ₒ s₂) = add' r₂ s₂ (r₁ /ₒ s₁) := by
  -- Porting note: `assoc_rw` & `noncomm_ring` were not ported yet
  -- Porting note: `Quotient.mk'` required
  simp only [add', oreDiv, add'', Quotient.mk', Quotient.lift_mk]
  -- Porting note: `Quotient.eq` should be used in `rw` instead of `simp`
  rw [Quotient.eq]
  have hb := ore_eq (↑s₂) s₁
  -- Porting note: `set ... with h; rw [← h]; clear h`s aren't required anymore
  set rb := oreNum (↑s₂) s₁
  set sb := oreDenom (↑s₂) s₁
  have ha := ore_eq (↑s₁) s₂
  set ra := oreNum (↑s₁) s₂
  set sa := oreDenom (↑s₁) s₂
  rcases oreCondition ra sb with ⟨rc, sc, hc⟩
  -- r#, s#
  have : (s₁ : R) * (rb * rc) = s₁ * (sa * sc) := by
    rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← ha, mul_assoc]
  rcases ore_left_cancel _ _ s₁ this with ⟨sd, hd⟩
  -- s+
  use sc * sd
  use rc * sd
  dsimp
  constructor
  · rw [add_mul, add_mul, add_comm, mul_assoc (a := r₁) (b := (sa : R)),
      ← mul_assoc (a := (sa : R)), ← hd, mul_assoc (a := r₂) (b := ra),
      ← mul_assoc (a := ra) (b := (sc : R)), hc]
    simp only [mul_assoc]
  · 

Proof state:
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : ↥S
rb : R := oreNum (↑s₂) s₁
sb : ↥S := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : ↥S := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : ↥S
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : ↥S
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ ↑s₁ * ↑(oreDenom (↑s₁) s₂) * (↑sc * ↑sd) = ↑s₂ * ↑(oreDenom (↑s₂) s₁) * (rc * ↑sd)

Next tactic:
rw [mul_assoc, ← mul_assoc (sa : R), ← hd, hb]
private theorem add'_comm (r₁ r₂ : R) (s₁ s₂ : S) :
    add' r₁ s₁ (r₂ /ₒ s₂) = add' r₂ s₂ (r₁ /ₒ s₁) := by
  -- Porting note: `assoc_rw` & `noncomm_ring` were not ported yet
  -- Porting note: `Quotient.mk'` required
  simp only [add', oreDiv, add'', Quotient.mk', Quotient.lift_mk]
  -- Porting note: `Quotient.eq` should be used in `rw` instead of `simp`
  rw [Quotient.eq]
  have hb := ore_eq (↑s₂) s₁
  -- Porting note: `set ... with h; rw [← h]; clear h`s aren't required anymore
  set rb := oreNum (↑s₂) s₁
  set sb := oreDenom (↑s₂) s₁
  have ha := ore_eq (↑s₁) s₂
  set ra := oreNum (↑s₁) s₂
  set sa := oreDenom (↑s₁) s₂
  rcases oreCondition ra sb with ⟨rc, sc, hc⟩
  -- r#, s#
  have : (s₁ : R) * (rb * rc) = s₁ * (sa * sc) := by
    rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← ha, mul_assoc]
  rcases ore_left_cancel _ _ s₁ this with ⟨sd, hd⟩
  -- s+
  use sc * sd
  use rc * sd
  dsimp
  constructor
  · rw [add_mul, add_mul, add_comm, mul_assoc (a := r₁) (b := (sa : R)),
      ← mul_assoc (a := (sa : R)), ← hd, mul_assoc (a := r₂) (b := ra),
      ← mul_assoc (a := ra) (b := (sc : R)), hc]
    simp only [mul_assoc]
  · rw [mul_assoc, ← mul_assoc (sa : R), ← hd, hb]
    

Proof state:
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : ↥S
rb : R := oreNum (↑s₂) s₁
sb : ↥S := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : ↥S := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : ↥S
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : ↥S
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ ↑s₁ * (rb * rc * ↑sd) = ↑s₁ * rb * (rc * ↑sd)

Next tactic:
simp only [mul_assoc]
/-- The addition on the Ore localization. -/
private def add : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] := fun x =>
  Quotient.lift (fun rs : R × S => add' rs.1 rs.2 x)
    (by
      

Proof state:
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
⊢ ∀ (a b : R × ↥S),
    a ≈ b → (fun rs => OreLocalization.add' rs.1 rs.2 x) a = (fun rs => OreLocalization.add' rs.1 rs.2 x) b

Next tactic:
rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ hyz
/-- The addition on the Ore localization. -/
private def add : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] := fun x =>
  Quotient.lift (fun rs : R × S => add' rs.1 rs.2 x)
    (by
      rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ hyz
      

Proof state:
case mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
hyz : (r₁, s₁) ≈ (r₂, s₂)
⊢ (fun rs => OreLocalization.add' rs.1 rs.2 x) (r₁, s₁) = (fun rs => OreLocalization.add' rs.1 rs.2 x) (r₂, s₂)

Next tactic:
induction' x using OreLocalization.ind with r₃ s₃
/-- The addition on the Ore localization. -/
private def add : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] := fun x =>
  Quotient.lift (fun rs : R × S => add' rs.1 rs.2 x)
    (by
      rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ hyz
      induction' x using OreLocalization.ind with r₃ s₃
      

Proof state:
case mk.mk.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
hyz : (r₁, s₁) ≈ (r₂, s₂)
r₃ : R
s₃ : ↥S
⊢ (fun rs => OreLocalization.add' rs.1 rs.2 (r₃ /ₒ s₃)) (r₁, s₁) =
    (fun rs => OreLocalization.add' rs.1 rs.2 (r₃ /ₒ s₃)) (r₂, s₂)

Next tactic:
dsimp
/-- The addition on the Ore localization. -/
private def add : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] := fun x =>
  Quotient.lift (fun rs : R × S => add' rs.1 rs.2 x)
    (by
      rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ hyz
      induction' x using OreLocalization.ind with r₃ s₃
      dsimp; 

Proof state:
case mk.mk.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
hyz : (r₁, s₁) ≈ (r₂, s₂)
r₃ : R
s₃ : ↥S
⊢ OreLocalization.add' r₁ s₁ (r₃ /ₒ s₃) = OreLocalization.add' r₂ s₂ (r₃ /ₒ s₃)

Next tactic:
rw [add'_comm, add'_comm r₂]
/-- The addition on the Ore localization. -/
private def add : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] := fun x =>
  Quotient.lift (fun rs : R × S => add' rs.1 rs.2 x)
    (by
      rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ hyz
      induction' x using OreLocalization.ind with r₃ s₃
      dsimp; rw [add'_comm, add'_comm r₂]
      -- Porting note: `Quotient.mk'` required
      

Proof state:
case mk.mk.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
hyz : (r₁, s₁) ≈ (r₂, s₂)
r₃ : R
s₃ : ↥S
⊢ OreLocalization.add' r₃ s₃ (r₁ /ₒ s₁) = OreLocalization.add' r₃ s₃ (r₂ /ₒ s₂)

Next tactic:
simp [(· /ₒ ·), Quotient.mk', Quotient.sound hyz]
@[simp]
theorem add_oreDiv {r r' : R} {s : S} : r /ₒ s + r' /ₒ s = (r + r') /ₒ s := by
  

Proof state:
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r r' : R
s : ↥S
⊢ r /ₒ s + r' /ₒ s = (r + r') /ₒ s

Next tactic:
simp [oreDiv_add_char s s 1 1 (by simp)]
@[simp]
theorem add_oreDiv {r r' : R} {s : S} : r /ₒ s + r' /ₒ s = (r + r') /ₒ s := by
  simp [oreDiv_add_char s s 1 1 (by 

Proof state:
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r r' : R
s : ↥S
⊢ ↑s * ↑1 = ↑s * 1

Next tactic:
simp
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  

Proof state:
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x y z : OreLocalization R S
⊢ x + y + z = x + (y + z)

Next tactic:
induction' x using OreLocalization.ind with r₁ s₁
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  

Proof state:
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
y z : OreLocalization R S
r₁ : R
s₁ : ↥S
⊢ r₁ /ₒ s₁ + y + z = r₁ /ₒ s₁ + (y + z)

Next tactic:
induction' y using OreLocalization.ind with r₂ s₂
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  

Proof state:
case c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
z : OreLocalization R S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
⊢ r₁ /ₒ s₁ + r₂ /ₒ s₂ + z = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + z)

Next tactic:
induction' z using OreLocalization.ind with r₃ s₃
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  

Proof state:
case c.c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
⊢ r₁ /ₒ s₁ + r₂ /ₒ s₂ + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + r₃ /ₒ s₃)

Next tactic:
rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; 

Proof state:
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
ha' : r₁ /ₒ s₁ + r₂ /ₒ s₂ = (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa)
⊢ r₁ /ₒ s₁ + r₂ /ₒ s₂ + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + r₃ /ₒ s₃)

Next tactic:
rw [ha']
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; 

Proof state:
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
ha' : r₁ /ₒ s₁ + r₂ /ₒ s₂ = (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa)
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + r₃ /ₒ s₃)

Next tactic:
clear ha'
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  

Proof state:
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + r₃ /ₒ s₃)

Next tactic:
rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩; 

Proof state:
case c.c.c.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : ↥S
hb : ↑s₂ * ↑sb = ↑s₃ * rb
hb' : r₂ /ₒ s₂ + r₃ /ₒ s₃ = (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + r₃ /ₒ s₃)

Next tactic:
rw [hb']
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩; rw [hb']; 

Proof state:
case c.c.c.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : ↥S
hb : ↑s₂ * ↑sb = ↑s₃ * rb
hb' : r₂ /ₒ s₂ + r₃ /ₒ s₃ = (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)

Next tactic:
clear hb'
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩; rw [hb']; clear hb'
  

Proof state:
case c.c.c.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : ↥S
hb : ↑s₂ * ↑sb = ↑s₃ * rb
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)

Next tactic:
rcases oreDivAddChar' (r₁ * sa + r₂ * ra) r₃ (s₁ * sa) s₃ with ⟨rc, sc, hc, q⟩
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩; rw [hb']; clear hb'
  rcases oreDivAddChar' (r₁ * sa + r₂ * ra) r₃ (s₁ * sa) s₃ with ⟨rc, sc, hc, q⟩; 

Proof state:
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : ↥S
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : ↥S
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
q : (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = ((r₁ * ↑sa + r₂ * ra) * ↑sc + r₃ * rc) /ₒ (s₁ * sa * sc)
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)

Next tactic:
rw [q]
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩; rw [hb']; clear hb'
  rcases oreDivAddChar' (r₁ * sa + r₂ * ra) r₃ (s₁ * sa) s₃ with ⟨rc, sc, hc, q⟩; rw [q]; 

Proof state:
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : ↥S
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : ↥S
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
q : (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = ((r₁ * ↑sa + r₂ * ra) * ↑sc + r₃ * rc) /ₒ (s₁ * sa * sc)
⊢ ((r₁ * ↑sa + r₂ * ra) * ↑sc + r₃ * rc) /ₒ (s₁ * sa * sc) = r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)

Next tactic:
clear q
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩; rw [hb']; clear hb'
  rcases oreDivAddChar' (r₁ * sa + r₂ * ra) r₃ (s₁ * sa) s₃ with ⟨rc, sc, hc, q⟩; rw [q]; clear q
  

Proof state:
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : ↥S
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : ↥S
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
⊢ ((r₁ * ↑sa + r₂ * ra) * ↑sc + r₃ * rc) /ₒ (s₁ * sa * sc) = r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)

Next tactic:
rcases oreDivAddChar' r₁ (r₂ * sb + r₃ * rb) s₁ (s₂ * sb) with ⟨rd, sd, hd, q⟩
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩; rw [hb']; clear hb'
  rcases oreDivAddChar' (r₁ * sa + r₂ * ra) r₃ (s₁ * sa) s₃ with ⟨rc, sc, hc, q⟩; rw [q]; clear q
  rcases oreDivAddChar' r₁ (r₂ * sb + r₃ * rb) s₁ (s₂ * sb) with ⟨rd, sd, hd, q⟩; 

Proof state:
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : ↥S
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : ↥S
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : ↥S
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
q : r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb) = (r₁ * ↑sd + (r₂ * ↑sb + r₃ * rb) * rd) /ₒ (s₁ * sd)
⊢ ((r₁ * ↑sa + r₂ * ra) * ↑sc + r₃ * rc) /ₒ (s₁ * sa * sc) = r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)

Next tactic:
rw [q]
protected theorem add_assoc (x y z : R[S⁻¹]) : x + y + z = x + (y + z) := by
  -- Porting note: `assoc_rw` was not ported yet
  induction' x using OreLocalization.ind with r₁ s₁
  induction' y using OreLocalization.ind with r₂ s₂
  induction' z using OreLocalization.ind with r₃ s₃
  rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩; rw [ha']; clear ha'
  rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩; rw [hb']; clear hb'
  rcases oreDivAddChar' (r₁ * sa + r₂ * ra) r₃ (s₁ * sa) s₃ with ⟨rc, sc, hc, q⟩; rw [q]; clear q
  rcases oreDivAddChar' r₁ (r₂ * sb + r₃ * rb) s₁ (s₂ * sb) with ⟨rd, sd, hd, q⟩; rw [q]; 

Proof state:
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ : ↥S
ra : R
sa : ↥S
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : ↥S
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : ↥S
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : ↥S
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
q : r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb) = (r₁ * ↑sd + (r₂ * ↑sb + r₃ * rb) * rd) /ₒ (s₁ * sd)
⊢ ((r₁ * ↑sa + r₂ * ra) * ↑sc + r₃ * rc) /ₒ (s₁ * sa * sc) = (r₁ * ↑sd + (r₂ * ↑sb + r₃ * rb) * rd) /ₒ (s₁ * sd)

Next tactic:
clear q