l3lab/ntp-mathlib huggingface dataset:
private theorem mul'_char (r₁ r₂ : R) (s₁ s₂ : S) (u : S) (v : R) (huv : r₂ * (u : R) = s₁ * v) :
    OreLocalization.mul' r₁ s₁ r₂ s₂ = r₁ * v /ₒ (s₂ * u) := by
  -- Porting note: `assoc_rw` was not ported yet
  simp only [mul']
  have h₀ := ore_eq r₂ s₁; set v₀ := oreNum r₂ s₁; set u₀ := oreDenom r₂ s₁
  rcases oreCondition (u₀ : R) u with ⟨r₃, s₃, h₃⟩
  have :=
    calc
      (s₁ : R) * (v * r₃) = r₂ * u * r₃ := by rw [← mul_assoc, ← huv]
      _ = r₂ * u₀ * s₃ := by rw [mul_assoc, mul_assoc, h₃]
      _ = s₁ * (v₀ * s₃) := by rw [← mul_assoc, h₀]
  rcases ore_left_cancel _ _ _ this with ⟨s₄, hs₄⟩
  symm; rw [oreDiv_eq_iff]
  use s₃ * s₄; use r₃ * s₄; simp only [Submonoid.coe_mul]; constructor
  · rw [mul_assoc (b := v₀), ← mul_assoc (a := v₀), ← hs₄]
    simp only [mul_assoc]
  · rw [mul_assoc (b := (u₀ : R)), ← mul_assoc (a := (u₀ : R)), h₃]
    

Proof state:
case h.right
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : ↥S
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : ↥S := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : ↥S
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : ↥S
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ ↑s₂ * (↑u * r₃ * ↑s₄) = ↑s₂ * ↑u * (r₃ * ↑s₄)

Next tactic:
simp only [mul_assoc]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
have h₁ := ore_eq r₁ s₂
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
h₁ : r₁ * ↑(oreDenom r₁ s₂) = ↑s₂ * oreNum r₁ s₂
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
set r₁' := oreNum r₁ s₂
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
h₁ : r₁ * ↑(oreDenom r₁ s₂) = ↑s₂ * r₁'
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
set s₂' := oreDenom r₁ s₂
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    

Proof state:
case mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * r₁' * ↑s_star = ↑{ val := ↑s₂ * p, property := hp } * p'
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
dsimp at h₂
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    

Proof state:
case mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    

Proof state:
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(s₂' * s_star) * p_flat
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
simp only [S.coe_mul] at h₃
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    

Proof state:
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ r₁ * r * ↑s_flat = ↑s₂ * p * (p' * p_flat)

Next tactic:
rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ r₁ * (↑(oreDenom r₁ s₂) * ↑s_star * p_flat) = r₁ * ↑s₂' * ↑s_star * p_flat

Next tactic:
simp only [mul_assoc]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    

Proof state:
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
this : r₁ * r * ↑s_flat = ↑s₂ * p * (p' * p_flat)
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    OreLocalization.mul' (r₂ * p) { val := ↑s₂ * p, property := hp } (r₁ * r) { val := ↑s₁ * r, property := hr }

Next tactic:
rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    

Proof state:
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
this : r₁ * r * ↑s_flat = ↑s₂ * p * (p' * p_flat)
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ = r₂ * p * (p' * p_flat) /ₒ ({ val := ↑s₁ * r, property := hr } * s_flat)

Next tactic:
clear this
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    clear this
    

Proof state:
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ = r₂ * p * (p' * p_flat) /ₒ ({ val := ↑s₁ * r, property := hr } * s_flat)

Next tactic:
have hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S := by
      rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
      exact S.mul_mem hr (SetLike.coe_mem s_flat)
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    clear this
    have hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S := by
      

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S

Next tactic:
rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    clear this
    have hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S := by
      rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
      

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ ↑s₁ * r * ↑s_flat ∈ S

Next tactic:
exact S.mul_mem hr (SetLike.coe_mem s_flat)
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    clear this
    have hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S := by
      rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
      exact S.mul_mem hr (SetLike.coe_mem s_flat)
    

Proof state:
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ = r₂ * p * (p' * p_flat) /ₒ ({ val := ↑s₁ * r, property := hr } * s_flat)

Next tactic:
have : (⟨↑s₁ * r, hr⟩ : S) * s_flat = ⟨s₁ * s₂' * s_star * p_flat, hsssp⟩ := by
      ext
      simp only [Submonoid.coe_mul]
      rw [mul_assoc, h₃, ← mul_assoc, ← mul_assoc]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    clear this
    have hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S := by
      rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
      exact S.mul_mem hr (SetLike.coe_mem s_flat)
    have : (⟨↑s₁ * r, hr⟩ : S) * s_flat = ⟨s₁ * s₂' * s_star * p_flat, hsssp⟩ := by
      

Proof state:
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
⊢ { val := ↑s₁ * r, property := hr } * s_flat = { val := ↑s₁ * ↑s₂' * ↑s_star * p_flat, property := hsssp }

Next tactic:
ext
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    clear this
    have hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S := by
      rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
      exact S.mul_mem hr (SetLike.coe_mem s_flat)
    have : (⟨↑s₁ * r, hr⟩ : S) * s_flat = ⟨s₁ * s₂' * s_star * p_flat, hsssp⟩ := by
      ext
      

Proof state:
case a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
⊢ ↑({ val := ↑s₁ * r, property := hr } * s_flat) = ↑{ val := ↑s₁ * ↑s₂' * ↑s_star * p_flat, property := hsssp }

Next tactic:
simp only [Submonoid.coe_mul]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    clear this
    have hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S := by
      rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
      exact S.mul_mem hr (SetLike.coe_mem s_flat)
    have : (⟨↑s₁ * r, hr⟩ : S) * s_flat = ⟨s₁ * s₂' * s_star * p_flat, hsssp⟩ := by
      ext
      simp only [Submonoid.coe_mul]
      

Proof state:
case a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
⊢ ↑s₁ * r * ↑s_flat = ↑s₁ * ↑(oreDenom r₁ s₂) * ↑s_star * p_flat

Next tactic:
rw [mul_assoc, h₃, ← mul_assoc, ← mul_assoc]
/-- The multiplication on the Ore localization of monoids. -/
protected def mul : R[S⁻¹] → R[S⁻¹] → R[S⁻¹] :=
  lift₂Expand mul' fun r₂ p s₂ hp r₁ r s₁ hr => by
    have h₁ := ore_eq r₁ s₂
    set r₁' := oreNum r₁ s₂
    set s₂' := oreDenom r₁ s₂
    rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
    dsimp at h₂
    rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
    simp only [S.coe_mul] at h₃
    have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) := by
      rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
      simp only [mul_assoc]
    rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
    clear this
    have hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S := by
      rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
      exact S.mul_mem hr (SetLike.coe_mem s_flat)
    have : (⟨↑s₁ * r, hr⟩ : S) * s_flat = ⟨s₁ * s₂' * s_star * p_flat, hsssp⟩ := by
      ext
      simp only [Submonoid.coe_mul]
      rw [mul_assoc, h₃, ← mul_assoc, ← mul_assoc]
    

Proof state:
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : ↥S
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : ↥S
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : ↥S := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : ↥S
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : ↥S
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
this : { val := ↑s₁ * r, property := hr } * s_flat = { val := ↑s₁ * ↑s₂' * ↑s_star * p_flat, property := hsssp }
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ = r₂ * p * (p' * p_flat) /ₒ ({ val := ↑s₁ * r, property := hr } * s_flat)

Next tactic:
rw [this]