l3lab/ntp-mathlib huggingface dataset:
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
⊢ Function.Injective ⇑(toLin (dualProd R M)) ↔ Function.Injective ⇑(Module.Dual.eval R M)

Next tactic:
refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
⊢ Function.Injective (⇑(LinearEquiv.symm e) ∘ ⇑(toLin (dualProd R M))) ↔ Function.Injective ⇑(Module.Dual.eval R M)

Next tactic:
rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
⊢ Function.Injective ⇑(↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)) ↔ Function.Injective ⇑(Module.Dual.eval R M)

Next tactic:
change Function.Injective h_d ↔ _
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
⊢ Function.Injective ⇑h_d ↔ Function.Injective ⇑(Module.Dual.eval R M)

Next tactic:
have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
⊢ h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M)

Next tactic:
refine' LinearMap.ext fun x => Prod.ext _ _
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · 

Proof state:
case refine'_1
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
x : Module.Dual R M × M
⊢ (h_d x).1 = ((LinearMap.prodMap LinearMap.id (Module.Dual.eval R M)) x).1

Next tactic:
ext
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      

Proof state:
case refine'_1.h
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
x : Module.Dual R M × M
x✝ : M
⊢ (h_d x).1 x✝ = ((LinearMap.prodMap LinearMap.id (Module.Dual.eval R M)) x).1 x✝

Next tactic:
dsimp [Module.Dual.eval, LinearEquiv.prodComm]
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      

Proof state:
case refine'_1.h
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
x : Module.Dual R M × M
x✝ : M
⊢ 0 + x.1 x✝ = x.1 x✝

Next tactic:
simp
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
    · 

Proof state:
case refine'_2
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
x : Module.Dual R M × M
⊢ (h_d x).2 = ((LinearMap.prodMap LinearMap.id (Module.Dual.eval R M)) x).2

Next tactic:
ext
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
    · ext
      

Proof state:
case refine'_2.h
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
x : Module.Dual R M × M
x✝ : Module.Dual R M
⊢ (h_d x).2 x✝ = ((LinearMap.prodMap LinearMap.id (Module.Dual.eval R M)) x).2 x✝

Next tactic:
dsimp [Module.Dual.eval, LinearEquiv.prodComm]
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      

Proof state:
case refine'_2.h
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
x : Module.Dual R M × M
x✝ : Module.Dual R M
⊢ x✝ x.2 + x.1 0 = x✝ x.2

Next tactic:
simp
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
this : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M)
⊢ Function.Injective ⇑h_d ↔ Function.Injective ⇑(Module.Dual.eval R M)

Next tactic:
rw [this, LinearMap.coe_prodMap]
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
  rw [this, LinearMap.coe_prodMap]
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
this : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M)
⊢ Function.Injective (Prod.map ⇑LinearMap.id ⇑(Module.Dual.eval R M)) ↔ Function.Injective ⇑(Module.Dual.eval R M)

Next tactic:
refine' Prod.map_injective.trans _
theorem nondenerate_dualProd :
    (dualProd R M).Nondegenerate ↔ Function.Injective (Module.Dual.eval R M) := by
  classical
  rw [nondegenerate_iff_ker_eq_bot]
  rw [LinearMap.ker_eq_bot]
  let e := LinearEquiv.prodComm R _ _ ≪≫ₗ Module.dualProdDualEquivDual R (Module.Dual R M) M
  let h_d := e.symm.toLinearMap.comp (BilinForm.toLin <| dualProd R M)
  refine' (Function.Injective.of_comp_iff e.symm.injective
    (BilinForm.toLin <| dualProd R M)).symm.trans _
  rw [← LinearEquiv.coe_toLinearMap, ← LinearMap.coe_comp]
  change Function.Injective h_d ↔ _
  have : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M) := by
    refine' LinearMap.ext fun x => Prod.ext _ _
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
    · ext
      dsimp [Module.Dual.eval, LinearEquiv.prodComm]
      simp
  rw [this, LinearMap.coe_prodMap]
  refine' Prod.map_injective.trans _
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
e : (Module.Dual R M × Module.Dual R (Module.Dual R M)) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) :=
  LinearEquiv.prodComm R (Module.Dual R M) (Module.Dual R (Module.Dual R M)) ≪≫ₗ
    Module.dualProdDualEquivDual R (Module.Dual R M) M
