[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
⊢ Equivalence fun rs rs' => ∃ u v, rs'.fst * ↑u = rs.fst * v ∧ ↑rs'.snd * ↑u = ↑rs.snd * v
[PROOFSTEP]
refine ⟨fun _ => ⟨1, 1, by simp⟩, ?_, ?_⟩
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
x✝ : R × { x // x ∈ S }
⊢ x✝.fst * ↑1 = x✝.fst * 1 ∧ ↑x✝.snd * ↑1 = ↑x✝.snd * 1
[PROOFSTEP]
simp
[GOAL]
case refine_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
⊢ ∀ {x y : R × { x // x ∈ S }},
    (∃ u v, y.fst * ↑u = x.fst * v ∧ ↑y.snd * ↑u = ↑x.snd * v) →
      ∃ u v, x.fst * ↑u = y.fst * v ∧ ↑x.snd * ↑u = ↑y.snd * v
[PROOFSTEP]
rintro ⟨r, s⟩ ⟨r', s'⟩ ⟨u, v, hru, hsu⟩
[GOAL]
case refine_1.mk.mk.intro.intro.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : (r', s').fst * ↑u = (r, s).fst * v
hsu : ↑(r', s').snd * ↑u = ↑(r, s).snd * v
⊢ ∃ u v, (r, s).fst * ↑u = (r', s').fst * v ∧ ↑(r, s).snd * ↑u = ↑(r', s').snd * v
[PROOFSTEP]
dsimp only at *
[GOAL]
case refine_1.mk.mk.intro.intro.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
⊢ ∃ u v, r * ↑u = r' * v ∧ ↑s * ↑u = ↑s' * v
[PROOFSTEP]
rcases oreCondition (s : R) s' with ⟨r₂, s₂, h₁⟩
[GOAL]
case refine_1.mk.mk.intro.intro.intro.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
⊢ ∃ u v, r * ↑u = r' * v ∧ ↑s * ↑u = ↑s' * v
[PROOFSTEP]
rcases oreCondition r₂ u with ⟨r₃, s₃, h₂⟩
[GOAL]
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 : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : { x // x ∈ S }
h₂ : r₂ * ↑s₃ = ↑u * r₃
⊢ ∃ u v, r * ↑u = r' * v ∧ ↑s * ↑u = ↑s' * v
[PROOFSTEP]
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]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : { x // x ∈ S }
h₂ : r₂ * ↑s₃ = ↑u * r₃
⊢ ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
[PROOFSTEP]
rw [← mul_assoc _ (s₂ : R), h₁, mul_assoc, h₂, ← mul_assoc, ← hsu, mul_assoc]
[GOAL]
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 : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : { x // x ∈ S }
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
⊢ ∃ u v, r * ↑u = r' * v ∧ ↑s * ↑u = ↑s' * v
[PROOFSTEP]
rcases ore_left_cancel (v * r₃) (s₂ * s₃) s this with ⟨w, hw⟩
[GOAL]
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 : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : { x // x ∈ S }
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : { x // x ∈ S }
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ ∃ u v, r * ↑u = r' * v ∧ ↑s * ↑u = ↑s' * v
[PROOFSTEP]
refine ⟨s₂ * s₃ * w, u * r₃ * w, ?_, ?_⟩
[GOAL]
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 : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : { x // x ∈ S }
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : { x // x ∈ S }
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ r * ↑(s₂ * s₃ * w) = r' * (↑u * r₃ * ↑w)
[PROOFSTEP]
simp only [Submonoid.coe_mul, ← hw]
[GOAL]
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 : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : { x // x ∈ S }
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : { x // x ∈ S }
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ ↑s * ↑(s₂ * s₃ * w) = ↑s' * (↑u * r₃ * ↑w)
[PROOFSTEP]
simp only [Submonoid.coe_mul, ← hw]
[GOAL]
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 : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : { x // x ∈ S }
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : { x // x ∈ S }
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ r * (v * r₃ * ↑w) = r' * (↑u * r₃ * ↑w)
[PROOFSTEP]
simp only [← mul_assoc, hru]
[GOAL]
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 : { x // x ∈ S }
r' : R
s' u : { x // x ∈ S }
v : R
hru : r' * ↑u = r * v
hsu : ↑s' * ↑u = ↑s * v
r₂ : R
s₂ : { x // x ∈ S }
h₁ : ↑s * ↑s₂ = ↑s' * r₂
r₃ : R
s₃ : { x // x ∈ S }
h₂ : r₂ * ↑s₃ = ↑u * r₃
this : ↑s * (v * r₃) = ↑s * (↑s₂ * ↑s₃)
w : { x // x ∈ S }
hw : v * r₃ * ↑w = ↑s₂ * ↑s₃ * ↑w
⊢ ↑s * (v * r₃ * ↑w) = ↑s' * (↑u * r₃ * ↑w)
[PROOFSTEP]
simp only [← mul_assoc, hsu]
[GOAL]
case refine_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
⊢ ∀ {x y z : R × { x // x ∈ S }},
    (∃ u v, y.fst * ↑u = x.fst * v ∧ ↑y.snd * ↑u = ↑x.snd * v) →
      (∃ u v, z.fst * ↑u = y.fst * v ∧ ↑z.snd * ↑u = ↑y.snd * v) →
        ∃ u v, z.fst * ↑u = x.fst * v ∧ ↑z.snd * ↑u = ↑x.snd * v
[PROOFSTEP]
rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ ⟨r₃, s₃⟩ ⟨u, v, hur₁, hs₁u⟩ ⟨u', v', hur₂, hs₂u⟩
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ u : { x // x ∈ S }
v : R
hur₁ : (r₂, s₂).fst * ↑u = (r₁, s₁).fst * v
hs₁u : ↑(r₂, s₂).snd * ↑u = ↑(r₁, s₁).snd * v
u' : { x // x ∈ S }
v' : R
hur₂ : (r₃, s₃).fst * ↑u' = (r₂, s₂).fst * v'
hs₂u : ↑(r₃, s₃).snd * ↑u' = ↑(r₂, s₂).snd * v'
⊢ ∃ u v, (r₃, s₃).fst * ↑u = (r₁, s₁).fst * v ∧ ↑(r₃, s₃).snd * ↑u = ↑(r₁, s₁).snd * v
[PROOFSTEP]
rcases oreCondition v' u with ⟨r', s', h⟩
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ u : { x // x ∈ S }
v : R
hur₁ : (r₂, s₂).fst * ↑u = (r₁, s₁).fst * v
hs₁u : ↑(r₂, s₂).snd * ↑u = ↑(r₁, s₁).snd * v
u' : { x // x ∈ S }
v' : R
hur₂ : (r₃, s₃).fst * ↑u' = (r₂, s₂).fst * v'
hs₂u : ↑(r₃, s₃).snd * ↑u' = ↑(r₂, s₂).snd * v'
r' : R
s' : { x // x ∈ S }
h : v' * ↑s' = ↑u * r'
⊢ ∃ u v, (r₃, s₃).fst * ↑u = (r₁, s₁).fst * v ∧ ↑(r₃, s₃).snd * ↑u = ↑(r₁, s₁).snd * v
[PROOFSTEP]
dsimp only at *
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ u : { x // x ∈ S }
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : { x // x ∈ S }
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : { x // x ∈ S }
h : v' * ↑s' = ↑u * r'
⊢ ∃ u v, r₃ * ↑u = r₁ * v ∧ ↑s₃ * ↑u = ↑s₁ * v
[PROOFSTEP]
refine ⟨u' * s', v * r', ?_, ?_⟩
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ u : { x // x ∈ S }
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : { x // x ∈ S }
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : { x // x ∈ S }
h : v' * ↑s' = ↑u * r'
⊢ r₃ * ↑(u' * s') = r₁ * (v * r')
[PROOFSTEP]
simp only [Submonoid.coe_mul, ← mul_assoc]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ u : { x // x ∈ S }
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : { x // x ∈ S }
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : { x // x ∈ S }
h : v' * ↑s' = ↑u * r'
⊢ ↑s₃ * ↑(u' * s') = ↑s₁ * (v * r')
[PROOFSTEP]
simp only [Submonoid.coe_mul, ← mul_assoc]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ u : { x // x ∈ S }
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : { x // x ∈ S }
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : { x // x ∈ S }
h : v' * ↑s' = ↑u * r'
⊢ r₃ * ↑u' * ↑s' = r₁ * v * r'
[PROOFSTEP]
rw [hur₂, mul_assoc, h, ← mul_assoc, hur₁]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ u : { x // x ∈ S }
v : R
hur₁ : r₂ * ↑u = r₁ * v
hs₁u : ↑s₂ * ↑u = ↑s₁ * v
u' : { x // x ∈ S }
v' : R
hur₂ : r₃ * ↑u' = r₂ * v'
hs₂u : ↑s₃ * ↑u' = ↑s₂ * v'
r' : R
s' : { x // x ∈ S }
h : v' * ↑s' = ↑u * r'
⊢ ↑s₃ * ↑u' * ↑s' = ↑s₁ * v * r'
[PROOFSTEP]
rw [hs₂u, mul_assoc, h, ← mul_assoc, hs₁u]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
β : OreLocalization R S → Prop
c : ∀ (r : R) (s : { x // x ∈ S }), β (r /ₒ s)
⊢ ∀ (q : OreLocalization R S), β q
[PROOFSTEP]
apply Quotient.ind
[GOAL]
case a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
β : OreLocalization R S → Prop
c : ∀ (r : R) (s : { x // x ∈ S }), β (r /ₒ s)
⊢ ∀ (a : R × { x // x ∈ S }), β (Quotient.mk (oreEqv R S) a)
[PROOFSTEP]
rintro ⟨r, s⟩
[GOAL]
case a.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
β : OreLocalization R S → Prop
c : ∀ (r : R) (s : { x // x ∈ S }), β (r /ₒ s)
r : R
s : { x // x ∈ S }
⊢ β (Quotient.mk (oreEqv R S) (r, s))
[PROOFSTEP]
exact c r s
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
t : R
hst : ↑s * t ∈ S
⊢ r /ₒ s = r * t /ₒ { val := ↑s * t, property := hst }
[PROOFSTEP]
apply Quotient.sound
[GOAL]
case a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
t : R
hst : ↑s * t ∈ S
⊢ (r, s) ≈ (r * t, { val := ↑s * t, property := hst })
[PROOFSTEP]
refine' ⟨s, t * s, _, _⟩
[GOAL]
case a.refine'_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
t : R
hst : ↑s * t ∈ S
⊢ (r * t, { val := ↑s * t, property := hst }).fst * ↑s = (r, s).fst * (t * ↑s)
[PROOFSTEP]
dsimp
[GOAL]
case a.refine'_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
t : R
hst : ↑s * t ∈ S
⊢ ↑(r * t, { val := ↑s * t, property := hst }).snd * ↑s = ↑(r, s).snd * (t * ↑s)
[PROOFSTEP]
dsimp
[GOAL]
case a.refine'_1
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
t : R
hst : ↑s * t ∈ S
⊢ r * t * ↑s = r * (t * ↑s)
[PROOFSTEP]
rw [mul_assoc]
[GOAL]
case a.refine'_2
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
t : R
hst : ↑s * t ∈ S
⊢ ↑s * t * ↑s = ↑s * (t * ↑s)
[PROOFSTEP]
rw [mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s s' : { x // x ∈ S }
⊢ ↑s * ↑s' ∈ S
[PROOFSTEP]
norm_cast
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s s' : { x // x ∈ S }
⊢ ↑(s * s') ∈ S
[PROOFSTEP]
apply SetLike.coe_mem
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
⊢ r₁ * r * r₂ /ₒ s = r₁ * r' * r₂ /ₒ s
[PROOFSTEP]
rcases oreCondition r₂ t with
  ⟨r₂', t', hr₂⟩
    -- porting note: todo: use `assoc_rw`?
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
r₂' : R
t' : { x // x ∈ S }
hr₂ : r₂ * ↑t' = ↑t * r₂'
⊢ r₁ * r * r₂ /ₒ s = r₁ * r' * r₂ /ₒ s
[PROOFSTEP]
calc
  r₁ * r * r₂ /ₒ s = r₁ * r * r₂ * t' /ₒ (s * t') := OreLocalization.expand (r₁ * r * r₂) s t' _
  _ = r₁ * r * (r₂ * t') /ₒ (s * t') := by simp [← mul_assoc]
  _ = r₁ * r * (t * r₂') /ₒ (s * t') := by rw [hr₂]
  _ = r₁ * (r * t) * r₂' /ₒ (s * t') := by simp [← mul_assoc]
  _ = r₁ * (r' * t) * r₂' /ₒ (s * t') := by rw [h]
  _ = r₁ * r' * (t * r₂') /ₒ (s * t') := by simp [← mul_assoc]
  _ = r₁ * r' * (r₂ * t') /ₒ (s * t') := by rw [hr₂]
  _ = r₁ * r' * r₂ * t' /ₒ (s * t') := by simp [← mul_assoc]
  _ = r₁ * r' * r₂ /ₒ s := (OreLocalization.expand _ _ _ _).symm
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
r₂' : R
t' : { x // x ∈ S }
hr₂ : r₂ * ↑t' = ↑t * r₂'
⊢ r₁ * r * r₂ * ↑t' /ₒ (s * t') = r₁ * r * (r₂ * ↑t') /ₒ (s * t')
[PROOFSTEP]
simp [← mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
r₂' : R
t' : { x // x ∈ S }
hr₂ : r₂ * ↑t' = ↑t * r₂'
⊢ r₁ * r * (r₂ * ↑t') /ₒ (s * t') = r₁ * r * (↑t * r₂') /ₒ (s * t')
[PROOFSTEP]
rw [hr₂]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
r₂' : R
t' : { x // x ∈ S }
hr₂ : r₂ * ↑t' = ↑t * r₂'
⊢ r₁ * r * (↑t * r₂') /ₒ (s * t') = r₁ * (r * ↑t) * r₂' /ₒ (s * t')
[PROOFSTEP]
simp [← mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
r₂' : R
t' : { x // x ∈ S }
hr₂ : r₂ * ↑t' = ↑t * r₂'
⊢ r₁ * (r * ↑t) * r₂' /ₒ (s * t') = r₁ * (r' * ↑t) * r₂' /ₒ (s * t')
[PROOFSTEP]
rw [h]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
r₂' : R
t' : { x // x ∈ S }
hr₂ : r₂ * ↑t' = ↑t * r₂'
⊢ r₁ * (r' * ↑t) * r₂' /ₒ (s * t') = r₁ * r' * (↑t * r₂') /ₒ (s * t')
[PROOFSTEP]
simp [← mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
r₂' : R
t' : { x // x ∈ S }
hr₂ : r₂ * ↑t' = ↑t * r₂'
⊢ r₁ * r' * (↑t * r₂') /ₒ (s * t') = r₁ * r' * (r₂ * ↑t') /ₒ (s * t')
[PROOFSTEP]
rw [hr₂]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r r' r₁ r₂ : R
s t : { x // x ∈ S }
h : r * ↑t = r' * ↑t
r₂' : R
t' : { x // x ∈ S }
hr₂ : r₂ * ↑t' = ↑t * r₂'
⊢ r₁ * r' * (r₂ * ↑t') /ₒ (s * t') = r₁ * r' * r₂ * ↑t' /ₒ (s * t')
[PROOFSTEP]
simp [← mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : (r₂, s₂).fst * ↑u = (r₁, s₁).fst * v
hs₂ : ↑(r₂, s₂).snd * ↑u = ↑(r₁, s₁).snd * v
⊢ (fun p => P p.fst p.snd) (r₁, s₁) = (fun p => P p.fst p.snd) (r₂, s₂)
[PROOFSTEP]
dsimp at *
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
hs₂ : ↑s₂ * ↑u = ↑s₁ * v
⊢ P r₁ s₁ = P r₂ s₂
[PROOFSTEP]
have s₁vS : (s₁ : R) * v ∈ S := by
  rw [← hs₂, ← S.coe_mul]
  exact SetLike.coe_mem (s₂ * u)
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
hs₂ : ↑s₂ * ↑u = ↑s₁ * v
⊢ ↑s₁ * v ∈ S
[PROOFSTEP]
rw [← hs₂, ← S.coe_mul]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
hs₂ : ↑s₂ * ↑u = ↑s₁ * v
⊢ ↑(s₂ * u) ∈ S
[PROOFSTEP]
exact SetLike.coe_mem (s₂ * u)
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
hs₂ : ↑s₂ * ↑u = ↑s₁ * v
s₁vS : ↑s₁ * v ∈ S
⊢ P r₁ s₁ = P r₂ s₂
[PROOFSTEP]
replace hs₂ : s₂ * u = ⟨(s₁ : R) * v, s₁vS⟩
[GOAL]
case hs₂
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
hs₂ : ↑s₂ * ↑u = ↑s₁ * v
s₁vS : ↑s₁ * v ∈ S
⊢ s₂ * u = { val := ↑s₁ * v, property := s₁vS }
[PROOFSTEP]
ext
[GOAL]
case hs₂.a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
hs₂ : ↑s₂ * ↑u = ↑s₁ * v
s₁vS : ↑s₁ * v ∈ S
⊢ ↑(s₂ * u) = ↑{ val := ↑s₁ * v, property := s₁vS }
[PROOFSTEP]
simp [hs₂]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
s₁vS : ↑s₁ * v ∈ S
hs₂ : s₂ * u = { val := ↑s₁ * v, property := s₁vS }
⊢ P r₁ s₁ = P r₂ s₂
[PROOFSTEP]
rw [hP r₁ v s₁ s₁vS, hP r₂ u s₂ (by norm_cast; rwa [hs₂]), hr₂]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
s₁vS : ↑s₁ * v ∈ S
hs₂ : s₂ * u = { val := ↑s₁ * v, property := s₁vS }
⊢ ↑s₂ * ↑u ∈ S
[PROOFSTEP]
norm_cast
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
s₁vS : ↑s₁ * v ∈ S
hs₂ : s₂ * u = { val := ↑s₁ * v, property := s₁vS }
⊢ ↑(s₂ * u) ∈ S
[PROOFSTEP]
rwa [hs₂]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
s₁vS : ↑s₁ * v ∈ S
hs₂ : s₂ * u = { val := ↑s₁ * v, property := s₁vS }
⊢ P (r₁ * v) { val := ↑s₁ * v, property := s₁vS } = P (r₁ * v) { val := ↑s₂ * ↑u, property := (_ : ↑s₂ * ↑u ∈ S) }
[PROOFSTEP]
simp only [← hs₂]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → C
hP : ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S), P r s = P (r * t) { val := ↑s * t, property := ht }
x✝² x✝¹ : R × { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
x✝ : (r₁, s₁) ≈ (r₂, s₂)
u : { x // x ∈ S }
v : R
hr₂ : r₂ * ↑u = r₁ * v
s₁vS : ↑s₁ * v ∈ S
hs₂ : s₂ * u = { val := ↑s₁ * v, property := s₁vS }
⊢ P (r₁ * v) (s₂ * u) = P (r₁ * v) { val := ↑s₂ * ↑u, property := (_ : ↑s₂ * ↑u ∈ S) }
[PROOFSTEP]
rfl
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ : R
s₁ : { x // x ∈ S }
r₂ t₂ : R
s₂ : { x // x ∈ S }
ht₂ : ↑s₂ * t₂ ∈ S
⊢ P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
[PROOFSTEP]
have := hP r₁ 1 s₁ (by simp) r₂ t₂ s₂ ht₂
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ : R
s₁ : { x // x ∈ S }
r₂ t₂ : R
s₂ : { x // x ∈ S }
ht₂ : ↑s₂ * t₂ ∈ S
⊢ ↑s₁ * 1 ∈ S
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ : R
s₁ : { x // x ∈ S }
r₂ t₂ : R
s₂ : { x // x ∈ S }
ht₂ : ↑s₂ * t₂ ∈ S
this :
  P r₁ s₁ r₂ s₂ =
    P (r₁ * 1) { val := ↑s₁ * 1, property := (_ : ↑s₁ * 1 ∈ S) } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
⊢ P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
[PROOFSTEP]
simp [this]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ t₁ : R
s₁ : { x // x ∈ S }
ht₁ : ↑s₁ * t₁ ∈ S
⊢ (fun r₁ s₁ =>
        liftExpand (P r₁ s₁)
          (_ :
            ∀ (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
              P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }))
      r₁ s₁ =
    (fun r₁ s₁ =>
        liftExpand (P r₁ s₁)
          (_ :
            ∀ (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
              P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }))
      (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ }
[PROOFSTEP]
ext x
[GOAL]
case h
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ t₁ : R
s₁ : { x // x ∈ S }
ht₁ : ↑s₁ * t₁ ∈ S
x : OreLocalization R S
⊢ (fun r₁ s₁ =>
        liftExpand (P r₁ s₁)
          (_ :
            ∀ (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
              P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }))
      r₁ s₁ x =
    (fun r₁ s₁ =>
        liftExpand (P r₁ s₁)
          (_ :
            ∀ (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
              P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }))
      (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } x
[PROOFSTEP]
induction' x using OreLocalization.ind with r₂ s₂
[GOAL]
case h.c
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ t₁ : R
s₁ : { x // x ∈ S }
ht₁ : ↑s₁ * t₁ ∈ S
r₂ : R
s₂ : { x // x ∈ S }
⊢ (fun r₁ s₁ =>
        liftExpand (P r₁ s₁)
          (_ :
            ∀ (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
              P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }))
      r₁ s₁ (r₂ /ₒ s₂) =
    (fun r₁ s₁ =>
        liftExpand (P r₁ s₁)
          (_ :
            ∀ (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
              P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }))
      (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ /ₒ s₂)
[PROOFSTEP]
dsimp only
[GOAL]
case h.c
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ t₁ : R
s₁ : { x // x ∈ S }
ht₁ : ↑s₁ * t₁ ∈ S
r₂ : R
s₂ : { x // x ∈ S }
⊢ liftExpand (P r₁ s₁)
      (_ :
        ∀ (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
          P r₁ s₁ r₂ s₂ = P r₁ s₁ (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ })
      (r₂ /ₒ s₂) =
    liftExpand (P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ })
      (_ :
        ∀ (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
          P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } r₂ s₂ =
            P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ })
      (r₂ /ₒ s₂)
[PROOFSTEP]
rw [liftExpand_of, liftExpand_of, hP r₁ t₁ s₁ ht₁ r₂ 1 s₂ (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ t₁ : R
s₁ : { x // x ∈ S }
ht₁ : ↑s₁ * t₁ ∈ S
r₂ : R
s₂ : { x // x ∈ S }
⊢ ↑s₂ * 1 ∈ S
[PROOFSTEP]
simp
[GOAL]
case h.c
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
C : Sort u_2
P : R → { x // x ∈ S } → R → { x // x ∈ S } → C
hP :
  ∀ (r₁ t₁ : R) (s₁ : { x // x ∈ S }) (ht₁ : ↑s₁ * t₁ ∈ S) (r₂ t₂ : R) (s₂ : { x // x ∈ S }) (ht₂ : ↑s₂ * t₂ ∈ S),
    P r₁ s₁ r₂ s₂ = P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * t₂) { val := ↑s₂ * t₂, property := ht₂ }
r₁ t₁ : R
s₁ : { x // x ∈ S }
ht₁ : ↑s₁ * t₁ ∈ S
r₂ : R
s₂ : { x // x ∈ S }
⊢ P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } (r₂ * 1) { val := ↑s₂ * 1, property := (_ : ↑s₂ * 1 ∈ S) } =
    P (r₁ * t₁) { val := ↑s₁ * t₁, property := ht₁ } r₂ s₂
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
⊢ OreLocalization.mul' r₁ s₁ r₂ s₂ = r₁ * v /ₒ (s₂ * u)
[PROOFSTEP]
simp only [mul']
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
⊢ r₁ * oreNum r₂ s₁ /ₒ (s₂ * oreDenom r₂ s₁) = r₁ * v /ₒ (s₂ * u)
[PROOFSTEP]
have h₀ := ore_eq r₂ s₁
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
h₀ : r₂ * ↑(oreDenom r₂ s₁) = ↑s₁ * oreNum r₂ s₁
⊢ r₁ * oreNum r₂ s₁ /ₒ (s₂ * oreDenom r₂ s₁) = r₁ * v /ₒ (s₂ * u)
[PROOFSTEP]
set v₀ := oreNum r₂ s₁
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
h₀ : r₂ * ↑(oreDenom r₂ s₁) = ↑s₁ * v₀
⊢ r₁ * v₀ /ₒ (s₂ * oreDenom r₂ s₁) = r₁ * v /ₒ (s₂ * u)
[PROOFSTEP]
set u₀ := oreDenom r₂ s₁
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
⊢ r₁ * v₀ /ₒ (s₂ * u₀) = r₁ * v /ₒ (s₂ * u)
[PROOFSTEP]
rcases oreCondition (u₀ : R) u with ⟨r₃, s₃, h₃⟩
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
⊢ r₁ * v₀ /ₒ (s₂ * u₀) = r₁ * v /ₒ (s₂ * u)
[PROOFSTEP]
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₀]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
⊢ ↑s₁ * (v * r₃) = r₂ * ↑u * r₃
[PROOFSTEP]
rw [← mul_assoc, ← huv]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
⊢ r₂ * ↑u * r₃ = r₂ * ↑u₀ * ↑s₃
[PROOFSTEP]
rw [mul_assoc, mul_assoc, h₃]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
⊢ r₂ * ↑u₀ * ↑s₃ = ↑s₁ * (v₀ * ↑s₃)
[PROOFSTEP]
rw [← mul_assoc, h₀]
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
⊢ r₁ * v₀ /ₒ (s₂ * u₀) = r₁ * v /ₒ (s₂ * u)
[PROOFSTEP]
rcases ore_left_cancel _ _ _ this with ⟨s₄, hs₄⟩
[GOAL]
case mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ r₁ * v₀ /ₒ (s₂ * u₀) = r₁ * v /ₒ (s₂ * u)
[PROOFSTEP]
symm
[GOAL]
case mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ r₁ * v /ₒ (s₂ * u) = r₁ * v₀ /ₒ (s₂ * u₀)
[PROOFSTEP]
rw [oreDiv_eq_iff]
[GOAL]
case mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ ∃ u_1 v_1, r₁ * v₀ * ↑u_1 = r₁ * v * v_1 ∧ ↑(s₂ * u₀) * ↑u_1 = ↑(s₂ * u) * v_1
[PROOFSTEP]
use s₃ * s₄
[GOAL]
case h
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ ∃ v_1, r₁ * v₀ * ↑(s₃ * s₄) = r₁ * v * v_1 ∧ ↑(s₂ * u₀) * ↑(s₃ * s₄) = ↑(s₂ * u) * v_1
[PROOFSTEP]
use r₃ * s₄
[GOAL]
case h
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ r₁ * v₀ * ↑(s₃ * s₄) = r₁ * v * (r₃ * ↑s₄) ∧ ↑(s₂ * u₀) * ↑(s₃ * s₄) = ↑(s₂ * u) * (r₃ * ↑s₄)
[PROOFSTEP]
simp only [Submonoid.coe_mul]
[GOAL]
case h
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ r₁ * oreNum r₂ s₁ * (↑s₃ * ↑s₄) = r₁ * v * (r₃ * ↑s₄) ∧ ↑s₂ * ↑(oreDenom r₂ s₁) * (↑s₃ * ↑s₄) = ↑s₂ * ↑u * (r₃ * ↑s₄)
[PROOFSTEP]
constructor
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ r₁ * oreNum r₂ s₁ * (↑s₃ * ↑s₄) = r₁ * v * (r₃ * ↑s₄)
[PROOFSTEP]
rw [mul_assoc (b := v₀), ← mul_assoc (a := v₀), ← hs₄]
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ r₁ * (v * r₃ * ↑s₄) = r₁ * v * (r₃ * ↑s₄)
[PROOFSTEP]
simp only [mul_assoc]
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ ↑s₂ * ↑(oreDenom r₂ s₁) * (↑s₃ * ↑s₄) = ↑s₂ * ↑u * (r₃ * ↑s₄)
[PROOFSTEP]
rw [mul_assoc (b := (u₀ : R)), ← mul_assoc (a := (u₀ : R)), h₃]
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ u : { x // x ∈ S }
v : R
huv : r₂ * ↑u = ↑s₁ * v
v₀ : R := oreNum r₂ s₁
u₀ : { x // x ∈ S } := oreDenom r₂ s₁
h₀ : r₂ * ↑u₀ = ↑s₁ * v₀
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑u₀ * ↑s₃ = ↑u * r₃
this : ↑s₁ * (v * r₃) = ↑s₁ * (v₀ * ↑s₃)
s₄ : { x // x ∈ S }
hs₄ : v * r₃ * ↑s₄ = v₀ * ↑s₃ * ↑s₄
⊢ ↑s₂ * (↑u * r₃ * ↑s₄) = ↑s₂ * ↑u * (r₃ * ↑s₄)
[PROOFSTEP]
simp only [mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ 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 }
[PROOFSTEP]
have h₁ := ore_eq r₁ s₂
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ 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 }
[PROOFSTEP]
set r₁' := oreNum r₁ s₂
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ 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 }
[PROOFSTEP]
set s₂' := oreDenom r₁ s₂
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ 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 }
[PROOFSTEP]
rcases oreCondition (↑s₂ * r₁') ⟨s₂ * p, hp⟩ with ⟨p', s_star, h₂⟩
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ 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 }
[PROOFSTEP]
dsimp at h₂ 
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ 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 }
[PROOFSTEP]
rcases oreCondition r (s₂' * s_star) with ⟨p_flat, s_flat, h₃⟩
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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 }
[PROOFSTEP]
simp only [S.coe_mul] at h₃ 
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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 }
[PROOFSTEP]
have : r₁ * r * s_flat = s₂ * p * (p' * p_flat) :=
  by
  rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
  simp only [mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ S }
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ r₁ * r * ↑s_flat = ↑s₂ * p * (p' * p_flat)
[PROOFSTEP]
rw [← mul_assoc, ← h₂, ← h₁, mul_assoc, h₃]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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
[PROOFSTEP]
simp only [mul_assoc]
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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 }
[PROOFSTEP]
rw [mul'_char (r₂ * p) (r₁ * r) ⟨↑s₂ * p, hp⟩ ⟨↑s₁ * r, hr⟩ _ _ this]
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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)
[PROOFSTEP]
clear this
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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)
[PROOFSTEP]
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)
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ S }
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
[PROOFSTEP]
rw [mul_assoc, mul_assoc, ← mul_assoc (s₂' : R), ← h₃, ← mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ S }
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
⊢ ↑s₁ * r * ↑s_flat ∈ S
[PROOFSTEP]
exact S.mul_mem hr (SetLike.coe_mem s_flat)
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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)
[PROOFSTEP]
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]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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 }
[PROOFSTEP]
ext
[GOAL]
case a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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 }
[PROOFSTEP]
simp only [Submonoid.coe_mul]
[GOAL]
case a
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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
[PROOFSTEP]
rw [mul_assoc, h₃, ← mul_assoc, ← mul_assoc]
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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)
[PROOFSTEP]
rw [this]
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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₁ * ↑s₂' * ↑s_star * p_flat, property := hsssp }
[PROOFSTEP]
clear this
[GOAL]
case mk.mk.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ 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₁ * ↑s₂' * ↑s_star * p_flat, property := hsssp }
[PROOFSTEP]
rcases ore_left_cancel (p * p') (r₁' * (s_star : R)) s₂ (by simp [← mul_assoc, h₂]) with ⟨s₂'', h₂''⟩
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ S }
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
⊢ ↑s₂ * (p * p') = ↑s₂ * (r₁' * ↑s_star)
[PROOFSTEP]
simp [← mul_assoc, h₂]
[GOAL]
case mk.mk.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ S }
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
s₂'' : { x // x ∈ S }
h₂'' : p * p' * ↑s₂'' = r₁' * ↑s_star * ↑s₂''
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    r₂ * p * (p' * p_flat) /ₒ { val := ↑s₁ * ↑s₂' * ↑s_star * p_flat, property := hsssp }
[PROOFSTEP]
rw [← mul_assoc, mul_assoc r₂, OreLocalization.eq_of_num_factor_eq h₂'']
[GOAL]
case mk.mk.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ S }
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑s₁ * ↑s₂' * ↑s_star * p_flat ∈ S
s₂'' : { x // x ∈ S }
h₂'' : p * p' * ↑s₂'' = r₁' * ↑s_star * ↑s₂''
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    r₂ * (r₁' * ↑s_star) * p_flat /ₒ { val := ↑s₁ * ↑s₂' * ↑s_star * p_flat, property := hsssp }
[PROOFSTEP]
norm_cast at hsssp ⊢
[GOAL]
case mk.mk.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ S }
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑(s₁ * s₂' * s_star) * p_flat ∈ S
s₂'' : { x // x ∈ S }
h₂'' : p * p' * ↑s₂'' = r₁' * ↑s_star * ↑s₂''
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ =
    r₂ * (r₁' * ↑s_star) * p_flat /ₒ
      { val := ↑(s₁ * s₂' * s_star) * p_flat, property := (_ : (fun x => x ∈ S) (↑(s₁ * s₂' * s_star) * p_flat)) }
[PROOFSTEP]
rw [← OreLocalization.expand _ _ _ hsssp, ← mul_assoc]
[GOAL]
case mk.mk.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₂ p : R
s₂ : { x // x ∈ S }
hp : ↑s₂ * p ∈ S
r₁ r : R
s₁ : { x // x ∈ S }
hr : ↑s₁ * r ∈ S
r₁' : R := oreNum r₁ s₂
s₂' : { x // x ∈ S } := oreDenom r₁ s₂
h₁ : r₁ * ↑s₂' = ↑s₂ * r₁'
p' : R
s_star : { x // x ∈ S }
h₂ : ↑s₂ * oreNum r₁ s₂ * ↑s_star = ↑s₂ * p * p'
p_flat : R
s_flat : { x // x ∈ S }
h₃ : r * ↑s_flat = ↑(oreDenom r₁ s₂) * ↑s_star * p_flat
hsssp : ↑(s₁ * s₂' * s_star) * p_flat ∈ S
s₂'' : { x // x ∈ S }
h₂'' : p * p' * ↑s₂'' = r₁' * ↑s_star * ↑s₂''
⊢ OreLocalization.mul' r₂ s₂ r₁ s₁ = r₂ * r₁' * ↑s_star /ₒ (s₁ * s₂' * s_star)
[PROOFSTEP]
apply OreLocalization.expand
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
hr : r ∈ S
⊢ r /ₒ { val := r, property := hr } = 1
[PROOFSTEP]
rw [OreLocalization.one_def, oreDiv_eq_iff]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
hr : r ∈ S
⊢ ∃ u v, 1 * ↑u = r * v ∧ ↑1 * ↑u = ↑{ val := r, property := hr } * v
[PROOFSTEP]
exact ⟨⟨r, hr⟩, 1, by simp, by simp⟩
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
hr : r ∈ S
⊢ 1 * ↑{ val := r, property := hr } = r * 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
hr : r ∈ S
⊢ ↑1 * ↑{ val := r, property := hr } = ↑{ val := r, property := hr } * 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
⊢ 1 * x = x
[PROOFSTEP]
induction' x using OreLocalization.ind with r s
[GOAL]
case c
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ 1 * (r /ₒ s) = r /ₒ s
[PROOFSTEP]
simp [OreLocalization.one_def, oreDiv_mul_char (1 : R) r (1 : S) s r 1 (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ r * ↑1 = ↑1 * r
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
⊢ x * 1 = x
[PROOFSTEP]
induction' x using OreLocalization.ind with r s
[GOAL]
case c
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ r /ₒ s * 1 = r /ₒ s
[PROOFSTEP]
simp [OreLocalization.one_def, oreDiv_mul_char r 1 s 1 1 s (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ 1 * ↑s = ↑s * 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
x y z : OreLocalization R S
⊢ x * y * z = x * (y * z)
[PROOFSTEP]
induction' x using OreLocalization.ind with r₁ s₁
[GOAL]
case c
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
y z : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * y * z = r₁ /ₒ s₁ * (y * z)
[PROOFSTEP]
induction' y using OreLocalization.ind with r₂ s₂
[GOAL]
case c.c
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
z : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * (r₂ /ₒ s₂) * z = r₁ /ₒ s₁ * (r₂ /ₒ s₂ * z)
[PROOFSTEP]
induction' z using OreLocalization.ind with r₃ s₃
[GOAL]
case c.c.c
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * (r₂ /ₒ s₂) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ /ₒ s₂ * (r₃ /ₒ s₃))
[PROOFSTEP]
rcases oreDivMulChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
ha' : r₁ /ₒ s₁ * (r₂ /ₒ s₂) = r₁ * ra /ₒ (s₂ * sa)
⊢ r₁ /ₒ s₁ * (r₂ /ₒ s₂) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ /ₒ s₂ * (r₃ /ₒ s₃))
[PROOFSTEP]
rw [ha']
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
ha' : r₁ /ₒ s₁ * (r₂ /ₒ s₂) = r₁ * ra /ₒ (s₂ * sa)
⊢ r₁ * ra /ₒ (s₂ * sa) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ /ₒ s₂ * (r₃ /ₒ s₃))
[PROOFSTEP]
clear ha'
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
⊢ r₁ * ra /ₒ (s₂ * sa) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ /ₒ s₂ * (r₃ /ₒ s₃))
[PROOFSTEP]
rcases oreDivMulChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
hb' : r₂ /ₒ s₂ * (r₃ /ₒ s₃) = r₂ * rb /ₒ (s₃ * sb)
⊢ r₁ * ra /ₒ (s₂ * sa) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ /ₒ s₂ * (r₃ /ₒ s₃))
[PROOFSTEP]
rw [hb']
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
hb' : r₂ /ₒ s₂ * (r₃ /ₒ s₃) = r₂ * rb /ₒ (s₃ * sb)
⊢ r₁ * ra /ₒ (s₂ * sa) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ * rb /ₒ (s₃ * sb))
[PROOFSTEP]
clear hb'
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
⊢ r₁ * ra /ₒ (s₂ * sa) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ * rb /ₒ (s₃ * sb))
[PROOFSTEP]
rcases oreCondition rb sa with ⟨rc, sc, hc⟩
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
rc : R
sc : { x // x ∈ S }
hc : rb * ↑sc = ↑sa * rc
⊢ r₁ * ra /ₒ (s₂ * sa) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ * rb /ₒ (s₃ * sb))
[PROOFSTEP]
rw [oreDiv_mul_char (r₁ * ra) r₃ (s₂ * sa) s₃ rc (sb * sc)
    (by
      simp only [Submonoid.coe_mul]
      rw [← mul_assoc, hb, mul_assoc, hc, ← mul_assoc])]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
rc : R
sc : { x // x ∈ S }
hc : rb * ↑sc = ↑sa * rc
⊢ r₃ * ↑(sb * sc) = ↑(s₂ * sa) * rc
[PROOFSTEP]
simp only [Submonoid.coe_mul]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
rc : R
sc : { x // x ∈ S }
hc : rb * ↑sc = ↑sa * rc
⊢ r₃ * (↑sb * ↑sc) = ↑s₂ * ↑sa * rc
[PROOFSTEP]
rw [← mul_assoc, hb, mul_assoc, hc, ← mul_assoc]
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
rc : R
sc : { x // x ∈ S }
hc : rb * ↑sc = ↑sa * rc
⊢ r₁ * ra * rc /ₒ (s₃ * (sb * sc)) = r₁ /ₒ s₁ * (r₂ * rb /ₒ (s₃ * sb))
[PROOFSTEP]
rw [mul_assoc, ← mul_assoc s₃]
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
rc : R
sc : { x // x ∈ S }
hc : rb * ↑sc = ↑sa * rc
⊢ r₁ * (ra * rc) /ₒ (s₃ * sb * sc) = r₁ /ₒ s₁ * (r₂ * rb /ₒ (s₃ * sb))
[PROOFSTEP]
symm
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
rc : R
sc : { x // x ∈ S }
hc : rb * ↑sc = ↑sa * rc
⊢ r₁ /ₒ s₁ * (r₂ * rb /ₒ (s₃ * sb)) = r₁ * (ra * rc) /ₒ (s₃ * sb * sc)
[PROOFSTEP]
apply oreDiv_mul_char
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.huv
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
rb : R
sb : { x // x ∈ S }
hb : r₃ * ↑sb = ↑s₂ * rb
rc : R
sc : { x // x ∈ S }
hc : rb * ↑sc = ↑sa * rc
⊢ r₂ * rb * ↑sc = ↑s₁ * (ra * rc)
[PROOFSTEP]
rw [mul_assoc, hc, ← mul_assoc (b := ra), ← ha, mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
s s' : { x // x ∈ S }
⊢ ↑s /ₒ s' * (↑s' /ₒ s) = 1
[PROOFSTEP]
simp [oreDiv_mul_char (s : R) s' s' s 1 1 (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
s s' : { x // x ∈ S }
⊢ ↑s' * ↑1 = ↑s' * 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s t : { x // x ∈ S }
⊢ r /ₒ s * (1 /ₒ t) = r /ₒ (t * s)
[PROOFSTEP]
simp [oreDiv_mul_char r 1 s t 1 s (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s t : { x // x ∈ S }
⊢ 1 * ↑s = ↑s * 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s t : { x // x ∈ S }
⊢ r /ₒ s * (↑s /ₒ t) = r /ₒ t
[PROOFSTEP]
simp [oreDiv_mul_char r s s t 1 1 (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s t : { x // x ∈ S }
⊢ ↑s * ↑1 = ↑s * 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s t : { x // x ∈ S }
⊢ r₁ /ₒ s * (↑s * r₂ /ₒ t) = r₁ * r₂ /ₒ t
[PROOFSTEP]
simp [oreDiv_mul_char r₁ (s * r₂) s t r₂ 1 (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s t : { x // x ∈ S }
⊢ ↑s * r₂ * ↑1 = ↑s * r₂
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
p r : R
s : { x // x ∈ S }
⊢ r /ₒ 1 * (p /ₒ s) = r * p /ₒ s
[PROOFSTEP]
simp [oreDiv_mul_char r p 1 s p 1 (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Monoid R
S : Submonoid R
inst✝ : OreSet S
p r : R
s : { x // x ∈ S }
⊢ p * ↑1 = ↑1 * p
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
⊢ (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s = (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht }
[PROOFSTEP]
simp only []
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
⊢ ↑f r * ↑(↑fS s)⁻¹ = ↑f (r * t) * ↑(↑fS { val := ↑s * t, property := ht })⁻¹
[PROOFSTEP]
have : (fS ⟨s * t, ht⟩ : T) = fS s * f t := by simp only [← hf, MonoidHom.map_mul]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
⊢ ↑(↑fS { val := ↑s * t, property := ht }) = ↑(↑fS s) * ↑f t
[PROOFSTEP]
simp only [← hf, MonoidHom.map_mul]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
this : ↑(↑fS { val := ↑s * t, property := ht }) = ↑(↑fS s) * ↑f t
⊢ ↑f r * ↑(↑fS s)⁻¹ = ↑f (r * t) * ↑(↑fS { val := ↑s * t, property := ht })⁻¹
[PROOFSTEP]
conv_rhs =>
  rw [MonoidHom.map_mul, ← mul_one (f r), ← Units.val_one, ← mul_left_inv (fS s)]
  rw [Units.val_mul, ← mul_assoc, mul_assoc _ (fS s : T), ← this, mul_assoc]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
this : ↑(↑fS { val := ↑s * t, property := ht }) = ↑(↑fS s) * ↑f t
| ↑f (r * t) * ↑(↑fS { val := ↑s * t, property := ht })⁻¹
[PROOFSTEP]
  rw [MonoidHom.map_mul, ← mul_one (f r), ← Units.val_one, ← mul_left_inv (fS s)]
  rw [Units.val_mul, ← mul_assoc, mul_assoc _ (fS s : T), ← this, mul_assoc]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
this : ↑(↑fS { val := ↑s * t, property := ht }) = ↑(↑fS s) * ↑f t
| ↑f (r * t) * ↑(↑fS { val := ↑s * t, property := ht })⁻¹
[PROOFSTEP]
  rw [MonoidHom.map_mul, ← mul_one (f r), ← Units.val_one, ← mul_left_inv (fS s)]
  rw [Units.val_mul, ← mul_assoc, mul_assoc _ (fS s : T), ← this, mul_assoc]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
this : ↑(↑fS { val := ↑s * t, property := ht }) = ↑(↑fS s) * ↑f t
| ↑f (r * t) * ↑(↑fS { val := ↑s * t, property := ht })⁻¹
[PROOFSTEP]
rw [MonoidHom.map_mul, ← mul_one (f r), ← Units.val_one, ← mul_left_inv (fS s)]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
this : ↑(↑fS { val := ↑s * t, property := ht }) = ↑(↑fS s) * ↑f t
| ↑f r * ↑((↑fS s)⁻¹ * ↑fS s) * ↑f t * ↑(↑fS { val := ↑s * t, property := ht })⁻¹
[PROOFSTEP]
rw [Units.val_mul, ← mul_assoc, mul_assoc _ (fS s : T), ← this, mul_assoc]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x : OreLocalization R S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
this : ↑(↑fS { val := ↑s * t, property := ht }) = ↑(↑fS s) * ↑f t
⊢ ↑f r * ↑(↑fS s)⁻¹ =
    ↑f r * ↑(↑fS s)⁻¹ * (↑(↑fS { val := ↑s * t, property := ht }) * ↑(↑fS { val := ↑s * t, property := ht })⁻¹)
[PROOFSTEP]
simp only [mul_one, Units.mul_inv]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
⊢ (fun x =>
        liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
          (_ :
            ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
                (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
          x)
      1 =
    1
[PROOFSTEP]
simp only []
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
⊢ liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
      (_ :
        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s = (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
      1 =
    1
[PROOFSTEP]
rw [OreLocalization.one_def, liftExpand_of]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
⊢ ↑f 1 * ↑(↑fS 1)⁻¹ = 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x y : OreLocalization R S
⊢ OneHom.toFun
      {
        toFun := fun x =>
          liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
            (_ :
              ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
                (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
                  (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
            x,
        map_one' :=
          (_ :
            (fun x =>
                  liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
                    (_ :
                      ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
                        (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
                          (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
                    x)
                1 =
              1) }
      (x * y) =
    OneHom.toFun
        {
          toFun := fun x =>
            liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
              (_ :
                ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
                  (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
                    (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
              x,
          map_one' :=
            (_ :
              (fun x =>
                    liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
                      (_ :
                        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
                          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
                            (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
                      x)
                  1 =
                1) }
        x *
      OneHom.toFun
        {
          toFun := fun x =>
            liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
              (_ :
                ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
                  (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
                    (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
              x,
          map_one' :=
            (_ :
              (fun x =>
                    liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
                      (_ :
                        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
                          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
                            (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
                      x)
                  1 =
                1) }
        y
[PROOFSTEP]
simp only []
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
x y : OreLocalization R S
⊢ liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
      (_ :
        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s = (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
      (x * y) =
    liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        x *
      liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        y
[PROOFSTEP]
induction' x using OreLocalization.ind with r₁ s₁
[GOAL]
case c
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
y : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
⊢ liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
      (_ :
        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s = (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
      (r₁ /ₒ s₁ * y) =
    liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₁ /ₒ s₁) *
      liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        y
[PROOFSTEP]
induction' y using OreLocalization.ind with r₂ s₂
[GOAL]
case c.c
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
⊢ liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
      (_ :
        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s = (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
      (r₁ /ₒ s₁ * (r₂ /ₒ s₂)) =
    liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₁ /ₒ s₁) *
      liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₂ /ₒ s₂)
[PROOFSTEP]
rcases oreDivMulChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
ha' : r₁ /ₒ s₁ * (r₂ /ₒ s₂) = r₁ * ra /ₒ (s₂ * sa)
⊢ liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
      (_ :
        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s = (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
      (r₁ /ₒ s₁ * (r₂ /ₒ s₂)) =
    liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₁ /ₒ s₁) *
      liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₂ /ₒ s₂)
[PROOFSTEP]
rw [ha']
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
ha' : r₁ /ₒ s₁ * (r₂ /ₒ s₂) = r₁ * ra /ₒ (s₂ * sa)
⊢ liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
      (_ :
        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s = (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
      (r₁ * ra /ₒ (s₂ * sa)) =
    liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₁ /ₒ s₁) *
      liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₂ /ₒ s₂)
[PROOFSTEP]
clear ha'
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
⊢ liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
      (_ :
        ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
          (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s = (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
      (r₁ * ra /ₒ (s₂ * sa)) =
    liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₁ /ₒ s₁) *
      liftExpand (fun r s => ↑f r * ↑(↑fS s)⁻¹)
        (_ :
          ∀ (r t : R) (s : { x // x ∈ S }) (ht : ↑s * t ∈ S),
            (fun r s => ↑f r * ↑(↑fS s)⁻¹) r s =
              (fun r s => ↑f r * ↑(↑fS s)⁻¹) (r * t) { val := ↑s * t, property := ht })
        (r₂ /ₒ s₂)
[PROOFSTEP]
rw [liftExpand_of, liftExpand_of, liftExpand_of]
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
⊢ ↑f (r₁ * ra) * ↑(↑fS (s₂ * sa))⁻¹ = ↑f r₁ * ↑(↑fS s₁)⁻¹ * (↑f r₂ * ↑(↑fS s₂)⁻¹)
[PROOFSTEP]
conv_rhs =>
  congr
  ·skip
  congr
  rw [← mul_one (f r₂), ← (fS sa).mul_inv, ← mul_assoc, ← hf, ← f.map_mul, ha, f.map_mul]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₁ * ↑(↑fS s₁)⁻¹ * (↑f r₂ * ↑(↑fS s₂)⁻¹)
[PROOFSTEP]
  congr
  ·skip
  congr
  rw [← mul_one (f r₂), ← (fS sa).mul_inv, ← mul_assoc, ← hf, ← f.map_mul, ha, f.map_mul]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₁ * ↑(↑fS s₁)⁻¹ * (↑f r₂ * ↑(↑fS s₂)⁻¹)
[PROOFSTEP]
  congr
  ·skip
  congr
  rw [← mul_one (f r₂), ← (fS sa).mul_inv, ← mul_assoc, ← hf, ← f.map_mul, ha, f.map_mul]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₁ * ↑(↑fS s₁)⁻¹ * (↑f r₂ * ↑(↑fS s₂)⁻¹)
[PROOFSTEP]
congr
[GOAL]
case a
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₁ * ↑(↑fS s₁)⁻¹
case a
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₂ * ↑(↑fS s₂)⁻¹
[PROOFSTEP]
·skip
[GOAL]
case a
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₁ * ↑(↑fS s₁)⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₁ * ↑(↑fS s₁)⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₁ * ↑(↑fS s₁)⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₂ * ↑(↑fS s₂)⁻¹
[PROOFSTEP]
congr
[GOAL]
case a.a
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑f r₂
case a.a
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
| ↑(↑fS s₂)⁻¹
[PROOFSTEP]
rw [← mul_one (f r₂), ← (fS sa).mul_inv, ← mul_assoc, ← hf, ← f.map_mul, ha, f.map_mul]
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
⊢ ↑f (r₁ * ra) * ↑(↑fS (s₂ * sa))⁻¹ = ↑f r₁ * ↑(↑fS s₁)⁻¹ * (↑f ↑s₁ * ↑f ra * ↑(↑fS sa)⁻¹ * ↑(↑fS s₂)⁻¹)
[PROOFSTEP]
rw [mul_assoc, mul_assoc, mul_assoc, ← mul_assoc _ (f s₁), hf s₁, (fS s₁).inv_mul, one_mul, f.map_mul, mul_assoc,
  fS.map_mul, ← Units.val_mul]
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : r₂ * ↑sa = ↑s₁ * ra
⊢ ↑f r₁ * (↑f ra * ↑(↑fS s₂ * ↑fS sa)⁻¹) = ↑f r₁ * (↑f ra * ↑((↑fS sa)⁻¹ * (↑fS s₂)⁻¹))
[PROOFSTEP]
rfl
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r : R
⊢ ↑(universalMulHom f fS hf) (↑numeratorHom r) = ↑f r
[PROOFSTEP]
simp [numeratorHom_apply, universalMulHom_apply]
[GOAL]
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
φ : OreLocalization R S →* T
huniv : ∀ (r : R), ↑φ (↑numeratorHom r) = ↑f r
⊢ φ = universalMulHom f fS hf
[PROOFSTEP]
ext x
[GOAL]
case h
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
φ : OreLocalization R S →* T
huniv : ∀ (r : R), ↑φ (↑numeratorHom r) = ↑f r
x : OreLocalization R S
⊢ ↑φ x = ↑(universalMulHom f fS hf) x
[PROOFSTEP]
induction' x using OreLocalization.ind with r s
[GOAL]
case h.c
R : Type u_1
inst✝² : Monoid R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Monoid T
f : R →* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
φ : OreLocalization R S →* T
huniv : ∀ (r : R), ↑φ (↑numeratorHom r) = ↑f r
r : R
s : { x // x ∈ S }
⊢ ↑φ (r /ₒ s) = ↑(universalMulHom f fS hf) (r /ₒ s)
[PROOFSTEP]
rw [universalMulHom_apply, ← huniv r, numeratorHom_apply, ← mul_one (φ (r /ₒ s)), ← Units.val_one, ←
  mul_right_inv (fS s), Units.val_mul, ← mul_assoc, ← hf, ← huniv, ← φ.map_mul, numeratorHom_apply,
  OreLocalization.mul_cancel]
[GOAL]
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * (r₂ /ₒ s₂) = r₁ * r₂ /ₒ (s₁ * s₂)
[PROOFSTEP]
rw [oreDiv_mul_char r₁ r₂ s₁ s₂ r₂ s₁ (by simp [mul_comm]), mul_comm s₂]
[GOAL]
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
⊢ r₂ * ↑s₁ = ↑s₁ * r₂
[PROOFSTEP]
simp [mul_comm]
[GOAL]
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
src✝ : Monoid (OreLocalization R S) := instMonoidOreLocalization
x y : OreLocalization R S
⊢ x * y = y * x
[PROOFSTEP]
induction' x using OreLocalization.ind with r₁ s₁
[GOAL]
case c
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
src✝ : Monoid (OreLocalization R S) := instMonoidOreLocalization
y : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * y = y * (r₁ /ₒ s₁)
[PROOFSTEP]
induction' y using OreLocalization.ind with r₂ s₂
[GOAL]
case c.c
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
src✝ : Monoid (OreLocalization R S) := instMonoidOreLocalization
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * (r₂ /ₒ s₂) = r₂ /ₒ s₂ * (r₁ /ₒ s₁)
[PROOFSTEP]
rw [oreDiv_mul_oreDiv_comm, oreDiv_mul_oreDiv_comm, mul_comm r₁, mul_comm s₁]
[GOAL]
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
⊢ OneHom.toFun { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) } (r₁ * r₂) =
    OneHom.toFun { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) } r₁ *
      OneHom.toFun { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) } r₂
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
z : OreLocalization R S
⊢ ∃ x,
    z *
        OneHom.toFun
          ↑{ toOneHom := { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) },
              map_mul' := (_ : ∀ (r₁ r₂ : R), ↑numeratorHom (r₁ * r₂) = ↑numeratorHom r₁ * ↑numeratorHom r₂) }
          ↑x.snd =
      OneHom.toFun
        (↑{ toOneHom := { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) },
            map_mul' := (_ : ∀ (r₁ r₂ : R), ↑numeratorHom (r₁ * r₂) = ↑numeratorHom r₁ * ↑numeratorHom r₂) })
        x.fst
[PROOFSTEP]
induction' z using OreLocalization.ind with r s
[GOAL]
case c
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ ∃ x,
    r /ₒ s *
        OneHom.toFun
          ↑{ toOneHom := { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) },
              map_mul' := (_ : ∀ (r₁ r₂ : R), ↑numeratorHom (r₁ * r₂) = ↑numeratorHom r₁ * ↑numeratorHom r₂) }
          ↑x.snd =
      OneHom.toFun
        (↑{ toOneHom := { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) },
            map_mul' := (_ : ∀ (r₁ r₂ : R), ↑numeratorHom (r₁ * r₂) = ↑numeratorHom r₁ * ↑numeratorHom r₂) })
        x.fst
[PROOFSTEP]
use(r, s)
[GOAL]
case h
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ r /ₒ s *
      OneHom.toFun
        ↑{ toOneHom := { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) },
            map_mul' := (_ : ∀ (r₁ r₂ : R), ↑numeratorHom (r₁ * r₂) = ↑numeratorHom r₁ * ↑numeratorHom r₂) }
        ↑(r, s).snd =
    OneHom.toFun
      ↑{ toOneHom := { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) },
          map_mul' := (_ : ∀ (r₁ r₂ : R), ↑numeratorHom (r₁ * r₂) = ↑numeratorHom r₁ * ↑numeratorHom r₂) }
      (r, s).fst
[PROOFSTEP]
dsimp
[GOAL]
case h
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ r /ₒ s * ↑numeratorHom ↑s = ↑numeratorHom r
[PROOFSTEP]
rw [numeratorHom_apply, numeratorHom_apply]
[GOAL]
case h
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ r /ₒ s * (↑s /ₒ 1) = r /ₒ 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
⊢ OneHom.toFun
        (↑{ toOneHom := { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) },
            map_mul' := (_ : ∀ (r₁ r₂ : R), ↑numeratorHom (r₁ * r₂) = ↑numeratorHom r₁ * ↑numeratorHom r₂) })
        r₁ =
      OneHom.toFun
        (↑{ toOneHom := { toFun := ↑numeratorHom, map_one' := (_ : ↑numeratorHom 1 = ↑numeratorHom 1) },
            map_mul' := (_ : ∀ (r₁ r₂ : R), ↑numeratorHom (r₁ * r₂) = ↑numeratorHom r₁ * ↑numeratorHom r₂) })
        r₂ ↔
    ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
dsimp
[GOAL]
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
⊢ ↑numeratorHom r₁ = ↑numeratorHom r₂ ↔ ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
constructor
[GOAL]
case mp
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
⊢ ↑numeratorHom r₁ = ↑numeratorHom r₂ → ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
intro h
[GOAL]
case mp
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
h : ↑numeratorHom r₁ = ↑numeratorHom r₂
⊢ ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
rw [numeratorHom_apply, numeratorHom_apply, oreDiv_eq_iff] at h 
[GOAL]
case mp
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
h : ∃ u v, r₂ * ↑u = r₁ * v ∧ ↑1 * ↑u = ↑1 * v
⊢ ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
rcases h with ⟨u, v, h₁, h₂⟩
[GOAL]
case mp.intro.intro.intro
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
u : { x // x ∈ S }
v : R
h₁ : r₂ * ↑u = r₁ * v
h₂ : ↑1 * ↑u = ↑1 * v
⊢ ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
dsimp at h₂ 
[GOAL]
case mp.intro.intro.intro
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
u : { x // x ∈ S }
v : R
h₁ : r₂ * ↑u = r₁ * v
h₂ : 1 * ↑u = 1 * v
⊢ ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
rw [one_mul, one_mul] at h₂ 
[GOAL]
case mp.intro.intro.intro
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
u : { x // x ∈ S }
v : R
h₁ : r₂ * ↑u = r₁ * v
h₂ : ↑u = v
⊢ ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
subst h₂
[GOAL]
case mp.intro.intro.intro
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
u : { x // x ∈ S }
h₁ : r₂ * ↑u = r₁ * ↑u
⊢ ∃ c, ↑c * r₁ = ↑c * r₂
[PROOFSTEP]
use u
[GOAL]
case h
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
u : { x // x ∈ S }
h₁ : r₂ * ↑u = r₁ * ↑u
⊢ ↑u * r₁ = ↑u * r₂
[PROOFSTEP]
simpa only [mul_comm] using h₁.symm
[GOAL]
case mpr
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
⊢ (∃ c, ↑c * r₁ = ↑c * r₂) → ↑numeratorHom r₁ = ↑numeratorHom r₂
[PROOFSTEP]
rintro ⟨s, h⟩
[GOAL]
case mpr.intro
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s : { x // x ∈ S }
h : ↑s * r₁ = ↑s * r₂
⊢ ↑numeratorHom r₁ = ↑numeratorHom r₂
[PROOFSTEP]
rw [numeratorHom_apply, numeratorHom_apply, oreDiv_eq_iff]
[GOAL]
case mpr.intro
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s : { x // x ∈ S }
h : ↑s * r₁ = ↑s * r₂
⊢ ∃ u v, r₂ * ↑u = r₁ * v ∧ ↑1 * ↑u = ↑1 * v
[PROOFSTEP]
refine' ⟨s, s, _, _⟩
[GOAL]
case mpr.intro.refine'_1
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s : { x // x ∈ S }
h : ↑s * r₁ = ↑s * r₂
⊢ r₂ * ↑s = r₁ * ↑s
[PROOFSTEP]
simpa [mul_comm] using h.symm
[GOAL]
case mpr.intro.refine'_2
R : Type u_1
inst✝¹ : CommMonoid R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s : { x // x ∈ S }
h : ↑s * r₁ = ↑s * r₂
⊢ ↑1 * ↑s = ↑1 * ↑s
[PROOFSTEP]
simp [one_mul]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
⊢ OreLocalization.add'' r₁ s₁ r₂ s₂ = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
simp only [add'']
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂) /ₒ (s₁ * oreDenom (↑s₁) s₂) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
have ha := ore_eq (s₁ : R) s₂
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂) /ₒ (s₁ * oreDenom (↑s₁) s₂) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
set! ra := oreNum (s₁ : R) s₂ with h
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
h : ra = oreNum (↑s₁) s₂
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂) /ₒ (s₁ * oreDenom (↑s₁) s₂) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
rw [← h] at *
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
h : ra = ra
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * ra) /ₒ (s₁ * oreDenom (↑s₁) s₂) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
clear h
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * ra) /ₒ (s₁ * oreDenom (↑s₁) s₂) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
set! sa := oreDenom (s₁ : R) s₂ with h
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
h : sa = oreDenom (↑s₁) s₂
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * ra) /ₒ (s₁ * oreDenom (↑s₁) s₂) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
rw [← h] at *
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
h : sa = sa
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
clear h
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
rcases oreCondition (sa : R) sb with
  ⟨rc, sc, hc⟩
    -- s*, r*
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
have : (s₂ : R) * (rb * rc) = s₂ * (ra * sc) := by rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← mul_assoc, ha]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
⊢ ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
[PROOFSTEP]
rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← mul_assoc, ha]
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
rcases ore_left_cancel _ _ s₂ this with
  ⟨sd, hd⟩
    -- s#
[GOAL]
case mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) = (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb)
[PROOFSTEP]
symm
[GOAL]
case mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ (r₁ * ↑sb + r₂ * rb) /ₒ (s₁ * sb) = (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa)
[PROOFSTEP]
rw [oreDiv_eq_iff]
[GOAL]
case mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ ∃ u v, (r₁ * ↑sa + r₂ * ra) * ↑u = (r₁ * ↑sb + r₂ * rb) * v ∧ ↑(s₁ * sa) * ↑u = ↑(s₁ * sb) * v
[PROOFSTEP]
use sc * sd
[GOAL]
case h
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ ∃ v, (r₁ * ↑sa + r₂ * ra) * ↑(sc * sd) = (r₁ * ↑sb + r₂ * rb) * v ∧ ↑(s₁ * sa) * ↑(sc * sd) = ↑(s₁ * sb) * v
[PROOFSTEP]
use rc * sd
[GOAL]
case h
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ (r₁ * ↑sa + r₂ * ra) * ↑(sc * sd) = (r₁ * ↑sb + r₂ * rb) * (rc * ↑sd) ∧
    ↑(s₁ * sa) * ↑(sc * sd) = ↑(s₁ * sb) * (rc * ↑sd)
[PROOFSTEP]
constructor
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ (r₁ * ↑sa + r₂ * ra) * ↑(sc * sd) = (r₁ * ↑sb + r₂ * rb) * (rc * ↑sd)
[PROOFSTEP]
simp only [Submonoid.coe_mul]
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ ↑(s₁ * sa) * ↑(sc * sd) = ↑(s₁ * sb) * (rc * ↑sd)
[PROOFSTEP]
simp only [Submonoid.coe_mul]
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂) * (↑sc * ↑sd) = (r₁ * ↑sb + r₂ * rb) * (rc * ↑sd)
[PROOFSTEP]
noncomm_ring
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ r₁ * (↑(oreDenom (↑s₁) s₂) * (↑sc * ↑sd)) + r₂ * (oreNum (↑s₁) s₂ * (↑sc * ↑sd)) =
    r₁ * (↑sb * (rc * ↑sd)) + r₂ * (rb * (rc * ↑sd))
[PROOFSTEP]
rw [← mul_assoc (a := rb), hd, ← mul_assoc (a := (sa : R)), hc]
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ r₁ * (↑sb * rc * ↑sd) + r₂ * (oreNum (↑s₁) s₂ * (↑sc * ↑sd)) = r₁ * (↑sb * (rc * ↑sd)) + r₂ * (ra * ↑sc * ↑sd)
[PROOFSTEP]
noncomm_ring
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ ↑s₁ * ↑(oreDenom (↑s₁) s₂) * (↑sc * ↑sd) = ↑s₁ * ↑sb * (rc * ↑sd)
[PROOFSTEP]
rw [mul_assoc (a := (s₁ : R)), ← mul_assoc (a := (sa : R)), hc]
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
rb : R
sb : { x // x ∈ S }
hb : ↑s₁ * ↑sb = ↑s₂ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
rc : R
sc : { x // x ∈ S }
hc : ↑sa * ↑sc = ↑sb * rc
this : ↑s₂ * (rb * rc) = ↑s₂ * (ra * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ra * ↑sc * ↑sd
⊢ ↑s₁ * (↑sb * rc * ↑sd) = ↑s₁ * ↑sb * (rc * ↑sd)
[PROOFSTEP]
noncomm_ring
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
⊢ ∀ (a b : R × { x // x ∈ S }),
    a ≈ b → OreLocalization.add'' a.fst a.snd r₂ s₂ = OreLocalization.add'' b.fst b.snd r₂ s₂
[PROOFSTEP]
rintro ⟨r₁', s₁'⟩ ⟨r₁, s₁⟩
  ⟨sb, rb, hb, hb'⟩
      -- s*, r*
[GOAL]
case mk.mk.intro.intro.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : (r₁, s₁).fst * ↑sb = (r₁', s₁').fst * rb
hb' : ↑(r₁, s₁).snd * ↑sb = ↑(r₁', s₁').snd * rb
⊢ OreLocalization.add'' (r₁', s₁').fst (r₁', s₁').snd r₂ s₂ = OreLocalization.add'' (r₁, s₁).fst (r₁, s₁).snd r₂ s₂
[PROOFSTEP]
rcases oreCondition (s₁' : R) s₂ with
  ⟨rc, sc, hc⟩
    --s~~, r~~
[GOAL]
case mk.mk.intro.intro.intro.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : (r₁, s₁).fst * ↑sb = (r₁', s₁').fst * rb
hb' : ↑(r₁, s₁).snd * ↑sb = ↑(r₁', s₁').snd * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
⊢ OreLocalization.add'' (r₁', s₁').fst (r₁', s₁').snd r₂ s₂ = OreLocalization.add'' (r₁, s₁).fst (r₁, s₁).snd r₂ s₂
[PROOFSTEP]
rcases oreCondition rb sc with
  ⟨rd, sd, hd⟩
    -- s#, r#
[GOAL]
case mk.mk.intro.intro.intro.mk.mk.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : (r₁, s₁).fst * ↑sb = (r₁', s₁').fst * rb
hb' : ↑(r₁, s₁).snd * ↑sb = ↑(r₁', s₁').snd * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
⊢ OreLocalization.add'' (r₁', s₁').fst (r₁', s₁').snd r₂ s₂ = OreLocalization.add'' (r₁, s₁).fst (r₁, s₁).snd r₂ s₂
[PROOFSTEP]
dsimp at *
[GOAL]
case mk.mk.intro.intro.intro.mk.mk.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
⊢ OreLocalization.add'' r₁' s₁' r₂ s₂ = OreLocalization.add'' r₁ s₁ r₂ s₂
[PROOFSTEP]
rw [add''_char _ _ _ _ rc sc hc]
[GOAL]
case mk.mk.intro.intro.intro.mk.mk.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
⊢ (r₁' * ↑sc + r₂ * rc) /ₒ (s₁' * sc) = OreLocalization.add'' r₁ s₁ r₂ s₂
[PROOFSTEP]
have : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd) := by
  simp only [Submonoid.coe_mul]
  rw [← mul_assoc, hb', mul_assoc, hd, ← mul_assoc, hc, mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
⊢ ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
[PROOFSTEP]
simp only [Submonoid.coe_mul]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
⊢ ↑s₁ * (↑sb * ↑sd) = ↑s₂ * (rc * rd)
[PROOFSTEP]
rw [← mul_assoc, hb', mul_assoc, hd, ← mul_assoc, hc, mul_assoc]
[GOAL]
case mk.mk.intro.intro.intro.mk.mk.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
⊢ (r₁' * ↑sc + r₂ * rc) /ₒ (s₁' * sc) = OreLocalization.add'' r₁ s₁ r₂ s₂
[PROOFSTEP]
rw [add''_char _ _ _ _ (rc * rd : R) (sb * sd : S) this]
[GOAL]
case mk.mk.intro.intro.intro.mk.mk.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
⊢ (r₁' * ↑sc + r₂ * rc) /ₒ (s₁' * sc) = (r₁ * ↑(sb * sd) + r₂ * (rc * rd)) /ₒ (s₁ * (sb * sd))
[PROOFSTEP]
simp only [Submonoid.coe_mul]
[GOAL]
case mk.mk.intro.intro.intro.mk.mk.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
⊢ (r₁' * ↑sc + r₂ * rc) /ₒ (s₁' * sc) = (r₁ * (↑sb * ↑sd) + r₂ * (rc * rd)) /ₒ (s₁ * (sb * sd))
[PROOFSTEP]
rw [← mul_assoc (a := r₁) (b := (sb : R)), hb, mul_assoc (a := r₁') (b := (rb : R)), hd, ← mul_assoc, ← mul_assoc, ←
  add_mul, oreDiv_eq_iff]
[GOAL]
case mk.mk.intro.intro.intro.mk.mk.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
⊢ ∃ u v, (r₁' * ↑sc + r₂ * rc) * rd * ↑u = (r₁' * ↑sc + r₂ * rc) * v ∧ ↑(s₁ * (sb * sd)) * ↑u = ↑(s₁' * sc) * v
[PROOFSTEP]
use 1
[GOAL]
case h
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
⊢ ∃ v, (r₁' * ↑sc + r₂ * rc) * rd * ↑1 = (r₁' * ↑sc + r₂ * rc) * v ∧ ↑(s₁ * (sb * sd)) * ↑1 = ↑(s₁' * sc) * v
[PROOFSTEP]
use rd
[GOAL]
case h
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
⊢ (r₁' * ↑sc + r₂ * rc) * rd * ↑1 = (r₁' * ↑sc + r₂ * rc) * rd ∧ ↑(s₁ * (sb * sd)) * ↑1 = ↑(s₁' * sc) * rd
[PROOFSTEP]
constructor
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
⊢ (r₁' * ↑sc + r₂ * rc) * rd * ↑1 = (r₁' * ↑sc + r₂ * rc) * rd
[PROOFSTEP]
simp
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * ↑(sb * sd) = ↑s₂ * (rc * rd)
⊢ ↑(s₁ * (sb * sd)) * ↑1 = ↑(s₁' * sc) * rd
[PROOFSTEP]
simp only [mul_one, Submonoid.coe_one, Submonoid.coe_mul] at this ⊢
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₂ : R
s₂ : { x // x ∈ S }
r₁' : R
s₁' : { x // x ∈ S }
r₁ : R
s₁ : { x // x ∈ S }
sb : { x // x ∈ S }
rb : R
hb : r₁ * ↑sb = r₁' * rb
hb' : ↑s₁ * ↑sb = ↑s₁' * rb
rc : R
sc : { x // x ∈ S }
hc : ↑s₁' * ↑sc = ↑s₂ * rc
rd : R
sd : { x // x ∈ S }
hd : rb * ↑sd = ↑sc * rd
this : ↑s₁ * (↑sb * ↑sd) = ↑s₂ * (rc * rd)
⊢ ↑s₁ * (↑sb * ↑sd) = ↑s₁' * ↑sc * rd
[PROOFSTEP]
rw [hc, this, mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
⊢ OreLocalization.add' r₁ s₁ (r₂ /ₒ s₂) = OreLocalization.add' r₂ s₂ (r₁ /ₒ s₁)
[PROOFSTEP]
simp only [add', oreDiv, add'', Quotient.mk', Quotient.lift_mk]
  -- Porting note: `Quotient.eq` should be used in `rw` instead of `simp`
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
⊢ Quotient.mk (oreEqv R S) (r₂ * ↑(oreDenom (↑s₂) s₁) + r₁ * oreNum (↑s₂) s₁, s₂ * oreDenom (↑s₂) s₁) =
    Quotient.mk (oreEqv R S) (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂, s₁ * oreDenom (↑s₁) s₂)
[PROOFSTEP]
rw [Quotient.eq]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
⊢ (r₂ * ↑(oreDenom (↑s₂) s₁) + r₁ * oreNum (↑s₂) s₁, s₂ * oreDenom (↑s₂) s₁) ≈
    (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂, s₁ * oreDenom (↑s₁) s₂)
[PROOFSTEP]
have hb := ore_eq (↑s₂) s₁
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
hb : ↑s₂ * ↑(oreDenom (↑s₂) s₁) = ↑s₁ * oreNum (↑s₂) s₁
⊢ (r₂ * ↑(oreDenom (↑s₂) s₁) + r₁ * oreNum (↑s₂) s₁, s₂ * oreDenom (↑s₂) s₁) ≈
    (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂, s₁ * oreDenom (↑s₁) s₂)
[PROOFSTEP]
set rb := oreNum (↑s₂) s₁
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
hb : ↑s₂ * ↑(oreDenom (↑s₂) s₁) = ↑s₁ * rb
⊢ (r₂ * ↑(oreDenom (↑s₂) s₁) + r₁ * rb, s₂ * oreDenom (↑s₂) s₁) ≈
    (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂, s₁ * oreDenom (↑s₁) s₂)
[PROOFSTEP]
set sb := oreDenom (↑s₂) s₁
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
⊢ (r₂ * ↑sb + r₁ * rb, s₂ * sb) ≈ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂, s₁ * oreDenom (↑s₁) s₂)
[PROOFSTEP]
have ha := ore_eq (↑s₁) s₂
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * oreNum (↑s₁) s₂
⊢ (r₂ * ↑sb + r₁ * rb, s₂ * sb) ≈ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * oreNum (↑s₁) s₂, s₁ * oreDenom (↑s₁) s₂)
[PROOFSTEP]
set ra := oreNum (↑s₁) s₂
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
ha : ↑s₁ * ↑(oreDenom (↑s₁) s₂) = ↑s₂ * ra
⊢ (r₂ * ↑sb + r₁ * rb, s₂ * sb) ≈ (r₁ * ↑(oreDenom (↑s₁) s₂) + r₂ * ra, s₁ * oreDenom (↑s₁) s₂)
[PROOFSTEP]
set sa := oreDenom (↑s₁) s₂
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
⊢ (r₂ * ↑sb + r₁ * rb, s₂ * sb) ≈ (r₁ * ↑sa + r₂ * ra, s₁ * sa)
[PROOFSTEP]
rcases oreCondition ra sb with
  ⟨rc, sc, hc⟩
    -- r#, s#
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
⊢ (r₂ * ↑sb + r₁ * rb, s₂ * sb) ≈ (r₁ * ↑sa + r₂ * ra, s₁ * sa)
[PROOFSTEP]
have : (s₁ : R) * (rb * rc) = s₁ * (sa * sc) := by rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← ha, mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
⊢ ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
[PROOFSTEP]
rw [← mul_assoc, ← hb, mul_assoc, ← hc, ← mul_assoc, ← ha, mul_assoc]
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
⊢ (r₂ * ↑sb + r₁ * rb, s₂ * sb) ≈ (r₁ * ↑sa + r₂ * ra, s₁ * sa)
[PROOFSTEP]
rcases ore_left_cancel _ _ s₁ this with
  ⟨sd, hd⟩
    -- s+
[GOAL]
case mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ (r₂ * ↑sb + r₁ * rb, s₂ * sb) ≈ (r₁ * ↑sa + r₂ * ra, s₁ * sa)
[PROOFSTEP]
use sc * sd
[GOAL]
case h
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ ∃ v,
    (r₁ * ↑sa + r₂ * ra, s₁ * sa).fst * ↑(sc * sd) = (r₂ * ↑sb + r₁ * rb, s₂ * sb).fst * v ∧
      ↑(r₁ * ↑sa + r₂ * ra, s₁ * sa).snd * ↑(sc * sd) = ↑(r₂ * ↑sb + r₁ * rb, s₂ * sb).snd * v
[PROOFSTEP]
use rc * sd
[GOAL]
case h
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ (r₁ * ↑sa + r₂ * ra, s₁ * sa).fst * ↑(sc * sd) = (r₂ * ↑sb + r₁ * rb, s₂ * sb).fst * (rc * ↑sd) ∧
    ↑(r₁ * ↑sa + r₂ * ra, s₁ * sa).snd * ↑(sc * sd) = ↑(r₂ * ↑sb + r₁ * rb, s₂ * sb).snd * (rc * ↑sd)
[PROOFSTEP]
dsimp
[GOAL]
case h
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : { x // x ∈ 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)
[PROOFSTEP]
constructor
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : { x // x ∈ 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)
[PROOFSTEP]
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]
[GOAL]
case h.left
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : { x // x ∈ 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)
[PROOFSTEP]
simp only [mul_assoc]
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ ↑s₁ * ↑(oreDenom (↑s₁) s₂) * (↑sc * ↑sd) = ↑s₂ * ↑(oreDenom (↑s₂) s₁) * (rc * ↑sd)
[PROOFSTEP]
rw [mul_assoc, ← mul_assoc (sa : R), ← hd, hb]
[GOAL]
case h.right
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ r₂ : R
s₁ s₂ : { x // x ∈ S }
rb : R := oreNum (↑s₂) s₁
sb : { x // x ∈ S } := oreDenom (↑s₂) s₁
hb : ↑s₂ * ↑sb = ↑s₁ * rb
ra : R := oreNum (↑s₁) s₂
sa : { x // x ∈ S } := oreDenom (↑s₁) s₂
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rc : R
sc : { x // x ∈ S }
hc : ra * ↑sc = ↑sb * rc
this : ↑s₁ * (rb * rc) = ↑s₁ * (↑sa * ↑sc)
sd : { x // x ∈ S }
hd : rb * rc * ↑sd = ↑sa * ↑sc * ↑sd
⊢ ↑s₁ * (rb * rc * ↑sd) = ↑s₁ * rb * (rc * ↑sd)
[PROOFSTEP]
simp only [mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
⊢ ∀ (a b : R × { x // x ∈ S }),
    a ≈ b → (fun rs => OreLocalization.add' rs.fst rs.snd x) a = (fun rs => OreLocalization.add' rs.fst rs.snd x) b
[PROOFSTEP]
rintro ⟨r₁, s₁⟩ ⟨r₂, s₂⟩ hyz
[GOAL]
case mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
hyz : (r₁, s₁) ≈ (r₂, s₂)
⊢ (fun rs => OreLocalization.add' rs.fst rs.snd x) (r₁, s₁) = (fun rs => OreLocalization.add' rs.fst rs.snd x) (r₂, s₂)
[PROOFSTEP]
induction' x using OreLocalization.ind with r₃ s₃
[GOAL]
case mk.mk.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
hyz : (r₁, s₁) ≈ (r₂, s₂)
r₃ : R
s₃ : { x // x ∈ S }
⊢ (fun rs => OreLocalization.add' rs.fst rs.snd (r₃ /ₒ s₃)) (r₁, s₁) =
    (fun rs => OreLocalization.add' rs.fst rs.snd (r₃ /ₒ s₃)) (r₂, s₂)
[PROOFSTEP]
dsimp
[GOAL]
case mk.mk.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
hyz : (r₁, s₁) ≈ (r₂, s₂)
r₃ : R
s₃ : { x // x ∈ S }
⊢ OreLocalization.add' r₁ s₁ (r₃ /ₒ s₃) = OreLocalization.add' r₂ s₂ (r₃ /ₒ s₃)
[PROOFSTEP]
rw [add'_comm, add'_comm r₂]
  -- Porting note: `Quotient.mk'` required
[GOAL]
case mk.mk.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
hyz : (r₁, s₁) ≈ (r₂, s₂)
r₃ : R
s₃ : { x // x ∈ S }
⊢ OreLocalization.add' r₃ s₃ (r₁ /ₒ s₁) = OreLocalization.add' r₃ s₃ (r₂ /ₒ s₂)
[PROOFSTEP]
simp [(· /ₒ ·), Quotient.mk', Quotient.sound hyz]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r r' : R
s : { x // x ∈ S }
⊢ r /ₒ s + r' /ₒ s = (r + r') /ₒ s
[PROOFSTEP]
simp [oreDiv_add_char s s 1 1 (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r r' : R
s : { x // x ∈ S }
⊢ ↑s * ↑1 = ↑s * 1
[PROOFSTEP]
simp
[GOAL]
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)
[PROOFSTEP]
induction' x using OreLocalization.ind with r₁ s₁
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
y z : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ + y + z = r₁ /ₒ s₁ + (y + z)
[PROOFSTEP]
induction' y using OreLocalization.ind with r₂ s₂
[GOAL]
case c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
z : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ + r₂ /ₒ s₂ + z = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + z)
[PROOFSTEP]
induction' z using OreLocalization.ind with r₃ s₃
[GOAL]
case c.c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ + r₂ /ₒ s₂ + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + r₃ /ₒ s₃)
[PROOFSTEP]
rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ 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₃)
[PROOFSTEP]
rw [ha']
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ 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₃)
[PROOFSTEP]
clear ha'
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ /ₒ s₂ + r₃ /ₒ s₃)
[PROOFSTEP]
rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨rb, sb, hb, hb'⟩
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ 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₃)
[PROOFSTEP]
rw [hb']
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ 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)
[PROOFSTEP]
clear hb'
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) + r₃ /ₒ s₃ = r₁ /ₒ s₁ + (r₂ * ↑sb + r₃ * rb) /ₒ (s₂ * sb)
[PROOFSTEP]
rcases oreDivAddChar' (r₁ * sa + r₂ * ra) r₃ (s₁ * sa) s₃ with ⟨rc, sc, hc, q⟩
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ 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)
[PROOFSTEP]
rw [q]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ 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)
[PROOFSTEP]
clear q
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ 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)
[PROOFSTEP]
rcases oreDivAddChar' r₁ (r₂ * sb + r₃ * rb) s₁ (s₂ * sb) with ⟨rd, sd, hd, q⟩
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ 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)
[PROOFSTEP]
rw [q]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ 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)
[PROOFSTEP]
clear q
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
⊢ ((r₁ * ↑sa + r₂ * ra) * ↑sc + r₃ * rc) /ₒ (s₁ * sa * sc) = (r₁ * ↑sd + (r₂ * ↑sb + r₃ * rb) * rd) /ₒ (s₁ * sd)
[PROOFSTEP]
simp only [right_distrib, mul_assoc, add_assoc]
  -- Porting note: `simp` required because `repeat' rw` behaves differently
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
⊢ (r₁ * (↑sa * ↑sc) + (r₂ * (ra * ↑sc) + r₃ * rc)) /ₒ (s₁ * (sa * sc)) =
    (r₁ * ↑sd + (r₂ * (↑sb * rd) + r₃ * (rb * rd))) /ₒ (s₁ * sd)
[PROOFSTEP]
simp only [← add_oreDiv]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
⊢ r₁ * (↑sa * ↑sc) /ₒ (s₁ * (sa * sc)) + (r₂ * (ra * ↑sc) /ₒ (s₁ * (sa * sc)) + r₃ * rc /ₒ (s₁ * (sa * sc))) =
    r₁ * ↑sd /ₒ (s₁ * sd) + (r₂ * (↑sb * rd) /ₒ (s₁ * sd) + r₃ * (rb * rd) /ₒ (s₁ * sd))
[PROOFSTEP]
congr 1
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
⊢ r₁ * (↑sa * ↑sc) /ₒ (s₁ * (sa * sc)) = r₁ * ↑sd /ₒ (s₁ * sd)
[PROOFSTEP]
rw [← OreLocalization.expand', ← mul_assoc, ← mul_assoc, ← OreLocalization.expand', ← OreLocalization.expand']
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
⊢ r₂ * (ra * ↑sc) /ₒ (s₁ * (sa * sc)) + r₃ * rc /ₒ (s₁ * (sa * sc)) =
    r₂ * (↑sb * rd) /ₒ (s₁ * sd) + r₃ * (rb * rd) /ₒ (s₁ * sd)
[PROOFSTEP]
congr 1
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
⊢ r₂ * (ra * ↑sc) /ₒ (s₁ * (sa * sc)) = r₂ * (↑sb * rd) /ₒ (s₁ * sd)
[PROOFSTEP]
simp_rw [← Submonoid.coe_mul] at ha hd 
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑(s₁ * sd) = ↑(s₂ * sb) * rd
⊢ r₂ * (ra * ↑sc) /ₒ (s₁ * (sa * sc)) = r₂ * (↑sb * rd) /ₒ (s₁ * sd)
[PROOFSTEP]
rw [Subtype.coe_eq_of_eq_mk hd, ← mul_assoc, ← mul_assoc, ← mul_assoc, ← OreLocalization.expand, ←
  OreLocalization.expand', Subtype.coe_eq_of_eq_mk ha, ← OreLocalization.expand]
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑(s₁ * sd) = ↑(s₂ * sb) * rd
⊢ r₂ /ₒ s₂ = r₂ * ↑sb /ₒ (s₂ * sb)
[PROOFSTEP]
apply OreLocalization.expand'
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
⊢ r₃ * rc /ₒ (s₁ * (sa * sc)) = r₃ * (rb * rd) /ₒ (s₁ * sd)
[PROOFSTEP]
rcases oreCondition (sd : R) (sa * sc) with ⟨re, _, _⟩
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a.e_a.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑s₂ * ↑sb = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa) * ↑sc = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑s₁ * ↑sd = ↑(s₂ * sb) * rd
re : R
fst✝ : { x // x ∈ S }
snd✝ : ↑sd * ↑fst✝ = ↑(sa * sc) * re
⊢ r₃ * rc /ₒ (s₁ * (sa * sc)) = r₃ * (rb * rd) /ₒ (s₁ * sd)
[PROOFSTEP]
simp_rw [← Submonoid.coe_mul] at hb hc hd 
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a.e_a.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑(s₂ * sb) = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa * sc) = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑(s₁ * sd) = ↑(s₂ * sb) * rd
re : R
fst✝ : { x // x ∈ S }
snd✝ : ↑sd * ↑fst✝ = ↑(sa * sc) * re
⊢ r₃ * rc /ₒ (s₁ * (sa * sc)) = r₃ * (rb * rd) /ₒ (s₁ * sd)
[PROOFSTEP]
rw [← mul_assoc, Subtype.coe_eq_of_eq_mk hc]
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a.e_a.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑(s₂ * sb) = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa * sc) = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑(s₁ * sd) = ↑(s₂ * sb) * rd
re : R
fst✝ : { x // x ∈ S }
snd✝ : ↑sd * ↑fst✝ = ↑(sa * sc) * re
⊢ r₃ * rc /ₒ { val := ↑s₃ * rc, property := (_ : ↑s₃ * rc ∈ ↑S) } = r₃ * (rb * rd) /ₒ (s₁ * sd)
[PROOFSTEP]
rw [← OreLocalization.expand, Subtype.coe_eq_of_eq_mk hd, ← mul_assoc, ← OreLocalization.expand,
  Subtype.coe_eq_of_eq_mk hb]
[GOAL]
case c.c.c.mk.mk.intro.mk.mk.intro.mk.mk.intro.mk.mk.intro.e_a.e_a.mk.mk
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
rb : R
sb : { x // x ∈ S }
hb : ↑(s₂ * sb) = ↑s₃ * rb
rc : R
sc : { x // x ∈ S }
hc : ↑(s₁ * sa * sc) = ↑s₃ * rc
rd : R
sd : { x // x ∈ S }
hd : ↑(s₁ * sd) = ↑(s₂ * sb) * rd
re : R
fst✝ : { x // x ∈ S }
snd✝ : ↑sd * ↑fst✝ = ↑(sa * sc) * re
⊢ r₃ /ₒ s₃ = r₃ * rb /ₒ { val := ↑s₃ * rb, property := (_ : ↑s₃ * rb ∈ ↑S) }
[PROOFSTEP]
apply OreLocalization.expand
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
s : { x // x ∈ S }
⊢ 0 /ₒ s = 0
[PROOFSTEP]
rw [OreLocalization.zero_def, oreDiv_eq_iff]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
s : { x // x ∈ S }
⊢ ∃ u v, 0 * ↑u = 0 * v ∧ ↑1 * ↑u = ↑s * v
[PROOFSTEP]
exact ⟨s, 1, by simp⟩
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
s : { x // x ∈ S }
⊢ 0 * ↑s = 0 * 1 ∧ ↑1 * ↑s = ↑s * 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
⊢ 0 + x = x
[PROOFSTEP]
induction x using OreLocalization.ind
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r✝ : R
s✝ : { x // x ∈ S }
⊢ 0 + r✝ /ₒ s✝ = r✝ /ₒ s✝
[PROOFSTEP]
rw [← zero_div_eq_zero, add_oreDiv]
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r✝ : R
s✝ : { x // x ∈ S }
⊢ (0 + r✝) /ₒ s✝ = r✝ /ₒ s✝
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x y : OreLocalization R S
⊢ x + y = y + x
[PROOFSTEP]
induction x using OreLocalization.ind
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
y : OreLocalization R S
r✝ : R
s✝ : { x // x ∈ S }
⊢ r✝ /ₒ s✝ + y = y + r✝ /ₒ s✝
[PROOFSTEP]
induction y using OreLocalization.ind
[GOAL]
case c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r✝¹ : R
s✝¹ : { x // x ∈ S }
r✝ : R
s✝ : { x // x ∈ S }
⊢ r✝¹ /ₒ s✝¹ + r✝ /ₒ s✝ = r✝ /ₒ s✝ + r✝¹ /ₒ s✝¹
[PROOFSTEP]
change add' _ _ (_ /ₒ _) = _
[GOAL]
case c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r✝¹ : R
s✝¹ : { x // x ∈ S }
r✝ : R
s✝ : { x // x ∈ S }
⊢ OreLocalization.add' (r✝, s✝).fst (r✝, s✝).snd (r✝¹ /ₒ s✝¹) = r✝ /ₒ s✝ + r✝¹ /ₒ s✝¹
[PROOFSTEP]
apply add'_comm
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
src✝ : Add (OreLocalization R S) := instAddOreLocalization
x : OreLocalization R S
⊢ x + 0 = x
[PROOFSTEP]
rw [OreLocalization.add_comm, OreLocalization.zero_add]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
⊢ 0 * x = 0
[PROOFSTEP]
induction' x using OreLocalization.ind with r s
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ 0 * (r /ₒ s) = 0
[PROOFSTEP]
rw [OreLocalization.zero_def, oreDiv_mul_char 0 r 1 s r 1 (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ r * ↑1 = ↑1 * r
[PROOFSTEP]
simp
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ 0 * r /ₒ (s * 1) = 0 /ₒ 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
⊢ x * 0 = 0
[PROOFSTEP]
induction' x using OreLocalization.ind with r s
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ r /ₒ s * 0 = 0
[PROOFSTEP]
rw [OreLocalization.zero_def, oreDiv_mul_char r 0 s 1 0 1 (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ 0 * ↑1 = ↑s * 0
[PROOFSTEP]
simp
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ r * 0 /ₒ (1 * 1) = 0 /ₒ 1
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x y z : OreLocalization R S
⊢ x * (y + z) = x * y + x * z
[PROOFSTEP]
induction' x using OreLocalization.ind with r₁ s₁
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
y z : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * (y + z) = r₁ /ₒ s₁ * y + r₁ /ₒ s₁ * z
[PROOFSTEP]
induction' y using OreLocalization.ind with r₂ s₂
[GOAL]
case c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
z : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * (r₂ /ₒ s₂ + z) = r₁ /ₒ s₁ * (r₂ /ₒ s₂) + r₁ /ₒ s₁ * z
[PROOFSTEP]
induction' z using OreLocalization.ind with r₃ s₃
[GOAL]
case c.c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
⊢ r₁ /ₒ s₁ * (r₂ /ₒ s₂ + r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ /ₒ s₂) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
rcases oreDivAddChar' r₂ r₃ s₂ s₃ with ⟨ra, sa, ha, q⟩
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
q : r₂ /ₒ s₂ + r₃ /ₒ s₃ = (r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)
⊢ r₁ /ₒ s₁ * (r₂ /ₒ s₂ + r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₂ /ₒ s₂) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [q]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
q : r₂ /ₒ s₂ + r₃ /ₒ s₃ = (r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = r₁ /ₒ s₁ * (r₂ /ₒ s₂) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
clear q
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = r₁ /ₒ s₁ * (r₂ /ₒ s₂) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [OreLocalization.expand' r₂ s₂ sa]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = r₁ /ₒ s₁ * (r₂ * ↑sa /ₒ (s₂ * sa)) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
rcases oreDivMulChar' r₁ (r₂ * sa) s₁ (s₂ * sa) with ⟨rb, sb, hb, q⟩
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
q : r₁ /ₒ s₁ * (r₂ * ↑sa /ₒ (s₂ * sa)) = r₁ * rb /ₒ (s₂ * sa * sb)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = r₁ /ₒ s₁ * (r₂ * ↑sa /ₒ (s₂ * sa)) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [q]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
q : r₁ /ₒ s₁ * (r₂ * ↑sa /ₒ (s₂ * sa)) = r₁ * rb /ₒ (s₂ * sa * sb)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = r₁ * rb /ₒ (s₂ * sa * sb) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
clear q
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = r₁ * rb /ₒ (s₂ * sa * sb) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
have hs₃rasb : ↑s₃ * (ra * sb) ∈ S := by
  rw [← mul_assoc, ← ha]
  norm_cast
  apply SetLike.coe_mem
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
⊢ ↑s₃ * (ra * ↑sb) ∈ S
[PROOFSTEP]
rw [← mul_assoc, ← ha]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
⊢ ↑s₂ * ↑sa * ↑sb ∈ S
[PROOFSTEP]
norm_cast
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
⊢ ↑(s₂ * sa * sb) ∈ S
[PROOFSTEP]
apply SetLike.coe_mem
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = r₁ * rb /ₒ (s₂ * sa * sb) + r₁ /ₒ s₁ * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [OreLocalization.expand _ _ _ hs₃rasb]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) =
    r₁ * rb /ₒ (s₂ * sa * sb) + r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ { val := ↑s₃ * (ra * ↑sb), property := hs₃rasb })
[PROOFSTEP]
have ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * sb) := by simp [ha, ← mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
⊢ ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
[PROOFSTEP]
simp [ha, ← mul_assoc]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) =
    r₁ * rb /ₒ (s₂ * sa * sb) + r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ { val := ↑s₃ * (ra * ↑sb), property := hs₃rasb })
[PROOFSTEP]
rw [← Subtype.coe_eq_of_eq_mk ha']
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) =
    r₁ * rb /ₒ (s₂ * sa * sb) + r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb))
[PROOFSTEP]
rcases oreDivMulChar' r₁ (r₃ * (ra * sb)) s₁ (s₂ * sa * sb) with ⟨rc, sc, hc, hc'⟩
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) =
    r₁ * rb /ₒ (s₂ * sa * sb) + r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb))
[PROOFSTEP]
rw [hc']
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = r₁ * rb /ₒ (s₂ * sa * sb) + r₁ * rc /ₒ (s₂ * sa * sb * sc)
[PROOFSTEP]
rw [oreDiv_add_char (s₂ * sa * sb) (s₂ * sa * sb * sc) 1 sc (by simp)]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
⊢ ↑(s₂ * sa * sb) * ↑sc = ↑(s₂ * sa * sb * sc) * 1
[PROOFSTEP]
simp
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) /ₒ (s₂ * sa)) = (r₁ * rb * ↑sc + r₁ * rc * 1) /ₒ (s₂ * sa * sb * sc)
[PROOFSTEP]
rw [OreLocalization.expand' (r₂ * ↑sa + r₃ * ra) (s₂ * sa) (sb * sc)]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
⊢ r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) * ↑(sb * sc) /ₒ (s₂ * sa * (sb * sc))) =
    (r₁ * rb * ↑sc + r₁ * rc * 1) /ₒ (s₂ * sa * sb * sc)
[PROOFSTEP]
conv_lhs =>
  congr
  ·skip
  congr
  rw [add_mul, S.coe_mul, ← mul_assoc, hb, ← mul_assoc, mul_assoc r₃, hc, mul_assoc, ← mul_add]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) * ↑(sb * sc) /ₒ (s₂ * sa * (sb * sc)))
[PROOFSTEP]
  congr
  ·skip
  congr
  rw [add_mul, S.coe_mul, ← mul_assoc, hb, ← mul_assoc, mul_assoc r₃, hc, mul_assoc, ← mul_add]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) * ↑(sb * sc) /ₒ (s₂ * sa * (sb * sc)))
[PROOFSTEP]
  congr
  ·skip
  congr
  rw [add_mul, S.coe_mul, ← mul_assoc, hb, ← mul_assoc, mul_assoc r₃, hc, mul_assoc, ← mul_add]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| r₁ /ₒ s₁ * ((r₂ * ↑sa + r₃ * ra) * ↑(sb * sc) /ₒ (s₂ * sa * (sb * sc)))
[PROOFSTEP]
congr
[GOAL]
case a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| r₁ /ₒ s₁
case a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| (r₂ * ↑sa + r₃ * ra) * ↑(sb * sc) /ₒ (s₂ * sa * (sb * sc))
[PROOFSTEP]
·skip
[GOAL]
case a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| r₁ /ₒ s₁
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| r₁ /ₒ s₁
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| r₁ /ₒ s₁
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| (r₂ * ↑sa + r₃ * ra) * ↑(sb * sc) /ₒ (s₂ * sa * (sb * sc))
[PROOFSTEP]
congr
[GOAL]
case a.r
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| (r₂ * ↑sa + r₃ * ra) * ↑(sb * sc)
case a.s
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
| s₂ * sa * (sb * sc)
[PROOFSTEP]
rw [add_mul, S.coe_mul, ← mul_assoc, hb, ← mul_assoc, mul_assoc r₃, hc, mul_assoc, ← mul_add]
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
⊢ r₁ /ₒ s₁ * (↑s₁ * (rb * ↑sc + rc) /ₒ (s₂ * sa * (sb * sc))) = (r₁ * rb * ↑sc + r₁ * rc * 1) /ₒ (s₂ * sa * sb * sc)
[PROOFSTEP]
rw [OreLocalization.mul_cancel']
[GOAL]
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₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₂ * ↑sa = ↑s₃ * ra
rb : R
sb : { x // x ∈ S }
hb : r₂ * ↑sa * ↑sb = ↑s₁ * rb
hs₃rasb : ↑s₃ * (ra * ↑sb) ∈ S
ha' : ↑(s₂ * sa * sb) = ↑s₃ * (ra * ↑sb)
rc : R
sc : { x // x ∈ S }
hc : r₃ * (ra * ↑sb) * ↑sc = ↑s₁ * rc
hc' : r₁ /ₒ s₁ * (r₃ * (ra * ↑sb) /ₒ (s₂ * sa * sb)) = r₁ * rc /ₒ (s₂ * sa * sb * sc)
⊢ r₁ * (rb * ↑sc + rc) /ₒ (s₂ * sa * (sb * sc)) = (r₁ * rb * ↑sc + r₁ * rc * 1) /ₒ (s₂ * sa * sb * sc)
[PROOFSTEP]
simp only [mul_one, Submonoid.coe_mul, mul_add, ← mul_assoc]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
x y z : OreLocalization R S
⊢ (x + y) * z = x * z + y * z
[PROOFSTEP]
induction' x using OreLocalization.ind with r₁ s₁
[GOAL]
case c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
y z : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
⊢ (r₁ /ₒ s₁ + y) * z = r₁ /ₒ s₁ * z + y * z
[PROOFSTEP]
induction' y using OreLocalization.ind with r₂ s₂
[GOAL]
case c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
z : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
⊢ (r₁ /ₒ s₁ + r₂ /ₒ s₂) * z = r₁ /ₒ s₁ * z + r₂ /ₒ s₂ * z
[PROOFSTEP]
induction' z using OreLocalization.ind with r₃ s₃
[GOAL]
case c.c.c
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
⊢ (r₁ /ₒ s₁ + r₂ /ₒ s₂) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₃ /ₒ s₃) + r₂ /ₒ s₂ * (r₃ /ₒ s₃)
[PROOFSTEP]
rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨ra, sa, ha, ha'⟩
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ 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₂ * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [ha']
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ 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₂ * (r₃ /ₒ s₃)
[PROOFSTEP]
clear ha'
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑s₁ * ↑sa = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₃ /ₒ s₃) + r₂ /ₒ s₂ * (r₃ /ₒ s₃)
[PROOFSTEP]
norm_cast at ha 
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) * (r₃ /ₒ s₃) = r₁ /ₒ s₁ * (r₃ /ₒ s₃) + r₂ /ₒ s₂ * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [OreLocalization.expand' r₁ s₁ sa]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) * (r₃ /ₒ s₃) = r₁ * ↑sa /ₒ (s₁ * sa) * (r₃ /ₒ s₃) + r₂ /ₒ s₂ * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [OreLocalization.expand r₂ s₂ ra (by rw [← ha]; apply SetLike.coe_mem)]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ ↑s₂ * ra ∈ S
[PROOFSTEP]
rw [← ha]
[GOAL]
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ ↑(s₁ * sa) ∈ S
[PROOFSTEP]
apply SetLike.coe_mem
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) * (r₃ /ₒ s₃) =
    r₁ * ↑sa /ₒ (s₁ * sa) * (r₃ /ₒ s₃) + r₂ * ra /ₒ { val := ↑s₂ * ra, property := (_ : ↑s₂ * ra ∈ S) } * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [← Subtype.coe_eq_of_eq_mk ha]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) * (r₃ /ₒ s₃) =
    r₁ * ↑sa /ₒ (s₁ * sa) * (r₃ /ₒ s₃) + r₂ * ra /ₒ (s₁ * sa) * (r₃ /ₒ s₃)
[PROOFSTEP]
repeat rw [oreDiv_mul_oreDiv]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) /ₒ (s₁ * sa) * (r₃ /ₒ s₃) =
    r₁ * ↑sa /ₒ (s₁ * sa) * (r₃ /ₒ s₃) + r₂ * ra /ₒ (s₁ * sa) * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [oreDiv_mul_oreDiv]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa)) =
    r₁ * ↑sa /ₒ (s₁ * sa) * (r₃ /ₒ s₃) + r₂ * ra /ₒ (s₁ * sa) * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [oreDiv_mul_oreDiv]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa)) =
    r₁ * ↑sa * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa)) + r₂ * ra /ₒ (s₁ * sa) * (r₃ /ₒ s₃)
[PROOFSTEP]
rw [oreDiv_mul_oreDiv]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa)) =
    r₁ * ↑sa * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa)) +
      r₂ * ra * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa))
[PROOFSTEP]
rw [oreDiv_mul_oreDiv]
[GOAL]
case c.c.c.mk.mk.intro
R : Type u_1
inst✝¹ : Semiring R
S : Submonoid R
inst✝ : OreSet S
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
ra : R
sa : { x // x ∈ S }
ha : ↑(s₁ * sa) = ↑s₂ * ra
⊢ (r₁ * ↑sa + r₂ * ra) * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa)) =
    r₁ * ↑sa * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa)) +
      r₂ * ra * oreNum r₃ (s₁ * sa) /ₒ (s₃ * oreDenom r₃ (s₁ * sa))
[PROOFSTEP]
simp only [add_mul, add_oreDiv]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
⊢ OneHom.toFun
      (↑{ toOneHom := ↑src✝,
          map_mul' :=
            (_ :
              ∀ (x y : OreLocalization R S),
                OneHom.toFun (↑src✝) (x * y) = OneHom.toFun (↑src✝) x * OneHom.toFun (↑src✝) y) })
      0 =
    0
[PROOFSTEP]
change (universalMulHom f.toMonoidHom fS hf : R[S⁻¹] → T) 0 = 0
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
⊢ ↑(universalMulHom (↑f) fS hf) 0 = 0
[PROOFSTEP]
rw [OreLocalization.zero_def, universalMulHom_apply]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
⊢ ↑↑f 0 * ↑(↑fS 1)⁻¹ = 0
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
x y : OreLocalization R S
⊢ OneHom.toFun
      (↑{ toOneHom := ↑src✝,
          map_mul' :=
            (_ :
              ∀ (x y : OreLocalization R S),
                OneHom.toFun (↑src✝) (x * y) = OneHom.toFun (↑src✝) x * OneHom.toFun (↑src✝) y) })
      (x + y) =
    OneHom.toFun
        (↑{ toOneHom := ↑src✝,
            map_mul' :=
              (_ :
                ∀ (x y : OreLocalization R S),
                  OneHom.toFun (↑src✝) (x * y) = OneHom.toFun (↑src✝) x * OneHom.toFun (↑src✝) y) })
        x +
      OneHom.toFun
        (↑{ toOneHom := ↑src✝,
            map_mul' :=
              (_ :
                ∀ (x y : OreLocalization R S),
                  OneHom.toFun (↑src✝) (x * y) = OneHom.toFun (↑src✝) x * OneHom.toFun (↑src✝) y) })
        y
[PROOFSTEP]
change
  (universalMulHom f.toMonoidHom fS hf : R[S⁻¹] → T) (x + y) =
    (universalMulHom f.toMonoidHom fS hf : R[S⁻¹] → T) x + (universalMulHom f.toMonoidHom fS hf : R[S⁻¹] → T) y
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
x y : OreLocalization R S
⊢ ↑(universalMulHom (↑f) fS hf) (x + y) = ↑(universalMulHom (↑f) fS hf) x + ↑(universalMulHom (↑f) fS hf) y
[PROOFSTEP]
induction' x using OreLocalization.ind with r₁ s₁
[GOAL]
case c
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
y : OreLocalization R S
r₁ : R
s₁ : { x // x ∈ S }
⊢ ↑(universalMulHom (↑f) fS hf) (r₁ /ₒ s₁ + y) =
    ↑(universalMulHom (↑f) fS hf) (r₁ /ₒ s₁) + ↑(universalMulHom (↑f) fS hf) y
[PROOFSTEP]
induction' y using OreLocalization.ind with r₂ s₂
[GOAL]
case c.c
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
⊢ ↑(universalMulHom (↑f) fS hf) (r₁ /ₒ s₁ + r₂ /ₒ s₂) =
    ↑(universalMulHom (↑f) fS hf) (r₁ /ₒ s₁) + ↑(universalMulHom (↑f) fS hf) (r₂ /ₒ s₂)
[PROOFSTEP]
rcases oreDivAddChar' r₁ r₂ s₁ s₂ with ⟨r₃, s₃, h₃, h₃'⟩
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
h₃' : r₁ /ₒ s₁ + r₂ /ₒ s₂ = (r₁ * ↑s₃ + r₂ * r₃) /ₒ (s₁ * s₃)
⊢ ↑(universalMulHom (↑f) fS hf) (r₁ /ₒ s₁ + r₂ /ₒ s₂) =
    ↑(universalMulHom (↑f) fS hf) (r₁ /ₒ s₁) + ↑(universalMulHom (↑f) fS hf) (r₂ /ₒ s₂)
[PROOFSTEP]
rw [h₃']
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
h₃' : r₁ /ₒ s₁ + r₂ /ₒ s₂ = (r₁ * ↑s₃ + r₂ * r₃) /ₒ (s₁ * s₃)
⊢ ↑(universalMulHom (↑f) fS hf) ((r₁ * ↑s₃ + r₂ * r₃) /ₒ (s₁ * s₃)) =
    ↑(universalMulHom (↑f) fS hf) (r₁ /ₒ s₁) + ↑(universalMulHom (↑f) fS hf) (r₂ /ₒ s₂)
[PROOFSTEP]
clear h₃'
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
⊢ ↑(universalMulHom (↑f) fS hf) ((r₁ * ↑s₃ + r₂ * r₃) /ₒ (s₁ * s₃)) =
    ↑(universalMulHom (↑f) fS hf) (r₁ /ₒ s₁) + ↑(universalMulHom (↑f) fS hf) (r₂ /ₒ s₂)
[PROOFSTEP]
simp only [universalMulHom_apply, RingHom.toMonoidHom_eq_coe, MonoidHom.coe_coe]
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
⊢ ↑f (r₁ * ↑s₃ + r₂ * r₃) * ↑(↑fS (s₁ * s₃))⁻¹ = ↑f r₁ * ↑(↑fS s₁)⁻¹ + ↑f r₂ * ↑(↑fS s₂)⁻¹
[PROOFSTEP]
simp only [mul_inv_rev, MonoidHom.map_mul, RingHom.map_add, RingHom.map_mul, Units.val_mul]
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
⊢ (↑f r₁ * ↑f ↑s₃ + ↑f r₂ * ↑f r₃) * (↑(↑fS s₃)⁻¹ * ↑(↑fS s₁)⁻¹) = ↑f r₁ * ↑(↑fS s₁)⁻¹ + ↑f r₂ * ↑(↑fS s₂)⁻¹
[PROOFSTEP]
rw [add_mul, ← mul_assoc, mul_assoc (f r₁), hf, ← Units.val_mul]
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
⊢ ↑f r₁ * ↑(↑fS s₃ * (↑fS s₃)⁻¹) * ↑(↑fS s₁)⁻¹ + ↑f r₂ * ↑f r₃ * (↑(↑fS s₃)⁻¹ * ↑(↑fS s₁)⁻¹) =
    ↑f r₁ * ↑(↑fS s₁)⁻¹ + ↑f r₂ * ↑(↑fS s₂)⁻¹
[PROOFSTEP]
simp only [mul_one, mul_right_inv, Units.val_one]
[GOAL]
case c.c.mk.mk.intro
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
⊢ ↑f r₁ * ↑(↑fS s₁)⁻¹ + ↑f r₂ * ↑f r₃ * (↑(↑fS s₃)⁻¹ * ↑(↑fS s₁)⁻¹) = ↑f r₁ * ↑(↑fS s₁)⁻¹ + ↑f r₂ * ↑(↑fS s₂)⁻¹
[PROOFSTEP]
congr 1
[GOAL]
case c.c.mk.mk.intro.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
⊢ ↑f r₂ * ↑f r₃ * (↑(↑fS s₃)⁻¹ * ↑(↑fS s₁)⁻¹) = ↑f r₂ * ↑(↑fS s₂)⁻¹
[PROOFSTEP]
rw [mul_assoc]
[GOAL]
case c.c.mk.mk.intro.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
⊢ ↑f r₂ * (↑f r₃ * (↑(↑fS s₃)⁻¹ * ↑(↑fS s₁)⁻¹)) = ↑f r₂ * ↑(↑fS s₂)⁻¹
[PROOFSTEP]
congr 1
[GOAL]
case c.c.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑s₁ * ↑s₃ = ↑s₂ * r₃
⊢ ↑f r₃ * (↑(↑fS s₃)⁻¹ * ↑(↑fS s₁)⁻¹) = ↑(↑fS s₂)⁻¹
[PROOFSTEP]
norm_cast at h₃ 
[GOAL]
case c.c.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
⊢ ↑f r₃ * (↑(↑fS s₃)⁻¹ * ↑(↑fS s₁)⁻¹) = ↑(↑fS s₂)⁻¹
[PROOFSTEP]
have h₃' := Subtype.coe_eq_of_eq_mk h₃
[GOAL]
case c.c.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
⊢ ↑f r₃ * (↑(↑fS s₃)⁻¹ * ↑(↑fS s₁)⁻¹) = ↑(↑fS s₂)⁻¹
[PROOFSTEP]
rw [← Units.val_mul, ← mul_inv_rev, ← fS.map_mul, h₃']
[GOAL]
case c.c.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
⊢ ↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹ = ↑(↑fS s₂)⁻¹
[PROOFSTEP]
have hs₂r₃ : ↑s₂ * r₃ ∈ S := by
  rw [← h₃]
  exact SetLike.coe_mem (s₁ * s₃)
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
⊢ ↑s₂ * r₃ ∈ S
[PROOFSTEP]
rw [← h₃]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
⊢ ↑(s₁ * s₃) ∈ S
[PROOFSTEP]
exact SetLike.coe_mem (s₁ * s₃)
[GOAL]
case c.c.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
⊢ ↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹ = ↑(↑fS s₂)⁻¹
[PROOFSTEP]
apply (Units.inv_mul_cancel_left (fS s₂) _).symm.trans
[GOAL]
case c.c.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
⊢ ↑(↑fS s₂)⁻¹ * (↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹)) = ↑(↑fS s₂)⁻¹
[PROOFSTEP]
conv_lhs =>
  congr
  ·skip
  rw [← Units.mul_inv_cancel_left (fS ⟨s₂ * r₃, hs₂r₃⟩) (fS s₂), mul_assoc, mul_assoc]
  congr
  ·skip
  rw [← hf, ← mul_assoc (f s₂), ← f.map_mul]
  conv =>
    congr
    ·skip
    congr
    rw [← h₃]
  rw [hf, ← mul_assoc, ← h₃', Units.inv_mul]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂)⁻¹ * (↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹))
[PROOFSTEP]
  congr
  ·skip
  rw [← Units.mul_inv_cancel_left (fS ⟨s₂ * r₃, hs₂r₃⟩) (fS s₂), mul_assoc, mul_assoc]
  congr
  ·skip
  rw [← hf, ← mul_assoc (f s₂), ← f.map_mul]
  conv =>
    congr
    ·skip
    congr
    rw [← h₃]
  rw [hf, ← mul_assoc, ← h₃', Units.inv_mul]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂)⁻¹ * (↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹))
[PROOFSTEP]
  congr
  ·skip
  rw [← Units.mul_inv_cancel_left (fS ⟨s₂ * r₃, hs₂r₃⟩) (fS s₂), mul_assoc, mul_assoc]
  congr
  ·skip
  rw [← hf, ← mul_assoc (f s₂), ← f.map_mul]
  conv =>
    congr
    ·skip
    congr
    rw [← h₃]
  rw [hf, ← mul_assoc, ← h₃', Units.inv_mul]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂)⁻¹ * (↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹))
[PROOFSTEP]
congr
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂)⁻¹
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹)
[PROOFSTEP]
·skip
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂)⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂)⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂)⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹)
[PROOFSTEP]
rw [← Units.mul_inv_cancel_left (fS ⟨s₂ * r₃, hs₂r₃⟩) (fS s₂), mul_assoc, mul_assoc]
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ }) *
    (↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹ *
      (↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹)))
[PROOFSTEP]
congr
[GOAL]
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹ *
    (↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹))
[PROOFSTEP]
·skip
[GOAL]
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })
[PROOFSTEP]
skip
[GOAL]
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })
[PROOFSTEP]
skip
[GOAL]
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })
[PROOFSTEP]
skip
[GOAL]
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹ *
    (↑(↑fS s₂) * (↑f r₃ * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹))
[PROOFSTEP]
rw [← hf, ← mul_assoc (f s₂), ← f.map_mul]
[GOAL]
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹ *
    (↑f (↑s₂ * r₃) * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹)
[PROOFSTEP]
conv =>
  congr
  ·skip
  congr
  rw [← h₃]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹ *
    (↑f (↑s₂ * r₃) * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹)
[PROOFSTEP]
  congr
  ·skip
  congr
  rw [← h₃]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹ *
    (↑f (↑s₂ * r₃) * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹)
[PROOFSTEP]
congr
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑f (↑s₂ * r₃) * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹
[PROOFSTEP]
·skip
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹
[PROOFSTEP]
skip
[GOAL]
case a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑f (↑s₂ * r₃) * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹
[PROOFSTEP]
congr
[GOAL]
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑f (↑s₂ * r₃)
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹
[PROOFSTEP]
rw [← h₃]
[GOAL]
case a.a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
| ↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ })⁻¹ *
    (↑f ↑(s₁ * s₃) * ↑(↑fS { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) })⁻¹)
[PROOFSTEP]
rw [hf, ← mul_assoc, ← h₃', Units.inv_mul]
[GOAL]
case c.c.mk.mk.intro.e_a.e_a
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
src✝ : OreLocalization R S →* T := universalMulHom (↑f) fS hf
r₁ : R
s₁ : { x // x ∈ S }
r₂ : R
s₂ : { x // x ∈ S }
r₃ : R
s₃ : { x // x ∈ S }
h₃ : ↑(s₁ * s₃) = ↑s₂ * r₃
h₃' : s₁ * s₃ = { val := ↑s₂ * r₃, property := (_ : ↑s₂ * r₃ ∈ ↑S) }
hs₂r₃ : ↑s₂ * r₃ ∈ S
⊢ ↑(↑fS s₂)⁻¹ * (↑(↑fS { val := ↑s₂ * r₃, property := hs₂r₃ }) * (1 * ↑(↑fS (s₁ * s₃))⁻¹)) = ↑(↑fS s₂)⁻¹
[PROOFSTEP]
rw [one_mul, ← h₃', Units.mul_inv, mul_one]
[GOAL]
R : Type u_1
inst✝² : Semiring R
S : Submonoid R
inst✝¹ : OreSet S
T : Type u_2
inst✝ : Semiring T
f : R →+* T
fS : { x // x ∈ S } →* Tˣ
hf : ∀ (s : { x // x ∈ S }), ↑f ↑s = ↑(↑fS s)
r : R
⊢ ↑(universalHom f fS hf) (↑numeratorHom r) = ↑f r
[PROOFSTEP]
simp [numeratorHom_apply, universalHom_apply]
[GOAL]
R : Type u_1
inst✝¹ : Ring R
S : Submonoid R
inst✝ : OreSet S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
⊢ (fun r s => -r /ₒ s) r s = (fun r s => -r /ₒ s) (r * t) { val := ↑s * t, property := ht }
[PROOFSTEP]
simp only []
[GOAL]
R : Type u_1
inst✝¹ : Ring R
S : Submonoid R
inst✝ : OreSet S
r t : R
s : { x // x ∈ S }
ht : ↑s * t ∈ S
⊢ -r /ₒ s = -(r * t) /ₒ { val := ↑s * t, property := ht }
[PROOFSTEP]
rw [neg_mul_eq_neg_mul, ← OreLocalization.expand]
[GOAL]
R : Type u_1
inst✝¹ : Ring R
S : Submonoid R
inst✝ : OreSet S
x : OreLocalization R S
⊢ -x + x = 0
[PROOFSTEP]
induction' x using OreLocalization.ind with r s
[GOAL]
case c
R : Type u_1
inst✝¹ : Ring R
S : Submonoid R
inst✝ : OreSet S
r : R
s : { x // x ∈ S }
⊢ -(r /ₒ s) + r /ₒ s = 0
[PROOFSTEP]
simp
[GOAL]
R : Type u_1
inst✝¹ : Ring R
S : Submonoid R
inst✝ : OreSet S
hS : S ≤ R⁰
r₁ r₂ : R
h : ↑numeratorHom r₁ = ↑numeratorHom r₂
⊢ r₁ = r₂
[PROOFSTEP]
rw [numeratorHom_apply, numeratorHom_apply, oreDiv_eq_iff] at h 
[GOAL]
R : Type u_1
inst✝¹ : Ring R
S : Submonoid R
inst✝ : OreSet S
hS : S ≤ R⁰
r₁ r₂ : R
h : ∃ u v, r₂ * ↑u = r₁ * v ∧ ↑1 * ↑u = ↑1 * v
⊢ r₁ = r₂
[PROOFSTEP]
rcases h with ⟨u, v, h₁, h₂⟩
[GOAL]
case intro.intro.intro
R : Type u_1
inst✝¹ : Ring R
S : Submonoid R
inst✝ : OreSet S
hS : S ≤ R⁰
r₁ r₂ : R
u : { x // x ∈ S }
v : R
h₁ : r₂ * ↑u = r₁ * v
h₂ : ↑1 * ↑u = ↑1 * v
⊢ r₁ = r₂
[PROOFSTEP]
simp only [S.coe_one, one_mul] at h₂ 
[GOAL]
case intro.intro.intro
R : Type u_1
inst✝¹ : Ring R
S : Submonoid R
inst✝ : OreSet S
hS : S ≤ R⁰
r₁ r₂ : R
u : { x // x ∈ S }
v : R
h₁ : r₂ * ↑u = r₁ * v
h₂ : ↑u = v
⊢ r₁ = r₂
[PROOFSTEP]
rwa [← h₂, mul_cancel_right_mem_nonZeroDivisors (hS (SetLike.coe_mem u)), eq_comm] at h₁ 
[GOAL]
R : Type u_1
inst✝² : Ring R
S : Submonoid R
inst✝¹ : OreSet S
inst✝ : Nontrivial R
hS : S ≤ R⁰
h : 0 = 1
⊢ False
[PROOFSTEP]
rw [OreLocalization.one_def, OreLocalization.zero_def] at h 
[GOAL]
R : Type u_1
inst✝² : Ring R
S : Submonoid R
inst✝¹ : OreSet S
inst✝ : Nontrivial R
hS : S ≤ R⁰
h : 0 /ₒ 1 = 1 /ₒ 1
⊢ False
[PROOFSTEP]
apply nonZeroDivisors.coe_ne_zero 1 (numeratorHom_inj hS h).symm
[GOAL]
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
⊢ ∀ (r t : R) (s : { x // x ∈ R⁰ }) (ht : ↑s * t ∈ R⁰),
    (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) r s =
      (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) (r * t)
        { val := ↑s * t, property := ht }
[PROOFSTEP]
intro r t s hst
[GOAL]
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
r t : R
s : { x // x ∈ R⁰ }
hst : ↑s * t ∈ R⁰
⊢ (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) r s =
    (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) (r * t)
      { val := ↑s * t, property := hst }
[PROOFSTEP]
by_cases hr : r = 0
[GOAL]
case pos
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
r t : R
s : { x // x ∈ R⁰ }
hst : ↑s * t ∈ R⁰
hr : r = 0
⊢ (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) r s =
    (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) (r * t)
      { val := ↑s * t, property := hst }
[PROOFSTEP]
simp [hr]
[GOAL]
case neg
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
r t : R
s : { x // x ∈ R⁰ }
hst : ↑s * t ∈ R⁰
hr : ¬r = 0
⊢ (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) r s =
    (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) (r * t)
      { val := ↑s * t, property := hst }
[PROOFSTEP]
by_cases ht : t = 0
[GOAL]
case pos
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
r t : R
s : { x // x ∈ R⁰ }
hst : ↑s * t ∈ R⁰
hr : ¬r = 0
ht : t = 0
⊢ (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) r s =
    (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) (r * t)
      { val := ↑s * t, property := hst }
[PROOFSTEP]
exfalso
[GOAL]
case pos.h
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
r t : R
s : { x // x ∈ R⁰ }
hst : ↑s * t ∈ R⁰
hr : ¬r = 0
ht : t = 0
⊢ False
[PROOFSTEP]
apply nonZeroDivisors.coe_ne_zero ⟨_, hst⟩
[GOAL]
case pos.h
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
r t : R
s : { x // x ∈ R⁰ }
hst : ↑s * t ∈ R⁰
hr : ¬r = 0
ht : t = 0
⊢ ↑{ val := ↑s * t, property := hst } = 0
[PROOFSTEP]
simp [ht, mul_zero]
[GOAL]
case neg
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
r t : R
s : { x // x ∈ R⁰ }
hst : ↑s * t ∈ R⁰
hr : ¬r = 0
ht : ¬t = 0
⊢ (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) r s =
    (fun r s => if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) (r * t)
      { val := ↑s * t, property := hst }
[PROOFSTEP]
simp only [hr, ht, dif_neg, not_false_iff, or_self_iff, mul_eq_zero]
[GOAL]
case neg
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
r t : R
s : { x // x ∈ R⁰ }
hst : ↑s * t ∈ R⁰
hr : ¬r = 0
ht : ¬t = 0
⊢ ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) } =
    ↑s * t /ₒ { val := r * t, property := (_ : ∀ (x : R), x * (r * t) = 0 → x = 0) }
[PROOFSTEP]
apply OreLocalization.expand
[GOAL]
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
x : OreLocalization R R⁰
h : x ≠ 0
⊢ x * x⁻¹ = 1
[PROOFSTEP]
induction' x using OreLocalization.ind with r s
[GOAL]
case c
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
x : OreLocalization R R⁰
h✝ : x ≠ 0
r : R
s : { x // x ∈ R⁰ }
h : r /ₒ s ≠ 0
⊢ r /ₒ s * (r /ₒ s)⁻¹ = 1
[PROOFSTEP]
rw [OreLocalization.inv_def, OreLocalization.one_def]
[GOAL]
case c
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
x : OreLocalization R R⁰
h✝ : x ≠ 0
r : R
s : { x // x ∈ R⁰ }
h : r /ₒ s ≠ 0
⊢ (r /ₒ s * if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) = 1 /ₒ 1
[PROOFSTEP]
by_cases hr : r = 0
[GOAL]
case pos
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
x : OreLocalization R R⁰
h✝ : x ≠ 0
r : R
s : { x // x ∈ R⁰ }
h : r /ₒ s ≠ 0
hr : r = 0
⊢ (r /ₒ s * if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) = 1 /ₒ 1
[PROOFSTEP]
exfalso
[GOAL]
case pos.h
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
x : OreLocalization R R⁰
h✝ : x ≠ 0
r : R
s : { x // x ∈ R⁰ }
h : r /ₒ s ≠ 0
hr : r = 0
⊢ False
[PROOFSTEP]
apply h
[GOAL]
case pos.h
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
x : OreLocalization R R⁰
h✝ : x ≠ 0
r : R
s : { x // x ∈ R⁰ }
h : r /ₒ s ≠ 0
hr : r = 0
⊢ r /ₒ s = 0
[PROOFSTEP]
simp [hr]
[GOAL]
case neg
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
x : OreLocalization R R⁰
h✝ : x ≠ 0
r : R
s : { x // x ∈ R⁰ }
h : r /ₒ s ≠ 0
hr : ¬r = 0
⊢ (r /ₒ s * if hr : r = 0 then 0 else ↑s /ₒ { val := r, property := (_ : ∀ (x : R), x * r = 0 → x = 0) }) = 1 /ₒ 1
[PROOFSTEP]
simp [hr]
[GOAL]
case neg
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
x : OreLocalization R R⁰
h✝ : x ≠ 0
r : R
s : { x // x ∈ R⁰ }
h : r /ₒ s ≠ 0
hr : ¬r = 0
⊢ 1 = 1 /ₒ 1
[PROOFSTEP]
apply OreLocalization.div_eq_one'
[GOAL]
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
⊢ 0⁻¹ = 0
[PROOFSTEP]
rw [OreLocalization.zero_def, OreLocalization.inv_def]
[GOAL]
R : Type u_1
inst✝³ : Ring R
inst✝² : Nontrivial R
inst✝¹ : OreSet R⁰
inst✝ : NoZeroDivisors R
⊢ (if hr : 0 = 0 then 0 else ↑1 /ₒ { val := 0, property := (_ : ∀ (x : R), x * 0 = 0 → x = 0) }) = 0 /ₒ 1
[PROOFSTEP]
simp
