l3lab/ntp-mathlib huggingface dataset:
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
r' : R
s' u : ↥S
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : ↥S
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : ↥S
h₂ : r₂ * ↑s₃ = ↑u * r₃
⊢ ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)

Next tactic:
rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      

Proof state:
case refine_1.mk.mk.intro.intro.intro.mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
r' : R
s' u : ↥S
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : ↥S
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : ↥S
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
⊢ ∃ u v, r * ↑u = r' * v ∧ ↑s * ↑u = ↑s' * v

Next tactic:
rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      

Proof state:
case refine_1.mk.mk.intro.intro.intro.mk.mk.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
r' : R
s' u : ↥S
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : ↥S
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : ↥S
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : ↥S
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ ∃ u v, r * ↑u = r' * v ∧ ↑s * ↑u = ↑s' * v

Next tactic:
refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> 

Proof state:
case refine_1.mk.mk.intro.intro.intro.mk.mk.mk.mk.intro.refine_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
r' : R
s' u : ↥S
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : ↥S
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : ↥S
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : ↥S
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ r * ↑(s₂ * s₃ * w) = r' * (↑u * r₃ * ↑w)

Next tactic:
simp only [Submonoid.coe_mul, ← hw]
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> 

Proof state:
case refine_1.mk.mk.intro.intro.intro.mk.mk.mk.mk.intro.refine_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
r' : R
s' u : ↥S
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : ↥S
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : ↥S
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : ↥S
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ ↑s * ↑(s₂ * s₃ * w) = ↑s' * (↑u * r₃ * ↑w)

Next tactic:
simp only [Submonoid.coe_mul, ← hw]
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · 

Proof state:
case refine_1.mk.mk.intro.intro.intro.mk.mk.mk.mk.intro.refine_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
r' : R
s' u : ↥S
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : ↥S
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : ↥S
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : ↥S
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ r * (v * r₃ * ↑w) = r' * (↑u * r₃ * ↑w)

Next tactic:
simp only [← mul_assoc, hru]
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · 

Proof state:
case refine_1.mk.mk.intro.intro.intro.mk.mk.mk.mk.intro.refine_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
r' : R
s' u : ↥S
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : ↥S
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : ↥S
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : ↥S
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ ↑s * (v * r₃ * ↑w) = ↑s' * (↑u * r₃ * ↑w)

Next tactic:
simp only [← mul_assoc, hsu]
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · simp only [← mul_assoc, hsu]
    · 

Proof state:
case refine_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
⊢ ∀ {x y z : R × ↥S},
    (∃ u v, y.1 * ↑u = x.1 * v ∧ ↑y.2 * ↑u = ↑x.2 * v) →
      (∃ u v, z.1 * ↑u = y.1 * v ∧ ↑z.2 * ↑u = ↑y.2 * v) → ∃ u v, z.1 * ↑u = x.1 * v ∧ ↑z.2 * ↑u = ↑x.2 * v

Next tactic:
rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · simp only [← mul_assoc, hsu]
    · rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
      

Proof state:
case refine_2.mk.mk.mk.intro.intro.intro.intro.intro.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ u : ↥S
v : R
hur₁ : (r₂, s₂).1 * ↑u = (r₁, s₁).1 * v
hs₁u : ↑(r₂, s₂).2 * ↑u = ↑(r₁, s₁).2 * v
u' : ↥S
v' : R
hur₂ : (r₃, s₃).1 * ↑u' = (r₂, s₂).1 * v'
hs₂u : ↑(r₃, s₃).2 * ↑u' = ↑(r₂, s₂).2 * v'
⊢ ∃ u v, (r₃, s₃).1 * ↑u = (r₁, s₁).1 * v ∧ ↑(r₃, s₃).2 * ↑u = ↑(r₁, s₁).2 * v

Next tactic:
rcases oreCondition v' u with ⟨r', s', h⟩
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · simp only [← mul_assoc, hsu]
    · rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
      rcases oreCondition v' u with ⟨r', s', h⟩; 

Proof state:
case refine_2.mk.mk.mk.intro.intro.intro.intro.intro.intro.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ u : ↥S
v : R
hur₁ : (r₂, s₂).1 * ↑u = (r₁, s₁).1 * v
hs₁u : ↑(r₂, s₂).2 * ↑u = ↑(r₁, s₁).2 * v
u' : ↥S
v' : R
hur₂ : (r₃, s₃).1 * ↑u' = (r₂, s₂).1 * v'
hs₂u : ↑(r₃, s₃).2 * ↑u' = ↑(r₂, s₂).2 * v'
r' : R
s' : ↥S
h : v' * ↑s' = ↑u * r'
⊢ ∃ u v, (r₃, s₃).1 * ↑u = (r₁, s₁).1 * v ∧ ↑(r₃, s₃).2 * ↑u = ↑(r₁, s₁).2 * v

