l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem piQuotientLift_single [Fintype ι] [DecidableEq ι] (p : ∀ i, Submodule R (Ms i))
    (q : Submodule R N) (f : ∀ i, Ms i →ₗ[R] N) (hf : ∀ i, p i ≤ q.comap (f i)) (i)
    (x : Ms i ⧸ p i) : piQuotientLift p q f hf (Pi.single i x) = mapQ _ _ (f i) (hf i) x := by
  simp_rw [piQuotientLift, lsum_apply, sum_apply, comp_apply, proj_apply]
  rw [Finset.sum_eq_single i]
  · rw [Pi.single_eq_same]
  · rintro j - hj
    rw [Pi.single_eq_of_ne hj, _root_.map_zero]
  · 

Proof state:
case h₁
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
q : Submodule R N
f : (i : ι) → Ms i →ₗ[R] N
hf : ∀ (i : ι), p i ≤ comap (f i) q
i : ι
x : Ms i ⧸ p i
⊢ i ∉ Finset.univ → (mapQ (p i) q (f i) (_ : p i ≤ comap (f i) q)) (Pi.single i x i) = 0

Next tactic:
intros
@[simp]
theorem piQuotientLift_single [Fintype ι] [DecidableEq ι] (p : ∀ i, Submodule R (Ms i))
    (q : Submodule R N) (f : ∀ i, Ms i →ₗ[R] N) (hf : ∀ i, p i ≤ q.comap (f i)) (i)
    (x : Ms i ⧸ p i) : piQuotientLift p q f hf (Pi.single i x) = mapQ _ _ (f i) (hf i) x := by
  simp_rw [piQuotientLift, lsum_apply, sum_apply, comp_apply, proj_apply]
  rw [Finset.sum_eq_single i]
  · rw [Pi.single_eq_same]
  · rintro j - hj
    rw [Pi.single_eq_of_ne hj, _root_.map_zero]
  · intros
    

Proof state:
case h₁
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
q : Submodule R N
f : (i : ι) → Ms i →ₗ[R] N
hf : ∀ (i : ι), p i ≤ comap (f i) q
i : ι
x : Ms i ⧸ p i
a✝ : i ∉ Finset.univ
⊢ (mapQ (p i) q (f i) (_ : p i ≤ comap (f i) q)) (Pi.single i x i) = 0

Next tactic:
have := Finset.mem_univ i
@[simp]
theorem piQuotientLift_single [Fintype ι] [DecidableEq ι] (p : ∀ i, Submodule R (Ms i))
    (q : Submodule R N) (f : ∀ i, Ms i →ₗ[R] N) (hf : ∀ i, p i ≤ q.comap (f i)) (i)
    (x : Ms i ⧸ p i) : piQuotientLift p q f hf (Pi.single i x) = mapQ _ _ (f i) (hf i) x := by
  simp_rw [piQuotientLift, lsum_apply, sum_apply, comp_apply, proj_apply]
  rw [Finset.sum_eq_single i]
  · rw [Pi.single_eq_same]
  · rintro j - hj
    rw [Pi.single_eq_of_ne hj, _root_.map_zero]
  · intros
    have := Finset.mem_univ i
    

Proof state:
case h₁
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
q : Submodule R N
f : (i : ι) → Ms i →ₗ[R] N
hf : ∀ (i : ι), p i ≤ comap (f i) q
i : ι
x : Ms i ⧸ p i
a✝ : i ∉ Finset.univ
this : i ∈ Finset.univ
⊢ (mapQ (p i) q (f i) (_ : p i ≤ comap (f i) q)) (Pi.single i x i) = 0