h_d : Module.Dual R M × M →ₗ[R] Module.Dual R M × Module.Dual R (Module.Dual R M) :=
  ↑(LinearEquiv.symm e) ∘ₗ toLin (dualProd R M)
this : h_d = LinearMap.prodMap LinearMap.id (Module.Dual.eval R M)
⊢ Function.Injective ⇑LinearMap.id ∧ Function.Injective ⇑(Module.Dual.eval R M) ↔
    Function.Injective ⇑(Module.Dual.eval R M)

Next tactic:
exact and_iff_right Function.injective_id
/-- The quadratic form on `Module.Dual R M × M` defined as `Q (f, x) = f x`. -/
@[simps]
def dualProd : QuadraticForm R (Module.Dual R M × M) where
  toFun p := p.1 p.2
  toFun_smul a p := by
    

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁴ : CommSemiring R
inst✝³ : AddCommMonoid M
inst✝² : AddCommMonoid N
inst✝¹ : Module R M
inst✝ : Module R N
a : R
p : Module.Dual R M × M
⊢ (fun p => p.1 p.2) (a • p) = a * a * (fun p => p.1 p.2) p

Next tactic:
dsimp only
/-- The quadratic form on `Module.Dual R M × M` defined as `Q (f, x) = f x`. -/
@[simps]
def dualProd : QuadraticForm R (Module.Dual R M × M) where
  toFun p := p.1 p.2
  toFun_smul a p := by
    dsimp only  -- porting note: added
    

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁴ : CommSemiring R
inst✝³ : AddCommMonoid M
inst✝² : AddCommMonoid N
inst✝¹ : Module R M
inst✝ : Module R N
a : R
p : Module.Dual R M × M
⊢ (a • p).1 (a • p).2 = a * a * p.1 p.2

Next tactic:
rw [Prod.smul_fst, Prod.smul_snd, LinearMap.smul_apply, LinearMap.map_smul, smul_eq_mul,
      smul_eq_mul, mul_assoc]
/-- The quadratic form on `Module.Dual R M × M` defined as `Q (f, x) = f x`. -/
@[simps]
def dualProd : QuadraticForm R (Module.Dual R M × M) where
  toFun p := p.1 p.2
  toFun_smul a p := by
    dsimp only  -- porting note: added
    rw [Prod.smul_fst, Prod.smul_snd, LinearMap.smul_apply, LinearMap.map_smul, smul_eq_mul,
      smul_eq_mul, mul_assoc]
  exists_companion' :=
    ⟨BilinForm.dualProd R M, fun p q => by
      

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁴ : CommSemiring R
inst✝³ : AddCommMonoid M
inst✝² : AddCommMonoid N
inst✝¹ : Module R M
inst✝ : Module R N
p q : Module.Dual R M × M
⊢ (fun p => p.1 p.2) (p + q) =
    (fun p => p.1 p.2) p + (fun p => p.1 p.2) q + BilinForm.bilin (BilinForm.dualProd R M) p q

Next tactic:
dsimp only
/-- The quadratic form on `Module.Dual R M × M` defined as `Q (f, x) = f x`. -/
@[simps]
def dualProd : QuadraticForm R (Module.Dual R M × M) where
  toFun p := p.1 p.2
  toFun_smul a p := by
    dsimp only  -- porting note: added
    rw [Prod.smul_fst, Prod.smul_snd, LinearMap.smul_apply, LinearMap.map_smul, smul_eq_mul,
      smul_eq_mul, mul_assoc]
  exists_companion' :=
    ⟨BilinForm.dualProd R M, fun p q => by
      dsimp only  -- porting note: added
      

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁴ : CommSemiring R
inst✝³ : AddCommMonoid M
inst✝² : AddCommMonoid N
inst✝¹ : Module R M
inst✝ : Module R N
p q : Module.Dual R M × M
⊢ (p + q).1 (p + q).2 = p.1 p.2 + q.1 q.2 + BilinForm.bilin (BilinForm.dualProd R M) p q

