@@ -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 :=
357364ext (λ 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+
359375section galois_coinsertion
360376
361377variables {ι : Type *} {f : M →[L] N} (hf : function.injective f)
@@ -480,6 +496,67 @@ namespace hom
480496
481497open 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` -/
484561def 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
505582end 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+
507680end language
508681end first_order
0 commit comments