l3lab/ntp-mathlib huggingface dataset:
theorem conj_trans (e₁ : M ≃ₗ[R] M₂) (e₂ : M₂ ≃ₗ[R] M₃) :
    e₁.conj.trans e₂.conj = (e₁.trans e₂).conj := by
  ext f x
  

Proof state:
case h.h
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝⁶ : CommSemiring R
inst✝⁵ : AddCommMonoid M
inst✝⁴ : AddCommMonoid M₂
inst✝³ : AddCommMonoid M₃
inst✝² : Module R M
inst✝¹ : Module R M₂
inst✝ : Module R M₃
e₁ : M ≃ₗ[R] M₂
e₂ : M₂ ≃ₗ[R] M₃
f : Module.End R M
x : M₃
⊢ ((conj e₁ ≪≫ₗ conj e₂) f) x = ((conj (e₁ ≪≫ₗ e₂)) f) x

Next tactic:
rfl
@[simp]
theorem conj_id (e : M ≃ₗ[R] M₂) : e.conj LinearMap.id = LinearMap.id := by
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝⁶ : CommSemiring R
inst✝⁵ : AddCommMonoid M
inst✝⁴ : AddCommMonoid M₂
inst✝³ : AddCommMonoid M₃
inst✝² : Module R M
inst✝¹ : Module R M₂
inst✝ : Module R M₃
e : M ≃ₗ[R] M₂
⊢ (conj e) LinearMap.id = LinearMap.id

Next tactic:
ext
@[simp]
theorem conj_id (e : M ≃ₗ[R] M₂) : e.conj LinearMap.id = LinearMap.id := by
  ext
  

Proof state:
case h
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝⁶ : CommSemiring R
inst✝⁵ : AddCommMonoid M
inst✝⁴ : AddCommMonoid M₂
inst✝³ : AddCommMonoid M₃
inst✝² : Module R M
inst✝¹ : Module R M₂
inst✝ : Module R M₃
e : M ≃ₗ[R] M₂
x✝ : M₂
⊢ ((conj e) LinearMap.id) x✝ = LinearMap.id x✝

Next tactic:
simp [conj_apply]
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by 

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
⊢ ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q

Next tactic:
rintro ⟨x, hx⟩
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; 

Proof state:
case mk
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
x : ↥p
hx : x ∈ q
⊢ (LinearMap.domRestrict (Submodule.subtype p) q) { val := x, property := hx } ∈ map (Submodule.subtype p) q

Next tactic:
exact ⟨x, hx, rfl⟩
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; exact ⟨x, hx, rfl⟩) with
    invFun := by
      

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
src✝ : ↥q →ₗ[R] ↥(map (Submodule.subtype p) q) :=
  LinearMap.codRestrict (map (Submodule.subtype p) q) (LinearMap.domRestrict (Submodule.subtype p) q)
    (_ : ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q)
⊢ ↥(map (Submodule.subtype p) q) → ↥q

Next tactic:
rintro ⟨x, hx⟩
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; exact ⟨x, hx, rfl⟩) with
    invFun := by
      rintro ⟨x, hx⟩
      

Proof state:
case mk
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
src✝ : ↥q →ₗ[R] ↥(map (Submodule.subtype p) q) :=
  LinearMap.codRestrict (map (Submodule.subtype p) q) (LinearMap.domRestrict (Submodule.subtype p) q)
    (_ : ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q)
x : M
hx : x ∈ map (Submodule.subtype p) q
⊢ ↥q

Next tactic:
refine' ⟨⟨x, _⟩, _⟩
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; exact ⟨x, hx, rfl⟩) with
    invFun := by
      rintro ⟨x, hx⟩
      refine' ⟨⟨x, _⟩, _⟩ <;> 

Proof state:
case mk.refine'_1
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
src✝ : ↥q →ₗ[R] ↥(map (Submodule.subtype p) q) :=
  LinearMap.codRestrict (map (Submodule.subtype p) q) (LinearMap.domRestrict (Submodule.subtype p) q)
    (_ : ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q)