Next tactic:
rw [BilinForm.dualProd_apply, Prod.fst_add, Prod.snd_add, LinearMap.add_apply, map_add,
        map_add, add_right_comm _ (q.1 q.2), add_comm (q.1 p.2) (p.1 q.2), ← add_assoc, ←
        add_assoc]
/-- The isometry sending `(Q.prod $ -Q)` to `(QuadraticForm.dualProd R M)`.

This is `σ` from Proposition 4.8, page 84 of
[*Hermitian K-Theory and Geometric Applications*][hyman1973]; though we swap the order of the pairs.
-/
@[simps!]
def toDualProd (Q : QuadraticForm R M) [Invertible (2 : R)] :
    (Q.prod <| -Q) →qᵢ QuadraticForm.dualProd R M where
  toLinearMap := LinearMap.prod
    (Q.associated.toLin.comp (LinearMap.fst _ _ _) + Q.associated.toLin.comp (LinearMap.snd _ _ _))
    (LinearMap.fst _ _ _ - LinearMap.snd _ _ _)
  map_app' x := by
    

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
Q : QuadraticForm R M
inst✝ : Invertible 2
x : M × M
⊢ (dualProd R M)
      (AddHom.toFun
        (LinearMap.prod
            (BilinForm.toLin (associated Q) ∘ₗ LinearMap.fst R M M +
              BilinForm.toLin (associated Q) ∘ₗ LinearMap.snd R M M)
            (LinearMap.fst R M M - LinearMap.snd R M M)).toAddHom
        x) =
    (prod Q (-Q)) x

Next tactic:
dsimp only [associated, associatedHom]
/-- The isometry sending `(Q.prod $ -Q)` to `(QuadraticForm.dualProd R M)`.

This is `σ` from Proposition 4.8, page 84 of
[*Hermitian K-Theory and Geometric Applications*][hyman1973]; though we swap the order of the pairs.
-/
@[simps!]
def toDualProd (Q : QuadraticForm R M) [Invertible (2 : R)] :
    (Q.prod <| -Q) →qᵢ QuadraticForm.dualProd R M where
  toLinearMap := LinearMap.prod
    (Q.associated.toLin.comp (LinearMap.fst _ _ _) + Q.associated.toLin.comp (LinearMap.snd _ _ _))
    (LinearMap.fst _ _ _ - LinearMap.snd _ _ _)
  map_app' x := by
    dsimp only [associated, associatedHom]
    dsimp
    -- porting note: added `()` around `Submonoid.smul_def`
    

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
Q : QuadraticForm R M
inst✝ : Invertible 2
x : M × M
⊢ { val := ⅟2, property := (_ : ⅟2 ∈ Set.center R) } • polar (⇑Q) x.1 (x.1 - x.2) +
      { val := ⅟2, property := (_ : ⅟2 ∈ Set.center R) } • polar (⇑Q) x.2 (x.1 - x.2) =
    Q x.1 + -Q x.2

Next tactic:
simp [polar_comm _ x.1 x.2, ← sub_add, mul_sub, sub_mul, smul_sub, (Submonoid.smul_def), ←
      sub_eq_add_neg (Q x.1) (Q x.2)]
/-- The cardinality of the complex numbers, as a type. -/
@[simp]
theorem mk_complex : #ℂ = 𝔠 := by
  

Proof state:
⊢ #ℂ = 𝔠

Next tactic:
rw [mk_congr Complex.equivRealProd, mk_prod, lift_id, mk_real, continuum_mul_self]