/- Copyright (c) 2015 Haitao Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author : Haitao Zhang -/ import algebra.group data.set .subgroup namespace group_theory -- ⁻¹ in eq.ops conflicts with group ⁻¹ -- open eq.ops notation H1 ▸ H2 := eq.subst H1 H2 open set open function open group_theory.ops open quot local attribute set [reducible] section defs variables {A B : Type} variable [s1 : group A] variable [s2 : group B] include s1 include s2 -- the Prop of being hom definition homomorphic [reducible] (f : A → B) : Prop := ∀ a b, f (a*b) = (f a)*(f b) -- type class for inference structure is_hom_class [class] (f : A → B) : Type := (is_hom : homomorphic f) -- the proof of hom_prop if the class can be inferred definition is_hom (f : A → B) [h : is_hom_class f] : homomorphic f := @is_hom_class.is_hom A B s1 s2 f h definition ker (f : A → B) [h : is_hom_class f] : set A := {a : A | f a = 1} definition isomorphic (f : A → B) := injective f ∧ homomorphic f structure is_iso_class [class] (f : A → B) extends is_hom_class f : Type := (inj : injective f) lemma iso_is_inj (f : A → B) [h : is_iso_class f] : injective f:= @is_iso_class.inj A B s1 s2 f h lemma iso_is_iso (f : A → B) [h : is_iso_class f] : isomorphic f:= and.intro (iso_is_inj f) (is_hom f) end defs section variables {A B : Type} variable [s1 : group A] definition id_is_iso [instance] : @is_hom_class A A s1 s1 (@id A) := is_hom_class.mk (take a b, rfl) variable [s2 : group B] include s1 include s2 variable f : A → B variable [h : is_hom_class f] include h theorem hom_map_one : f 1 = 1 := have P : f 1 = (f 1) * (f 1), from calc f 1 = f (1*1) : mul_one ... = (f 1) * (f 1) : is_hom f, eq.symm (mul.right_inv (f 1) ▸ (mul_inv_eq_of_eq_mul P)) theorem hom_map_inv (a : A) : f a⁻¹ = (f a)⁻¹ := have P : f 1 = 1, from hom_map_one f, have P1 : f (a⁻¹ * a) = 1, from (eq.symm (mul.left_inv a)) ▸ P, have P2 : (f a⁻¹) * (f a) = 1, from (is_hom f a⁻¹ a) ▸ P1, have P3 : (f a⁻¹) * (f a) = (f a)⁻¹ * (f a), from eq.symm (mul.left_inv (f a)) ▸ P2, mul_right_cancel P3 theorem hom_map_mul_closed (H : set A) : mul_closed_on H → mul_closed_on (f ' H) := assume Pclosed, assume b1, assume b2, assume Pb1 : b1 ∈ f ' H, assume Pb2 : b2 ∈ f ' H, obtain a1 (Pa1 : a1 ∈ H ∧ f a1 = b1), from Pb1, obtain a2 (Pa2 : a2 ∈ H ∧ f a2 = b2), from Pb2, have Pa1a2 : a1 * a2 ∈ H, from Pclosed a1 a2 (and.left Pa1) (and.left Pa2), have Pb1b2 : f (a1 * a2) = b1 * b2, from calc f (a1 * a2) = f a1 * f a2 : is_hom f a1 a2 ... = b1 * f a2 : {and.right Pa1} ... = b1 * b2 : {and.right Pa2}, mem_image Pa1a2 Pb1b2 lemma ker.has_one : 1 ∈ ker f := hom_map_one f lemma ker.has_inv : subgroup.has_inv (ker f) := take a, assume Pa : f a = 1, calc f a⁻¹ = (f a)⁻¹ : by rewrite (hom_map_inv f) ... = 1⁻¹ : by rewrite Pa ... = 1 : by rewrite one_inv lemma ker.mul_closed : mul_closed_on (ker f) := take x y, assume (Px : f x = 1) (Py : f y = 1), calc f (x*y) = (f x) * (f y) : by rewrite [is_hom f] ... = 1 : by rewrite [Px, Py, mul_one] lemma ker.normal : same_left_right_coset (ker f) := take a, funext (assume x, begin esimp [ker, set_of, glcoset, grcoset], rewrite [*(is_hom f), mul_eq_one_iff_mul_eq_one (f a⁻¹) (f x)] end) definition ker_is_normal_subgroup : is_normal_subgroup (ker f) := is_normal_subgroup.mk (ker.has_one f) (ker.mul_closed f) (ker.has_inv f) (ker.normal f) -- additional subgroup variable variable {H : set A} variable [is_subgH : is_subgroup H] include is_subgH theorem hom_map_subgroup : is_subgroup (f ' H) := have Pone : 1 ∈ f ' H, from mem_image (@subg_has_one _ _ H _) (hom_map_one f), have Pclosed : mul_closed_on (f ' H), from hom_map_mul_closed f H subg_mul_closed, have Pinv : ∀ b, b ∈ f ' H → b⁻¹ ∈ f ' H, from assume b, assume Pimg, obtain a (Pa : a ∈ H ∧ f a = b), from Pimg, have Painv : a⁻¹ ∈ H, from subg_has_inv a (and.left Pa), have Pfainv : (f a)⁻¹ ∈ f ' H, from mem_image Painv (hom_map_inv f a), and.right Pa ▸ Pfainv, is_subgroup.mk Pone Pclosed Pinv end section hom_theorem variables {A B : Type} variable [s1 : group A] variable [s2 : group B] include s1 include s2 variable {f : A → B} variable [h : is_hom_class f] include h definition ker_nsubg [instance] : is_normal_subgroup (ker f) := is_normal_subgroup.mk (ker.has_one f) (ker.mul_closed f) (ker.has_inv f) (ker.normal f) definition quot_over_ker [instance] : group (coset_of (ker f)) := mk_quotient_group (ker f) -- under the wrap the tower of concepts collapse to a simple condition example (a x : A) : (x ∈ a ∘> ker f) = (f (a⁻¹*x) = 1) := rfl lemma ker_coset_same_val (a b : A): same_lcoset (ker f) a b → f a = f b := assume Psame, have Pin : f (b⁻¹*a) = 1, from subg_same_lcoset_in_lcoset a b Psame, have P : (f b)⁻¹ * (f a) = 1, from calc (f b)⁻¹ * (f a) = (f b⁻¹) * (f a) : (hom_map_inv f) ... = f (b⁻¹*a) : by rewrite [is_hom f] ... = 1 : by rewrite Pin, eq.symm (inv_inv (f b) ▸ inv_eq_of_mul_eq_one P) definition ker_natural_map : (coset_of (ker f)) → B := quot.lift f ker_coset_same_val example (a : A) : ker_natural_map ⟦a⟧ = f a := rfl lemma ker_coset_hom (a b : A) : ker_natural_map (⟦a⟧*⟦b⟧) = (ker_natural_map ⟦a⟧) * (ker_natural_map ⟦b⟧) := calc ker_natural_map (⟦a⟧*⟦b⟧) = ker_natural_map ⟦a*b⟧ : rfl ... = f (a*b) : rfl ... = (f a) * (f b) : by rewrite [is_hom f] ... = (ker_natural_map ⟦a⟧) * (ker_natural_map ⟦b⟧) : rfl lemma ker_map_is_hom : homomorphic (ker_natural_map : coset_of (ker f) → B) := take aK bK, quot.ind (λ a, quot.ind (λ b, ker_coset_hom a b) bK) aK lemma ker_coset_inj (a b : A) : (ker_natural_map ⟦a⟧ = ker_natural_map ⟦b⟧) → ⟦a⟧ = ⟦b⟧ := assume Pfeq : f a = f b, have Painb : a ∈ b ∘> ker f, from calc f (b⁻¹*a) = (f b⁻¹) * (f a) : by rewrite [is_hom f] ... = (f b)⁻¹ * (f a) : by rewrite (hom_map_inv f) ... = (f a)⁻¹ * (f a) : by rewrite Pfeq ... = 1 : by rewrite (mul.left_inv (f a)), quot.sound (@subg_in_lcoset_same_lcoset _ _ (ker f) _ a b Painb) lemma ker_map_is_inj : injective (ker_natural_map : coset_of (ker f) → B) := take aK bK, quot.ind (λ a, quot.ind (λ b, ker_coset_inj a b) bK) aK -- a special case of the fundamental homomorphism theorem or the first isomorphism theorem theorem first_isomorphism_theorem : isomorphic (ker_natural_map : coset_of (ker f) → B) := and.intro ker_map_is_inj ker_map_is_hom end hom_theorem end group_theory