Next tactic:
contradiction
/-- Lift a family of maps to a quotient of direct sums. -/
def quotientPiLift (p : ∀ i, Submodule R (Ms i)) (f : ∀ i, Ms i →ₗ[R] Ns i)
    (hf : ∀ i, p i ≤ ker (f i)) : (∀ i, Ms i) ⧸ pi Set.univ p →ₗ[R] ∀ i, Ns i :=
  (pi Set.univ p).liftQ (LinearMap.pi fun i => (f i).comp (proj i)) fun x hx =>
    mem_ker.mpr <| by
      

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁶ : CommRing R
Ms : ι → Type u_3
inst✝⁵ : (i : ι) → AddCommGroup (Ms i)
inst✝⁴ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝³ : AddCommGroup N
inst✝² : Module R N
Ns : ι → Type u_5
inst✝¹ : (i : ι) → AddCommGroup (Ns i)
inst✝ : (i : ι) → Module R (Ns i)
p : (i : ι) → Submodule R (Ms i)
f : (i : ι) → Ms i →ₗ[R] Ns i
hf : ∀ (i : ι), p i ≤ ker (f i)
x : (i : ι) → Ms i
hx : x ∈ pi Set.univ p
⊢ (LinearMap.pi fun i => f i ∘ₗ proj i) x = 0

Next tactic:
ext i
/-- Lift a family of maps to a quotient of direct sums. -/
def quotientPiLift (p : ∀ i, Submodule R (Ms i)) (f : ∀ i, Ms i →ₗ[R] Ns i)
    (hf : ∀ i, p i ≤ ker (f i)) : (∀ i, Ms i) ⧸ pi Set.univ p →ₗ[R] ∀ i, Ns i :=
  (pi Set.univ p).liftQ (LinearMap.pi fun i => (f i).comp (proj i)) fun x hx =>
    mem_ker.mpr <| by
      ext i
      

Proof state:
case h
ι : Type u_1
R : Type u_2
inst✝⁶ : CommRing R
Ms : ι → Type u_3
inst✝⁵ : (i : ι) → AddCommGroup (Ms i)
inst✝⁴ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝³ : AddCommGroup N
inst✝² : Module R N
Ns : ι → Type u_5
inst✝¹ : (i : ι) → AddCommGroup (Ns i)
inst✝ : (i : ι) → Module R (Ns i)
p : (i : ι) → Submodule R (Ms i)
f : (i : ι) → Ms i →ₗ[R] Ns i
hf : ∀ (i : ι), p i ≤ ker (f i)
x : (i : ι) → Ms i
hx : x ∈ pi Set.univ p
i : ι
⊢ (LinearMap.pi fun i => f i ∘ₗ proj i) x i = OfNat.ofNat 0 i