Next tactic:
dsimp only at *
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · simp only [← mul_assoc, hsu]
    · rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
      rcases oreCondition v' u with ⟨r', s', h⟩; dsimp only at *
      

Proof state:
case refine_2.mk.mk.mk.intro.intro.intro.intro.intro.intro.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ u : ↥S
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : ↥S
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : ↥S
h : v' * ↑s' = ↑u * r'
⊢ ∃ u v, r₃ * ↑u = r₁ * v ∧ ↑s₃ * ↑u = ↑s₁ * v

Next tactic:
refine ⟨u' * s', v * r', ?_, ?_⟩
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · simp only [← mul_assoc, hsu]
    · rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
      rcases oreCondition v' u with ⟨r', s', h⟩; dsimp only at *
      refine ⟨u' * s', v * r', ?_, ?_⟩ <;> 

Proof state:
case refine_2.mk.mk.mk.intro.intro.intro.intro.intro.intro.mk.mk.refine_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ u : ↥S
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : ↥S
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : ↥S
h : v' * ↑s' = ↑u * r'
⊢ r₃ * ↑(u' * s') = r₁ * (v * r')

Next tactic:
simp only [Submonoid.coe_mul, ← mul_assoc]
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · simp only [← mul_assoc, hsu]
    · rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
      rcases oreCondition v' u with ⟨r', s', h⟩; dsimp only at *
      refine ⟨u' * s', v * r', ?_, ?_⟩ <;> 

Proof state:
case refine_2.mk.mk.mk.intro.intro.intro.intro.intro.intro.mk.mk.refine_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ u : ↥S
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : ↥S
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : ↥S
h : v' * ↑s' = ↑u * r'
⊢ ↑s₃ * ↑(u' * s') = ↑s₁ * (v * r')

Next tactic:
simp only [Submonoid.coe_mul, ← mul_assoc]
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · simp only [← mul_assoc, hsu]
    · rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
      rcases oreCondition v' u with ⟨r', s', h⟩; dsimp only at *
      refine ⟨u' * s', v * r', ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← mul_assoc]
      · 

Proof state:
case refine_2.mk.mk.mk.intro.intro.intro.intro.intro.intro.mk.mk.refine_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ u : ↥S
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : ↥S
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : ↥S
h : v' * ↑s' = ↑u * r'
⊢ r₃ * ↑u' * ↑s' = r₁ * v * r'

Next tactic:
rw [hur₂, mul_assoc, h, ← mul_assoc, hur₁]
/-- The setoid on `R × S` used for the Ore localization. -/
def oreEqv : Setoid (R × S) where
  r rs rs' := ∃ (u : S) (v : R), rs'.1 * u = rs.1 * v ∧ (rs'.2 : R) * u = rs.2 * v
  iseqv := by
    refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
    · rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩; dsimp only at *
      rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
      rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
      have : (s : R) * ((v : R) * r₃) = (s : R) * (s₂ * s₃) := by
        -- porting note: the proof used `assoc_rw`
        rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
      rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
      refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← hw]
      · simp only [← mul_assoc, hru]
      · simp only [← mul_assoc, hsu]
    · rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
      rcases oreCondition v' u with ⟨r', s', h⟩; dsimp only at *
      refine ⟨u' * s', v * r', ?_, ?_⟩ <;> simp only [Submonoid.coe_mul, ← mul_assoc]
      · rw [hur₂, mul_assoc, h, ← mul_assoc, hur₁]
      · 

Proof state:
case refine_2.mk.mk.mk.intro.intro.intro.intro.intro.intro.mk.mk.refine_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : ↥S
r₂ : R
s₂ : ↥S
r₃ : R
s₃ u : ↥S
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : ↥S
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : ↥S
h : v' * ↑s' = ↑u * r'
⊢ ↑s₃ * ↑u' * ↑s' = ↑s₁ * v * r'

Next tactic:
rw [hs₂u, mul_assoc, h, ← mul_assoc, hs₁u]
@[elab_as_elim]
protected theorem ind {β : R[S⁻¹] → Prop} (c : ∀ (r : R) (s : S), β (r /ₒ s)) : ∀ q, β q := by
  

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
β : OreLocalization R S → Prop
c : ∀ (r : R) (s : ↥S), β (r /ₒ s)
⊢ ∀ (q : OreLocalization R S), β q

Next tactic:
apply Quotient.ind
@[elab_as_elim]
protected theorem ind {β : R[S⁻¹] → Prop} (c : ∀ (r : R) (s : S), β (r /ₒ s)) : ∀ q, β q := by
  apply Quotient.ind
  

Proof state:
case a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
β : OreLocalization R S → Prop
c : ∀ (r : R) (s : ↥S), β (r /ₒ s)
⊢ ∀ (a : R × ↥S), β ⟦a⟧

Next tactic:
rintro ⟨r, s⟩
@[elab_as_elim]
protected theorem ind {β : R[S⁻¹] → Prop} (c : ∀ (r : R) (s : S), β (r /ₒ s)) : ∀ q, β q := by
  apply Quotient.ind
  rintro ⟨r, s⟩
  

Proof state:
case a.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
β : OreLocalization R S → Prop
c : ∀ (r : R) (s : ↥S), β (r /ₒ s)
r : R
s : ↥S
⊢ β ⟦(r, s)⟧

Next tactic:
exact c r s
/-- A fraction `r /ₒ s` is equal to its expansion by an arbitrary factor `t` if `s * t ∈ S`. -/
protected theorem expand (r : R) (s : S) (t : R) (hst : (s : R) * t ∈ S) :
    r /ₒ s = r * t /ₒ ⟨s * t, hst⟩ := by
  

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
t : R
hst : ↑s * t ∈ S
⊢ r /ₒ s = r * t /ₒ { val := ↑s * t, property := hst }

Next tactic:
apply Quotient.sound
/-- A fraction `r /ₒ s` is equal to its expansion by an arbitrary factor `t` if `s * t ∈ S`. -/
protected theorem expand (r : R) (s : S) (t : R) (hst : (s : R) * t ∈ S) :
    r /ₒ s = r * t /ₒ ⟨s * t, hst⟩ := by
  apply Quotient.sound
  

Proof state:
case a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
t : R
hst : ↑s * t ∈ S
⊢ (r, s) ≈ (r * t, { val := ↑s * t, property := hst })

Next tactic:
refine' ⟨s, t * s, _, _⟩
/-- A fraction `r /ₒ s` is equal to its expansion by an arbitrary factor `t` if `s * t ∈ S`. -/
protected theorem expand (r : R) (s : S) (t : R) (hst : (s : R) * t ∈ S) :
    r /ₒ s = r * t /ₒ ⟨s * t, hst⟩ := by
  apply Quotient.sound
  refine' ⟨s, t * s, _, _⟩ <;> 

Proof state:
case a.refine'_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
t : R
hst : ↑s * t ∈ S
⊢ (r * t, { val := ↑s * t, property := hst }).1 * ↑s = (r, s).1 * (t * ↑s)

Next tactic:
dsimp
/-- A fraction `r /ₒ s` is equal to its expansion by an arbitrary factor `t` if `s * t ∈ S`. -/
protected theorem expand (r : R) (s : S) (t : R) (hst : (s : R) * t ∈ S) :
    r /ₒ s = r * t /ₒ ⟨s * t, hst⟩ := by
  apply Quotient.sound
  refine' ⟨s, t * s, _, _⟩ <;> 

Proof state:
case a.refine'_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
t : R
hst : ↑s * t ∈ S
⊢ ↑(r * t, { val := ↑s * t, property := hst }).2 * ↑s = ↑(r, s).2 * (t * ↑s)

Next tactic:
dsimp
/-- A fraction `r /ₒ s` is equal to its expansion by an arbitrary factor `t` if `s * t ∈ S`. -/
protected theorem expand (r : R) (s : S) (t : R) (hst : (s : R) * t ∈ S) :
    r /ₒ s = r * t /ₒ ⟨s * t, hst⟩ := by
  apply Quotient.sound
  refine' ⟨s, t * s, _, _⟩ <;> dsimp <;> 

Proof state:
case a.refine'_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
t : R
hst : ↑s * t ∈ S
⊢ r * t * ↑s = r * (t * ↑s)

Next tactic:
rw [mul_assoc]
/-- A fraction `r /ₒ s` is equal to its expansion by an arbitrary factor `t` if `s * t ∈ S`. -/
protected theorem expand (r : R) (s : S) (t : R) (hst : (s : R) * t ∈ S) :
    r /ₒ s = r * t /ₒ ⟨s * t, hst⟩ := by
  apply Quotient.sound
  refine' ⟨s, t * s, _, _⟩ <;> dsimp <;> 

Proof state:
case a.refine'_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : ↥S
t : R
hst : ↑s * t ∈ S
⊢ ↑s * t * ↑s = ↑s * (t * ↑s)

Next tactic:
rw [mul_assoc]
/-- A fraction is equal to its expansion by a factor from s. -/
protected theorem expand' (r : R) (s s' : S) : r /ₒ s = r * s' /ₒ (s * s') :=
  OreLocalization.expand r s s' (by 

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s s' : ↥S
⊢ ↑s * ↑s' ∈ S

Next tactic:
norm_cast
/-- A fraction is equal to its expansion by a factor from s. -/
protected theorem expand' (r : R) (s s' : S) : r /ₒ s = r * s' /ₒ (s * s') :=
  OreLocalization.expand r s s' (by norm_cast; 

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s s' : ↥S
⊢ ↑(s * s') ∈ S

Next tactic:
apply SetLike.coe_mem