x : M
hx : x ∈ map (Submodule.subtype p) q
⊢ x ∈ p

Next tactic:
rcases hx with ⟨⟨_, h⟩, _, rfl⟩
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; exact ⟨x, hx, rfl⟩) with
    invFun := by
      rintro ⟨x, hx⟩
      refine' ⟨⟨x, _⟩, _⟩ <;> 

Proof state:
case mk.refine'_2
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
src✝ : ↥q →ₗ[R] ↥(map (Submodule.subtype p) q) :=
  LinearMap.codRestrict (map (Submodule.subtype p) q) (LinearMap.domRestrict (Submodule.subtype p) q)
    (_ : ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q)
x : M
hx : x ∈ map (Submodule.subtype p) q
⊢ { val := x, property := (_ : x ∈ p) } ∈ q

Next tactic:
rcases hx with ⟨⟨_, h⟩, _, rfl⟩
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; exact ⟨x, hx, rfl⟩) with
    invFun := by
      rintro ⟨x, hx⟩
      refine' ⟨⟨x, _⟩, _⟩ <;> rcases hx with ⟨⟨_, h⟩, _, rfl⟩ <;> 

Proof state:
case mk.refine'_1.intro.mk.intro
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
src✝ : ↥q →ₗ[R] ↥(map (Submodule.subtype p) q) :=
  LinearMap.codRestrict (map (Submodule.subtype p) q) (LinearMap.domRestrict (Submodule.subtype p) q)
    (_ : ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q)
val✝ : M
h : val✝ ∈ p
left✝ : { val := val✝, property := h } ∈ ↑q
⊢ (Submodule.subtype p) { val := val✝, property := h } ∈ p

Next tactic:
assumption
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; exact ⟨x, hx, rfl⟩) with
    invFun := by
      rintro ⟨x, hx⟩
      refine' ⟨⟨x, _⟩, _⟩ <;> rcases hx with ⟨⟨_, h⟩, _, rfl⟩ <;> 

Proof state:
case mk.refine'_2.intro.mk.intro
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
src✝ : ↥q →ₗ[R] ↥(map (Submodule.subtype p) q) :=
  LinearMap.codRestrict (map (Submodule.subtype p) q) (LinearMap.domRestrict (Submodule.subtype p) q)
    (_ : ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q)
val✝ : M
h : val✝ ∈ p
left✝ : { val := val✝, property := h } ∈ ↑q
⊢ { val := (Submodule.subtype p) { val := val✝, property := h },
      property := (_ : (Submodule.subtype p) { val := val✝, property := h } ∈ p) } ∈
    q

Next tactic:
assumption
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; exact ⟨x, hx, rfl⟩) with
    invFun := by
      rintro ⟨x, hx⟩
      refine' ⟨⟨x, _⟩, _⟩ <;> rcases hx with ⟨⟨_, h⟩, _, rfl⟩ <;> assumption
    left_inv := fun ⟨⟨_, _⟩, _⟩ => rfl
    right_inv := fun ⟨x, ⟨_, h⟩, _, rfl⟩ => by 

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
src✝ : ↥q →ₗ[R] ↥(map (Submodule.subtype p) q) :=
  LinearMap.codRestrict (map (Submodule.subtype p) q) (LinearMap.domRestrict (Submodule.subtype p) q)
    (_ : ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q)