Next tactic:
simpa using hf i (mem_pi.mp hx i (Set.mem_univ i))
theorem left_inv : Function.LeftInverse (invFun p) (toFun p) := fun x =>
  Quotient.inductionOn' x fun x' => by
    

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
x : ((i : ι) → Ms i) ⧸ pi Set.univ p
x' : (i : ι) → Ms i
⊢ invFun p (toFun p (Quotient.mk'' x')) = Quotient.mk'' x'

Next tactic:
rw [Quotient.mk''_eq_mk x']
theorem left_inv : Function.LeftInverse (invFun p) (toFun p) := fun x =>
  Quotient.inductionOn' x fun x' => by
    rw [Quotient.mk''_eq_mk x']
    

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
x : ((i : ι) → Ms i) ⧸ pi Set.univ p
x' : (i : ι) → Ms i
⊢ invFun p (toFun p (Quotient.mk x')) = Quotient.mk x'

Next tactic:
dsimp only [toFun, invFun]
theorem left_inv : Function.LeftInverse (invFun p) (toFun p) := fun x =>
  Quotient.inductionOn' x fun x' => by
    rw [Quotient.mk''_eq_mk x']
    dsimp only [toFun, invFun]
    

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
x : ((i : ι) → Ms i) ⧸ pi Set.univ p
x' : (i : ι) → Ms i
⊢ (piQuotientLift p (pi Set.univ p) single (_ : ∀ (x : ι), p x ≤ comap (single x) (pi Set.univ p)))
      ((quotientPiLift p (fun i => mkQ (p i)) (_ : ∀ (i : ι), p i ≤ ker (mkQ (p i)))) (Quotient.mk x')) =
    Quotient.mk x'

Next tactic:
rw [quotientPiLift_mk p, funext fun i => (mkQ_apply (p i) (x' i)), piQuotientLift_mk p,
      lsum_single, id_apply]
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
⊢ Function.RightInverse (invFun p) (toFun p)

Next tactic:
dsimp only [toFun, invFun]
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
⊢ Function.RightInverse
    ⇑(piQuotientLift p (pi Set.univ p) single (_ : ∀ (x : ι), p x ≤ comap (single x) (pi Set.univ p)))
    ⇑(quotientPiLift p (fun i => mkQ (p i)) (_ : ∀ (i : ι), p i ≤ ker (mkQ (p i))))

Next tactic:
rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
⊢ ⇑(quotientPiLift p (fun i => mkQ (p i)) (_ : ∀ (i : ι), p i ≤ ker (mkQ (p i))) ∘ₗ
        piQuotientLift p (pi Set.univ p) single (_ : ∀ (x : ι), p x ≤ comap (single x) (pi Set.univ p))) =
    ⇑LinearMap.id

Next tactic:
refine' congr_arg _ (pi_ext fun i x => Quotient.inductionOn' x fun x' => funext fun j => _)
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
  refine' congr_arg _ (pi_ext fun i x => Quotient.inductionOn' x fun x' => funext fun j => _)
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
i : ι
x : Ms i ⧸ p i
x' : Ms i
j : ι
⊢ (quotientPiLift p (fun i => mkQ (p i)) (_ : ∀ (i : ι), p i ≤ ker (mkQ (p i))) ∘ₗ
        piQuotientLift p (pi Set.univ p) single (_ : ∀ (x : ι), p x ≤ comap (single x) (pi Set.univ p)))
      (Pi.single i (Quotient.mk'' x')) j =
    LinearMap.id (Pi.single i (Quotient.mk'' x')) j

Next tactic:
rw [comp_apply, piQuotientLift_single, Quotient.mk''_eq_mk, mapQ_apply,
    quotientPiLift_mk, id_apply]
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
  refine' congr_arg _ (pi_ext fun i x => Quotient.inductionOn' x fun x' => funext fun j => _)
  rw [comp_apply, piQuotientLift_single, Quotient.mk''_eq_mk, mapQ_apply,
    quotientPiLift_mk, id_apply]
  

Proof state:
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
i : ι
x : Ms i ⧸ p i
x' : Ms i
j : ι
⊢ (fun i_1 => (mkQ (p i_1)) ((single i) x' i_1)) j = Pi.single i (Quotient.mk x') j

Next tactic:
by_cases hij : i = j
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
  refine' congr_arg _ (pi_ext fun i x => Quotient.inductionOn' x fun x' => funext fun j => _)
  rw [comp_apply, piQuotientLift_single, Quotient.mk''_eq_mk, mapQ_apply,
    quotientPiLift_mk, id_apply]
  by_cases hij : i = j <;> 

Proof state:
case pos
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
i : ι
x : Ms i ⧸ p i
x' : Ms i
j : ι
hij : i = j
⊢ (fun i_1 => (mkQ (p i_1)) ((single i) x' i_1)) j = Pi.single i (Quotient.mk x') j

Next tactic:
simp only [mkQ_apply, coe_single]
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
  refine' congr_arg _ (pi_ext fun i x => Quotient.inductionOn' x fun x' => funext fun j => _)
  rw [comp_apply, piQuotientLift_single, Quotient.mk''_eq_mk, mapQ_apply,
    quotientPiLift_mk, id_apply]
  by_cases hij : i = j <;> 

Proof state:
case neg
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
i : ι
x : Ms i ⧸ p i
x' : Ms i
j : ι
hij : ¬i = j
⊢ (fun i_1 => (mkQ (p i_1)) ((single i) x' i_1)) j = Pi.single i (Quotient.mk x') j

Next tactic:
simp only [mkQ_apply, coe_single]
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
  refine' congr_arg _ (pi_ext fun i x => Quotient.inductionOn' x fun x' => funext fun j => _)
  rw [comp_apply, piQuotientLift_single, Quotient.mk''_eq_mk, mapQ_apply,
    quotientPiLift_mk, id_apply]
  by_cases hij : i = j <;> simp only [mkQ_apply, coe_single]
  · 

Proof state:
case pos
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
i : ι
x : Ms i ⧸ p i
x' : Ms i
j : ι
hij : i = j
⊢ Quotient.mk (Pi.single i x' j) = Pi.single i (Quotient.mk x') j

Next tactic:
subst hij
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
  refine' congr_arg _ (pi_ext fun i x => Quotient.inductionOn' x fun x' => funext fun j => _)
  rw [comp_apply, piQuotientLift_single, Quotient.mk''_eq_mk, mapQ_apply,
    quotientPiLift_mk, id_apply]
  by_cases hij : i = j <;> simp only [mkQ_apply, coe_single]
  · subst hij
    

Proof state:
case pos
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
i : ι
x : Ms i ⧸ p i
x' : Ms i
⊢ Quotient.mk (Pi.single i x' i) = Pi.single i (Quotient.mk x') i

Next tactic:
rw [Pi.single_eq_same, Pi.single_eq_same]
theorem right_inv : Function.RightInverse (invFun p) (toFun p) := by
  dsimp only [toFun, invFun]
  rw [Function.rightInverse_iff_comp, ← coe_comp, ← @id_coe R]
  refine' congr_arg _ (pi_ext fun i x => Quotient.inductionOn' x fun x' => funext fun j => _)
  rw [comp_apply, piQuotientLift_single, Quotient.mk''_eq_mk, mapQ_apply,
    quotientPiLift_mk, id_apply]
  by_cases hij : i = j <;> simp only [mkQ_apply, coe_single]
  · subst hij
    rw [Pi.single_eq_same, Pi.single_eq_same]
  · 

Proof state:
case neg
ι : Type u_1
R : Type u_2
inst✝⁸ : CommRing R
Ms : ι → Type u_3
inst✝⁷ : (i : ι) → AddCommGroup (Ms i)
inst✝⁶ : (i : ι) → Module R (Ms i)
N : Type u_4
inst✝⁵ : AddCommGroup N
inst✝⁴ : Module R N
Ns : ι → Type u_5
inst✝³ : (i : ι) → AddCommGroup (Ns i)
inst✝² : (i : ι) → Module R (Ns i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
p : (i : ι) → Submodule R (Ms i)
i : ι
x : Ms i ⧸ p i
x' : Ms i
j : ι
hij : ¬i = j
⊢ Quotient.mk (Pi.single i x' j) = Pi.single i (Quotient.mk x') j

Next tactic:
rw [Pi.single_eq_of_ne (Ne.symm hij), Pi.single_eq_of_ne (Ne.symm hij), Quotient.mk_zero]
/-- An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`. -/
@[to_additive AddLocalization.r'
    "An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`."]
def r' : Con (M × S) := by
  -- note we multiply by `c` on the left so that we can later generalize to `•`
  

Proof state:
M : Type u_1
inst✝² : CommMonoid M
S : Submonoid M
N : Type u_2
inst✝¹ : CommMonoid N
P : Type u_3
inst✝ : CommMonoid P
⊢ Con (M × ↥S)

Next tactic:
refine
    { r := fun a b : M × S ↦ ∃ c : S, ↑c * (↑b.2 * a.1) = c * (a.2 * b.1)
      iseqv := ⟨fun a ↦ ⟨1, rfl⟩, fun ⟨c, hc⟩ ↦ ⟨c, hc.symm⟩, ?_⟩
      mul' := ?_ }
/-- An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`. -/
@[to_additive AddLocalization.r'
    "An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`."]
def r' : Con (M × S) := by
  -- note we multiply by `c` on the left so that we can later generalize to `•`
  refine
    { r := fun a b : M × S ↦ ∃ c : S, ↑c * (↑b.2 * a.1) = c * (a.2 * b.1)
      iseqv := ⟨fun a ↦ ⟨1, rfl⟩, fun ⟨c, hc⟩ ↦ ⟨c, hc.symm⟩, ?_⟩
      mul' := ?_ }
  · 

Proof state:
case refine_1
M : Type u_1
inst✝² : CommMonoid M
S : Submonoid M
N : Type u_2
inst✝¹ : CommMonoid N
P : Type u_3
inst✝ : CommMonoid P
⊢ ∀ {x y z : M × ↥S},
    (∃ c, ↑c * (↑y.2 * x.1) = ↑c * (↑x.2 * y.1)) →
      (∃ c, ↑c * (↑z.2 * y.1) = ↑c * (↑y.2 * z.1)) → ∃ c, ↑c * (↑z.2 * x.1) = ↑c * (↑x.2 * z.1)

Next tactic:
rintro a b c ⟨t₁, ht₁⟩ ⟨t₂, ht₂⟩
/-- An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`. -/
@[to_additive AddLocalization.r'
    "An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`."]
def r' : Con (M × S) := by
  -- note we multiply by `c` on the left so that we can later generalize to `•`
  refine
    { r := fun a b : M × S ↦ ∃ c : S, ↑c * (↑b.2 * a.1) = c * (a.2 * b.1)
      iseqv := ⟨fun a ↦ ⟨1, rfl⟩, fun ⟨c, hc⟩ ↦ ⟨c, hc.symm⟩, ?_⟩
      mul' := ?_ }
  · rintro a b c ⟨t₁, ht₁⟩ ⟨t₂, ht₂⟩
    

Proof state:
case refine_1.intro.intro
M : Type u_1
inst✝² : CommMonoid M
S : Submonoid M
N : Type u_2
inst✝¹ : CommMonoid N
P : Type u_3
inst✝ : CommMonoid P
a b c : M × ↥S
t₁ : ↥S
ht₁ : ↑t₁ * (↑b.2 * a.1) = ↑t₁ * (↑a.2 * b.1)
t₂ : ↥S
ht₂ : ↑t₂ * (↑c.2 * b.1) = ↑t₂ * (↑b.2 * c.1)
⊢ ∃ c_1, ↑c_1 * (↑c.2 * a.1) = ↑c_1 * (↑a.2 * c.1)

Next tactic:
use t₂ * t₁ * b.2
/-- An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`. -/
@[to_additive AddLocalization.r'
    "An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`."]
def r' : Con (M × S) := by
  -- note we multiply by `c` on the left so that we can later generalize to `•`
  refine
    { r := fun a b : M × S ↦ ∃ c : S, ↑c * (↑b.2 * a.1) = c * (a.2 * b.1)
      iseqv := ⟨fun a ↦ ⟨1, rfl⟩, fun ⟨c, hc⟩ ↦ ⟨c, hc.symm⟩, ?_⟩
      mul' := ?_ }
  · rintro a b c ⟨t₁, ht₁⟩ ⟨t₂, ht₂⟩
    use t₂ * t₁ * b.2
    

Proof state:
case h
M : Type u_1
inst✝² : CommMonoid M
S : Submonoid M
N : Type u_2
inst✝¹ : CommMonoid N
P : Type u_3
inst✝ : CommMonoid P
a b c : M × ↥S
t₁ : ↥S
ht₁ : ↑t₁ * (↑b.2 * a.1) = ↑t₁ * (↑a.2 * b.1)
t₂ : ↥S
ht₂ : ↑t₂ * (↑c.2 * b.1) = ↑t₂ * (↑b.2 * c.1)
⊢ ↑(t₂ * t₁ * b.2) * (↑c.2 * a.1) = ↑(t₂ * t₁ * b.2) * (↑a.2 * c.1)

Next tactic:
simp only [Submonoid.coe_mul]
/-- An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`. -/
@[to_additive AddLocalization.r'
    "An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`."]
def r' : Con (M × S) := by
  -- note we multiply by `c` on the left so that we can later generalize to `•`
  refine
    { r := fun a b : M × S ↦ ∃ c : S, ↑c * (↑b.2 * a.1) = c * (a.2 * b.1)
      iseqv := ⟨fun a ↦ ⟨1, rfl⟩, fun ⟨c, hc⟩ ↦ ⟨c, hc.symm⟩, ?_⟩
      mul' := ?_ }
  · rintro a b c ⟨t₁, ht₁⟩ ⟨t₂, ht₂⟩
    use t₂ * t₁ * b.2
    simp only [Submonoid.coe_mul]
    

Proof state:
case h
M : Type u_1
inst✝² : CommMonoid M
S : Submonoid M
N : Type u_2
inst✝¹ : CommMonoid N
P : Type u_3
inst✝ : CommMonoid P
a b c : M × ↥S
t₁ : ↥S
ht₁ : ↑t₁ * (↑b.2 * a.1) = ↑t₁ * (↑a.2 * b.1)
t₂ : ↥S
ht₂ : ↑t₂ * (↑c.2 * b.1) = ↑t₂ * (↑b.2 * c.1)
⊢ ↑t₂ * ↑t₁ * ↑b.2 * (↑c.2 * a.1) = ↑t₂ * ↑t₁ * ↑b.2 * (↑a.2 * c.1)

Next tactic:
calc
      (t₂ * t₁ * b.2 : M) * (c.2 * a.1) = t₂ * c.2 * (t₁ * (b.2 * a.1)) := by ac_rfl
      _ = t₁ * a.2 * (t₂ * (c.2 * b.1)) := by rw [ht₁]; ac_rfl
      _ = t₂ * t₁ * b.2 * (a.2 * c.1) := by rw [ht₂]; ac_rfl
/-- An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`. -/
@[to_additive AddLocalization.r'
    "An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`."]
def r' : Con (M × S) := by
  -- note we multiply by `c` on the left so that we can later generalize to `•`
  refine
    { r := fun a b : M × S ↦ ∃ c : S, ↑c * (↑b.2 * a.1) = c * (a.2 * b.1)
      iseqv := ⟨fun a ↦ ⟨1, rfl⟩, fun ⟨c, hc⟩ ↦ ⟨c, hc.symm⟩, ?_⟩
      mul' := ?_ }
  · rintro a b c ⟨t₁, ht₁⟩ ⟨t₂, ht₂⟩
    use t₂ * t₁ * b.2
    simp only [Submonoid.coe_mul]
    calc
      (t₂ * t₁ * b.2 : M) * (c.2 * a.1) = t₂ * c.2 * (t₁ * (b.2 * a.1)) := by 

Proof state:
M : Type u_1
inst✝² : CommMonoid M
S : Submonoid M
N : Type u_2
inst✝¹ : CommMonoid N
P : Type u_3
inst✝ : CommMonoid P
a b c : M × ↥S
t₁ : ↥S
ht₁ : ↑t₁ * (↑b.2 * a.1) = ↑t₁ * (↑a.2 * b.1)
t₂ : ↥S
ht₂ : ↑t₂ * (↑c.2 * b.1) = ↑t₂ * (↑b.2 * c.1)
⊢ ↑t₂ * ↑t₁ * ↑b.2 * (↑c.2 * a.1) = ↑t₂ * ↑c.2 * (↑t₁ * (↑b.2 * a.1))

Next tactic:
ac_rfl
/-- An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`. -/
@[to_additive AddLocalization.r'
    "An alternate form of the congruence relation on `M × S`, `M` a `CommMonoid` and `S` a
submonoid of `M`, whose quotient is the localization of `M` at `S`."]
def r' : Con (M × S) := by
  -- note we multiply by `c` on the left so that we can later generalize to `•`
  refine
    { r := fun a b : M × S ↦ ∃ c : S, ↑c * (↑b.2 * a.1) = c * (a.2 * b.1)
      iseqv := ⟨fun a ↦ ⟨1, rfl⟩, fun ⟨c, hc⟩ ↦ ⟨c, hc.symm⟩, ?_⟩
      mul' := ?_ }
  · rintro a b c ⟨t₁, ht₁⟩ ⟨t₂, ht₂⟩
    use t₂ * t₁ * b.2
    simp only [Submonoid.coe_mul]
    calc
      (t₂ * t₁ * b.2 : M) * (c.2 * a.1) = t₂ * c.2 * (t₁ * (b.2 * a.1)) := by ac_rfl
      _ = t₁ * a.2 * (t₂ * (c.2 * b.1)) := by 

Proof state:
M : Type u_1
inst✝² : CommMonoid M
S : Submonoid M
N : Type u_2
inst✝¹ : CommMonoid N
P : Type u_3
inst✝ : CommMonoid P
a b c : M × ↥S
t₁ : ↥S
ht₁ : ↑t₁ * (↑b.2 * a.1) = ↑t₁ * (↑a.2 * b.1)
t₂ : ↥S
ht₂ : ↑t₂ * (↑c.2 * b.1) = ↑t₂ * (↑b.2 * c.1)
⊢ ↑t₂ * ↑c.2 * (↑t₁ * (↑b.2 * a.1)) = ↑t₁ * ↑a.2 * (↑t₂ * (↑c.2 * b.1))

Next tactic:
rw [ht₁]