(* (c) Copyright 2006-2016 Microsoft Corporation and Inria.                  *)
(* Distributed under the terms of CeCILL-B.                                  *)
From mathcomp
From mathcomp
(******************************************************************************)
(* This file contains the definitions of:                                     *)
(*                                                                            *)
(*   {morphism D >-> rT} ==                                                   *)
(*     the structure type of functions that are group morphisms mapping a     *)
(*     domain set D : {set aT} to a type rT; rT must have a finGroupType      *)
(*     structure, and D is usually a group (most of the theory expects this). *)
(*            mfun == the coercion projecting {morphism D >-> rT} to aT -> rT *)
(*                                                                            *)
(* Basic examples:                                                            *)
(*            idm D == the identity morphism with domain D, or more precisely *)
(*                     the identity function, but with a canonical            *)
(*                     {morphism G -> gT} structure.                          *)
(*          trivm D == the trivial morphism with domain D.                    *)
(* If f has a {morphism D >-> rT} structure                                   *)
(*           'dom f == D, the domain of f.                                    *)
(*           f @* A == the image of A by f, where f is defined.               *)
(*                  := f @: (D :&: A)                                         *)
(*        f @*^-1 R == the pre-image of R by f, where f is defined.           *)
(*                  :=  D :&: f @^-1: R                                       *)
(*           'ker f == the kernel of f.                                       *)
(*                  :=  f @*^-1 1                                             *)
(*         'ker_G f == the kernel of f restricted to G.                       *)
(*                  :=  G :&: 'ker f (this is a pure notation)                *)
(*          'injm f <=> f injective on D.                                     *)
(*                  <-> ker f \subset 1 (this is a pure notation)             *)
(*        invm injf == the inverse morphism of f, with domain f @* D, when f  *)
(*                     is injective (injf : 'injm f).                         *)
(*    restrm f sDom == the restriction of f to a subset A of D, given         *)
(*                     (sDom : A \subset D); restrm f sDom is transparently   *)
(*                     identical to f; the restrmP and domP lemmas provide    *)
(*                     opaque restrictions.                                   *)
(*     invm f infj  == the inverse morphism for an injective f, with domain   *)
(*                     f @* D, given (injf : 'injm f).                        *)
(*                                                                            *)
(*      G \isog H  <=> G and H are isomorphic as groups.                      *)
(*       H \homg G <=> H is a homomorphic image of G.                         *)
(*      isom G H f <=> f maps G isomorphically to H, provided D contains G.   *)
(*                  := f @: G^# == H^#                                        *)
(*                                                                            *)
(* If, moreover, g : {morphism G >-> gT} with G : {group aT},                 *)
(*  factm sKer sDom == the (natural) factor morphism mapping f @* G to g @* G *)
(*                     with sDom : G \subset D, sKer : 'ker f \subset 'ker g. *)
(*    ifactm injf g == the (natural) factor morphism mapping f @* G to g @* G *)
(*                     when f is injective (injf : 'injm f); here g must      *)
(*                     denote an actual morphism structure, not its function  *)
(*                     projection.                                            *)
(*                                                                            *)
(* If g has a {morphism G >-> aT} structure for any G : {group gT}, then      *)
(*           f \o g has a canonical {morphism g @*^-1 D >-> rT} structure.    *)
(*                                                                            *)
(* Finally, for an arbitrary function f : aT -> rT                            *)
(*     morphic D f <=> f preserves group multiplication in D, i.e.,           *)
(*                     f (x * y) = (f x) * (f y) for all x, y in D.           *)
(*        morphm fM == a function identical to f, but with a canonical        *)
(*                     {morphism D >-> rT} structure, given fM : morphic D f. *)
(*      misom D C f <=> f is a morphism that maps D isomorphically to C.      *)
(*                  := morphic D f && isom D C f                              *)
(******************************************************************************)
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Reserved Notation "x \isog y" (at level 70).
Section MorphismStructure.
Variables aT rT : finGroupType.
Structure morphism (D : {set aT}) : Type := Morphism {
mfun :> aT -> FinGroup.sort rT;
_ : {in D &, {morph mfun : x y / x * y}}
}.
(* We give the 'lightest' possible specification to define morphisms: local   *)
(* congruence, in D, with the group law of aT. We then provide the properties *)
(* for the 'textbook' notion of morphism, when the required structures are    *)
(* available (e.g. its domain is a group).                                    *)
Definition morphism_for D of phant rT := morphism D.
Definition clone_morphism D f :=
let: Morphism _ fM := f
return {type of @Morphism D for f} -> morphism_for D (Phant rT)
in fun k => k fM.
Variables (D A : {set aT}) (R : {set rT}) (x : aT) (y : rT) (f : aT -> rT).
Variant morphim_spec : Prop := MorphimSpec z & z \in D & z \in A & y = f z.

Lemma morphR : {in D &, {morph f : x y / [~ x, y]}}.