l3lab/ntp-mathlib huggingface dataset:
/-- If `P` is a submodule of `M` and `Q` a submodule of `N`,
and `f : M ≃ₗ N` maps `P` to `Q`, then `M ⧸ P` is equivalent to `N ⧸ Q`. -/
@[simps]
def Quotient.equiv {N : Type*} [AddCommGroup N] [Module R N] (P : Submodule R M)
    (Q : Submodule R N) (f : M ≃ₗ[R] N) (hf : P.map f = Q) : (M ⧸ P) ≃ₗ[R] N ⧸ Q :=
  { P.mapQ Q (f : M →ₗ[R] N) fun x hx => hf ▸ Submodule.mem_map_of_mem hx with
    toFun := P.mapQ Q (f : M →ₗ[R] N) fun x hx => hf ▸ Submodule.mem_map_of_mem hx
    invFun :=
      Q.mapQ P (f.symm : N →ₗ[R] M) fun x hx => by
        rw [← hf, Submodule.mem_map] at hx
        obtain ⟨y, hy, rfl⟩ := hx
        

Proof state:
case intro.intro
R : Type u_1
M : Type u_2
r : R
x y✝ : M
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
p p' : Submodule R M
R₂ : Type u_3
M₂ : Type u_4
inst✝⁴ : Ring R₂
inst✝³ : AddCommGroup M₂
inst✝² : Module R₂ M₂
τ₁₂ : R →+* R₂
q : Submodule R₂ M₂
N : Type u_5
inst✝¹ : AddCommGroup N
inst✝ : Module R N
P : Submodule R M
Q : Submodule R N
f : M ≃ₗ[R] N
hf : map f P = Q
src✝ : M ⧸ P →ₗ[R] N ⧸ Q := mapQ P Q ↑f (_ : ∀ x ∈ P, x ∈ comap (↑f) Q)
y : M
hy : y ∈ P
⊢ f y ∈ comap (↑(LinearEquiv.symm f)) P

Next tactic:
simpa
/-- If `P` is a submodule of `M` and `Q` a submodule of `N`,
and `f : M ≃ₗ N` maps `P` to `Q`, then `M ⧸ P` is equivalent to `N ⧸ Q`. -/
@[simps]
def Quotient.equiv {N : Type*} [AddCommGroup N] [Module R N] (P : Submodule R M)
    (Q : Submodule R N) (f : M ≃ₗ[R] N) (hf : P.map f = Q) : (M ⧸ P) ≃ₗ[R] N ⧸ Q :=
  { P.mapQ Q (f : M →ₗ[R] N) fun x hx => hf ▸ Submodule.mem_map_of_mem hx with
    toFun := P.mapQ Q (f : M →ₗ[R] N) fun x hx => hf ▸ Submodule.mem_map_of_mem hx
    invFun :=
      Q.mapQ P (f.symm : N →ₗ[R] M) fun x hx => by
        rw [← hf, Submodule.mem_map] at hx
        obtain ⟨y, hy, rfl⟩ := hx
        simpa
    left_inv := fun x => Quotient.inductionOn' x (by 

Proof state:
R : Type u_1
M : Type u_2
r : R
x✝ y : M
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
p p' : Submodule R M
R₂ : Type u_3
M₂ : Type u_4
inst✝⁴ : Ring R₂
inst✝³ : AddCommGroup M₂
inst✝² : Module R₂ M₂
τ₁₂ : R →+* R₂
q : Submodule R₂ M₂
N : Type u_5
inst✝¹ : AddCommGroup N
inst✝ : Module R N
P : Submodule R M
Q : Submodule R N
f : M ≃ₗ[R] N
hf : map f P = Q
src✝ : M ⧸ P →ₗ[R] N ⧸ Q := mapQ P Q ↑f (_ : ∀ x ∈ P, x ∈ comap (↑f) Q)
x : M ⧸ P
⊢ ∀ (a : M),
    (mapQ Q P ↑(LinearEquiv.symm f) (_ : ∀ x ∈ Q, x ∈ comap (↑(LinearEquiv.symm f)) P))
        (AddHom.toFun
          {
              toAddHom :=
                { toFun := ⇑(mapQ P Q ↑f (_ : ∀ x ∈ P, x ∈ comap (↑f) Q)),
                  map_add' :=
                    (_ :
                      ∀ (x y : M ⧸ P),
                        AddHom.toFun src✝.toAddHom (x + y) =
                          AddHom.toFun src✝.toAddHom x + AddHom.toFun src✝.toAddHom y) },
              map_smul' :=
                (_ :
                  ∀ (r : R) (x : M ⧸ P),
                    AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }.toAddHom
          (Quotient.mk'' a)) =
      Quotient.mk'' a

Next tactic:
simp
/-- If `P` is a submodule of `M` and `Q` a submodule of `N`,
and `f : M ≃ₗ N` maps `P` to `Q`, then `M ⧸ P` is equivalent to `N ⧸ Q`. -/
@[simps]
def Quotient.equiv {N : Type*} [AddCommGroup N] [Module R N] (P : Submodule R M)
    (Q : Submodule R N) (f : M ≃ₗ[R] N) (hf : P.map f = Q) : (M ⧸ P) ≃ₗ[R] N ⧸ Q :=
  { P.mapQ Q (f : M →ₗ[R] N) fun x hx => hf ▸ Submodule.mem_map_of_mem hx with
    toFun := P.mapQ Q (f : M →ₗ[R] N) fun x hx => hf ▸ Submodule.mem_map_of_mem hx
    invFun :=
      Q.mapQ P (f.symm : N →ₗ[R] M) fun x hx => by
        rw [← hf, Submodule.mem_map] at hx
        obtain ⟨y, hy, rfl⟩ := hx
        simpa
    left_inv := fun x => Quotient.inductionOn' x (by simp)
    right_inv := fun x => Quotient.inductionOn' x (by 

Proof state:
R : Type u_1
M : Type u_2
r : R
x✝ y : M
inst✝⁷ : Ring R
inst✝⁶ : AddCommGroup M
inst✝⁵ : Module R M
p p' : Submodule R M
R₂ : Type u_3
M₂ : Type u_4
inst✝⁴ : Ring R₂
inst✝³ : AddCommGroup M₂
inst✝² : Module R₂ M₂
τ₁₂ : R →+* R₂
q : Submodule R₂ M₂
N : Type u_5
inst✝¹ : AddCommGroup N
inst✝ : Module R N
P : Submodule R M
Q : Submodule R N
f : M ≃ₗ[R] N
hf : map f P = Q
src✝ : M ⧸ P →ₗ[R] N ⧸ Q := mapQ P Q ↑f (_ : ∀ x ∈ P, x ∈ comap (↑f) Q)
x : N ⧸ Q
⊢ ∀ (a : N),
    AddHom.toFun
        {
            toAddHom :=
              { toFun := ⇑(mapQ P Q ↑f (_ : ∀ x ∈ P, x ∈ comap (↑f) Q)),
                map_add' :=
                  (_ :
                    ∀ (x y : M ⧸ P),
                      AddHom.toFun src✝.toAddHom (x + y) =
                        AddHom.toFun src✝.toAddHom x + AddHom.toFun src✝.toAddHom y) },
            map_smul' :=
              (_ :
                ∀ (r : R) (x : M ⧸ P),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }.toAddHom
        ((mapQ Q P ↑(LinearEquiv.symm f) (_ : ∀ x ∈ Q, x ∈ comap (↑(LinearEquiv.symm f)) P)) (Quotient.mk'' a)) =
      Quotient.mk'' a

Next tactic:
simp
@[simp]
theorem Quotient.equiv_trans {N O : Type*} [AddCommGroup N] [Module R N] [AddCommGroup O]
    [Module R O] (P : Submodule R M) (Q : Submodule R N) (S : Submodule R O) (e : M ≃ₗ[R] N)
    (f : N ≃ₗ[R] O) (he : P.map e = Q) (hf : Q.map f = S) (hef : P.map (e.trans f) = S) :
    Quotient.equiv P S (e.trans f) hef =
      (Quotient.equiv P Q e he).trans (Quotient.equiv Q S f hf) := by
  

Proof state:
R : Type u_1
M : Type u_2
r : R
x y : M
inst✝⁹ : Ring R
inst✝⁸ : AddCommGroup M
inst✝⁷ : Module R M
p p' : Submodule R M
R₂ : Type u_3
M₂ : Type u_4
inst✝⁶ : Ring R₂
inst✝⁵ : AddCommGroup M₂
inst✝⁴ : Module R₂ M₂
τ₁₂ : R →+* R₂
q : Submodule R₂ M₂
N : Type u_5
O : Type u_6
inst✝³ : AddCommGroup N
inst✝² : Module R N
inst✝¹ : AddCommGroup O
inst✝ : Module R O
P : Submodule R M
Q : Submodule R N
S : Submodule R O
e : M ≃ₗ[R] N
f : N ≃ₗ[R] O
he : map e P = Q
hf : map f Q = S
hef : map (e ≪≫ₗ f) P = S
⊢ equiv P S (e ≪≫ₗ f) hef = equiv P Q e he ≪≫ₗ equiv Q S f hf

Next tactic:
ext
@[simp]
theorem Quotient.equiv_trans {N O : Type*} [AddCommGroup N] [Module R N] [AddCommGroup O]
    [Module R O] (P : Submodule R M) (Q : Submodule R N) (S : Submodule R O) (e : M ≃ₗ[R] N)
    (f : N ≃ₗ[R] O) (he : P.map e = Q) (hf : Q.map f = S) (hef : P.map (e.trans f) = S) :
    Quotient.equiv P S (e.trans f) hef =
      (Quotient.equiv P Q e he).trans (Quotient.equiv Q S f hf) := by
  ext
  -- `simp` can deal with `hef` depending on `e` and `f`
  

Proof state:
case h
R : Type u_1
M : Type u_2
r : R
x y : M
inst✝⁹ : Ring R
inst✝⁸ : AddCommGroup M
inst✝⁷ : Module R M
p p' : Submodule R M
R₂ : Type u_3
M₂ : Type u_4
inst✝⁶ : Ring R₂
inst✝⁵ : AddCommGroup M₂
inst✝⁴ : Module R₂ M₂
τ₁₂ : R →+* R₂
q : Submodule R₂ M₂
N : Type u_5
O : Type u_6
inst✝³ : AddCommGroup N
inst✝² : Module R N
inst✝¹ : AddCommGroup O
inst✝ : Module R O
P : Submodule R M
Q : Submodule R N
S : Submodule R O
e : M ≃ₗ[R] N
f : N ≃ₗ[R] O
he : map e P = Q
hf : map f Q = S
hef : map (e ≪≫ₗ f) P = S
x✝ : M ⧸ P
⊢ (equiv P S (e ≪≫ₗ f) hef) x✝ = (equiv P Q e he ≪≫ₗ equiv Q S f hf) x✝

Next tactic:
simp only [Quotient.equiv_apply, LinearEquiv.trans_apply, LinearEquiv.coe_trans]
@[simp]
theorem Quotient.equiv_trans {N O : Type*} [AddCommGroup N] [Module R N] [AddCommGroup O]
    [Module R O] (P : Submodule R M) (Q : Submodule R N) (S : Submodule R O) (e : M ≃ₗ[R] N)
    (f : N ≃ₗ[R] O) (he : P.map e = Q) (hf : Q.map f = S) (hef : P.map (e.trans f) = S) :
    Quotient.equiv P S (e.trans f) hef =
      (Quotient.equiv P Q e he).trans (Quotient.equiv Q S f hf) := by
  ext
  -- `simp` can deal with `hef` depending on `e` and `f`
  simp only [Quotient.equiv_apply, LinearEquiv.trans_apply, LinearEquiv.coe_trans]
  -- `rw` can deal with `mapQ_comp` needing extra hypotheses coming from the RHS
  

Proof state:
case h
R : Type u_1
M : Type u_2
r : R
x y : M
inst✝⁹ : Ring R
inst✝⁸ : AddCommGroup M
inst✝⁷ : Module R M
p p' : Submodule R M
R₂ : Type u_3
M₂ : Type u_4
inst✝⁶ : Ring R₂
inst✝⁵ : AddCommGroup M₂
inst✝⁴ : Module R₂ M₂
τ₁₂ : R →+* R₂
q : Submodule R₂ M₂
N : Type u_5
O : Type u_6
inst✝³ : AddCommGroup N
inst✝² : Module R N
inst✝¹ : AddCommGroup O
inst✝ : Module R O
P : Submodule R M
Q : Submodule R N
S : Submodule R O
e : M ≃ₗ[R] N
f : N ≃ₗ[R] O
he : map e P = Q
hf : map f Q = S
hef : map (e ≪≫ₗ f) P = S
x✝ : M ⧸ P
⊢ (mapQ P S (↑f ∘ₗ ↑e) (_ : P ≤ comap (↑f ∘ₗ ↑e) S)) x✝ =
    (mapQ Q S ↑f (_ : ∀ x ∈ Q, x ∈ comap (↑f) S)) ((mapQ P Q ↑e (_ : ∀ x ∈ P, x ∈ comap (↑e) Q)) x✝)

Next tactic:
rw [mapQ_comp, LinearMap.comp_apply]
theorem range_mkQ_comp (f : M →ₛₗ[τ₁₂] M₂) : f.range.mkQ.comp f = 0 :=
  LinearMap.ext fun x => by 

Proof state:
R : Type u_1
M : Type u_2
R₂ : Type u_3
M₂ : Type u_4
R₃ : Type u_5
M₃ : Type u_6
inst✝¹⁰ : Ring R
inst✝⁹ : Ring R₂
inst✝⁸ : Ring R₃
inst✝⁷ : AddCommMonoid M
inst✝⁶ : AddCommGroup M₂
inst✝⁵ : AddCommMonoid M₃
inst✝⁴ : Module R M
inst✝³ : Module R₂ M₂
inst✝² : Module R₃ M₃
τ₁₂ : R →+* R₂
τ₂₃ : R₂ →+* R₃
τ₁₃ : R →+* R₃
inst✝¹ : RingHomCompTriple τ₁₂ τ₂₃ τ₁₃
inst✝ : RingHomSurjective τ₁₂
f : M →ₛₗ[τ₁₂] M₂
x : M
⊢ (comp (mkQ (range f)) f) x = 0 x

Next tactic:
simp
theorem ker_le_range_iff {f : M →ₛₗ[τ₁₂] M₂} {g : M₂ →ₛₗ[τ₂₃] M₃} :
    ker g ≤ range f ↔ f.range.mkQ.comp g.ker.subtype = 0 := by
  

Proof state:
R : Type u_1
M : Type u_2
R₂ : Type u_3
M₂ : Type u_4
R₃ : Type u_5
M₃ : Type u_6
inst✝¹⁰ : Ring R
inst✝⁹ : Ring R₂
inst✝⁸ : Ring R₃
inst✝⁷ : AddCommMonoid M
inst✝⁶ : AddCommGroup M₂
inst✝⁵ : AddCommMonoid M₃
inst✝⁴ : Module R M
inst✝³ : Module R₂ M₂
inst✝² : Module R₃ M₃
τ₁₂ : R →+* R₂
τ₂₃ : R₂ →+* R₃
τ₁₃ : R →+* R₃
inst✝¹ : RingHomCompTriple τ₁₂ τ₂₃ τ₁₃
inst✝ : RingHomSurjective τ₁₂
f : M →ₛₗ[τ₁₂] M₂
g : M₂ →ₛₗ[τ₂₃] M₃
⊢ ker g ≤ range f ↔ mkQ (range f) ∘ₗ Submodule.subtype (ker g) = 0

Next tactic:
rw [← range_le_ker_iff, Submodule.ker_mkQ, Submodule.range_subtype]
/-- An epimorphism is surjective. -/
theorem range_eq_top_of_cancel {f : M →ₛₗ[τ₁₂] M₂}
    (h : ∀ u v : M₂ →ₗ[R₂] M₂ ⧸ (range f), u.comp f = v.comp f → u = v) : range f = ⊤ := by
  

Proof state:
R : Type u_1
M : Type u_2
R₂ : Type u_3
M₂ : Type u_4
R₃ : Type u_5
M₃ : Type u_6
inst✝¹⁰ : Ring R
inst✝⁹ : Ring R₂
inst✝⁸ : Ring R₃
inst✝⁷ : AddCommMonoid M
inst✝⁶ : AddCommGroup M₂
inst✝⁵ : AddCommMonoid M₃
inst✝⁴ : Module R M
inst✝³ : Module R₂ M₂
inst✝² : Module R₃ M₃
τ₁₂ : R →+* R₂
τ₂₃ : R₂ →+* R₃
τ₁₃ : R →+* R₃
inst✝¹ : RingHomCompTriple τ₁₂ τ₂₃ τ₁₃
inst✝ : RingHomSurjective τ₁₂
f : M →ₛₗ[τ₁₂] M₂
h : ∀ (u v : M₂ →ₗ[R₂] M₂ ⧸ range f), comp u f = comp v f → u = v
⊢ range f = ⊤

Next tactic:
have h₁ : (0 : M₂ →ₗ[R₂] M₂ ⧸ (range f)).comp f = 0 := zero_comp _
/-- An epimorphism is surjective. -/
theorem range_eq_top_of_cancel {f : M →ₛₗ[τ₁₂] M₂}
    (h : ∀ u v : M₂ →ₗ[R₂] M₂ ⧸ (range f), u.comp f = v.comp f → u = v) : range f = ⊤ := by
  have h₁ : (0 : M₂ →ₗ[R₂] M₂ ⧸ (range f)).comp f = 0 := zero_comp _
  

Proof state:
R : Type u_1
M : Type u_2
R₂ : Type u_3
M₂ : Type u_4
R₃ : Type u_5
M₃ : Type u_6
inst✝¹⁰ : Ring R
inst✝⁹ : Ring R₂
inst✝⁸ : Ring R₃
inst✝⁷ : AddCommMonoid M
inst✝⁶ : AddCommGroup M₂
inst✝⁵ : AddCommMonoid M₃
inst✝⁴ : Module R M
inst✝³ : Module R₂ M₂
inst✝² : Module R₃ M₃
τ₁₂ : R →+* R₂
τ₂₃ : R₂ →+* R₃
τ₁₃ : R →+* R₃
inst✝¹ : RingHomCompTriple τ₁₂ τ₂₃ τ₁₃
inst✝ : RingHomSurjective τ₁₂
f : M →ₛₗ[τ₁₂] M₂
h : ∀ (u v : M₂ →ₗ[R₂] M₂ ⧸ range f), comp u f = comp v f → u = v
h₁ : comp 0 f = 0
⊢ range f = ⊤

Next tactic:
rw [← Submodule.ker_mkQ (range f), ← h 0 f.range.mkQ (Eq.trans h₁ (range_mkQ_comp _).symm)]
/-- An epimorphism is surjective. -/
theorem range_eq_top_of_cancel {f : M →ₛₗ[τ₁₂] M₂}
    (h : ∀ u v : M₂ →ₗ[R₂] M₂ ⧸ (range f), u.comp f = v.comp f → u = v) : range f = ⊤ := by
  have h₁ : (0 : M₂ →ₗ[R₂] M₂ ⧸ (range f)).comp f = 0 := zero_comp _
  rw [← Submodule.ker_mkQ (range f), ← h 0 f.range.mkQ (Eq.trans h₁ (range_mkQ_comp _).symm)]
  

Proof state:
R : Type u_1
M : Type u_2
R₂ : Type u_3
M₂ : Type u_4
R₃ : Type u_5
M₃ : Type u_6
inst✝¹⁰ : Ring R
inst✝⁹ : Ring R₂
inst✝⁸ : Ring R₃
inst✝⁷ : AddCommMonoid M
inst✝⁶ : AddCommGroup M₂
inst✝⁵ : AddCommMonoid M₃
inst✝⁴ : Module R M
inst✝³ : Module R₂ M₂
inst✝² : Module R₃ M₃
τ₁₂ : R →+* R₂
τ₂₃ : R₂ →+* R₃
τ₁₃ : R →+* R₃
inst✝¹ : RingHomCompTriple τ₁₂ τ₂₃ τ₁₃
inst✝ : RingHomSurjective τ₁₂
f : M →ₛₗ[τ₁₂] M₂
h : ∀ (u v : M₂ →ₗ[R₂] M₂ ⧸ range f), comp u f = comp v f → u = v
h₁ : comp 0 f = 0
⊢ ker 0 = ⊤

Next tactic:
exact ker_zero
/-- Quotienting by equal submodules gives linearly equivalent quotients. -/
def quotEquivOfEq (h : p = p') : (M ⧸ p) ≃ₗ[R] M ⧸ p' :=
  { @Quotient.congr _ _ (quotientRel p) (quotientRel p') (Equiv.refl _) fun a b => by
      

Proof state:
R : Type u_1
M : Type u_2
r : R
x y : M
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
p p' : Submodule R M
h : p = p'
a b : M
⊢ Setoid.r a b ↔ Setoid.r ((Equiv.refl M) a) ((Equiv.refl M) b)

Next tactic:
subst h
/-- Quotienting by equal submodules gives linearly equivalent quotients. -/
def quotEquivOfEq (h : p = p') : (M ⧸ p) ≃ₗ[R] M ⧸ p' :=
  { @Quotient.congr _ _ (quotientRel p) (quotientRel p') (Equiv.refl _) fun a b => by
      subst h
      

Proof state:
R : Type u_1
M : Type u_2
r : R
x y : M
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
p : Submodule R M
a b : M
⊢ Setoid.r a b ↔ Setoid.r ((Equiv.refl M) a) ((Equiv.refl M) b)

Next tactic:
rfl
/-- Quotienting by equal submodules gives linearly equivalent quotients. -/
def quotEquivOfEq (h : p = p') : (M ⧸ p) ≃ₗ[R] M ⧸ p' :=
  { @Quotient.congr _ _ (quotientRel p) (quotientRel p') (Equiv.refl _) fun a b => by
      subst h
      rfl with
    map_add' := by
      

Proof state:
R : Type u_1
M : Type u_2
r : R
x y : M
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
p p' : Submodule R M
h : p = p'
src✝ : Quotient (quotientRel p) ≃ Quotient (quotientRel p') :=
  Quotient.congr (Equiv.refl M) (_ : ∀ (a b : M), Setoid.r a b ↔ Setoid.r ((Equiv.refl M) a) ((Equiv.refl M) b))
⊢ ∀ (x y : M ⧸ p), Equiv.toFun src✝ (x + y) = Equiv.toFun src✝ x + Equiv.toFun src✝ y

Next tactic:
rintro ⟨x⟩ ⟨y⟩
/-- Quotienting by equal submodules gives linearly equivalent quotients. -/
def quotEquivOfEq (h : p = p') : (M ⧸ p) ≃ₗ[R] M ⧸ p' :=
  { @Quotient.congr _ _ (quotientRel p) (quotientRel p') (Equiv.refl _) fun a b => by
      subst h
      rfl with
    map_add' := by
      rintro ⟨x⟩ ⟨y⟩
      

Proof state:
case mk.mk
R : Type u_1
M : Type u_2
r : R
x✝¹ y✝¹ : M
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
p p' : Submodule R M
h : p = p'
src✝ : Quotient (quotientRel p) ≃ Quotient (quotientRel p') :=
  Quotient.congr (Equiv.refl M) (_ : ∀ (a b : M), Setoid.r a b ↔ Setoid.r ((Equiv.refl M) a) ((Equiv.refl M) b))
x✝ : M ⧸ p
x : M
y✝ : M ⧸ p
y : M
⊢ Equiv.toFun src✝ (Quot.mk Setoid.r x + Quot.mk Setoid.r y) =
    Equiv.toFun src✝ (Quot.mk Setoid.r x) + Equiv.toFun src✝ (Quot.mk Setoid.r y)

Next tactic:
rfl
/-- Quotienting by equal submodules gives linearly equivalent quotients. -/
def quotEquivOfEq (h : p = p') : (M ⧸ p) ≃ₗ[R] M ⧸ p' :=
  { @Quotient.congr _ _ (quotientRel p) (quotientRel p') (Equiv.refl _) fun a b => by
      subst h
      rfl with
    map_add' := by
      rintro ⟨x⟩ ⟨y⟩
      rfl
    map_smul' := by
      

Proof state:
R : Type u_1
M : Type u_2
r : R
x y : M
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
p p' : Submodule R M
h : p = p'
src✝ : Quotient (quotientRel p) ≃ Quotient (quotientRel p') :=
  Quotient.congr (Equiv.refl M) (_ : ∀ (a b : M), Setoid.r a b ↔ Setoid.r ((Equiv.refl M) a) ((Equiv.refl M) b))
⊢ ∀ (r : R) (x : M ⧸ p),
    AddHom.toFun
        { toFun := src✝.toFun,
          map_add' := (_ : ∀ (x y : M ⧸ p), Equiv.toFun src✝ (x + y) = Equiv.toFun src✝ x + Equiv.toFun src✝ y) }
        (r • x) =
      (RingHom.id R) r •
        AddHom.toFun
          { toFun := src✝.toFun,
            map_add' := (_ : ∀ (x y : M ⧸ p), Equiv.toFun src✝ (x + y) = Equiv.toFun src✝ x + Equiv.toFun src✝ y) }
          x

Next tactic:
rintro x ⟨y⟩
/-- Quotienting by equal submodules gives linearly equivalent quotients. -/
def quotEquivOfEq (h : p = p') : (M ⧸ p) ≃ₗ[R] M ⧸ p' :=
  { @Quotient.congr _ _ (quotientRel p) (quotientRel p') (Equiv.refl _) fun a b => by
      subst h
      rfl with
    map_add' := by
      rintro ⟨x⟩ ⟨y⟩
      rfl
    map_smul' := by
      rintro x ⟨y⟩
      

Proof state:
case mk
R : Type u_1
M : Type u_2
r : R
x✝¹ y✝ : M
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
p p' : Submodule R M
h : p = p'
src✝ : Quotient (quotientRel p) ≃ Quotient (quotientRel p') :=
  Quotient.congr (Equiv.refl M) (_ : ∀ (a b : M), Setoid.r a b ↔ Setoid.r ((Equiv.refl M) a) ((Equiv.refl M) b))
x : R
x✝ : M ⧸ p
y : M
⊢ AddHom.toFun
      { toFun := src✝.toFun,
        map_add' := (_ : ∀ (x y : M ⧸ p), Equiv.toFun src✝ (x + y) = Equiv.toFun src✝ x + Equiv.toFun src✝ y) }
      (x • Quot.mk Setoid.r y) =
    (RingHom.id R) x •
      AddHom.toFun
        { toFun := src✝.toFun,
          map_add' := (_ : ∀ (x y : M ⧸ p), Equiv.toFun src✝ (x + y) = Equiv.toFun src✝ x + Equiv.toFun src✝ y) }
        (Quot.mk Setoid.r y)

Next tactic:
rfl
@[simp]
theorem Quotient.equiv_refl (P : Submodule R M) (Q : Submodule R M)
    (hf : P.map (LinearEquiv.refl R M : M →ₗ[R] M) = Q) :
    Quotient.equiv P Q (LinearEquiv.refl R M) hf = quotEquivOfEq _ _ (by 

Proof state:
R : Type u_1
M : Type u_2
r : R
x y : M
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
p p' P Q : Submodule R M
hf : map (↑(LinearEquiv.refl R M)) P = Q
⊢ P = Q

Next tactic:
simpa using hf
/-- Given modules `M`, `M₂` over a commutative ring, together with submodules `p ⊆ M`, `q ⊆ M₂`,
the natural map $\{f ∈ Hom(M, M₂) | f(p) ⊆ q \} \to Hom(M/p, M₂/q)$ is linear. -/
def mapQLinear : compatibleMaps p q →ₗ[R] M ⧸ p →ₗ[R] M₂ ⧸ q
    where
  toFun f := mapQ _ _ f.val f.property
  map_add' x y := by
    

Proof state:
R : Type u_1
M : Type u_2
M₂ : Type u_3
r : R
x✝ y✝ : M
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M₂
inst✝ : Module R M₂
p : Submodule R M
q : Submodule R M₂
x y : ↥(compatibleMaps p q)
⊢ (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) (x + y) =
    (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) x + (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) y

Next tactic:
ext
/-- Given modules `M`, `M₂` over a commutative ring, together with submodules `p ⊆ M`, `q ⊆ M₂`,
the natural map $\{f ∈ Hom(M, M₂) | f(p) ⊆ q \} \to Hom(M/p, M₂/q)$ is linear. -/
def mapQLinear : compatibleMaps p q →ₗ[R] M ⧸ p →ₗ[R] M₂ ⧸ q
    where
  toFun f := mapQ _ _ f.val f.property
  map_add' x y := by
    ext
    

Proof state:
case h.h
R : Type u_1
M : Type u_2
M₂ : Type u_3
r : R
x✝¹ y✝ : M
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M₂
inst✝ : Module R M₂
p : Submodule R M
q : Submodule R M₂
x y : ↥(compatibleMaps p q)
x✝ : M
⊢ ((fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) (x + y) ∘ₗ mkQ p) x✝ =
    (((fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) x +
          (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) y) ∘ₗ
        mkQ p)
      x✝

Next tactic:
rfl
/-- Given modules `M`, `M₂` over a commutative ring, together with submodules `p ⊆ M`, `q ⊆ M₂`,
the natural map $\{f ∈ Hom(M, M₂) | f(p) ⊆ q \} \to Hom(M/p, M₂/q)$ is linear. -/
def mapQLinear : compatibleMaps p q →ₗ[R] M ⧸ p →ₗ[R] M₂ ⧸ q
    where
  toFun f := mapQ _ _ f.val f.property
  map_add' x y := by
    ext
    rfl
  map_smul' c f := by
    

Proof state:
R : Type u_1
M : Type u_2
M₂ : Type u_3
r : R
x y : M
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M₂
inst✝ : Module R M₂
p : Submodule R M
q : Submodule R M₂
c : R
f : ↥(compatibleMaps p q)
⊢ AddHom.toFun
      { toFun := fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q),
        map_add' :=
          (_ :
            ∀ (x y : ↥(compatibleMaps p q)),
              (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) (x + y) =
                (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) x +
                  (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) y) }
      (c • f) =
    (RingHom.id R) c •
      AddHom.toFun
        { toFun := fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q),
          map_add' :=
            (_ :
              ∀ (x y : ↥(compatibleMaps p q)),
                (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) (x + y) =
                  (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) x +
                    (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) y) }
        f

Next tactic:
ext
/-- Given modules `M`, `M₂` over a commutative ring, together with submodules `p ⊆ M`, `q ⊆ M₂`,
the natural map $\{f ∈ Hom(M, M₂) | f(p) ⊆ q \} \to Hom(M/p, M₂/q)$ is linear. -/
def mapQLinear : compatibleMaps p q →ₗ[R] M ⧸ p →ₗ[R] M₂ ⧸ q
    where
  toFun f := mapQ _ _ f.val f.property
  map_add' x y := by
    ext
    rfl
  map_smul' c f := by
    ext
    

Proof state:
case h.h
R : Type u_1
M : Type u_2
M₂ : Type u_3
r : R
x y : M
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M₂
inst✝ : Module R M₂
p : Submodule R M
q : Submodule R M₂
c : R
f : ↥(compatibleMaps p q)
x✝ : M
⊢ (AddHom.toFun
          { toFun := fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q),
            map_add' :=
              (_ :
                ∀ (x y : ↥(compatibleMaps p q)),
                  (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) (x + y) =
                    (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) x +
                      (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) y) }
          (c • f) ∘ₗ
        mkQ p)
      x✝ =
    (((RingHom.id R) c •
          AddHom.toFun
            { toFun := fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q),
              map_add' :=
                (_ :
                  ∀ (x y : ↥(compatibleMaps p q)),
                    (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) (x + y) =
                      (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) x +
                        (fun f => mapQ p q ↑f (_ : ↑f ∈ compatibleMaps p q)) y) }
            f) ∘ₗ
        mkQ p)
      x✝

Next tactic:
rfl
instance funLike : FunLike (Π₀ i, β i) ι β :=
  ⟨fun f => f.toFun, fun ⟨f₁, s₁⟩ ⟨f₂, s₁⟩ ↦ fun (h : f₁ = f₂) ↦ by
    

Proof state:
ι : Type u
γ : Type w
β : ι → Type v
β₁ : ι → Type v₁
β₂ : ι → Type v₂
inst✝² : (i : ι) → Zero (β i)
inst✝¹ : (i : ι) → Zero (β₁ i)
inst✝ : (i : ι) → Zero (β₂ i)
x✝¹ x✝ : Π₀ (i : ι), β i
f₁ : (i : ι) → β i
s₁✝ : Trunc { s // ∀ (i : ι), i ∈ s ∨ f₁ i = 0 }
f₂ : (i : ι) → β i
s₁ : Trunc { s // ∀ (i : ι), i ∈ s ∨ f₂ i = 0 }
h : f₁ = f₂
⊢ { toFun := f₁, support' := s₁✝ } = { toFun := f₂, support' := s₁ }

Next tactic:
subst h
instance funLike : FunLike (Π₀ i, β i) ι β :=
  ⟨fun f => f.toFun, fun ⟨f₁, s₁⟩ ⟨f₂, s₁⟩ ↦ fun (h : f₁ = f₂) ↦ by
    subst h
    

Proof state:
ι : Type u
γ : Type w
β : ι → Type v
β₁ : ι → Type v₁
β₂ : ι → Type v₂
inst✝² : (i : ι) → Zero (β i)
inst✝¹ : (i : ι) → Zero (β₁ i)
inst✝ : (i : ι) → Zero (β₂ i)
x✝¹ x✝ : Π₀ (i : ι), β i
f₁ : (i : ι) → β i
s₁✝ s₁ : Trunc { s // ∀ (i : ι), i ∈ s ∨ f₁ i = 0 }
⊢ { toFun := f₁, support' := s₁✝ } = { toFun := f₁, support' := s₁ }

Next tactic:
congr
instance funLike : FunLike (Π₀ i, β i) ι β :=
  ⟨fun f => f.toFun, fun ⟨f₁, s₁⟩ ⟨f₂, s₁⟩ ↦ fun (h : f₁ = f₂) ↦ by
    subst h
    congr
    

Proof state:
case e_support'
ι : Type u
γ : Type w
β : ι → Type v
β₁ : ι → Type v₁
β₂ : ι → Type v₂
inst✝² : (i : ι) → Zero (β i)
inst✝¹ : (i : ι) → Zero (β₁ i)
inst✝ : (i : ι) → Zero (β₂ i)
x✝¹ x✝ : Π₀ (i : ι), β i
f₁ : (i : ι) → β i
s₁✝ s₁ : Trunc { s // ∀ (i : ι), i ∈ s ∨ f₁ i = 0 }
⊢ s₁✝ = s₁

Next tactic:
apply Subsingleton.elim