l3lab/ntp-mathlib huggingface dataset:
/-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are
still either almost empty or full. -/
theorem ae_empty_or_univ' (hf : QuasiErgodic f μ) (hs : MeasurableSet s) (hs' : f ⁻¹' s =ᵐ[μ] s) :
    s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  obtain ⟨t, h₀, h₁, h₂⟩ := hf.toQuasiMeasurePreserving.exists_preimage_eq_of_preimage_ae hs hs'
  rcases hf.ae_empty_or_univ h₀ h₂ with (h₃ | h₃) <;> [

Proof state:
case intro.intro.intro.inl
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : QuasiErgodic f
hs : MeasurableSet s
hs' : f ⁻¹' s =ᶠ[ae μ] s
t : Set α
h₀ : MeasurableSet t
h₁ : t =ᶠ[ae μ] s
h₂ : f ⁻¹' t = t
h₃ : t =ᶠ[ae μ] ∅
⊢ s =ᶠ[ae μ] ∅ ∨ s =ᶠ[ae μ] univ

Next tactic:
left
/-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are
still either almost empty or full. -/
theorem ae_empty_or_univ' (hf : QuasiErgodic f μ) (hs : MeasurableSet s) (hs' : f ⁻¹' s =ᵐ[μ] s) :
    s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  obtain ⟨t, h₀, h₁, h₂⟩ := hf.toQuasiMeasurePreserving.exists_preimage_eq_of_preimage_ae hs hs'
  rcases hf.ae_empty_or_univ h₀ h₂ with (h₃ | h₃) <;> [left; 

Proof state:
case intro.intro.intro.inr
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : QuasiErgodic f
hs : MeasurableSet s
hs' : f ⁻¹' s =ᶠ[ae μ] s
t : Set α
h₀ : MeasurableSet t
h₁ : t =ᶠ[ae μ] s
h₂ : f ⁻¹' t = t
h₃ : t =ᶠ[ae μ] univ
⊢ s =ᶠ[ae μ] ∅ ∨ s =ᶠ[ae μ] univ

Next tactic:
right
/-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are
still either almost empty or full. -/
theorem ae_empty_or_univ' (hf : QuasiErgodic f μ) (hs : MeasurableSet s) (hs' : f ⁻¹' s =ᵐ[μ] s) :
    s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  obtain ⟨t, h₀, h₁, h₂⟩ := hf.toQuasiMeasurePreserving.exists_preimage_eq_of_preimage_ae hs hs'
  rcases hf.ae_empty_or_univ h₀ h₂ with (h₃ | h₃) <;> [left; right] <;> 

Proof state:
case intro.intro.intro.inl.h
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : QuasiErgodic f
hs : MeasurableSet s
hs' : f ⁻¹' s =ᶠ[ae μ] s
t : Set α
h₀ : MeasurableSet t
h₁ : t =ᶠ[ae μ] s
h₂ : f ⁻¹' t = t
h₃ : t =ᶠ[ae μ] ∅
⊢ s =ᶠ[ae μ] ∅

Next tactic:
exact ae_eq_trans h₁.symm h₃
/-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are
still either almost empty or full. -/
theorem ae_empty_or_univ' (hf : QuasiErgodic f μ) (hs : MeasurableSet s) (hs' : f ⁻¹' s =ᵐ[μ] s) :
    s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  obtain ⟨t, h₀, h₁, h₂⟩ := hf.toQuasiMeasurePreserving.exists_preimage_eq_of_preimage_ae hs hs'
  rcases hf.ae_empty_or_univ h₀ h₂ with (h₃ | h₃) <;> [left; right] <;> 

Proof state:
case intro.intro.intro.inr.h
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : QuasiErgodic f
hs : MeasurableSet s
hs' : f ⁻¹' s =ᶠ[ae μ] s
t : Set α
h₀ : MeasurableSet t
h₁ : t =ᶠ[ae μ] s
h₂ : f ⁻¹' t = t
h₃ : t =ᶠ[ae μ] univ
⊢ s =ᶠ[ae μ] univ

Next tactic:
exact ae_eq_trans h₁.symm h₃
/-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are
still either almost empty or full. -/
theorem ae_mem_or_ae_nmem₀ (hf : QuasiErgodic f μ) (hsm : NullMeasurableSet s μ)
    (hs : f ⁻¹' s =ᵐ[μ] s) :
    (∀ᵐ x ∂μ, x ∈ s) ∨ ∀ᵐ x ∂μ, x ∉ s :=
  (hf.ae_empty_or_univ₀ hsm hs).symm.imp (by 

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : QuasiErgodic f
hsm : NullMeasurableSet s
hs : f ⁻¹' s =ᶠ[ae μ] s
⊢ s =ᶠ[ae μ] univ → ∀ᵐ (x : α) ∂μ, x ∈ s

Next tactic:
simp [mem_ae_iff]
/-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are
still either almost empty or full. -/
theorem ae_mem_or_ae_nmem₀ (hf : QuasiErgodic f μ) (hsm : NullMeasurableSet s μ)
    (hs : f ⁻¹' s =ᵐ[μ] s) :
    (∀ᵐ x ∂μ, x ∈ s) ∨ ∀ᵐ x ∂μ, x ∉ s :=
  (hf.ae_empty_or_univ₀ hsm hs).symm.imp (by simp [mem_ae_iff]) (by 

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : QuasiErgodic f
hsm : NullMeasurableSet s
hs : f ⁻¹' s =ᶠ[ae μ] s
⊢ s =ᶠ[ae μ] ∅ → ∀ᵐ (x : α) ∂μ, x ∉ s

Next tactic:
simp [ae_iff]
/-- See also `Ergodic.ae_empty_or_univ_of_preimage_ae_le`. -/
theorem ae_empty_or_univ_of_preimage_ae_le' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : f ⁻¹' s ≤ᵐ[μ] s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
hs' : f ⁻¹' s ≤ᶠ[ae μ] s
h_fin : ↑↑μ s ≠ ⊤
⊢ s =ᶠ[ae μ] ∅ ∨ s =ᶠ[ae μ] univ

Next tactic:
refine' hf.quasiErgodic.ae_empty_or_univ' hs _
/-- See also `Ergodic.ae_empty_or_univ_of_preimage_ae_le`. -/
theorem ae_empty_or_univ_of_preimage_ae_le' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : f ⁻¹' s ≤ᵐ[μ] s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  refine' hf.quasiErgodic.ae_empty_or_univ' hs _
  

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
hs' : f ⁻¹' s ≤ᶠ[ae μ] s
h_fin : ↑↑μ s ≠ ⊤
⊢ f ⁻¹' s =ᶠ[ae μ] s

Next tactic:
refine' ae_eq_of_ae_subset_of_measure_ge hs' (hf.measure_preimage hs).symm.le _ h_fin
/-- See also `Ergodic.ae_empty_or_univ_of_preimage_ae_le`. -/
theorem ae_empty_or_univ_of_preimage_ae_le' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : f ⁻¹' s ≤ᵐ[μ] s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  refine' hf.quasiErgodic.ae_empty_or_univ' hs _
  refine' ae_eq_of_ae_subset_of_measure_ge hs' (hf.measure_preimage hs).symm.le _ h_fin
  

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
hs' : f ⁻¹' s ≤ᶠ[ae μ] s
h_fin : ↑↑μ s ≠ ⊤
⊢ MeasurableSet (f ⁻¹' s)

Next tactic:
exact measurableSet_preimage hf.measurable hs
/-- See also `Ergodic.ae_empty_or_univ_of_ae_le_preimage`. -/
theorem ae_empty_or_univ_of_ae_le_preimage' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : s ≤ᵐ[μ] f ⁻¹' s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
hs' : s ≤ᶠ[ae μ] f ⁻¹' s
h_fin : ↑↑μ s ≠ ⊤
⊢ s =ᶠ[ae μ] ∅ ∨ s =ᶠ[ae μ] univ

Next tactic:
replace h_fin : μ (f ⁻¹' s) ≠ ∞
/-- See also `Ergodic.ae_empty_or_univ_of_ae_le_preimage`. -/
theorem ae_empty_or_univ_of_ae_le_preimage' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : s ≤ᵐ[μ] f ⁻¹' s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  replace h_fin : μ (f ⁻¹' s) ≠ ∞; · 

Proof state:
case h_fin
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
hs' : s ≤ᶠ[ae μ] f ⁻¹' s
h_fin : ↑↑μ s ≠ ⊤
⊢ ↑↑μ (f ⁻¹' s) ≠ ⊤

Next tactic:
rwa [hf.measure_preimage hs]
/-- See also `Ergodic.ae_empty_or_univ_of_ae_le_preimage`. -/
theorem ae_empty_or_univ_of_ae_le_preimage' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : s ≤ᵐ[μ] f ⁻¹' s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  replace h_fin : μ (f ⁻¹' s) ≠ ∞; · rwa [hf.measure_preimage hs]
  

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
hs' : s ≤ᶠ[ae μ] f ⁻¹' s
h_fin : ↑↑μ (f ⁻¹' s) ≠ ⊤
⊢ s =ᶠ[ae μ] ∅ ∨ s =ᶠ[ae μ] univ

Next tactic:
refine' hf.quasiErgodic.ae_empty_or_univ' hs _
/-- See also `Ergodic.ae_empty_or_univ_of_ae_le_preimage`. -/
theorem ae_empty_or_univ_of_ae_le_preimage' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : s ≤ᵐ[μ] f ⁻¹' s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  replace h_fin : μ (f ⁻¹' s) ≠ ∞; · rwa [hf.measure_preimage hs]
  refine' hf.quasiErgodic.ae_empty_or_univ' hs _
  

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
hs' : s ≤ᶠ[ae μ] f ⁻¹' s
h_fin : ↑↑μ (f ⁻¹' s) ≠ ⊤
⊢ f ⁻¹' s =ᶠ[ae μ] s

Next tactic:
exact (ae_eq_of_ae_subset_of_measure_ge hs' (hf.measure_preimage hs).le hs h_fin).symm
/-- See also `Ergodic.ae_empty_or_univ_of_image_ae_le`. -/
theorem ae_empty_or_univ_of_image_ae_le' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : f '' s ≤ᵐ[μ] s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
hs' : f '' s ≤ᶠ[ae μ] s
h_fin : ↑↑μ s ≠ ⊤
⊢ s =ᶠ[ae μ] ∅ ∨ s =ᶠ[ae μ] univ

Next tactic:
replace hs' : s ≤ᵐ[μ] f ⁻¹' s :=
    (HasSubset.Subset.eventuallyLE (subset_preimage_image f s)).trans
      (hf.quasiMeasurePreserving.preimage_mono_ae hs')
/-- See also `Ergodic.ae_empty_or_univ_of_image_ae_le`. -/
theorem ae_empty_or_univ_of_image_ae_le' (hf : Ergodic f μ) (hs : MeasurableSet s)
    (hs' : f '' s ≤ᵐ[μ] s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by
  replace hs' : s ≤ᵐ[μ] f ⁻¹' s :=
    (HasSubset.Subset.eventuallyLE (subset_preimage_image f s)).trans
      (hf.quasiMeasurePreserving.preimage_mono_ae hs')
  

Proof state:
α : Type u_1
m : MeasurableSpace α
f : α → α
s : Set α
μ : Measure α
hf : Ergodic f
hs : MeasurableSet s
h_fin : ↑↑μ s ≠ ⊤
hs' : s ≤ᶠ[ae μ] f ⁻¹' s
⊢ s =ᶠ[ae μ] ∅ ∨ s =ᶠ[ae μ] univ

Next tactic:
exact ae_empty_or_univ_of_ae_le_preimage' hf hs hs' h_fin
/-- The dual submodule of a submodule with respect to a bilinear form. -/
def dualSubmodule (N : Submodule R M) : Submodule R M where
  carrier := { x | ∀ y ∈ N, B x y ∈ (1 : Submodule R S) }
  add_mem' {a b} ha hb y hy := by 

Proof state:
R : Type ?u.6128
S : Type ?u.6131
M : Type ?u.6134
inst✝⁶ : CommRing R
inst✝⁵ : Field S
inst✝⁴ : AddCommGroup M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
B : BilinForm S M
N : Submodule R M
a b : M
ha : a ∈ {x | ∀ y ∈ N, bilin B x y ∈ 1}
hb : b ∈ {x | ∀ y ∈ N, bilin B x y ∈ 1}
y : M
hy : y ∈ N
⊢ bilin B (a + b) y ∈ 1

Next tactic:
simpa using add_mem (ha y hy) (hb y hy)
/-- The dual submodule of a submodule with respect to a bilinear form. -/
def dualSubmodule (N : Submodule R M) : Submodule R M where
  carrier := { x | ∀ y ∈ N, B x y ∈ (1 : Submodule R S) }
  add_mem' {a b} ha hb y hy := by simpa using add_mem (ha y hy) (hb y hy)
  zero_mem' y _ := by 

Proof state:
R : Type ?u.6128
S : Type ?u.6131
M : Type ?u.6134
inst✝⁶ : CommRing R
inst✝⁵ : Field S
inst✝⁴ : AddCommGroup M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
B : BilinForm S M
N : Submodule R M
y : M
x✝ : y ∈ N
⊢ bilin B 0 y ∈ 1

Next tactic:
rw [B.zero_left]
/-- The dual submodule of a submodule with respect to a bilinear form. -/
def dualSubmodule (N : Submodule R M) : Submodule R M where
  carrier := { x | ∀ y ∈ N, B x y ∈ (1 : Submodule R S) }
  add_mem' {a b} ha hb y hy := by simpa using add_mem (ha y hy) (hb y hy)
  zero_mem' y _ := by rw [B.zero_left]; 

Proof state:
R : Type ?u.6128
S : Type ?u.6131
M : Type ?u.6134
inst✝⁶ : CommRing R
inst✝⁵ : Field S
inst✝⁴ : AddCommGroup M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
B : BilinForm S M
N : Submodule R M
y : M
x✝ : y ∈ N
⊢ 0 ∈ 1

Next tactic:
exact zero_mem _
/-- The dual submodule of a submodule with respect to a bilinear form. -/
def dualSubmodule (N : Submodule R M) : Submodule R M where
  carrier := { x | ∀ y ∈ N, B x y ∈ (1 : Submodule R S) }
  add_mem' {a b} ha hb y hy := by simpa using add_mem (ha y hy) (hb y hy)
  zero_mem' y _ := by rw [B.zero_left]; exact zero_mem _
  smul_mem' r a ha y hy := by
    

Proof state:
R : Type ?u.6128
S : Type ?u.6131
M : Type ?u.6134
inst✝⁶ : CommRing R
inst✝⁵ : Field S
inst✝⁴ : AddCommGroup M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
B : BilinForm S M
N : Submodule R M
r : R
a : M
ha :
  a ∈
    {
          toAddSubsemigroup :=
            { carrier := {x | ∀ y ∈ N, bilin B x y ∈ 1},
              add_mem' :=
                (_ :
                  ∀ {a b : M},
                    a ∈ {x | ∀ y ∈ N, bilin B x y ∈ 1} →
                      b ∈ {x | ∀ y ∈ N, bilin B x y ∈ 1} → ∀ y ∈ N, bilin B (a + b) y ∈ 1) },
          zero_mem' := (_ : ∀ y ∈ N, bilin B 0 y ∈ 1) }.toAddSubsemigroup.carrier
y : M
hy : y ∈ N
⊢ bilin B (r • a) y ∈ 1

Next tactic:
convert (1 : Submodule R S).smul_mem r (ha y hy)
/-- The dual submodule of a submodule with respect to a bilinear form. -/
def dualSubmodule (N : Submodule R M) : Submodule R M where
  carrier := { x | ∀ y ∈ N, B x y ∈ (1 : Submodule R S) }
  add_mem' {a b} ha hb y hy := by simpa using add_mem (ha y hy) (hb y hy)
  zero_mem' y _ := by rw [B.zero_left]; exact zero_mem _
  smul_mem' r a ha y hy := by
    convert (1 : Submodule R S).smul_mem r (ha y hy)
    

Proof state:
case h.e'_4
R : Type ?u.6128
S : Type ?u.6131
M : Type ?u.6134
inst✝⁶ : CommRing R
inst✝⁵ : Field S
inst✝⁴ : AddCommGroup M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
B : BilinForm S M
N : Submodule R M
r : R
a : M
ha :
  a ∈
    {
          toAddSubsemigroup :=
            { carrier := {x | ∀ y ∈ N, bilin B x y ∈ 1},
              add_mem' :=
                (_ :
                  ∀ {a b : M},
                    a ∈ {x | ∀ y ∈ N, bilin B x y ∈ 1} →
                      b ∈ {x | ∀ y ∈ N, bilin B x y ∈ 1} → ∀ y ∈ N, bilin B (a + b) y ∈ 1) },
          zero_mem' := (_ : ∀ y ∈ N, bilin B 0 y ∈ 1) }.toAddSubsemigroup.carrier
y : M
hy : y ∈ N
⊢ bilin B (r • a) y = r • bilin B a y

Next tactic:
rw [← IsScalarTower.algebraMap_smul S r a, bilin_smul_left, Algebra.smul_def]
lemma le_flip_dualSubmodule {N₁ N₂ : Submodule R M} :
    N₁ ≤ B.flip.dualSubmodule N₂ ↔ N₂ ≤ B.dualSubmodule N₁ := by
  

Proof state:
R : Type u_1
S : Type u_3
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : Field S
inst✝⁴ : AddCommGroup M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
B : BilinForm S M
N₁ N₂ : Submodule R M
⊢ N₁ ≤ dualSubmodule (flip B) N₂ ↔ N₂ ≤ dualSubmodule B N₁

Next tactic:
show (∀ (x : M), x ∈ N₁ → _) ↔ ∀ (x : M), x ∈ N₂ → _
lemma le_flip_dualSubmodule {N₁ N₂ : Submodule R M} :
    N₁ ≤ B.flip.dualSubmodule N₂ ↔ N₂ ≤ B.dualSubmodule N₁ := by
  show (∀ (x : M), x ∈ N₁ → _) ↔ ∀ (x : M), x ∈ N₂ → _
  

Proof state:
R : Type u_1
S : Type u_3
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : Field S
inst✝⁴ : AddCommGroup M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
B : BilinForm S M
N₁ N₂ : Submodule R M
⊢ (∀ x ∈ N₁, x ∈ dualSubmodule (flip B) N₂) ↔ ∀ x ∈ N₂, x ∈ dualSubmodule B N₁

Next tactic:
simp only [mem_dualSubmodule, Submodule.mem_one, flip_apply]
lemma le_flip_dualSubmodule {N₁ N₂ : Submodule R M} :
    N₁ ≤ B.flip.dualSubmodule N₂ ↔ N₂ ≤ B.dualSubmodule N₁ := by
  show (∀ (x : M), x ∈ N₁ → _) ↔ ∀ (x : M), x ∈ N₂ → _
  simp only [mem_dualSubmodule, Submodule.mem_one, flip_apply]
  

Proof state:
R : Type u_1
S : Type u_3
M : Type u_2
inst✝⁶ : CommRing R
inst✝⁵ : Field S
inst✝⁴ : AddCommGroup M
inst✝³ : Algebra R S
inst✝² : Module R M
inst✝¹ : Module S M
inst✝ : IsScalarTower R S M
B : BilinForm S M
N₁ N₂ : Submodule R M
⊢ (∀ x ∈ N₁, ∀ y ∈ N₂, ∃ y_1, (algebraMap R S) y_1 = bilin B y x) ↔
    ∀ x ∈ N₂, ∀ y ∈ N₁, ∃ y_1, (algebraMap R S) y_1 = bilin B x y

Next tactic:
exact forall₂_swap
/-- The natural paring of `B.dualSubmodule N` and `N`. -/
-- TODO: Show that this is perfect when `N` is a lattice and `B` is nondegenerate.
@[simps]
noncomputable
def dualSubmoduleToDual [NoZeroSMulDivisors R S] (N : Submodule R M) :
    B.dualSubmodule N →ₗ[R] Module.Dual R N :=
  { toFun := fun x ↦
    { toFun := B.dualSubmoduleParing x
      map_add' := fun x y ↦ NoZeroSMulDivisors.algebraMap_injective R S (by 

Proof state:
R : Type ?u.87584
S : Type ?u.87587
M : Type ?u.87590
inst✝⁷ : CommRing R
inst✝⁶ : Field S
inst✝⁵ : AddCommGroup M
inst✝⁴ : Algebra R S
inst✝³ : Module R M
inst✝² : Module S M
inst✝¹ : IsScalarTower R S M
B : BilinForm S M
inst✝ : NoZeroSMulDivisors R S
N : Submodule R M
x✝ : ↥(dualSubmodule B N)
x y : ↥N
⊢ (algebraMap R S) (dualSubmoduleParing B x✝ (x + y)) =
    (algebraMap R S) (dualSubmoduleParing B x✝ x + dualSubmoduleParing B x✝ y)

Next tactic:
simp
/-- The natural paring of `B.dualSubmodule N` and `N`. -/
-- TODO: Show that this is perfect when `N` is a lattice and `B` is nondegenerate.
@[simps]
noncomputable
def dualSubmoduleToDual [NoZeroSMulDivisors R S] (N : Submodule R M) :
    B.dualSubmodule N →ₗ[R] Module.Dual R N :=
  { toFun := fun x ↦
    { toFun := B.dualSubmoduleParing x
      map_add' := fun x y ↦ NoZeroSMulDivisors.algebraMap_injective R S (by simp)
      map_smul' := fun r m ↦ NoZeroSMulDivisors.algebraMap_injective R S
        (by 

Proof state:
R : Type ?u.87584
S : Type ?u.87587
M : Type ?u.87590
inst✝⁷ : CommRing R
inst✝⁶ : Field S
inst✝⁵ : AddCommGroup M
inst✝⁴ : Algebra R S
inst✝³ : Module R M
inst✝² : Module S M
inst✝¹ : IsScalarTower R S M
B : BilinForm S M
inst✝ : NoZeroSMulDivisors R S
N : Submodule R M
x : ↥(dualSubmodule B N)
r : R
m : ↥N
⊢ (algebraMap R S)
      (AddHom.toFun
        { toFun := dualSubmoduleParing B x,
          map_add' :=
            (_ :
              ∀ (x_1 y : ↥N),
                dualSubmoduleParing B x (x_1 + y) = dualSubmoduleParing B x x_1 + dualSubmoduleParing B x y) }
        (r • m)) =
    (algebraMap R S)
      ((RingHom.id R) r •
        AddHom.toFun
          { toFun := dualSubmoduleParing B x,
            map_add' :=
              (_ :
                ∀ (x_1 y : ↥N),
                  dualSubmoduleParing B x (x_1 + y) = dualSubmoduleParing B x x_1 + dualSubmoduleParing B x y) }
          m)

Next tactic:
simp [← Algebra.smul_def]
lemma dualSubmoduleToDual_injective (hB : B.Nondegenerate) [NoZeroSMulDivisors R S]
    (N : Submodule R M) (hN : Submodule.span S (N : Set M) = ⊤) :
    Function.Injective (B.dualSubmoduleToDual N) := by
  

Proof state:
R : Type u_3
S : Type u_2
M : Type u_1
inst✝⁷ : CommRing R
inst✝⁶ : Field S
inst✝⁵ : AddCommGroup M
inst✝⁴ : Algebra R S
inst✝³ : Module R M
inst✝² : Module S M
inst✝¹ : IsScalarTower R S M
B : BilinForm S M
hB : Nondegenerate B
inst✝ : NoZeroSMulDivisors R S
N : Submodule R M
hN : Submodule.span S ↑N = ⊤
⊢ Function.Injective ⇑(dualSubmoduleToDual B N)

Next tactic:
intro x y e
lemma dualSubmoduleToDual_injective (hB : B.Nondegenerate) [NoZeroSMulDivisors R S]
    (N : Submodule R M) (hN : Submodule.span S (N : Set M) = ⊤) :
    Function.Injective (B.dualSubmoduleToDual N) := by
  intro x y e
  

Proof state:
R : Type u_3
S : Type u_2
M : Type u_1
inst✝⁷ : CommRing R
inst✝⁶ : Field S
inst✝⁵ : AddCommGroup M
inst✝⁴ : Algebra R S
inst✝³ : Module R M
inst✝² : Module S M
inst✝¹ : IsScalarTower R S M
B : BilinForm S M
hB : Nondegenerate B
inst✝ : NoZeroSMulDivisors R S
N : Submodule R M
hN : Submodule.span S ↑N = ⊤
x y : ↥(dualSubmodule B N)
e : (dualSubmoduleToDual B N) x = (dualSubmoduleToDual B N) y
⊢ x = y

Next tactic:
ext
lemma dualSubmoduleToDual_injective (hB : B.Nondegenerate) [NoZeroSMulDivisors R S]
    (N : Submodule R M) (hN : Submodule.span S (N : Set M) = ⊤) :
    Function.Injective (B.dualSubmoduleToDual N) := by
  intro x y e
  ext
  

Proof state:
case a
R : Type u_3
S : Type u_2
M : Type u_1
inst✝⁷ : CommRing R
inst✝⁶ : Field S
inst✝⁵ : AddCommGroup M
inst✝⁴ : Algebra R S
inst✝³ : Module R M
inst✝² : Module S M
inst✝¹ : IsScalarTower R S M
B : BilinForm S M
hB : Nondegenerate B
inst✝ : NoZeroSMulDivisors R S
N : Submodule R M
hN : Submodule.span S ↑N = ⊤
x y : ↥(dualSubmodule B N)
e : (dualSubmoduleToDual B N) x = (dualSubmoduleToDual B N) y
⊢ ↑x = ↑y

Next tactic:
apply LinearMap.ker_eq_bot.mp hB.ker_eq_bot
lemma dualSubmoduleToDual_injective (hB : B.Nondegenerate) [NoZeroSMulDivisors R S]
    (N : Submodule R M) (hN : Submodule.span S (N : Set M) = ⊤) :
    Function.Injective (B.dualSubmoduleToDual N) := by
  intro x y e
  ext
  apply LinearMap.ker_eq_bot.mp hB.ker_eq_bot
  

Proof state:
case a.a
R : Type u_3
S : Type u_2
M : Type u_1
inst✝⁷ : CommRing R
inst✝⁶ : Field S
inst✝⁵ : AddCommGroup M
inst✝⁴ : Algebra R S
inst✝³ : Module R M
inst✝² : Module S M
inst✝¹ : IsScalarTower R S M
B : BilinForm S M
hB : Nondegenerate B
inst✝ : NoZeroSMulDivisors R S
N : Submodule R M
hN : Submodule.span S ↑N = ⊤
x y : ↥(dualSubmodule B N)
e : (dualSubmoduleToDual B N) x = (dualSubmoduleToDual B N) y
⊢ (toLin B) ↑x = (toLin B) ↑y

Next tactic:
apply LinearMap.ext_on hN
lemma dualSubmoduleToDual_injective (hB : B.Nondegenerate) [NoZeroSMulDivisors R S]
    (N : Submodule R M) (hN : Submodule.span S (N : Set M) = ⊤) :
    Function.Injective (B.dualSubmoduleToDual N) := by
  intro x y e
  ext
  apply LinearMap.ker_eq_bot.mp hB.ker_eq_bot
  apply LinearMap.ext_on hN
  

Proof state:
case a.a
R : Type u_3
S : Type u_2
M : Type u_1
inst✝⁷ : CommRing R
inst✝⁶ : Field S
inst✝⁵ : AddCommGroup M
inst✝⁴ : Algebra R S
inst✝³ : Module R M
inst✝² : Module S M
inst✝¹ : IsScalarTower R S M
B : BilinForm S M
hB : Nondegenerate B
inst✝ : NoZeroSMulDivisors R S
N : Submodule R M
hN : Submodule.span S ↑N = ⊤
x y : ↥(dualSubmodule B N)
e : (dualSubmoduleToDual B N) x = (dualSubmoduleToDual B N) y
⊢ Set.EqOn ⇑((toLin B) ↑x) ⇑((toLin B) ↑y) ↑N

Next tactic:
intro z hz
lemma dualSubmoduleToDual_injective (hB : B.Nondegenerate) [NoZeroSMulDivisors R S]
    (N : Submodule R M) (hN : Submodule.span S (N : Set M) = ⊤) :
    Function.Injective (B.dualSubmoduleToDual N) := by
  intro x y e
  ext
  apply LinearMap.ker_eq_bot.mp hB.ker_eq_bot
  apply LinearMap.ext_on hN
  intro z hz
  

Proof state:
case a.a
R : Type u_3
S : Type u_2
M : Type u_1
inst✝⁷ : CommRing R
inst✝⁶ : Field S
inst✝⁵ : AddCommGroup M
inst✝⁴ : Algebra R S
inst✝³ : Module R M
inst✝² : Module S M
inst✝¹ : IsScalarTower R S M
B : BilinForm S M
hB : Nondegenerate B
inst✝ : NoZeroSMulDivisors R S
N : Submodule R M
hN : Submodule.span S ↑N = ⊤
x y : ↥(dualSubmodule B N)
e : (dualSubmoduleToDual B N) x = (dualSubmoduleToDual B N) y
z : M
hz : z ∈ ↑N
⊢ ((toLin B) ↑x) z = ((toLin B) ↑y) z

Next tactic:
simpa using congr_arg (algebraMap R S) (LinearMap.congr_fun e ⟨z, hz⟩)
lemma dualSubmodule_span_of_basis {ι} [Fintype ι] [DecidableEq ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.dualSubmodule (Submodule.span R (Set.range b)) =
      Submodule.span R (Set.range <| B.dualBasis hB b) := by
  

Proof state:
R : Type u_4
S : Type u_3
M : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : Field S
inst✝⁶ : AddCommGroup M
inst✝⁵ : Algebra R S
inst✝⁴ : Module R M
inst✝³ : Module S M
inst✝² : IsScalarTower R S M
B : BilinForm S M
ι : Type u_1
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
hB : Nondegenerate B
b : Basis ι S M
⊢ dualSubmodule B (Submodule.span R (Set.range ⇑b)) = Submodule.span R (Set.range ⇑(dualBasis B hB b))

Next tactic:
apply le_antisymm
lemma dualSubmodule_span_of_basis {ι} [Fintype ι] [DecidableEq ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.dualSubmodule (Submodule.span R (Set.range b)) =
      Submodule.span R (Set.range <| B.dualBasis hB b) := by
  apply le_antisymm
  · 

Proof state:
case a
R : Type u_4
S : Type u_3
M : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : Field S
inst✝⁶ : AddCommGroup M
inst✝⁵ : Algebra R S
inst✝⁴ : Module R M
inst✝³ : Module S M
inst✝² : IsScalarTower R S M
B : BilinForm S M
ι : Type u_1
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
hB : Nondegenerate B
b : Basis ι S M
⊢ dualSubmodule B (Submodule.span R (Set.range ⇑b)) ≤ Submodule.span R (Set.range ⇑(dualBasis B hB b))

Next tactic:
intro x hx
lemma dualSubmodule_span_of_basis {ι} [Fintype ι] [DecidableEq ι]
    (hB : B.Nondegenerate) (b : Basis ι S M) :
    B.dualSubmodule (Submodule.span R (Set.range b)) =
      Submodule.span R (Set.range <| B.dualBasis hB b) := by
  apply le_antisymm
  · intro x hx
    

Proof state:
case a
R : Type u_4
S : Type u_3
M : Type u_2
inst✝⁸ : CommRing R
inst✝⁷ : Field S
inst✝⁶ : AddCommGroup M
inst✝⁵ : Algebra R S
inst✝⁴ : Module R M
inst✝³ : Module S M
inst✝² : IsScalarTower R S M
B : BilinForm S M
ι : Type u_1
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
hB : Nondegenerate B
b : Basis ι S M
x : M
hx : x ∈ dualSubmodule B (Submodule.span R (Set.range ⇑b))
⊢ x ∈ Submodule.span R (Set.range ⇑(dualBasis B hB b))

Next tactic:
rw [← (B.dualBasis hB b).sum_repr x]