Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit f548db4

Browse files
committed
feat(linear_algebra/affine_space): lattice structure on affine subspaces (#3288)
Define a `complete_lattice` instance on affine subspaces of an affine space, and prove a few basic lemmas relating to it. (There are plenty more things that could be proved about it, that I think can reasonably be added later.)
1 parent edd29d0 commit f548db4

File tree

2 files changed

+199
-19
lines changed

2 files changed

+199
-19
lines changed

src/algebra/add_torsor.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ by rw [←vsub_vadd_eq_vsub_sub, vsub_vadd]
220220
/-- The pairwise differences of a set of points. -/
221221
def vsub_set (s : set P) : set G := {g | ∃ x ∈ s, ∃ y ∈ s, g = x -ᵥ y}
222222

223+
/-- `vsub_set` of an empty set. -/
224+
@[simp] lemma vsub_set_empty : vsub_set G (∅ : set P) = ∅ :=
225+
begin
226+
rw set.eq_empty_iff_forall_not_mem,
227+
rintros g ⟨p, hp, hg⟩,
228+
exact hp
229+
end
230+
223231
/-- Each pairwise difference is in the `vsub_set`. -/
224232
lemma vsub_mem_vsub_set {p1 p2 : P} {s : set P} (hp1 : p1 ∈ s) (hp2 : p2 ∈ s) :
225233
(p1 -ᵥ p2) ∈ vsub_set G s :=

src/linear_algebra/affine_space.lean

Lines changed: 191 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,16 @@ add_torsor V P
4949
namespace affine_space
5050

5151
variables (k : Type*) (V : Type*) {P : Type*} [ring k] [add_comm_group V] [module k V]
52-
variables [S : affine_space k V P]
53-
include S
52+
variables [affine_space k V P]
5453

5554
/-- The submodule spanning the differences of a (possibly empty) set
5655
of points. -/
5756
def vector_span (s : set P) : submodule k V := submodule.span k (vsub_set V s)
5857

58+
/-- The definition of `vector_span`, for rewriting. -/
59+
lemma vector_span_def (s : set P) : vector_span k V s = submodule.span k (vsub_set V s) :=
60+
rfl
61+
5962
/-- The `vsub_set` lies within the `vector_span`. -/
6063
lemma vsub_set_subset_vector_span (s : set P) : vsub_set V s ⊆ vector_span k V s :=
6164
submodule.subset_span
@@ -334,8 +337,7 @@ structure affine_subspace (k : Type*) (V : Type*) (P : Type*) [ring k] [add_comm
334337
namespace affine_subspace
335338

336339
variables (k : Type*) (V : Type*) (P : Type*) [ring k] [add_comm_group V] [module k V]
337-
[S : affine_space k V P]
338-
include S
340+
[affine_space k V P]
339341

340342
instance : has_coe (affine_subspace k V P) (set P) := ⟨carrier⟩
341343
instance : has_mem P (affine_subspace k V P) := ⟨λ p s, p ∈ (s : set P)⟩
@@ -346,21 +348,6 @@ it is in that affine subspace. -/
346348
p ∈ (s : set P) ↔ p ∈ s :=
347349
iff.rfl
348350

349-
/-- The whole affine space as a subspace of itself. -/
350-
def univ : affine_subspace k V P :=
351-
{ carrier := set.univ,
352-
smul_vsub_vadd_mem := λ _ _ _ _ _ _ _, set.mem_univ _ }
353-
354-
/-- `univ`, coerced to a set, is the whole set of points. -/
355-
@[simp] lemma univ_coe : (univ k V P : set P) = set.univ :=
356-
rfl
357-
358-
/-- All points are in `univ`. -/
359-
lemma mem_univ (p : P) : p ∈ univ k V P :=
360-
set.mem_univ p
361-
362-
instance : inhabited (affine_subspace k V P) := ⟨univ k V P⟩
363-
364351
variables {k V P}
365352

366353
/-- The direction of an affine subspace is the submodule spanned by
@@ -523,6 +510,21 @@ that subspace's direction yields the original subspace. -/
523510
ext_of_direction_eq (direction_mk' p s.direction)
524511
⟨p, set.mem_inter (self_mem_mk' _ _) hp⟩
525512

513+
/-- If an affine subspace contains a set of points, it contains the
514+
`span_points` of that set. -/
515+
lemma span_points_subset_coe_of_subset_coe {s : set P} {s1 : affine_subspace k V P} (h : s ⊆ s1) :
516+
span_points k V s ⊆ s1 :=
517+
begin
518+
rintros p ⟨p1, hp1, v, hv, hp⟩,
519+
rw hp,
520+
have hp1s1 : p1 ∈ (s1 : set P) := set.mem_of_mem_of_subset hp1 h,
521+
refine vadd_mem_of_mem_direction _ hp1s1,
522+
have hs : vector_span k V s ≤ s1.direction := submodule.span_mono (vsub_set_mono V h),
523+
rw submodule.le_def at hs,
524+
rw ←submodule.mem_coe,
525+
exact set.mem_of_mem_of_subset hv hs
526+
end
527+
526528
end affine_subspace
527529

528530
section affine_span
@@ -563,6 +565,176 @@ mem_span_points k V p s hp
563565

564566
end affine_span
565567

568+
namespace affine_subspace
569+
570+
variables (k : Type*) (V : Type*) (P : Type*) [ring k] [add_comm_group V] [module k V]
571+
[S : affine_space k V P]
572+
include S
573+
574+
instance : complete_lattice (affine_subspace k V P) :=
575+
{ sup := λ s1 s2, affine_span k V (s1 ∪ s2),
576+
le_sup_left := λ s1 s2, set.subset.trans (set.subset_union_left s1 s2)
577+
(subset_span_points k V _),
578+
le_sup_right := λ s1 s2, set.subset.trans (set.subset_union_right s1 s2)
579+
(subset_span_points k V _),
580+
sup_le := λ s1 s2 s3 hs1 hs2, span_points_subset_coe_of_subset_coe (set.union_subset hs1 hs2),
581+
inf := λ s1 s2, mk (s1 ∩ s2)
582+
(λ c p1 p2 p3 hp1 hp2 hp3,
583+
⟨s1.smul_vsub_vadd_mem c p1 p2 p3 hp1.1 hp2.1 hp3.1,
584+
s2.smul_vsub_vadd_mem c p1 p2 p3 hp1.2 hp2.2 hp3.2⟩),
585+
inf_le_left := λ _ _, set.inter_subset_left _ _,
586+
inf_le_right := λ _ _, set.inter_subset_right _ _,
587+
le_inf := λ _ _ _, set.subset_inter,
588+
top := { carrier := set.univ,
589+
smul_vsub_vadd_mem := λ _ _ _ _ _ _ _, set.mem_univ _ },
590+
le_top := λ _ _ _, set.mem_univ _,
591+
bot := { carrier := ∅,
592+
smul_vsub_vadd_mem := λ _ _ _ _, false.elim },
593+
bot_le := λ _ _, false.elim,
594+
Sup := λ s, affine_span k V (⋃ s' ∈ s, (s' : set P)),
595+
Inf := λ s, mk (⋂ s' ∈ s, (s' : set P))
596+
(λ c p1 p2 p3 hp1 hp2 hp3, set.mem_bInter_iff.2 $ λ s2 hs2,
597+
s2.smul_vsub_vadd_mem c p1 p2 p3 (set.mem_bInter_iff.1 hp1 s2 hs2)
598+
(set.mem_bInter_iff.1 hp2 s2 hs2)
599+
(set.mem_bInter_iff.1 hp3 s2 hs2)),
600+
le_Sup := λ _ _ h, set.subset.trans (set.subset_bUnion_of_mem h) (subset_span_points k V _),
601+
Sup_le := λ _ _ h, span_points_subset_coe_of_subset_coe (set.bUnion_subset h),
602+
Inf_le := λ _ _, set.bInter_subset_of_mem,
603+
le_Inf := λ _ _, set.subset_bInter,
604+
.. partial_order.lift (coe : affine_subspace k V P → set P) (λ _ _, ext) }
605+
606+
instance : inhabited (affine_subspace k V P) := ⟨⊤⟩
607+
608+
/-- The `≤` order on subspaces is the same as that on the corresponding
609+
sets. -/
610+
lemma le_def (s1 s2 : affine_subspace k V P) : s1 ≤ s2 ↔ (s1 : set P) ⊆ s2 :=
611+
iff.rfl
612+
613+
/-- One subspace is less than or equal to another if and only if all
614+
its points are in the second subspace. -/
615+
lemma le_def' (s1 s2 : affine_subspace k V P) : s1 ≤ s2 ↔ ∀ p ∈ s1, p ∈ s2 :=
616+
iff.rfl
617+
618+
/-- The `<` order on subspaces is the same as that on the corresponding
619+
sets. -/
620+
lemma lt_def (s1 s2 : affine_subspace k V P) : s1 < s2 ↔ (s1 : set P) ⊂ s2 :=
621+
iff.rfl
622+
623+
/-- One subspace is not less than or equal to another if and only if
624+
it has a point not in the second subspace. -/
625+
lemma not_le_iff_exists (s1 s2 : affine_subspace k V P) : ¬ s1 ≤ s2 ↔ ∃ p ∈ s1, p ∉ s2 :=
626+
set.not_subset
627+
628+
/-- If a subspace is less than another, there is a point only in the
629+
second. -/
630+
lemma exists_of_lt {s1 s2 : affine_subspace k V P} (h : s1 < s2) : ∃ p ∈ s2, p ∉ s1 :=
631+
set.exists_of_ssubset h
632+
633+
/-- A subspace is less than another if and only if it is less than or
634+
equal to the second subspace and there is a point only in the
635+
second. -/
636+
lemma lt_iff_le_and_exists (s1 s2 : affine_subspace k V P) : s1 < s2 ↔ s1 ≤ s2 ∧ ∃ p ∈ s2, p ∉ s1 :=
637+
by rw [lt_iff_le_not_le, not_le_iff_exists]
638+
639+
variables {P}
640+
641+
/-- The affine span is the `Inf` of subspaces containing the given
642+
points. -/
643+
lemma affine_span_eq_Inf (s : set P) : affine_span k V s = Inf {s' | s ⊆ s'} :=
644+
le_antisymm (span_points_subset_coe_of_subset_coe (set.subset_bInter (λ _ h, h)))
645+
(Inf_le (subset_span_points k V _))
646+
647+
variables (P)
648+
649+
/-- The Galois insertion formed by `affine_span` and coercion back to
650+
a set. -/
651+
protected def gi : galois_insertion (affine_span k V) (coe : affine_subspace k V P → set P) :=
652+
{ choice := λ s _, affine_span k V s,
653+
gc := λ s1 s2, ⟨λ h, set.subset.trans (subset_span_points k V s1) h,
654+
span_points_subset_coe_of_subset_coe⟩,
655+
le_l_u := λ _, subset_span_points k V _,
656+
choice_eq := λ _ _, rfl }
657+
658+
/-- The span of the empty set is `⊥`. -/
659+
@[simp] lemma span_empty : affine_span k V (∅ : set P) = ⊥ :=
660+
(affine_subspace.gi k V P).gc.l_bot
661+
662+
/-- The span of `univ` is `⊤`. -/
663+
@[simp] lemma span_univ : affine_span k V (set.univ : set P) = ⊤ :=
664+
eq_top_iff.2 $ subset_span_points k V _
665+
666+
/-- The span of a union of sets is the sup of their spans. -/
667+
lemma span_union (s t : set P) : affine_span k V (s ∪ t) = affine_span k V s ⊔ affine_span k V t :=
668+
(affine_subspace.gi k V P).gc.l_sup
669+
670+
/-- The span of a union of an indexed family of sets is the sup of
671+
their spans. -/
672+
lemma span_Union {ι : Type*} (s : ι → set P) :
673+
affine_span k V (⋃ i, s i) = ⨆ i, affine_span k V (s i) :=
674+
(affine_subspace.gi k V P).gc.l_supr
675+
676+
/-- `⊤`, coerced to a set, is the whole set of points. -/
677+
@[simp] lemma top_coe : ((⊤ : affine_subspace k V P) : set P) = set.univ :=
678+
rfl
679+
680+
variables {P}
681+
682+
/-- All points are in `⊤`. -/
683+
lemma mem_top (p : P) : p ∈ (⊤ : affine_subspace k V P) :=
684+
set.mem_univ p
685+
686+
variables (P)
687+
688+
/-- The direction of `⊤` is the whole module as a submodule. -/
689+
@[simp] lemma direction_top : (⊤ : affine_subspace k V P).direction = ⊤ :=
690+
begin
691+
cases S.nonempty with p,
692+
ext v,
693+
refine ⟨imp_intro submodule.mem_top, λ hv, _⟩,
694+
have hpv : (v +ᵥ p -ᵥ p : V) ∈ (⊤ : affine_subspace k V P).direction :=
695+
vsub_mem_direction (mem_top k V _) (mem_top k V _),
696+
rwa vadd_vsub at hpv
697+
end
698+
699+
/-- `⊥`, coerced to a set, is the empty set. -/
700+
@[simp] lemma bot_coe : ((⊥ : affine_subspace k V P) : set P) = ∅ :=
701+
rfl
702+
703+
variables {P}
704+
705+
/-- No points are in `⊥`. -/
706+
lemma not_mem_bot (p : P) : p ∉ (⊥ : affine_subspace k V P) :=
707+
set.not_mem_empty p
708+
709+
variables (P)
710+
711+
/-- The direction of `⊥` is the submodule `⊥`. -/
712+
@[simp] lemma direction_bot : (⊥ : affine_subspace k V P).direction = ⊥ :=
713+
by rw [direction_eq_vector_span, bot_coe, vector_span_def, vsub_set_empty, submodule.span_empty]
714+
715+
/-- The inf of two affine subspaces, coerced to a set, is the
716+
intersection of the two sets of points. -/
717+
@[simp] lemma inf_coe (s1 s2 : affine_subspace k V P) : ((s1 ⊓ s2) : set P) = s1 ∩ s2 :=
718+
rfl
719+
720+
/-- A point is in the inf of two affine subspaces if and only if it is
721+
in both of them. -/
722+
lemma mem_inf_iff (p : P) (s1 s2 : affine_subspace k V P) : p ∈ s1 ⊓ s2 ↔ p ∈ s1 ∧ p ∈ s2 :=
723+
iff.rfl
724+
725+
/-- The direction of the inf of two affine subspaces is less than or
726+
equal to the inf of their directions. -/
727+
lemma direction_inf (s1 s2 : affine_subspace k V P) :
728+
(s1 ⊓ s2).direction ≤ s1.direction ⊓ s2.direction :=
729+
begin
730+
repeat { rw [direction_eq_vector_span, vector_span_def] },
731+
exact le_inf
732+
(Inf_le_Inf (λ p hp, set.subset.trans (vsub_set_mono V (set.inter_subset_left _ _)) hp))
733+
(Inf_le_Inf (λ p hp, set.subset.trans (vsub_set_mono V (set.inter_subset_right _ _)) hp))
734+
end
735+
736+
end affine_subspace
737+
566738
/-- An `affine_map k V1 P1 V2 P2` is a map from `P1` to `P2` that
567739
induces a corresponding linear map from `V1` to `V2`. -/
568740
structure affine_map (k : Type*) (V1 : Type*) (P1 : Type*) (V2 : Type*) (P2 : Type*)

0 commit comments

Comments
 (0)