(* (c) Copyright 2006-2016 Microsoft Corporation and Inria.                  *)
(* Distributed under the terms of CeCILL-B.                                  *)
From HB Require Import structures.
From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.
From mathcomp Require Import div fintype bigop prime finset fingroup morphism.
From mathcomp Require Import perm automorphism quotient gproduct ssralg.
From mathcomp Require Import finalg zmodp poly.

(******************************************************************************)
(*  Properties of cyclic groups.                                              *)
(* Definitions:                                                               *)
(* Defined in fingroup.v:                                                     *)
(*           <[x]> == the cycle (cyclic group) generated by x.                *)
(*            #[x] == the order of x, i.e., the cardinal of <[x]>.            *)
(* Defined in prime.v:                                                        *)
(*       totient n == Euler's totient function                                *)
(* Definitions in this file:                                                  *)
(*        cyclic G <=> G is a cyclic group.                                   *)
(*    metacyclic G <=> G is a metacyclic group (i.e., a cyclic extension of a *)
(*                     cyclic group).                                         *)
(*   generator G x <=> x is a generator of the (cyclic) group G.              *)
(*           Zpm x == the isomorphism mapping the additive group of integers  *)
(*                    mod #[x] to the cyclic group <[x]>.                     *)
(*      cyclem x n == the endomorphism y |-> y ^+ n of <[x]>.                 *)
(*      Zp_unitm x == the isomorphism mapping the multiplicative group of the *)
(*                    units of the ring of integers mod #[x] to the group of  *)
(*                    automorphisms of <[x]> (i.e., Aut <[x]>).               *)
(*                    Zp_unitm x maps u to cyclem x u.                        *)
(*    eltm dvd_y_x == the smallest morphism (with domain <[x]>) mapping x to  *)
(*                    y, given a proof dvd_y_x : #[y] %| #[x].                *)
(*   expg_invn G k == if coprime #|G| k, the inverse of exponent k in G.      *)
(* Basic results for these notions, plus the classical result that any finite *)
(* group isomorphic to a subgroup of a field is cyclic, hence that Aut G is   *)
(* cyclic when G is of prime order.                                           *)
(******************************************************************************)

Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.

Local Open Scope group_scope.
Import GRing.Theory.

(***********************************************************************)
(*  Cyclic groups.                                                     *)
(***********************************************************************)

Section Cyclic.

Variable gT : finGroupType.
Implicit Types (a x y : gT) (A B : {set gT}) (G K H : {group gT}).

Definition cyclic A := [exists x, A == <[x]>].

Lemma cyclicP A : reflect (exists x, A = <[x]>) (cyclic A).
Proof.
Admitted.

Lemma cycle_cyclic x : cyclic <[x]>.
Proof.
Admitted.

Lemma cyclic1 : cyclic [1 gT].
Proof.
Admitted.

(***********************************************************************)
(* Isomorphism with the additive group                                 *)
(***********************************************************************)

Section Zpm.

Variable a : gT.

Definition Zpm (i : 'Z_#[a]) := a ^+ i.

Lemma ZpmM : {in Zp #[a] &, {morph Zpm : x y / x * y}}.
Proof.
Admitted.

Canonical Zpm_morphism := Morphism ZpmM.

Lemma im_Zpm : Zpm @* Zp #[a] = <[a]>.
Proof.
Admitted.

Lemma injm_Zpm : 'injm Zpm.
Proof.
Admitted.

Lemma eq_expg_mod_order m n : (a ^+ m == a ^+ n) = (m == n %[mod #[a]]).
Proof.
Admitted.

Lemma eq_expg_ord d (m n : 'I_d) :
  d <= #[a]%g -> (a ^+ m == a ^+ n) = (m == n).
Proof.
Admitted.

Lemma expgD_Zp d (n m : 'Z_d) : (d > 0)%N ->
  #[a]%g %| d -> a ^+ (n + m)%R = a ^+ n * a ^+ m.
Proof.
Admitted.

Lemma Zp_isom : isom (Zp #[a]) <[a]> Zpm.
Proof.
Admitted.

Lemma Zp_isog : isog (Zp #[a]) <[a]>.
Proof.
Admitted.

End Zpm.

(***********************************************************************)
(*        Central and direct product of cycles                         *)
(***********************************************************************)

Lemma cyclic_abelian A : cyclic A -> abelian A.
Proof.
Admitted.

Lemma cycleMsub a b :
  commute a b -> coprime #[a] #[b] -> <[a]> \subset <[a * b]>.
Proof.
Admitted.

Lemma cycleM a b :
  commute a b -> coprime #[a] #[b] -> <[a * b]> = <[a]> * <[b]>.
Proof.
Admitted.

Lemma cyclicM A B :
    cyclic A -> cyclic B -> B \subset 'C(A) -> coprime #|A| #|B| ->
  cyclic (A * B).
Proof.
Admitted.

Lemma cyclicY K H :
    cyclic K -> cyclic H -> H \subset 'C(K) -> coprime #|K| #|H| ->
  cyclic (K <*> H).
Proof.
Admitted.

(***********************************************************************)
(*        Order properties                                             *)
(***********************************************************************)

Lemma order_dvdn a n : (#[a] %| n) = (a ^+ n == 1).
Proof.
Admitted.

Lemma order_inf a n : a ^+ n.
Proof.
Admitted.

Lemma order_dvdG G a : a \in G -> #[a] %| #|G|.
Proof.
Admitted.

Lemma expg_cardG G a : a \in G -> a ^+ #|G| = 1.
Proof.
Admitted.

Lemma expg_znat G x k : x \in G -> x ^+ (k%:R : 'Z_(#|G|))%R = x ^+ k.
Proof.
Admitted.

Lemma expg_zneg G x (k : 'Z_(#|G|)) : x \in G -> x ^+ (- k)%R = x ^- k.
Proof.
Admitted.

Lemma nt_gen_prime G x : prime #|G| -> x \in G^# -> G :=: <[x]>.
Proof.
Admitted.

Lemma nt_prime_order p x : prime p -> x ^+ p = 1 -> x != 1 -> #[x] = p.
Proof.
Admitted.

Lemma orderXdvd a n : #[a ^+ n] %| #[a].
Proof.
Admitted.

Lemma orderXgcd a n : #[a ^+ n] = #[a] %/ gcdn #[a] n.
Proof.
Admitted.

Lemma orderXdiv a n : n %| #[a] -> #[a ^+ n] = #[a] %/ n.
Proof.
Admitted.

Lemma orderXexp p m n x : #[x] = (p ^ n)%N -> #[x ^+ (p ^ m)] = (p ^ (n - m))%N.
Proof.
Admitted.

Lemma orderXpfactor p k n x :
  #[x ^+ (p ^ k)] = n -> prime p -> p %| n -> #[x] = (p ^ k * n)%N.
Proof.
Admitted.

Lemma orderXprime p n x :
  #[x ^+ p] = n -> prime p -> p %| n -> #[x] = (p * n)%N.
Proof.
Admitted.

Lemma orderXpnat m n x : #[x ^+ m] = n -> \pi(n).
Proof.
Admitted.

Lemma orderM a b :
  commute a b -> coprime #[a] #[b] -> #[a * b] = (#[a] * #[b])%N.
Proof.
Admitted.

Definition expg_invn A k := (egcdn k #|A|).1.

Lemma expgK G k :
  coprime #|G| k -> {in G, cancel (natexp^~ k) (natexp^~ (expg_invn G k))}.
Proof.
Admitted.

Lemma cyclic_dprod K H G :
  K \x H = G -> cyclic K -> cyclic H -> cyclic G = coprime #|K| #|H| .
Proof.
Admitted.

(***********************************************************************)
(*        Generator                                                    *)
(***********************************************************************)

Definition generator (A : {set gT}) a := A == <[a]>.

Lemma generator_cycle a : generator <[a]> a.
Proof.
Admitted.

Lemma cycle_generator a x : generator <[a]> x -> x \in <[a]>.
Proof.
Admitted.

Lemma generator_order a b : generator <[a]> b -> #[a] = #[b].
Proof.
Admitted.

End Cyclic.

Arguments cyclic {gT} A%_g.
Arguments generator {gT} A%_g a%_g.
Arguments expg_invn {gT} A%_g k%_N.
Arguments cyclicP {gT A}.
Prenex Implicits cyclic Zpm.

(* Euler's theorem *)
Theorem Euler_exp_totient a n : coprime a n -> a ^ totient n  = 1 %[mod n].
Proof.
Admitted.

Section Eltm.

Variables (aT rT : finGroupType) (x : aT) (y : rT).

Definition eltm & #[y] %| #[x] := fun x_i => y ^+ invm (injm_Zpm x) x_i.

Hypothesis dvd_y_x : #[y] %| #[x].

Lemma eltmE i : eltm dvd_y_x (x ^+ i) = y ^+ i.
Proof.
Admitted.

Lemma eltm_id : eltm dvd_y_x x = y.
Proof.
Admitted.

Lemma eltmM : {in <[x]> &, {morph eltm dvd_y_x : x_i x_j / x_i * x_j}}.
Proof.
Admitted.
Canonical eltm_morphism := Morphism eltmM.

Lemma im_eltm : eltm dvd_y_x @* <[x]> = <[y]>.
Proof.
Admitted.

Lemma ker_eltm : 'ker (eltm dvd_y_x) = <[x ^+ #[y]]>.
Proof.
Admitted.

Lemma injm_eltm : 'injm (eltm dvd_y_x) = (#[x] %| #[y]).
Proof.
Admitted.

End Eltm.

Section CycleSubGroup.

Variable gT : finGroupType.

(*  Gorenstein, 1.3.1 (i) *)
Lemma cycle_sub_group (a : gT) m :
     m %| #[a] ->
  [set H : {group gT} | H \subset <[a]> & #|H| == m]
     = [set <[a ^+ (#[a] %/ m)]>%G].
Proof.
Admitted.

Lemma cycle_subgroup_char a (H : {group gT}) : H \subset <[a]> -> H \char <[a]>.
Proof.
Admitted.

End CycleSubGroup.

(***********************************************************************)
(*  Reflected boolean property and morphic image, injection, bijection *)
(***********************************************************************)

Section MorphicImage.

Variables aT rT : finGroupType.
Variables (D : {group aT}) (f : {morphism D >-> rT}) (x : aT).
Hypothesis Dx : x \in D.

Lemma morph_order : #[f x] %| #[x].
Proof.
Admitted.

Lemma morph_generator A : generator A x -> generator (f @* A) (f x).
Proof.
Admitted.

End MorphicImage.

Section CyclicProps.

Variables gT : finGroupType.
Implicit Types (aT rT : finGroupType) (G H K : {group gT}).

Lemma cyclicS G H : H \subset G -> cyclic G -> cyclic H.
Proof.
Admitted.

Lemma cyclicJ G x : cyclic (G :^ x) = cyclic G.
Proof.
Admitted.

Lemma eq_subG_cyclic G H K :
  cyclic G -> H \subset G -> K \subset G -> (H :==: K) = (#|H| == #|K|).
Proof.
Admitted.

Lemma cardSg_cyclic G H K :
  cyclic G -> H \subset G -> K \subset G -> (#|H| %| #|K|) = (H \subset K).
Proof.
Admitted.

Lemma sub_cyclic_char G H : cyclic G -> (H \char G) = (H \subset G).
Proof.
Admitted.

Lemma morphim_cyclic rT G H (f : {morphism G >-> rT}) :
  cyclic H -> cyclic (f @* H).
Proof.
Admitted.

Lemma quotient_cycle x H : x \in 'N(H) -> <[x]> / H = <[coset H x]>.
Proof.
Admitted.

Lemma quotient_cyclic G H : cyclic G -> cyclic (G / H).
Proof.
Admitted.

Lemma quotient_generator x G H :
  x \in 'N(H) -> generator G x -> generator (G / H) (coset H x).
Proof.
Admitted.

Lemma prime_cyclic G : prime #|G| -> cyclic G.
Proof.
Admitted.

Lemma dvdn_prime_cyclic G p : prime p -> #|G| %| p -> cyclic G.
Proof.
Admitted.

Lemma cyclic_small G : #|G| <= 3 -> cyclic G.
Proof.
Admitted.

End CyclicProps.

Section IsoCyclic.

Variables gT rT : finGroupType.
Implicit Types (G H : {group gT}) (M : {group rT}).

Lemma injm_cyclic G H (f : {morphism G >-> rT}) :
  'injm f -> H \subset G -> cyclic (f @* H) = cyclic H.
Proof.
Admitted.

Lemma isog_cyclic G M : G \isog M -> cyclic G = cyclic M.
Proof.
Admitted.

Lemma isog_cyclic_card G M : cyclic G -> isog G M = cyclic M && (#|M| == #|G|).
Proof.
Admitted.

Lemma injm_generator G H (f : {morphism G >-> rT}) x :
    'injm f -> x \in G -> H \subset G ->
  generator (f @* H) (f x) = generator H x.
Proof.
Admitted.

End IsoCyclic.

(* Metacyclic groups. *)
Section Metacyclic.

Variable gT : finGroupType.
Implicit Types (A : {set gT}) (G H : {group gT}).

Definition metacyclic A :=
  [exists H : {group gT}, [&& cyclic H, H <| A & cyclic (A / H)]].

Lemma metacyclicP A : 
  reflect (exists H : {group gT}, [/\ cyclic H, H <| A & cyclic (A / H)]) 
          (metacyclic A).
Proof.
Admitted.

Lemma metacyclic1 : metacyclic 1.
Proof.
Admitted.

Lemma cyclic_metacyclic A : cyclic A -> metacyclic A.
Proof.
Admitted.

Lemma metacyclicS G H : H \subset G -> metacyclic G -> metacyclic H.
Proof.
Admitted.

End Metacyclic.

Arguments metacyclic {gT} A%_g.
Arguments metacyclicP {gT A}.

(* Automorphisms of cyclic groups. *)
Section CyclicAutomorphism.

Variable gT : finGroupType.

Section CycleAutomorphism.

Variable a : gT.

Section CycleMorphism.

Variable n : nat.

Definition cyclem & gT := fun x : gT => x ^+ n.

Lemma cyclemM : {in <[a]> & , {morph cyclem a : x y / x * y}}.
Proof.
Admitted.

Canonical cyclem_morphism := Morphism cyclemM.

End CycleMorphism.

Section ZpUnitMorphism.

Variable u : {unit 'Z_#[a]}.

Lemma injm_cyclem : 'injm (cyclem (val u) a).
Proof.
Admitted.

Lemma im_cyclem : cyclem (val u) a @* <[a]> = <[a]>.
Proof.
Admitted.

Definition Zp_unitm := aut injm_cyclem im_cyclem.

End ZpUnitMorphism.

Lemma Zp_unitmM : {in units_Zp #[a] &, {morph Zp_unitm : u v / u * v}}.
Proof.
Admitted.

Canonical Zp_unit_morphism := Morphism Zp_unitmM.

Lemma injm_Zp_unitm : 'injm Zp_unitm.
Proof.
Admitted.

Lemma generator_coprime m : generator <[a]> (a ^+ m) = coprime #[a] m.
Proof.
Admitted.

Lemma im_Zp_unitm : Zp_unitm @* units_Zp #[a] = Aut <[a]>.
Proof.
Admitted.

Lemma Zp_unit_isom : isom (units_Zp #[a]) (Aut <[a]>) Zp_unitm.
Proof.
Admitted.

Lemma Zp_unit_isog : isog (units_Zp #[a]) (Aut <[a]>).
Proof.
Admitted.

Lemma card_Aut_cycle : #|Aut <[a]>| = totient #[a].
Proof.
Admitted.

Lemma totient_gen : totient #[a] = #|[set x | generator <[a]> x]|.
Proof.
Admitted.

Lemma Aut_cycle_abelian : abelian (Aut <[a]>).
Proof.
Admitted.

End CycleAutomorphism.

Variable G : {group gT}.

Lemma Aut_cyclic_abelian : cyclic G -> abelian (Aut G).
Proof.
Admitted.

Lemma card_Aut_cyclic : cyclic G -> #|Aut G| = totient #|G|.
Proof.
Admitted.

Lemma sum_ncycle_totient :
  \sum_(d < #|G|.
Proof.
Admitted.

End CyclicAutomorphism.

Lemma sum_totient_dvd n : \sum_(d < n.
Proof.
Admitted.

Section FieldMulCyclic.

(***********************************************************************)
(* A classic application to finite multiplicative subgroups of fields. *)
(***********************************************************************)

Import GRing.Theory.

Variables (gT : finGroupType) (G : {group gT}).

Lemma order_inj_cyclic :
  {in G &, forall x y, #[x] = #[y] -> <[x]> = <[y]>} -> cyclic G.
Proof.
Admitted.

Lemma div_ring_mul_group_cyclic (R : unitRingType) (f : gT -> R) :
    f 1 = 1%R -> {in G &, {morph f : u v / u * v >-> (u * v)%R}} ->
    {in G^#, forall x, f x - 1 \in GRing.
Proof.
Admitted.

Lemma field_mul_group_cyclic (F : fieldType) (f : gT -> F) :
    {in G &, {morph f : u v / u * v >-> (u * v)%R}} ->
    {in G, forall x, f x = 1%R <-> x = 1} ->
  cyclic G.
Proof.
Admitted.

End FieldMulCyclic.

Lemma field_unit_group_cyclic (F : finFieldType) (G : {group {unit F}}) :
  cyclic G.
Proof.
Admitted.

Lemma units_Zp_cyclic p : prime p -> cyclic (units_Zp p).
Proof.
Admitted.

Section PrimitiveRoots.

Open Scope ring_scope.
Import GRing.Theory.

(* This subproof has  been extracted out of [has_prim_root] for performance reasons.
   See github PR #1059 for further documentation and investigation on this problem. *)
Lemma has_prim_root_subproof (F : fieldType) (n : nat) (rs : seq F)
    (n_gt0 : n > 0)
    (rsn1 : all n.
Proof.
Admitted.

Lemma has_prim_root (F : fieldType) (n : nat) (rs : seq F) :
    n > 0 -> all n.
Proof.
Admitted.

End PrimitiveRoots.

(***********************************************************************)
(*  Cycles of prime order                                              *)
(***********************************************************************)

Section AutPrime.

Variable gT : finGroupType.

Lemma Aut_prime_cycle_cyclic (a : gT) : prime #[a] -> cyclic (Aut <[a]>).
Proof.
Admitted.

Lemma Aut_prime_cyclic (G : {group gT}) : prime #|G| -> cyclic (Aut G).
Proof.
Admitted.

End AutPrime.