x✝ : ↥(map (Submodule.subtype p) q)
x : M
h : x ∈ p
left✝ : { val := x, property := h } ∈ ↑q
⊢ AddHom.toFun
      { toAddHom := src✝.toAddHom,
          map_smul' :=
            (_ :
              ∀ (r : R) (x : ↥q),
                AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }.toAddHom
      (Subtype.casesOn { val := x, property := (_ : ∃ a ∈ ↑q, (Submodule.subtype p) a = x) } fun x hx =>
        { val := { val := x, property := (_ : x ∈ p) }, property := (_ : { val := x, property := (_ : x ∈ p) } ∈ q) }) =
    { val := x, property := (_ : ∃ a ∈ ↑q, (Submodule.subtype p) a = x) }

Next tactic:
ext
/-- Given `p` a submodule of the module `M` and `q` a submodule of `p`, `p.equivSubtypeMap q`
is the natural `LinearEquiv` between `q` and `q.map p.subtype`. -/
def equivSubtypeMap (p : Submodule R M) (q : Submodule R p) : q ≃ₗ[R] q.map p.subtype :=
  { (p.subtype.domRestrict q).codRestrict _ (by rintro ⟨x, hx⟩; exact ⟨x, hx, rfl⟩) with
    invFun := by
      rintro ⟨x, hx⟩
      refine' ⟨⟨x, _⟩, _⟩ <;> rcases hx with ⟨⟨_, h⟩, _, rfl⟩ <;> assumption
    left_inv := fun ⟨⟨_, _⟩, _⟩ => rfl
    right_inv := fun ⟨x, ⟨_, h⟩, _, rfl⟩ => by ext; 

Proof state:
case a
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
src✝ : ↥q →ₗ[R] ↥(map (Submodule.subtype p) q) :=
  LinearMap.codRestrict (map (Submodule.subtype p) q) (LinearMap.domRestrict (Submodule.subtype p) q)
    (_ : ∀ (c : ↥q), (LinearMap.domRestrict (Submodule.subtype p) q) c ∈ map (Submodule.subtype p) q)
x✝ : ↥(map (Submodule.subtype p) q)
x : M
h : x ∈ p
left✝ : { val := x, property := h } ∈ ↑q
⊢ ↑(AddHom.toFun
        { toAddHom := src✝.toAddHom,
            map_smul' :=
              (_ :
                ∀ (r : R) (x : ↥q),
                  AddHom.toFun src✝.toAddHom (r • x) = (RingHom.id R) r • AddHom.toFun src✝.toAddHom x) }.toAddHom
        (Subtype.casesOn { val := x, property := (_ : ∃ a ∈ ↑q, (Submodule.subtype p) a = x) } fun x hx =>
          { val := { val := x, property := (_ : x ∈ p) },
            property := (_ : { val := x, property := (_ : x ∈ p) } ∈ q) })) =
    ↑{ val := x, property := (_ : ∃ a ∈ ↑q, (Submodule.subtype p) a = x) }

Next tactic:
rfl
@[simp]
theorem equivSubtypeMap_symm_apply {p : Submodule R M} {q : Submodule R p} (x : q.map p.subtype) :
    ((p.equivSubtypeMap q).symm x : M) = x := by
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
x : ↥(map (Submodule.subtype p) q)
⊢ ↑↑((LinearEquiv.symm (equivSubtypeMap p q)) x) = ↑x

Next tactic:
cases x
@[simp]
theorem equivSubtypeMap_symm_apply {p : Submodule R M} {q : Submodule R p} (x : q.map p.subtype) :
    ((p.equivSubtypeMap q).symm x : M) = x := by
  cases x
  

Proof state:
case mk
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
p : Submodule R M
q : Submodule R ↥p
val✝ : M
property✝ : val✝ ∈ map (Submodule.subtype p) q
⊢ ↑↑((LinearEquiv.symm (equivSubtypeMap p q)) { val := val✝, property := property✝ }) =
    ↑{ val := val✝, property := property✝ }

Next tactic:
rfl
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
⊢ Surjective ⇑(funLeft R M f)

Next tactic:
classical
    intro g
    refine' ⟨fun x => if h : ∃ y, f y = x then g h.choose else 0, _⟩
    · ext
      dsimp only [funLeft_apply]
      split_ifs with w
      · congr
        exact hf w.choose_spec
      · simp only [not_true, exists_apply_eq_apply] at w
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  classical
    

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
⊢ Surjective ⇑(funLeft R M f)

Next tactic:
intro g
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  classical
    intro g
    

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
g : m → M
⊢ ∃ a, (funLeft R M f) a = g

Next tactic:
refine' ⟨fun x => if h : ∃ y, f y = x then g h.choose else 0, _⟩
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  classical
    intro g
    refine' ⟨fun x => if h : ∃ y, f y = x then g h.choose else 0, _⟩
    · 

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
g : m → M
⊢ ((funLeft R M f) fun x => if h : ∃ y, f y = x then g (Exists.choose h) else 0) = g

Next tactic:
ext
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  classical
    intro g
    refine' ⟨fun x => if h : ∃ y, f y = x then g h.choose else 0, _⟩
    · ext
      

Proof state:
case h
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
g : m → M
x✝ : m
⊢ (funLeft R M f) (fun x => if h : ∃ y, f y = x then g (Exists.choose h) else 0) x✝ = g x✝

Next tactic:
dsimp only [funLeft_apply]
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  classical
    intro g
    refine' ⟨fun x => if h : ∃ y, f y = x then g h.choose else 0, _⟩
    · ext
      dsimp only [funLeft_apply]
      

Proof state:
case h
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
g : m → M
x✝ : m
⊢ (if h : ∃ y, f y = f x✝ then g (Exists.choose h) else 0) = g x✝

Next tactic:
split_ifs with w
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  classical
    intro g
    refine' ⟨fun x => if h : ∃ y, f y = x then g h.choose else 0, _⟩
    · ext
      dsimp only [funLeft_apply]
      split_ifs with w
      · 

Proof state:
case pos
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
g : m → M
x✝ : m
w : ∃ y, f y = f x✝
⊢ g (Exists.choose w) = g x✝

Next tactic:
congr
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  classical
    intro g
    refine' ⟨fun x => if h : ∃ y, f y = x then g h.choose else 0, _⟩
    · ext
      dsimp only [funLeft_apply]
      split_ifs with w
      · congr
        

Proof state:
case pos.e_a
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
g : m → M
x✝ : m
w : ∃ y, f y = f x✝
⊢ Exists.choose w = x✝

Next tactic:
exact hf w.choose_spec
theorem funLeft_surjective_of_injective (f : m → n) (hf : Injective f) :
    Surjective (funLeft R M f) := by
  classical
    intro g
    refine' ⟨fun x => if h : ∃ y, f y = x then g h.choose else 0, _⟩
    · ext
      dsimp only [funLeft_apply]
      split_ifs with w
      · congr
        exact hf w.choose_spec
      · 

Proof state:
case neg
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Injective f
g : m → M
x✝ : m
w : ¬∃ y, f y = f x✝
⊢ 0 = g x✝

Next tactic:
simp only [not_true, exists_apply_eq_apply] at w
theorem funLeft_injective_of_surjective (f : m → n) (hf : Surjective f) :
    Injective (funLeft R M f) := by
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Surjective f
⊢ Injective ⇑(funLeft R M f)

Next tactic:
obtain ⟨g, hg⟩ := hf.hasRightInverse
theorem funLeft_injective_of_surjective (f : m → n) (hf : Surjective f) :
    Injective (funLeft R M f) := by
  obtain ⟨g, hg⟩ := hf.hasRightInverse
  

Proof state:
case intro
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
R₄ : Type u_5
S : Type u_6
K : Type u_7
K₂ : Type u_8
M : Type u_9
M' : Type u_10
M₁ : Type u_11
M₂ : Type u_12
M₃ : Type u_13
M₄ : Type u_14
N : Type u_15
N₂ : Type u_16
ι : Type u_17
V : Type u_18
V₂ : Type u_19
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
m : Type u_20
n : Type u_21
p : Type u_22
f : m → n
hf : Surjective f
g : n → m
hg : Function.RightInverse g f
⊢ Injective ⇑(funLeft R M f)

Next tactic:
suffices LeftInverse (funLeft R M g) (funLeft R M f) by exact this.injective