l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem dualRestrict_comp_dualLift (W : Subspace K V) : W.dualRestrict.comp W.dualLift = 1 := by
  ext φ x
  

Proof state:
case h.h
K : Type u
V : Type v
inst✝² : Field K
inst✝¹ : AddCommGroup V
inst✝ : Module K V
W✝ W : Subspace K V
φ : Module.Dual K ↥W
x : ↥W
⊢ ((dualRestrict W ∘ₗ dualLift W) φ) x = (1 φ) x

Next tactic:
simp
theorem dualRestrict_leftInverse (W : Subspace K V) :
    Function.LeftInverse W.dualRestrict W.dualLift := fun x =>
  show W.dualRestrict.comp W.dualLift x = x by
    

Proof state:
K : Type u
V : Type v
inst✝² : Field K
inst✝¹ : AddCommGroup V
inst✝ : Module K V
W✝ W : Subspace K V
x : Module.Dual K ↥W
⊢ (dualRestrict W ∘ₗ dualLift W) x = x

Next tactic:
rw [dualRestrict_comp_dualLift]
theorem dualRestrict_leftInverse (W : Subspace K V) :
    Function.LeftInverse W.dualRestrict W.dualLift := fun x =>
  show W.dualRestrict.comp W.dualLift x = x by
    rw [dualRestrict_comp_dualLift]
    

Proof state:
K : Type u
V : Type v
inst✝² : Field K
inst✝¹ : AddCommGroup V
inst✝ : Module K V
W✝ W : Subspace K V
x : Module.Dual K ↥W
⊢ 1 x = x

Next tactic:
rfl
@[simp]
theorem quotAnnihilatorEquiv_apply (W : Subspace K V) (φ : Module.Dual K V) :
    W.quotAnnihilatorEquiv (Submodule.Quotient.mk φ) = W.dualRestrict φ := by
  

Proof state:
K : Type u
V : Type v
inst✝² : Field K
inst✝¹ : AddCommGroup V
inst✝ : Module K V
W✝ W : Subspace K V
φ : Module.Dual K V
⊢ (quotAnnihilatorEquiv W) (Submodule.Quotient.mk φ) = (dualRestrict W) φ

Next tactic:
ext
@[simp]
theorem quotAnnihilatorEquiv_apply (W : Subspace K V) (φ : Module.Dual K V) :
    W.quotAnnihilatorEquiv (Submodule.Quotient.mk φ) = W.dualRestrict φ := by
  ext
  

Proof state:
case h
K : Type u
V : Type v
inst✝² : Field K
inst✝¹ : AddCommGroup V
inst✝ : Module K V
W✝ W : Subspace K V
φ : Module.Dual K V
x✝ : ↥W
⊢ ((quotAnnihilatorEquiv W) (Submodule.Quotient.mk φ)) x✝ = ((dualRestrict W) φ) x✝

Next tactic:
rfl
instance instModuleDualFiniteDimensional [FiniteDimensional K V] :
    FiniteDimensional K (Module.Dual K V) := by
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
⊢ FiniteDimensional K (Module.Dual K V)

Next tactic:
infer_instance
@[simp]
theorem dual_finrank_eq : finrank K (Module.Dual K V) = finrank K V := by
  

Proof state:
K : Type u
V : Type v
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝¹ : AddCommGroup V₁
inst✝ : Module K V₁
⊢ finrank K (Module.Dual K V) = finrank K V

Next tactic:
by_cases h : Module.Finite K V
@[simp]
theorem dual_finrank_eq : finrank K (Module.Dual K V) = finrank K V := by
  by_cases h : Module.Finite K V
  · 

Proof state:
case pos
K : Type u
V : Type v
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝¹ : AddCommGroup V₁
inst✝ : Module K V₁
h : Module.Finite K V
⊢ finrank K (Module.Dual K V) = finrank K V

Next tactic:
classical exact LinearEquiv.finrank_eq (Basis.ofVectorSpace K V).toDualEquiv.symm
@[simp]
theorem dual_finrank_eq : finrank K (Module.Dual K V) = finrank K V := by
  by_cases h : Module.Finite K V
  · classical 

Proof state:
case pos
K : Type u
V : Type v
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝¹ : AddCommGroup V₁
inst✝ : Module K V₁
h : Module.Finite K V
⊢ finrank K (Module.Dual K V) = finrank K V

