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

Commit 4545e31

Browse files
committed
feat(model_theory/substructures): More operations on substructures (#11906)
Defines the substructure `first_order.language.hom.range`. Defines the homomorphisms `first_order.language.hom.dom_restrict` and `first_order.language.hom.cod_restrict`, and the embeddings `first_order.language.embedding.dom_restrict`, `first_order.language.embedding.cod_restrict` which restrict the domain or codomain of a first-order hom or embedding to a substructure. Defines the embedding `first_order.language.substructure.inclusion` between nested substructures.
1 parent 1ae8304 commit 4545e31

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

src/model_theory/basic.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ instance : inhabited (M ↪[L] M) := ⟨refl L M⟩
257257
lemma comp_assoc (f : M ↪[L] N) (g : N ↪[L] P) (h : P ↪[L] Q) :
258258
(h.comp g).comp f = h.comp (g.comp f) := rfl
259259

260+
@[simp] lemma comp_to_hom (hnp : N ↪[L] P) (hmn : M ↪[L] N) :
261+
(hnp.comp hmn).to_hom = hnp.to_hom.comp hmn.to_hom :=
262+
by { ext, simp only [coe_to_hom, comp_apply, hom.comp_apply] }
263+
260264
end embedding
261265

262266
namespace equiv

src/model_theory/substructures.lean

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ the least substructure of `M` containing `s`.
2121
substructure `s` under the homomorphism `f`, as a substructure.
2222
* `first_order.language.substructure.map` is defined so that `s.map f` is the image of the
2323
substructure `s` under the homomorphism `f`, as a substructure.
24+
* `first_order.language.hom.range` is defined so that `f.map` is the range of the
25+
the homomorphism `f`, as a substructure.
26+
* `first_order.language.hom.dom_restrict` and `first_order.language.hom.cod_restrict` restrict
27+
the domain and codomain respectively of first-order homomorphisms to substructures.
28+
* `first_order.language.embedding.dom_restrict` and `first_order.language.embedding.cod_restrict`
29+
restrict the domain and codomain respectively of first-order embeddings to substructures.
30+
* `first_order.language.substructure.inclusion` is the inclusion embedding between substructures.
2431
2532
## Main Results
2633
* `L.substructure M` forms a `complete_lattice`.
@@ -356,6 +363,15 @@ lemma comap_infi {ι : Sort*} (f : M →[L] N) (s : ι → L.substructure N) :
356363
@[simp] lemma map_id (S : L.substructure M) : S.map (hom.id L M) = S :=
357364
ext (λ x, ⟨λ ⟨_, h, rfl⟩, h, λ h, ⟨_, h, rfl⟩⟩)
358365

366+
lemma map_closure (f : M →[L] N) (s : set M) :
367+
(closure L s).map f = closure L (f '' s) :=
368+
eq.symm $ closure_eq_of_le (set.image_subset f subset_closure) $ map_le_iff_le_comap.2 $
369+
closure_le.2 $ λ x hx, subset_closure ⟨x, hx, rfl⟩
370+
371+
@[simp] lemma closure_image (f : M →[L] N) :
372+
closure L (f '' s) = map f (closure L s) :=
373+
(map_closure f s).symm
374+
359375
section galois_coinsertion
360376

361377
variables {ι : Type*} {f : M →[L] N} (hf : function.injective f)
@@ -480,6 +496,67 @@ namespace hom
480496

481497
open substructure
482498

499+
/-- The restriction of a first-order hom to a substructure `s ⊆ M` gives a hom `s → N`. -/
500+
@[simps] def dom_restrict (f : M →[L] N) (p : L.substructure M) : p →[L] N :=
501+
f.comp p.subtype.to_hom
502+
503+
/-- A first-order hom `f : M → N` whose values lie in a substructure `p ⊆ N` can be restricted to a
504+
hom `M → p`. -/
505+
@[simps] def cod_restrict (p : L.substructure N) (f : M →[L] N) (h : ∀c, f c ∈ p) : M →[L] p :=
506+
{ to_fun := λc, ⟨f c, h c⟩,
507+
map_rel' := λ n R x h, f.map_rel R x h }
508+
509+
@[simp] lemma comp_cod_restrict (f : M →[L] N) (g : N →[L] P) (p : L.substructure P)
510+
(h : ∀b, g b ∈ p) :
511+
((cod_restrict p g h).comp f : M →[L] p) = cod_restrict p (g.comp f) (assume b, h _) :=
512+
ext $ assume b, rfl
513+
514+
@[simp] lemma subtype_comp_cod_restrict (f : M →[L] N) (p : L.substructure N) (h : ∀b, f b ∈ p) :
515+
p.subtype.to_hom.comp (cod_restrict p f h) = f :=
516+
ext $ assume b, rfl
517+
518+
/-- The range of a first-order hom `f : M → N` is a submodule of `N`.
519+
See Note [range copy pattern]. -/
520+
def range (f : M →[L] N) : L.substructure N :=
521+
(map f ⊤).copy (set.range f) set.image_univ.symm
522+
523+
theorem range_coe (f : M →[L] N) :
524+
(range f : set N) = set.range f := rfl
525+
526+
@[simp] theorem mem_range
527+
{f : M →[L] N} {x} : x ∈ range f ↔ ∃ y, f y = x :=
528+
iff.rfl
529+
530+
lemma range_eq_map
531+
(f : M →[L] N) : f.range = map f ⊤ :=
532+
by { ext, simp }
533+
534+
theorem mem_range_self
535+
(f : M →[L] N) (x : M) : f x ∈ f.range := ⟨x, rfl⟩
536+
537+
@[simp] theorem range_id : range (id L M) = ⊤ :=
538+
set_like.coe_injective set.range_id
539+
540+
theorem range_comp (f : M →[L] N) (g : N →[L] P) :
541+
range (g.comp f : M →[L] P) = map g (range f) :=
542+
set_like.coe_injective (set.range_comp g f)
543+
544+
theorem range_comp_le_range (f : M →[L] N) (g : N →[L] P) :
545+
range (g.comp f : M →[L] P) ≤ range g :=
546+
set_like.coe_mono (set.range_comp_subset_range f g)
547+
548+
theorem range_eq_top {f : M →[L] N} :
549+
range f = ⊤ ↔ function.surjective f :=
550+
by rw [set_like.ext'_iff, range_coe, coe_top, set.range_iff_surjective]
551+
552+
lemma range_le_iff_comap {f : M →[L] N} {p : L.substructure N} :
553+
range f ≤ p ↔ comap f p = ⊤ :=
554+
by rw [range_eq_map, map_le_iff_le_comap, eq_top_iff]
555+
556+
lemma map_le_range {f : M →[L] N} {p : L.substructure M} :
557+
map f p ≤ range f :=
558+
set_like.coe_mono (set.image_subset_range f p)
559+
483560
/-- The substructure of elements `x : M` such that `f x = g x` -/
484561
def eq_locus (f g : M →[L] N) : substructure L M :=
485562
{ carrier := {x : M | f x = g x},
@@ -504,5 +581,101 @@ eq_of_eq_on_top $ hs ▸ eq_on_closure h
504581

505582
end hom
506583

584+
namespace embedding
585+
open substructure
586+
587+
/-- The restriction of a first-order embedding to a substructure `s ⊆ M` gives an embedding `s → N`.
588+
-/
589+
def dom_restrict (f : M ↪[L] N) (p : L.substructure M) : p ↪[L] N :=
590+
f.comp p.subtype
591+
592+
@[simp] lemma dom_restrict_apply (f : M ↪[L] N) (p : L.substructure M) (x : p) :
593+
f.dom_restrict p x = f x := rfl
594+
595+
/-- A first-order embedding `f : M → N` whose values lie in a substructure `p ⊆ N` can be restricted
596+
to an embedding `M → p`. -/
597+
def cod_restrict (p : L.substructure N) (f : M ↪[L] N) (h : ∀c, f c ∈ p) : M ↪[L] p :=
598+
{ to_fun := f.to_hom.cod_restrict p h,
599+
inj' := λ a b ab, f.injective (subtype.mk_eq_mk.1 ab),
600+
map_fun' := λ n F x, (f.to_hom.cod_restrict p h).map_fun' F x,
601+
map_rel' := λ n r x, begin
602+
simp only,
603+
rw [← p.subtype.map_rel, function.comp.assoc],
604+
change rel_map r ((hom.comp p.subtype.to_hom (f.to_hom.cod_restrict p h)) ∘ x) ↔ _,
605+
rw [hom.subtype_comp_cod_restrict, ← f.map_rel],
606+
refl,
607+
end }
608+
609+
@[simp] theorem cod_restrict_apply (p : L.substructure N) (f : M ↪[L] N) {h} (x : M) :
610+
(cod_restrict p f h x : N) = f x := rfl
611+
612+
@[simp] lemma comp_cod_restrict (f : M ↪[L] N) (g : N ↪[L] P) (p : L.substructure P)
613+
(h : ∀b, g b ∈ p) :
614+
((cod_restrict p g h).comp f : M ↪[L] p) = cod_restrict p (g.comp f) (assume b, h _) :=
615+
ext $ assume b, rfl
616+
617+
@[simp] lemma subtype_comp_cod_restrict (f : M ↪[L] N) (p : L.substructure N) (h : ∀b, f b ∈ p) :
618+
p.subtype.comp (cod_restrict p f h) = f :=
619+
ext $ assume b, rfl
620+
621+
/-- The equivalence between a substructure `s` and its image `s.map f.to_hom`, where `f` is an
622+
embedding. -/
623+
noncomputable def substructure_equiv_map (f : M ↪[L] N) (s : L.substructure M) :
624+
s ≃[L] s.map f.to_hom :=
625+
{ to_fun := cod_restrict (s.map f.to_hom) (f.dom_restrict s) (λ ⟨m, hm⟩, ⟨m, hm, rfl⟩),
626+
inv_fun := λ n, ⟨classical.some n.2, (classical.some_spec n.2).1⟩,
627+
left_inv := λ ⟨m, hm⟩, subtype.mk_eq_mk.2 (f.injective ((classical.some_spec (cod_restrict
628+
(s.map f.to_hom) (f.dom_restrict s) (λ ⟨m, hm⟩, ⟨m, hm, rfl⟩) ⟨m, hm⟩).2).2)),
629+
right_inv := λ ⟨n, hn⟩, subtype.mk_eq_mk.2 (classical.some_spec hn).2 }
630+
631+
@[simp] lemma substructure_equiv_map_apply (f : M ↪[L] N) (p : L.substructure M) (x : p) :
632+
(f.substructure_equiv_map p x : N) = f x := rfl
633+
634+
/-- The equivalence between the domain and the range of an embedding `f`. -/
635+
noncomputable def equiv_range (f : M ↪[L] N) :
636+
M ≃[L] f.to_hom.range :=
637+
{ to_fun := cod_restrict f.to_hom.range f f.to_hom.mem_range_self,
638+
inv_fun := λ n, classical.some n.2,
639+
left_inv := λ m, f.injective (classical.some_spec (cod_restrict f.to_hom.range f
640+
f.to_hom.mem_range_self m).2),
641+
right_inv := λ ⟨n, hn⟩, subtype.mk_eq_mk.2 (classical.some_spec hn) }
642+
643+
@[simp] lemma equiv_range_apply (f : M ↪[L] N) (x : M) :
644+
(f.equiv_range x : N) = f x := rfl
645+
646+
end embedding
647+
648+
namespace equiv
649+
650+
lemma to_hom_range (f : M ≃[L] N) :
651+
f.to_hom.range = ⊤ :=
652+
begin
653+
ext n,
654+
simp only [hom.mem_range, coe_to_hom, substructure.mem_top, iff_true],
655+
exact ⟨f.symm n, apply_symm_apply _ _⟩
656+
end
657+
658+
end equiv
659+
660+
namespace substructure
661+
662+
/-- The embedding associated to an inclusion of substructures. -/
663+
def inclusion {S T : L.substructure M} (h : S ≤ T) : S ↪[L] T :=
664+
S.subtype.cod_restrict _ (λ x, h x.2)
665+
666+
@[simp] lemma coe_inclusion {S T : L.substructure M} (h : S ≤ T) :
667+
(inclusion h : S → T) = set.inclusion h := rfl
668+
669+
lemma range_subtype (S : L.substructure M) : S.subtype.to_hom.range = S :=
670+
begin
671+
ext x,
672+
simp only [hom.mem_range, embedding.coe_to_hom, coe_subtype],
673+
refine ⟨_, λ h, ⟨⟨x, h⟩, rfl⟩⟩,
674+
rintros ⟨⟨y, hy⟩, rfl⟩,
675+
exact hy,
676+
end
677+
678+
end substructure
679+
507680
end language
508681
end first_order

0 commit comments

Comments
 (0)