1##############################################################################
2##
3#W  apps.gi                    GAP4 package `XMod'               Chris Wensley
4##
5#Y  Copyright (C) 2001-2019, Chris Wensley et al,
6#Y  School of Computer Science, Bangor University, U.K.
7
8##############################################################################
9##
10InstallMethod( LoopsXMod, "for a crossed module and an element", true,
11    [ IsPreXMod, IsObject ], 0,
12function( X0, a )
13
14    local M0, genM0, lenM0, P0, bdy0, act0, aut0, acta, elPa, p, c, m,
15          nPa, C0, G0, e1, e2, Pa, genPa, posPa, i, e, e2m, e1p, g, ngPa,
16          imda, j, pa, ma, bdy1, imact1, act1;
17
18    if not IsXMod( X0 ) then
19        Error( "X0 should be a crossed module" );
20    fi;
21    M0 := Source( X0 );
22    genM0 := GeneratorsOfGroup( M0 );
23    lenM0 := Length( genM0 );
24    P0 := Range( X0 );
25    if not ( a in P0 ) then
26        Error( "element a not in the range group P0" );
27    fi;
28    Info( InfoXMod, 3, "M0: ", Elements(M0) );
29    Info( InfoXMod, 3, List( Elements(M0), g -> Order(g) ) );
30    Info( InfoXMod, 3, "P0: ", Elements(P0) );
31    Info( InfoXMod, 3, List( Elements(P0), g -> Order(g) ) );
32    bdy0 := Boundary( X0 );
33    act0 := XModAction( X0 );
34    aut0 := Range( act0 );
35    acta := ImageElm( act0, a );
36    elPa := [ ];
37    for p in P0 do
38        c := Comm( p, a );
39        for m in M0 do
40            if ( ImageElm( bdy0, m ) = c ) then
41                Add( elPa, [p,m] );
42            fi;
43        od;
44    od;
45    nPa := Length( elPa );
46    Info( InfoXMod, 2, "elPa has length ", nPa );
47    Info( InfoXMod, 3, "with elements ", elPa );
48    C0 := PreCat1GroupOfPreXMod( X0 ).precat1;
49    G0 := Source( C0 );
50    e1 := Embedding( G0, 1 );
51    e2 := Embedding( G0, 2 );
52    Pa := Subgroup( G0, [ ] );
53    genPa := [ ];
54    posPa := [ ];
55    for i in [1..nPa] do
56        e := elPa[i];
57        p := e[1];
58        m := e[2];
59        e2m := ImageElm( e2, m );
60        e1p := ImageElm( e1, p );
61        g := e1p * e2m;
62        if not ( g in Pa ) then
63            Add( genPa, g );
64            Add( posPa, i );
65            Pa := Subgroup( G0, genPa );
66        fi;
67    od;
68    Info( InfoXMod, 2, "Pa has size ", Size( Pa ) );
69    ngPa := Length( genPa );
70    ## construct the boundary for X1
71    imda := ListWithIdenticalEntries( lenM0, 0 );
72    for j in [1..lenM0] do
73        m := genM0[j];
74        pa := ImageElm( bdy0, m );
75        ma := m^-1 * ImageElm( acta, m );
76        e2m := ImageElm( e2, ma );
77        e1p := ImageElm( e1, pa );
78        g := e1p * e2m;
79        if not ( g in Pa ) then
80            Error( "element g not in Pa" );
81        fi;
82        imda[j] := g;
83    od;
84    bdy1 := GroupHomomorphismByImages( M0, Pa, genM0, imda );
85    if ( bdy1 = fail ) then
86        Error( "bdy1 fails to be a homomorphism" );
87    fi;
88    if ( InfoLevel( InfoXMod ) > 1 ) then
89        Print( "the boundary map:\n" );
90        Display( bdy1 );
91    fi;
92    ## construct the action map for X1
93    imact1 := ListWithIdenticalEntries( ngPa, 0 );
94    for i in [1..ngPa] do
95        p := elPa[ posPa[i] ][1];
96        imact1[i] := ImageElm( act0, p );
97    od;
98    act1 := GroupHomomorphismByImages( Pa, aut0, genPa, imact1 );
99    if ( InfoLevel( InfoXMod ) > 1 ) then
100        Print( "the action map:\n" );
101        Display( act1 );
102    fi;
103    ## now we can construct the crossed module
104    return XModByBoundaryAndAction( bdy1, act1 );
105end );
106
107##############################################################################
108##
109InstallMethod( AllLoopsXMod, "default method for a crossed module", true,
110    [ IsPreXMod ], 0,
111function( X0 )
112
113    local bdy0, act0, M0, genM0, P0, genP0, igenP0, imgenM0, imbdy0, Q0,
114          conjP0, repsP0, eltsP0, nclP0, i, eclP0, relP0, c, p, genimbdy0,
115          len, class, j, r, k, q, pos, d, h, eqreps, numreps, a, X1, allX;
116
117    bdy0 := Boundary( X0 );
118    act0 := XModAction( X0 );
119    M0 := Source( X0 );
120    genM0 := GeneratorsOfGroup( M0 );
121    P0 := Range( X0 );
122    genP0 := GeneratorsOfGroup( P0 );
123    igenP0 := List( genP0, g -> ImageElm( act0, g ) );
124    imgenM0 := List( genM0, g -> List( igenP0, p -> ImageElm(p,g) ) );
125    imbdy0 := ImagesSource( bdy0 );
126    Q0 := P0/imbdy0;
127    SetName( P0, "P0" );
128    conjP0 := ConjugacyClasses( P0 );
129    repsP0 := List( conjP0, c -> Representative( c ) );
130    eltsP0 := List( conjP0, c -> Elements(c) );
131    nclP0 := Length( conjP0 );
132    if ( InfoLevel( InfoXMod ) > 1 ) then
133        Print( "#I  Size(P0) = ", Size(P0), "\n" );
134        Print( "#I  imgenM0 = ", imgenM0, "\n" );   #? this is not used
135        Print( "#I  cokernel of boundary has IdGroup ", IdGroup(Q0), "\n" );
136        Print( "#I  conjugacy class sizes, reps and orders:classes for P :-\n" );
137        Print( "#I  ", List( conjP0, c -> Size(c) ), "\n" );
138        Print( "#I  repsP0 = ", repsP0, "\n" );
139    fi;
140    if ( InfoLevel( InfoXMod ) > 2 ) then
141        Print( "\n#I  orders and elements in conjugacy classes:\n" );
142        for i in [1..nclP0] do
143            Print( "#I  ", i, " : ", Order(repsP0[i]), " > ", eltsP0[i], "\n" );
144        od;
145    fi;
146    eltsP0 := Elements( P0 );
147    eclP0 := ListWithIdenticalEntries( Size(P0), 1 );
148    relP0 := [1..nclP0];
149    for i in [2..nclP0] do
150        c := conjP0[i];
151        for p in c do
152            eclP0[ Position( eltsP0, p ) ] := i;
153        od;
154    od;
155    Info( InfoXMod, 3, "eclP0 = ", eclP0 );
156    genimbdy0 := GeneratorsOfGroup( imbdy0 );
157    for i in [1..nclP0] do
158        if ( relP0[i] = i ) then
159            len := 1;
160            class := [ i ];
161            j := 0;
162            while ( j < len  ) do
163                j := j+1;
164                c := class[j];
165                r := repsP0[c];
166                for k in imbdy0 do    ##? genimbdy do
167                    q := r*k;
168                    pos := Position( eltsP0, q );
169                    d := eclP0[pos];  ## the class of q
170                    if ( d <> c ) then
171                        Info( InfoXMod, 3, "[c,r,k,q,d] = ", [c,r,k,q,d] );
172                        for h in [1..nclP0] do
173                            if ( relP0[h] = d ) then
174                                relP0[h] := c;
175                            fi;
176                        od;
177                        Add( class, d );
178                        Info( InfoXMod, 3, "class = ", class );
179                    fi;
180                od;
181            od;
182        fi;
183    od;
184    eqreps := [ ];
185    for i in [1..nclP0] do
186        if ( i = relP0[i] ) then
187            Add( eqreps, repsP0[i] );
188        fi;
189    od;
190    numreps := Length( eqreps );
191    Info( InfoXMod, 2, "there are ", numreps,
192                       " equivalence classes with representatives:" );
193    Info( InfoXMod, 2, eqreps );
194    ## now run LoopsXMod on on the list eqreps
195    allX := ListWithIdenticalEntries( numreps, 0 );
196    for i in [1..numreps] do
197        a := eqreps[i];
198        X1 := LoopsXMod( X0, a );
199        Info( InfoXMod, 1, "LoopsXMod with a = ", a, ",  ",
200                           "IdGroup = ", IdGroup( X1 ) );
201        if ( InfoLevel( InfoXMod ) > 1 ) then
202            Display( X1 );
203        fi;
204        allX[i] := X1;
205    od;
206    return allX;
207end );
208