Next tactic:
exact LinearEquiv.finrank_eq (Basis.ofVectorSpace K V).toDualEquiv.symm
@[simp]
theorem dual_finrank_eq : finrank K (Module.Dual K V) = finrank K V := by
  by_cases h : Module.Finite K V
  · classical exact LinearEquiv.finrank_eq (Basis.ofVectorSpace K V).toDualEquiv.symm
  

Proof state:
case neg
K : Type u
V : Type v
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝¹ : AddCommGroup V₁
inst✝ : Module K V₁
h : ¬Module.Finite K V
⊢ finrank K (Module.Dual K V) = finrank K V

Next tactic:
rw [finrank_eq_zero_of_basis_imp_false, finrank_eq_zero_of_basis_imp_false]
@[simp]
theorem dual_finrank_eq : finrank K (Module.Dual K V) = finrank K V := by
  by_cases h : Module.Finite K V
  · classical exact LinearEquiv.finrank_eq (Basis.ofVectorSpace K V).toDualEquiv.symm
  rw [finrank_eq_zero_of_basis_imp_false, finrank_eq_zero_of_basis_imp_false]
  · 

Proof state:
case neg
K : Type u
V : Type v
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝¹ : AddCommGroup V₁
inst✝ : Module K V₁
h : ¬Module.Finite K V
⊢ ∀ (s : Finset V), Basis (↑↑s) K V → False

Next tactic:
exact fun _ b ↦ h (Module.Finite.of_basis b)
@[simp]
theorem dual_finrank_eq : finrank K (Module.Dual K V) = finrank K V := by
  by_cases h : Module.Finite K V
  · classical exact LinearEquiv.finrank_eq (Basis.ofVectorSpace K V).toDualEquiv.symm
  rw [finrank_eq_zero_of_basis_imp_false, finrank_eq_zero_of_basis_imp_false]
  · exact fun _ b ↦ h (Module.Finite.of_basis b)
  · 

Proof state:
case neg
K : Type u
V : Type v
inst✝⁴ : Field K
inst✝³ : AddCommGroup V
inst✝² : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝¹ : AddCommGroup V₁
inst✝ : Module K V₁
h : ¬Module.Finite K V
⊢ ∀ (s : Finset (Module.Dual K V)), Basis (↑↑s) K (Module.Dual K V) → False

Next tactic:
exact fun _ b ↦ h ((Module.finite_dual_iff K).mp <| Module.Finite.of_basis b)
theorem dualAnnihilator_dualAnnihilator_eq (W : Subspace K V) :
    W.dualAnnihilator.dualAnnihilator = Module.mapEvalEquiv K V W := by
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W✝ : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
W : Subspace K V
⊢ dualAnnihilator (dualAnnihilator W) = (Module.mapEvalEquiv K V) W

Next tactic:
have : _ = W := Subspace.dualAnnihilator_dualCoannihilator_eq
theorem dualAnnihilator_dualAnnihilator_eq (W : Subspace K V) :
    W.dualAnnihilator.dualAnnihilator = Module.mapEvalEquiv K V W := by
  have : _ = W := Subspace.dualAnnihilator_dualCoannihilator_eq
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W✝ : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
W : Subspace K V
this : dualCoannihilator (dualAnnihilator W) = W
⊢ dualAnnihilator (dualAnnihilator W) = (Module.mapEvalEquiv K V) W

Next tactic:
rw [dualCoannihilator, ← Module.mapEvalEquiv_symm_apply] at this
theorem dualAnnihilator_dualAnnihilator_eq (W : Subspace K V) :
    W.dualAnnihilator.dualAnnihilator = Module.mapEvalEquiv K V W := by
  have : _ = W := Subspace.dualAnnihilator_dualCoannihilator_eq
  rw [dualCoannihilator, ← Module.mapEvalEquiv_symm_apply] at this
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W✝ : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
W : Subspace K V
this : (OrderIso.symm (Module.mapEvalEquiv K V)) (dualAnnihilator (dualAnnihilator W)) = W
⊢ dualAnnihilator (dualAnnihilator W) = (Module.mapEvalEquiv K V) W

Next tactic:
rwa [← OrderIso.symm_apply_eq]
@[simp]
theorem finrank_dualCoannihilator_eq {Φ : Subspace K (Module.Dual K V)} :
    finrank K Φ.dualCoannihilator = finrank K Φ.dualAnnihilator := by
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
Φ : Subspace K (Module.Dual K V)
⊢ finrank K ↥(dualCoannihilator Φ) = finrank K ↥(dualAnnihilator Φ)

