Skip to content

Commit 97f1212

Browse files
feat(LinearAlgebra/AffineSpace/AffineSubspace): using AffineSubspace.direction to reinterpret AffineSubspace as Submodule (leanprover-community#38731)
* add `AffineSubspace.vsub_self_of_zero_mem` that states `s -ᵥ s = s ` if `0 ∈ s` * add `AffineSubspace.direction_eq_self_iff_zero_mem` that states that `0 ∈ s` iff the directions coerce back to the affine subspace. * add corresponding `CanLift` instance. * modify doc-string of `AffineSubspace.direction` to state that this can be used for reinterpretation of an affine subspace as a submodule. * add `Coe` instance based on `Submodule.toAffineSubspace` and adds corresponding @[coe] attribute. The PR also performs a slight cleanup of the file: statements about `SetLike` or `Submodule.toAffineSubspace` have been moved closer to their respective definitions. Because the PR was temporarily broken, I also added * the lemma `carrier_eq_coe (s : AffineSubspace k P) : s.carrier = s` Co-authored-by: Martin Winter <martin.winter.math@gmail.com>
1 parent 1450d19 commit 97f1212

1 file changed

Lines changed: 68 additions & 26 deletions

File tree

  • Mathlib/LinearAlgebra/AffineSpace/AffineSubspace

Mathlib/LinearAlgebra/AffineSpace/AffineSubspace/Defs.lean

Lines changed: 68 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -154,17 +154,6 @@ structure AffineSubspace (k : Type*) {V : Type*} (P : Type*) [Ring k] [AddCommGr
154154
∀ (c : k) {p₁ p₂ p₃ : P},
155155
p₁ ∈ carrier → p₂ ∈ carrier → p₃ ∈ carrier → c • (p₁ -ᵥ p₂ : V) +ᵥ p₃ ∈ carrier
156156

157-
namespace Submodule
158-
159-
variable {k V : Type*} [Ring k] [AddCommGroup V] [Module k V]
160-
161-
/-- Reinterpret `p : Submodule k V` as an `AffineSubspace k V`. -/
162-
def toAffineSubspace (p : Submodule k V) : AffineSubspace k V where
163-
carrier := p
164-
smul_vsub_vadd_mem _ _ _ _ h₁ h₂ h₃ := p.add_mem (p.smul_mem _ (p.sub_mem h₁ h₂)) h₃
165-
166-
end Submodule
167-
168157
namespace AffineSubspace
169158

170159
variable (k : Type*) {V : Type*} (P : Type*) [Ring k] [AddCommGroup V] [Module k V]
@@ -176,17 +165,74 @@ instance : SetLike (AffineSubspace k P) P where
176165

177166
instance : PartialOrder (AffineSubspace k P) := .ofSetLike (AffineSubspace k P) P
178167

168+
@[simp] lemma carrier_eq_coe (s : AffineSubspace k P) : s.carrier = s := rfl
169+
179170
/-- A point is in an affine subspace coerced to a set if and only if it is in that affine
180171
subspace. -/
181172
theorem mem_coe (p : P) (s : AffineSubspace k P) : p ∈ (s : Set P) ↔ p ∈ s := by simp
182173

183174
variable {k P}
184175

176+
/-- Two affine subspaces are equal if they have the same points. -/
177+
theorem coe_injective : Function.Injective ((↑) : AffineSubspace k P → Set P) :=
178+
SetLike.coe_injective
179+
180+
@[ext (iff := false)]
181+
theorem ext {p q : AffineSubspace k P} (h : ∀ x, x ∈ p ↔ x ∈ q) : p = q :=
182+
SetLike.ext h
183+
184+
protected theorem ext_iff (s₁ s₂ : AffineSubspace k P) : s₁ = s₂ ↔ (s₁ : Set P) = s₂ :=
185+
SetLike.ext'_iff
186+
187+
end AffineSubspace
188+
189+
namespace Submodule
190+
191+
variable {k V : Type*} [Ring k] [AddCommGroup V] [Module k V]
192+
193+
/-- Reinterprets `p : Submodule k V` as an `AffineSubspace k V`. -/
194+
@[coe] def toAffineSubspace (p : Submodule k V) : AffineSubspace k V where
195+
carrier := p
196+
smul_vsub_vadd_mem _ _ _ _ h₁ h₂ h₃ := p.add_mem (p.smul_mem _ (p.sub_mem h₁ h₂)) h₃
197+
198+
instance : Coe (Submodule k V) (AffineSubspace k V) := ⟨toAffineSubspace⟩
199+
200+
@[simp]
201+
theorem mem_toAffineSubspace {p : Submodule k V} {x : V} :
202+
x ∈ (p : AffineSubspace k V) ↔ x ∈ p := Iff.rfl
203+
204+
end Submodule
205+
206+
namespace AffineSubspace
207+
208+
variable {k : Type*} {V : Type*} {P : Type*} [Ring k] [AddCommGroup V] [Module k V]
209+
[AffineSpace V P]
210+
211+
lemma vsub_self_of_zero_mem {s : AffineSubspace k V} (hs : 0 ∈ s) :
212+
(s : Set V) -ᵥ s = s := by
213+
ext x
214+
constructor
215+
· rintro ⟨a, ha, b, hb, rfl⟩
216+
simpa using s.smul_vsub_vadd_mem 1 ha hb hs
217+
· exact fun h => ⟨x, h, 0, hs, by simp⟩
218+
219+
@[simp] lemma vsub_self_eq_iff_zero_mem {s : AffineSubspace k V} [Nonempty s] :
220+
(s : Set V) -ᵥ s = s ↔ 0 ∈ s := by
221+
refine ⟨fun h ↦ ?_, vsub_self_of_zero_mem⟩
222+
obtain x : s := Classical.choice inferInstance
223+
suffices (x : V) - x ∈ (s : Set _) by aesop
224+
rw [← h, mem_vsub]
225+
aesop
226+
185227
/-- The direction of an affine subspace is the submodule spanned by
186228
the pairwise differences of points. (Except in the case of an empty
187229
affine subspace, where the direction is the zero submodule, every
188230
vector in the direction is the difference of two points in the affine
189-
subspace.) -/
231+
subspace.)
232+
233+
This can also be used to reinterpret an affine subspace that contains
234+
zero as a submodule, see `direction_eq_self_iff_zero_mem`.
235+
-/
190236
def direction (s : AffineSubspace k P) : Submodule k V :=
191237
vectorSpan k (s : Set P)
192238

@@ -301,16 +347,17 @@ theorem mem_direction_iff_eq_vsub_left {s : AffineSubspace k P} {p : P} (hp : p
301347
rw [← SetLike.mem_coe, coe_direction_eq_vsub_set_left hp]
302348
exact ⟨fun ⟨p₂, hp₂, hv⟩ => ⟨p₂, hp₂, hv.symm⟩, fun ⟨p₂, hp₂, hv⟩ => ⟨p₂, hp₂, hv.symm⟩⟩
303349

304-
/-- Two affine subspaces are equal if they have the same points. -/
305-
theorem coe_injective : Function.Injective ((↑) : AffineSubspace k P → Set P) :=
306-
SetLike.coe_injective
307-
308-
@[ext (iff := false)]
309-
theorem ext {p q : AffineSubspace k P} (h : ∀ x, x ∈ p ↔ x ∈ q) : p = q :=
310-
SetLike.ext h
350+
/-- An affine subspace contains zero if and only if it equals its directions. -/
351+
@[simp] lemma direction_eq_self_iff_zero_mem {s : AffineSubspace k V} :
352+
s.direction = s ↔ 0 ∈ s where
353+
mp h := by rw [← h]; simp
354+
mpr h := by
355+
ext x
356+
rw [Submodule.mem_toAffineSubspace, ← SetLike.mem_coe]
357+
simp [s.coe_direction_eq_vsub_set ⟨0, h⟩, vsub_self_of_zero_mem h]
311358

312-
protected theorem ext_iff (s₁ s₂ : AffineSubspace k P) : s₁ = s₂ ↔ (s₁ : Set P) = s₂ :=
313-
SetLike.ext'_iff
359+
instance : CanLift (AffineSubspace k V) (Submodule k V) (·) (0 ∈ ·) :=
360+
fun _ hs => ⟨_, direction_eq_self_iff_zero_mem.mpr hs⟩⟩
314361

315362
/-- Two affine subspaces with the same direction and nonempty intersection are equal. -/
316363
theorem ext_of_direction_eq {s₁ s₂ : AffineSubspace k P} (hd : s₁.direction = s₂.direction)
@@ -401,11 +448,6 @@ namespace Submodule
401448

402449
variable {k V : Type*} [Ring k] [AddCommGroup V] [Module k V]
403450

404-
@[simp]
405-
theorem mem_toAffineSubspace {p : Submodule k V} {x : V} :
406-
x ∈ p.toAffineSubspace ↔ x ∈ p :=
407-
Iff.rfl
408-
409451
@[simp]
410452
theorem toAffineSubspace_direction (s : Submodule k V) : s.toAffineSubspace.direction = s := by
411453
ext x; simp [← s.toAffineSubspace.vadd_mem_iff_mem_direction _ s.zero_mem]

0 commit comments

Comments
 (0)