Next tactic:
rw [Submodule.dualCoannihilator, ← Module.evalEquiv_toLinearMap]
@[simp]
theorem finrank_dualCoannihilator_eq {Φ : Subspace K (Module.Dual K V)} :
    finrank K Φ.dualCoannihilator = finrank K Φ.dualAnnihilator := by
  rw [Submodule.dualCoannihilator, ← Module.evalEquiv_toLinearMap]
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
Φ : Subspace K (Module.Dual K V)
⊢ finrank K ↥(comap (↑(Module.evalEquiv K V)) (dualAnnihilator Φ)) = finrank K ↥(dualAnnihilator Φ)

Next tactic:
exact LinearEquiv.finrank_eq (LinearEquiv.ofSubmodule' _ _)
theorem finrank_add_finrank_dualCoannihilator_eq (W : Subspace K (Module.Dual K V)) :
    finrank K W + finrank K W.dualCoannihilator = finrank K V := by
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W✝ : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
W : Subspace K (Module.Dual K V)
⊢ finrank K ↥W + finrank K ↥(dualCoannihilator W) = finrank K V

Next tactic:
rw [finrank_dualCoannihilator_eq]
theorem finrank_add_finrank_dualCoannihilator_eq (W : Subspace K (Module.Dual K V)) :
    finrank K W + finrank K W.dualCoannihilator = finrank K V := by
  rw [finrank_dualCoannihilator_eq]
  -- Porting note: LinearEquiv.finrank_eq needs help
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W✝ : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
W : Subspace K (Module.Dual K V)
⊢ finrank K ↥W + finrank K ↥(dualAnnihilator W) = finrank K V

Next tactic:
let equiv := W.quotEquivAnnihilator
theorem finrank_add_finrank_dualCoannihilator_eq (W : Subspace K (Module.Dual K V)) :
    finrank K W + finrank K W.dualCoannihilator = finrank K V := by
  rw [finrank_dualCoannihilator_eq]
  -- Porting note: LinearEquiv.finrank_eq needs help
  let equiv := W.quotEquivAnnihilator
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W✝ : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
W : Subspace K (Module.Dual K V)
equiv : (Module.Dual K V ⧸ W) ≃ₗ[K] ↥(dualAnnihilator W) := quotEquivAnnihilator W
⊢ finrank K ↥W + finrank K ↥(dualAnnihilator W) = finrank K V

Next tactic:
have eq := LinearEquiv.finrank_eq (R := K) (M := (Module.Dual K V) ⧸ W)
    (M₂ := { x // x ∈ dualAnnihilator W }) equiv
theorem finrank_add_finrank_dualCoannihilator_eq (W : Subspace K (Module.Dual K V)) :
    finrank K W + finrank K W.dualCoannihilator = finrank K V := by
  rw [finrank_dualCoannihilator_eq]
  -- Porting note: LinearEquiv.finrank_eq needs help
  let equiv := W.quotEquivAnnihilator
  have eq := LinearEquiv.finrank_eq (R := K) (M := (Module.Dual K V) ⧸ W)
    (M₂ := { x // x ∈ dualAnnihilator W }) equiv
  

Proof state:
K : Type u
V : Type v
inst✝⁵ : Field K
inst✝⁴ : AddCommGroup V
inst✝³ : Module K V
W✝ : Subspace K V
V₁ : Type u_1
inst✝² : AddCommGroup V₁
inst✝¹ : Module K V₁
inst✝ : FiniteDimensional K V
W : Subspace K (Module.Dual K V)
equiv : (Module.Dual K V ⧸ W) ≃ₗ[K] ↥(dualAnnihilator W) := quotEquivAnnihilator W
eq : finrank K (Module.Dual K V ⧸ W) = finrank K ↥(dualAnnihilator W)
⊢ finrank K ↥W + finrank K ↥(dualAnnihilator W) = finrank K V

Next tactic:
rw [eq.symm, add_comm, Submodule.finrank_quotient_add_finrank, Subspace.dual_finrank_eq]
theorem ker_dualMap_eq_dualAnnihilator_range :
    LinearMap.ker f.dualMap = f.range.dualAnnihilator := by
  

Proof state:
R : Type uR
inst✝⁴ : CommSemiring R
M₁ : Type uM₁
M₂ : Type uM₂
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
⊢ ker (dualMap f) = Submodule.dualAnnihilator (range f)

Next tactic:
ext
theorem ker_dualMap_eq_dualAnnihilator_range :
    LinearMap.ker f.dualMap = f.range.dualAnnihilator := by
  ext
  

Proof state:
case h
R : Type uR
inst✝⁴ : CommSemiring R
M₁ : Type uM₁
M₂ : Type uM₂
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
x✝ : Dual R M₂
⊢ x✝ ∈ ker (dualMap f) ↔ x✝ ∈ Submodule.dualAnnihilator (range f)

Next tactic:
simp_rw [mem_ker, ext_iff, Submodule.mem_dualAnnihilator,
    ← SetLike.mem_coe, range_coe, Set.forall_range_iff]
theorem ker_dualMap_eq_dualAnnihilator_range :
    LinearMap.ker f.dualMap = f.range.dualAnnihilator := by
  ext
  simp_rw [mem_ker, ext_iff, Submodule.mem_dualAnnihilator,
    ← SetLike.mem_coe, range_coe, Set.forall_range_iff]
  

Proof state:
case h
R : Type uR
inst✝⁴ : CommSemiring R
M₁ : Type uM₁
M₂ : Type uM₂
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
x✝ : Dual R M₂
⊢ (∀ (x : M₁), ((dualMap f) x✝) x = 0 x) ↔ ∀ (i : M₁), x✝ (f i) = 0

Next tactic:
rfl
theorem range_dualMap_le_dualAnnihilator_ker :
    LinearMap.range f.dualMap ≤ f.ker.dualAnnihilator := by
  

Proof state:
R : Type uR
inst✝⁴ : CommSemiring R
M₁ : Type uM₁
M₂ : Type uM₂
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
⊢ range (dualMap f) ≤ Submodule.dualAnnihilator (ker f)

Next tactic:
rintro _ ⟨ψ, rfl⟩
theorem range_dualMap_le_dualAnnihilator_ker :
    LinearMap.range f.dualMap ≤ f.ker.dualAnnihilator := by
  rintro _ ⟨ψ, rfl⟩
  

Proof state:
case intro
R : Type uR
inst✝⁴ : CommSemiring R
M₁ : Type uM₁
M₂ : Type uM₂
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
ψ : Dual R M₂
⊢ (dualMap f) ψ ∈ Submodule.dualAnnihilator (ker f)

Next tactic:
simp_rw [Submodule.mem_dualAnnihilator, mem_ker]
theorem range_dualMap_le_dualAnnihilator_ker :
    LinearMap.range f.dualMap ≤ f.ker.dualAnnihilator := by
  rintro _ ⟨ψ, rfl⟩
  simp_rw [Submodule.mem_dualAnnihilator, mem_ker]
  

Proof state:
case intro
R : Type uR
inst✝⁴ : CommSemiring R
M₁ : Type uM₁
M₂ : Type uM₂
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
ψ : Dual R M₂
⊢ ∀ (w : M₁), f w = 0 → ((dualMap f) ψ) w = 0

Next tactic:
rintro x hx
theorem range_dualMap_le_dualAnnihilator_ker :
    LinearMap.range f.dualMap ≤ f.ker.dualAnnihilator := by
  rintro _ ⟨ψ, rfl⟩
  simp_rw [Submodule.mem_dualAnnihilator, mem_ker]
  rintro x hx
  

Proof state:
case intro
R : Type uR
inst✝⁴ : CommSemiring R
M₁ : Type uM₁
M₂ : Type uM₂
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
ψ : Dual R M₂
x : M₁
hx : f x = 0
⊢ ((dualMap f) ψ) x = 0

Next tactic:
rw [dualMap_apply, hx, map_zero]
/-- Given a submodule, corestrict to the pairing on `M ⧸ W` by
simultaneously restricting to `W.dualAnnihilator`.

See `Subspace.dualCopairing_nondegenerate`. -/
def dualCopairing (W : Submodule R M) : W.dualAnnihilator →ₗ[R] M ⧸ W →ₗ[R] R :=
  LinearMap.flip <|
    W.liftQ ((Module.dualPairing R M).domRestrict W.dualAnnihilator).flip
      (by
        

Proof state:
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
⊢ W ≤ LinearMap.ker (LinearMap.flip (LinearMap.domRestrict (dualPairing R M) (dualAnnihilator W)))

Next tactic:
intro w hw
/-- Given a submodule, corestrict to the pairing on `M ⧸ W` by
simultaneously restricting to `W.dualAnnihilator`.

See `Subspace.dualCopairing_nondegenerate`. -/
def dualCopairing (W : Submodule R M) : W.dualAnnihilator →ₗ[R] M ⧸ W →ₗ[R] R :=
  LinearMap.flip <|
    W.liftQ ((Module.dualPairing R M).domRestrict W.dualAnnihilator).flip
      (by
        intro w hw
        

Proof state:
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
w : M
hw : w ∈ W
⊢ w ∈ LinearMap.ker (LinearMap.flip (LinearMap.domRestrict (dualPairing R M) (dualAnnihilator W)))

Next tactic:
ext ⟨φ, hφ⟩
/-- Given a submodule, corestrict to the pairing on `M ⧸ W` by
simultaneously restricting to `W.dualAnnihilator`.

See `Subspace.dualCopairing_nondegenerate`. -/
def dualCopairing (W : Submodule R M) : W.dualAnnihilator →ₗ[R] M ⧸ W →ₗ[R] R :=
  LinearMap.flip <|
    W.liftQ ((Module.dualPairing R M).domRestrict W.dualAnnihilator).flip
      (by
        intro w hw
        ext ⟨φ, hφ⟩
        

Proof state:
case h.mk
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
w : M
hw : w ∈ W
φ : Dual R M
hφ : φ ∈ dualAnnihilator W
⊢ ((LinearMap.flip (LinearMap.domRestrict (dualPairing R M) (dualAnnihilator W))) w) { val := φ, property := hφ } =
    0 { val := φ, property := hφ }

Next tactic:
exact (mem_dualAnnihilator φ).mp hφ w hw
instance (W : Submodule R M) : FunLike (W.dualAnnihilator) M fun _ => R :=
  { coe := fun φ => φ.val,
    coe_injective' := fun φ ψ h => by
      

Proof state:
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
φ ψ : ↥(dualAnnihilator W)
h : (fun φ => ⇑↑φ) φ = (fun φ => ⇑↑φ) ψ
⊢ φ = ψ

Next tactic:
ext
instance (W : Submodule R M) : FunLike (W.dualAnnihilator) M fun _ => R :=
  { coe := fun φ => φ.val,
    coe_injective' := fun φ ψ h => by
      ext
      

Proof state:
case a.h
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
φ ψ : ↥(dualAnnihilator W)
h : (fun φ => ⇑↑φ) φ = (fun φ => ⇑↑φ) ψ
x✝ : M
⊢ ↑φ x✝ = ↑ψ x✝

Next tactic:
simp only [Function.funext_iff] at h
instance (W : Submodule R M) : FunLike (W.dualAnnihilator) M fun _ => R :=
  { coe := fun φ => φ.val,
    coe_injective' := fun φ ψ h => by
      ext
      simp only [Function.funext_iff] at h
      

Proof state:
case a.h
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
φ ψ : ↥(dualAnnihilator W)
x✝ : M
h : ∀ (a : M), ↑φ a = ↑ψ a
⊢ ↑φ x✝ = ↑ψ x✝

Next tactic:
exact h _
/-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/
theorem range_dualMap_mkQ_eq (W : Submodule R M) :
    LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by
  

Proof state:
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
⊢ LinearMap.range (LinearMap.dualMap (mkQ W)) = dualAnnihilator W

Next tactic:
ext φ
/-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/
theorem range_dualMap_mkQ_eq (W : Submodule R M) :
    LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by
  ext φ
  

Proof state:
case h
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
φ : Dual R M
⊢ φ ∈ LinearMap.range (LinearMap.dualMap (mkQ W)) ↔ φ ∈ dualAnnihilator W

Next tactic:
rw [LinearMap.mem_range]
/-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/
theorem range_dualMap_mkQ_eq (W : Submodule R M) :
    LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by
  ext φ
  rw [LinearMap.mem_range]
  

Proof state:
case h
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
φ : Dual R M
⊢ (∃ y, (LinearMap.dualMap (mkQ W)) y = φ) ↔ φ ∈ dualAnnihilator W

Next tactic:
constructor
/-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/
theorem range_dualMap_mkQ_eq (W : Submodule R M) :
    LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by
  ext φ
  rw [LinearMap.mem_range]
  constructor
  · 

Proof state:
case h.mp
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
φ : Dual R M
⊢ (∃ y, (LinearMap.dualMap (mkQ W)) y = φ) → φ ∈ dualAnnihilator W

Next tactic:
rintro ⟨ψ, rfl⟩
/-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/
theorem range_dualMap_mkQ_eq (W : Submodule R M) :
    LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by
  ext φ
  rw [LinearMap.mem_range]
  constructor
  · rintro ⟨ψ, rfl⟩
    

Proof state:
case h.mp.intro
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
ψ : Dual R (M ⧸ W)
⊢ (LinearMap.dualMap (mkQ W)) ψ ∈ dualAnnihilator W

Next tactic:
have := LinearMap.mem_range_self W.mkQ.dualMap ψ
/-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/
theorem range_dualMap_mkQ_eq (W : Submodule R M) :
    LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by
  ext φ
  rw [LinearMap.mem_range]
  constructor
  · rintro ⟨ψ, rfl⟩
    have := LinearMap.mem_range_self W.mkQ.dualMap ψ
    

Proof state:
case h.mp.intro
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
ψ : Dual R (M ⧸ W)
this : (LinearMap.dualMap (mkQ W)) ψ ∈ LinearMap.range (LinearMap.dualMap (mkQ W))
⊢ (LinearMap.dualMap (mkQ W)) ψ ∈ dualAnnihilator W

Next tactic:
simpa only [ker_mkQ] using W.mkQ.range_dualMap_le_dualAnnihilator_ker this
/-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/
theorem range_dualMap_mkQ_eq (W : Submodule R M) :
    LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by
  ext φ
  rw [LinearMap.mem_range]
  constructor
  · rintro ⟨ψ, rfl⟩
    have := LinearMap.mem_range_self W.mkQ.dualMap ψ
    simpa only [ker_mkQ] using W.mkQ.range_dualMap_le_dualAnnihilator_ker this
  · 

Proof state:
case h.mpr
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
φ : Dual R M
⊢ φ ∈ dualAnnihilator W → ∃ y, (LinearMap.dualMap (mkQ W)) y = φ

Next tactic:
intro hφ
/-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/
theorem range_dualMap_mkQ_eq (W : Submodule R M) :
    LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by
  ext φ
  rw [LinearMap.mem_range]
  constructor
  · rintro ⟨ψ, rfl⟩
    have := LinearMap.mem_range_self W.mkQ.dualMap ψ
    simpa only [ker_mkQ] using W.mkQ.range_dualMap_le_dualAnnihilator_ker this
  · intro hφ
    

Proof state:
case h.mpr
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
φ : Dual R M
hφ : φ ∈ dualAnnihilator W
⊢ ∃ y, (LinearMap.dualMap (mkQ W)) y = φ

Next tactic:
exists W.dualCopairing ⟨φ, hφ⟩
/-- Equivalence $(M/W)^* \approx \operatorname{ann}(W)$. That is, there is a one-to-one
correspondence between the dual of `M ⧸ W` and those elements of the dual of `M` that
vanish on `W`.

The inverse of this is `Submodule.dualCopairing`. -/
def dualQuotEquivDualAnnihilator (W : Submodule R M) :
    Module.Dual R (M ⧸ W) ≃ₗ[R] W.dualAnnihilator :=
  LinearEquiv.ofLinear
    (W.mkQ.dualMap.codRestrict W.dualAnnihilator fun φ =>
-- Porting note: broken dot notation lean4#1910 LinearMap.mem_range_self
      W.range_dualMap_mkQ_eq ▸ LinearMap.mem_range_self W.mkQ.dualMap φ)
    W.dualCopairing (by 

Proof state:
R : Type u_1
M : Type u_2
M' : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup M'
inst✝ : Module R M'
W : Submodule R M
⊢ LinearMap.comp
      (LinearMap.codRestrict (dualAnnihilator W) (LinearMap.dualMap (mkQ W))
        (_ : ∀ (φ : Dual R (M ⧸ W)), (LinearMap.dualMap (mkQ W)) φ ∈ dualAnnihilator W))
      (dualCopairing W) =
    LinearMap.id

Next tactic:
ext