1##############################################################################
2##
3#W  gp2map.gi                  GAP4 package `XMod'               Chris Wensley
4#W                                                                 & Murat Alp
5##  This file installs methods for 2DimensionalMappings
6##  for crossed modules and cat1-groups.
7##
8#Y  Copyright (C) 2001-2019, Chris Wensley et al,
9#Y  School of Computer Science, Bangor University, U.K.
10
11##############################################################################
12##
13#M  Is2DimensionalGroupMorphismData( <list> ) . . . . . . . . . . 2d-group map
14##
15##  this functions tests that boundaries are ok but no checks on actions
16##
17InstallMethod( Is2DimensionalGroupMorphismData,
18    "for list [ 2d-group, 2d-group, homomorphism, homomorphism ]", true,
19    [ IsList ], 0,
20function( L )
21
22    local src, rng, shom, rhom, mor, ok, sbdy, rbdy, st, sh, se, rt, rh, re,
23          sgen, rgen, im1, im2;
24
25    ok := ( Length(L) = 4 );
26    if not ok then
27        Info( InfoXMod, 2, "require list with 2 2dgroups and 2 group homs" );
28        return false;
29    fi;
30    src := L[1];  rng := L[2];  shom := L[3];  rhom := L[4];
31    ok := ( Is2DimensionalGroup( src ) and Is2DimensionalGroup( rng )
32            and IsGroupHomomorphism( shom) and IsGroupHomomorphism( rhom ) );
33    if not ok then
34        Info( InfoXMod, 2, "require two 2dgroups and two group homs" );
35        return false;
36    fi;
37    ok := ( ( Source( src ) = Source( shom ) )
38            and (  Range( src ) = Source( rhom ) )
39            and IsSubgroup( Source( rng ), Range( shom ) )
40            and IsSubgroup(  Range( rng ), Range( rhom ) ) );
41    if not ok then
42        Info( InfoXMod, 2, "sources and ranges do not match" );
43        return false;
44    fi;
45    sgen := GeneratorsOfGroup( Source(src) );
46    rgen := GeneratorsOfGroup( Range(src) );
47    if ( IsPreXMod( src ) and IsPreXMod( rng ) ) then
48        sbdy := Boundary( src );
49        rbdy := Boundary( rng );
50        im1 := List( sgen, g -> ImageElm( rbdy, ImageElm(shom,g) ) );
51        im2 := List( sgen, g -> ImageElm( rhom, ImageElm(sbdy,g) ) );
52        if not ( im1 = im2 ) then
53            Info( InfoXMod, 2, "boundaries and homs do not commute" );
54            return false;
55        fi;
56    elif ( IsPreCat1Group( src ) and IsPreCat1Group( rng ) ) then
57        st := TailMap( src );
58        rt := TailMap( rng );
59        im1 := List( sgen, g -> ImageElm( rt, ImageElm(shom,g) ) );
60        im2 := List( sgen, g -> ImageElm( rhom, ImageElm(st,g) ) );
61        if not ( im1 = im2 ) then
62            Info( InfoXMod, 2, "tail maps and homs do not commute" );
63            return false;
64        fi;
65        sh := HeadMap( src );
66        rh := HeadMap( rng );
67        im1 := List( sgen, g -> ImageElm( rh, ImageElm(shom,g) ) );
68        im2 := List( sgen, g -> ImageElm( rhom, ImageElm(sh,g) ) );
69        if not ( im1 = im2 ) then
70            Info( InfoXMod, 2, "head maps and homs do not commute" );
71            return false;
72        fi;
73        se := RangeEmbedding( src );
74        re := RangeEmbedding( rng );
75        im1 := List( rgen, g -> ImageElm( re, ImageElm(rhom,g) ) );
76        im2 := List( rgen, g -> ImageElm( shom, ImageElm(se,g) ) );
77        if not ( im1 = im2 ) then
78            Info( InfoXMod, 2, "range embeddings and homs do not commute" );
79            return false;
80        fi;
81    else
82        Info( InfoXMod, 2, "require 2 prexmods or precat1s, not one of each" );
83    fi;
84    return true;
85end );
86
87##############################################################################
88##
89#M  Make2DimensionalGroupMorphism( <list> ) . . . . . . . . . . . 2d-group map
90##
91InstallMethod( Make2DimensionalGroupMorphism,
92    "for list [ 2d-group, 2d-group, homomorphism, homomorphism ]", true,
93    [ IsList ], 0,
94function( L )
95
96    local mor;
97
98    if not Is2DimensionalGroupMorphismData( L ) then
99        return fail;
100    fi;
101    mor := rec();
102    ObjectifyWithAttributes( mor, Type2DimensionalGroupMorphism,
103        Source, L[1],
104        Range, L[2],
105        SourceHom, L[3],
106        RangeHom, L[4] );
107    return mor;
108end );
109
110#############################################################################
111##
112#M  IsPreXModMorphism       check diagram of group homs commutes
113##
114InstallMethod( IsPreXModMorphism, "generic method for morphisms of 2d-groups",
115    true, [ Is2DimensionalGroupMorphism ], 0,
116function( mor )
117
118    local PM, Pact, Pbdy, Prng, Psrc, QM, Qact, Qbdy, Qrng, Qsrc,
119          morsrc, morrng, x2, x1, y2, z2, y1, z1, gensrc, genrng;
120
121    PM := Source( mor );
122    QM := Range( mor );
123    if not ( IsPreXMod( PM ) and IsPreXMod( QM ) ) then
124        return false;
125    fi;
126    Psrc := Source( PM );
127    Prng := Range( PM );
128    Pbdy := Boundary( PM );
129    Pact := XModAction( PM );
130    Qsrc := Source( QM );
131    Qrng := Range( QM );
132    Qbdy := Boundary( QM );
133    Qact := XModAction( QM );
134    morsrc := SourceHom( mor );
135    morrng := RangeHom( mor );
136    # now check that the homomorphisms commute
137    gensrc := GeneratorsOfGroup( Psrc );
138    genrng := GeneratorsOfGroup( Prng );
139    Info( InfoXMod, 3, "Checking that the diagram commutes :- \n",
140        "    boundary( morsrc( x ) ) = morrng( boundary( x ) )" );
141    for x2 in gensrc do
142        y1 := ( x2 ^ morsrc ) ^ Qbdy;
143        z1 := ( x2 ^ Pbdy ) ^ morrng;
144        if not ( y1 = z1 ) then
145            Info( InfoXMod, 3, "Square does not commute! \n",
146                "when x2= ", x2, " Qbdy( morsrc(x2) )= ", y1, "\n",
147                "              and morrng( Pbdy(x2) )= ", z1 );
148            return false;
149        fi;
150    od;
151    # now check that the actions commute:
152    Info( InfoXMod, 3,
153          "Checking:  morsrc(x2^x1) = morsrc(x2)^(morrng(x1))" );
154    for x2 in gensrc do
155        for x1 in genrng do
156            y2 := ( x2 ^ ( x1 ^ Pact) ) ^ morsrc;
157            z2 := ( x2 ^ morsrc ) ^ ( ( x1 ^ morrng ) ^ Qact );
158            if not ( y2 = z2 ) then
159                Info( InfoXMod, 2, "Actions do not commute! \n",
160                      "When  x2 = ", x2, "  and  x1 = ", x1, "\n",
161                      "           morsrc(x2^x1) = ", y2, "\n",
162                      "and morsrc(x2)^(morrng(x1) = ", z2 );
163                return false;
164            fi;
165        od;
166    od;
167    return true;
168end );
169
170#############################################################################
171##
172#M  IsXModMorphism
173##
174InstallMethod( IsXModMorphism, "generic method for pre-xmod morphisms", true,
175    [ IsPreXModMorphism ], 0,
176function( mor )
177    return ( IsXMod( Source( mor ) ) and IsXMod(  Range( mor ) ) );
178end );
179
180#############################################################################
181##
182#F  MappingGeneratorsImages( <map> ) . . . . . . . for a 2DimensionalMapping
183##
184InstallOtherMethod( MappingGeneratorsImages, "for a 2DimensionalMapping",
185    true, [ Is2DimensionalMapping ], 0,
186function( map )
187    return [ MappingGeneratorsImages( SourceHom( map ) ),
188             MappingGeneratorsImages( RangeHom( map ) ) ];
189end );
190
191#############################################################################
192##
193#F  Display( <mor> ) . . . . print details of a (pre-)crossed module morphism
194##
195InstallMethod( Display, "display a morphism of pre-crossed modules", true,
196    [ IsPreXModMorphism ], 0,
197function( mor )
198
199    local morsrc, morrng, gensrc, genrng, P, Q, name, ok;
200
201    name := Name( mor );
202    P := Source( mor );
203    Q := Range( mor );
204    morsrc := SourceHom( mor );
205    gensrc := GeneratorsOfGroup( Source( P ) );
206    morrng := RangeHom( mor );
207    genrng := GeneratorsOfGroup( Range( P ) );
208    if IsXModMorphism( mor ) then
209        Print( "Morphism of crossed modules :- \n" );
210    else
211        Print( "Morphism of pre-crossed modules :- \n" );
212    fi;
213    Print( ": Source = ", P, " with generating sets:\n  " );
214    Print( gensrc, "\n  ", genrng, "\n" );
215    if ( Q = P ) then
216        Print( ": Range = Source\n" );
217    else
218        Print( ":  Range = ", Q, " with generating sets:\n  " );
219        Print( GeneratorsOfGroup( Source( Q ) ), "\n" );
220        Print( "  ", GeneratorsOfGroup( Range( Q ) ), "\n" );
221    fi;
222    Print( ": Source Homomorphism maps source generators to:\n" );
223    Print( "  ", List( gensrc, s -> ImageElm( morsrc, s ) ), "\n" );
224    Print( ": Range Homomorphism maps range generators to:\n" );
225    Print( "  ", List( genrng, r -> ImageElm( morrng, r ) ), "\n" );
226end );
227
228#############################################################################
229##
230#M  IsPreCat1GroupMorphism . . . . . . . check diagram of group homs commutes
231##
232InstallMethod( IsPreCat1GroupMorphism, "generic method for morphisms of 2d-groups",
233    true, [ Is2DimensionalGroupMorphism ], 0,
234function( mor )
235
236    local PCG, Prng, Psrc, Pt, Ph, Pe, QCG, Qrng, Qsrc, Qt, Qh, Qe,
237          morsrc, morrng, x2, x1, y2, z2, y1, z1, gensrc, genrng;
238
239    PCG := Source( mor );
240    QCG := Range( mor );
241    if not ( IsPreCat1Group( PCG ) and IsPreCat1Group( QCG ) ) then
242        return false;
243    fi;
244    Psrc := Source( PCG );
245    Prng := Range( PCG );
246    Pt := TailMap( PCG );
247    Ph := HeadMap( PCG );
248    Pe := RangeEmbedding( PCG );
249    Qsrc := Source( QCG );
250    Qrng := Range( QCG );
251    Qt := TailMap( QCG );
252    Qh := HeadMap( QCG );
253    Qe := RangeEmbedding( QCG );
254    morsrc := SourceHom( mor );
255    morrng := RangeHom( mor );
256    # now check that the homomorphisms commute
257    gensrc := GeneratorsOfGroup( Psrc );
258    genrng := GeneratorsOfGroup( Prng );
259    Info( InfoXMod, 3,
260          "Checking that the diagrams commute :- \n",
261          "    tail/head( morsrc( x ) ) = morrng( tail/head( x ) )" );
262    for x2 in gensrc do
263        y1 := ( x2 ^ morsrc ) ^ Qt;
264        z1 := ( x2 ^ Pt ) ^ morrng;
265        y2 := ( x2 ^ morsrc ) ^ Qh;
266        z2 := ( x2 ^ Ph ) ^ morrng;
267        if not ( ( y1 = z1 ) and ( y2 = z2 ) ) then
268            Info( InfoXMod, 3, "Square does not commute! \n",
269                  "when x2= ", x2, " Qt( morsrc(x2) )= ", y1, "\n",
270                  "              and morrng( Pt(x2) )= ", z1, "\n",
271                  "              and Qh( morsrc(x2) )= ", y2, "\n",
272                  "              and morrng( Ph(x2) )= ", z2 );
273            return false;
274        fi;
275    od;
276    for x2 in genrng do
277        y1 := ( x2 ^ morrng ) ^ Qe;
278        z1 := ( x2 ^ Pe ) ^ morsrc;
279        if not ( y1 = z1 ) then
280            Info( InfoXMod, 3, "Square does not commute! \n",
281                  "when x2= ", x2, " Qe( morrng(x2) )= ", y1, "\n",
282                  "              and morsrc( Pe(x2) )= ", z1 );
283            return false;
284        fi;
285    od;
286    return true;
287end );
288
289#############################################################################
290##
291#M  IsCat1GroupMorphism
292##
293InstallMethod( IsCat1GroupMorphism, "generic method for cat1-group homomorphisms",
294    true, [ IsPreCat1GroupMorphism ], 0,
295function( mor )
296    return ( IsCat1Group( Source( mor ) ) and IsCat1Group(  Range( mor ) ) );
297end );
298
299#############################################################################
300##
301#F  Display( <mor> ) . . . . . . print details of a (pre-)cat1-group morphism
302##
303InstallMethod( Display, "display a morphism of pre-cat1 groups", true,
304    [ IsPreCat1GroupMorphism ], 0,
305function( mor )
306
307    local morsrc, morrng, gensrc, genrng, P, Q, name, ok;
308
309    if not HasName( mor ) then
310        # name := PreCat1GroupMorphismName( mor );
311        SetName( mor, "[..=>..]=>[..=>..]" );
312    fi;
313    name := Name( mor );
314    P := Source( mor );
315    Q := Range( mor );
316    morsrc := SourceHom( mor );
317    gensrc := GeneratorsOfGroup( Source( P ) );
318    morrng := RangeHom( mor );
319    genrng := GeneratorsOfGroup( Range( P ) );
320    if IsCat1GroupMorphism( mor ) then
321        Print( "Morphism of cat1-groups :- \n" );
322    else
323        Print( "Morphism of pre-cat1 groups :- \n" );
324    fi;
325    Print( ": Source = ", P, " with generating sets:\n  " );
326    Print( gensrc, "\n  ", genrng, "\n" );
327    if ( Q = P ) then
328        Print( ": Range = Source\n" );
329    else
330        Print( ":  Range = ", Q, " with generating sets:\n  " );
331        Print( GeneratorsOfGroup( Source( Q ) ), "\n" );
332        Print( "  ", GeneratorsOfGroup( Range( Q ) ), "\n" );
333    fi;
334    Print( ": Source Homomorphism maps source generators to:\n" );
335    Print( "  ", List( gensrc, s -> ImageElm( morsrc, s ) ), "\n" );
336    Print( ": Range Homomorphism maps range generators to:\n" );
337    Print( "  ", List( genrng, r -> ImageElm( morrng, r ) ), "\n" );
338end );
339
340##############################################################################
341##
342#M  CompositionMorphism  . . . . . . . . . . . . for two 2Dimensional-mappings
343##
344InstallOtherMethod( CompositionMorphism, "generic method for 2d-mappings",
345    IsIdenticalObj, [ Is2DimensionalMapping, Is2DimensionalMapping ], 0,
346function( mor2, mor1 )
347
348    local srchom, rnghom, comp, ok;
349
350    if not ( Range( mor1 ) = Source( mor2 ) ) then
351        Info( InfoXMod, 2, "Range(mor1) <> Source(mor2)" );
352        return fail;
353    fi;
354    srchom := CompositionMapping2( SourceHom( mor2 ), SourceHom( mor1 ) );
355    rnghom := CompositionMapping2( RangeHom( mor2 ), RangeHom( mor1 ) );
356    comp := Make2DimensionalGroupMorphism(
357                [ Source(mor1), Range(mor2), srchom, rnghom ]);
358    if IsPreCat1Group( Source( mor1 ) ) then
359        if ( IsPreCat1GroupMorphism( mor1 )
360             and IsPreCat1GroupMorphism( mor2 ) ) then
361            SetIsPreCat1GroupMorphism( comp, true );
362        fi;
363        if ( IsCat1GroupMorphism( mor1 ) and IsCat1GroupMorphism( mor2 ) ) then
364            SetIsCat1GroupMorphism( comp, true );
365        fi;
366    else
367        if ( IsPreXModMorphism( mor1 ) and
368             IsPreXModMorphism( mor2 ) ) then
369            SetIsPreXModMorphism( comp, true );
370        fi;
371        if ( IsXModMorphism( mor1 ) and IsXModMorphism( mor2 ) ) then
372            SetIsXModMorphism( comp, true );
373        fi;
374    fi;
375    return comp;
376end );
377
378##############################################################################
379##
380#M  InverseGeneralMapping . . . . . . . . . . . . . for a 2Dimensional-mapping
381##
382InstallOtherMethod( InverseGeneralMapping, "generic method for 2d-mapping",
383    true, [ Is2DimensionalMapping ], 0,
384function( mor )
385
386    local sinv, rinv, inv, ok;
387
388    if not IsBijective( mor ) then
389        Info( InfoXMod, 1, "mor is not bijective" );
390        return fail;
391    fi;
392    sinv := InverseGeneralMapping( SourceHom( mor ) );
393    rinv := InverseGeneralMapping( RangeHom( mor ) );
394    inv := Make2DimensionalGroupMorphism( [Range(mor),Source(mor),sinv,rinv] );
395    if IsPreXModMorphism( mor ) then
396        SetIsPreXModMorphism( inv, true );
397        if IsXModMorphism( mor ) then
398            SetIsXModMorphism( inv, true );
399        fi;
400    elif IsPreCat1GroupMorphism( mor ) then
401        SetIsPreCat1GroupMorphism( inv, true );
402        if IsCat1GroupMorphism( mor ) then
403            SetIsCat1GroupMorphism( inv, true );
404        fi;
405    fi;
406    SetIsInjective( inv, true );
407    SetIsSurjective( inv, true );
408    return inv;
409end );
410
411##############################################################################
412##
413#M  IdentityMapping( <obj> )
414##
415InstallOtherMethod( IdentityMapping, "for 2d-group object", true,
416    [ Is2DimensionalDomain ], 0,
417function( obj )
418
419    local shom, rhom;
420
421    shom := IdentityMapping( Source( obj ) );
422    rhom := IdentityMapping( Range( obj ) );
423    if IsPreXModObj( obj ) then
424        return PreXModMorphismByGroupHomomorphisms( obj, obj, shom, rhom );
425    elif IsPreCat1Obj( obj ) then
426        return PreCat1GroupMorphismByGroupHomomorphisms( obj, obj, shom, rhom );
427    else
428        return fail;
429    fi;
430end );
431
432##############################################################################
433##
434#M  InclusionMorphism2DimensionalDomains( <obj>, <sub> )
435##
436InstallMethod( InclusionMorphism2DimensionalDomains, "one 2d-object in another",
437    true, [ Is2DimensionalDomain, Is2DimensionalDomain ], 0,
438function( obj, sub )
439
440    local shom, rhom;
441
442    shom := InclusionMappingGroups( Source( obj ), Source( sub ) );
443    rhom := InclusionMappingGroups( Range( obj ), Range( sub ) );
444    if IsPreXModObj( obj ) then
445        return PreXModMorphismByGroupHomomorphisms( sub, obj, shom, rhom );
446    elif IsPreCat1Obj( obj ) then
447        return PreCat1GroupMorphismByGroupHomomorphisms( sub, obj, shom, rhom );
448    else
449        return fail;
450    fi;
451end );
452
453##############################################################################
454##
455#F  PreXModMorphism( <src>,<rng>,<srchom>,<rnghom> ) pre-crossed mod morphism
456##
457##  (need to extend to other sets of parameters)
458##
459InstallGlobalFunction( PreXModMorphism, function( arg )
460
461    local ok, mor, nargs;
462
463    nargs := Length( arg );
464    # two pre-xmods and two homomorphisms
465    if ( nargs = 4 ) then
466        mor := Make2DimensionalGroupMorphism( [arg[1],arg[2],arg[3],arg[4] ] );
467    else
468        # alternatives not allowed
469        Info( InfoXMod, 2, "usage: PreXModMorphism([src,rng,srchom,rnghom]);" );
470        return fail;
471    fi;
472    ok := IsPreXModMorphism( mor );
473    return mor;
474end );
475
476###############################################################################
477##
478#F  XModMorphism( <src>, <rng>, <srchom>, <rnghom> )    crossed module morphism
479##
480##  (need to extend to other sets of parameters)
481##
482InstallGlobalFunction( XModMorphism, function( arg )
483
484    local nargs;
485
486    nargs := Length( arg );
487    # two xmods and two homomorphisms
488    if ( ( nargs = 4 ) and IsXMod( arg[1] ) and IsXMod( arg[2])
489                       and IsGroupHomomorphism( arg[3] )
490                       and IsGroupHomomorphism( arg[4] ) ) then
491        return XModMorphismByGroupHomomorphisms(arg[1],arg[2],arg[3],arg[4]);
492    fi;
493    # alternatives not allowed
494    Info( InfoXMod, 2, "usage: XModMorphism( src, rng, srchom, rnghom );" );
495    return fail;
496end );
497
498###############################################################################
499##
500#F  PreCat1GroupMorphism( <src>,<rng>,<srchom>,<rnghom> ) pre-cat1-grp morphism
501##
502##  (need to extend to other sets of parameters)
503##
504InstallGlobalFunction( PreCat1GroupMorphism, function( arg )
505
506    local nargs;
507
508    nargs := Length( arg );
509    # two pre-cat1s and two homomorphisms
510    if ( ( nargs = 4 ) and IsPreCat1Group( arg[1] ) and IsPreCat1Group( arg[2])
511                       and IsGroupHomomorphism( arg[3] )
512                       and IsGroupHomomorphism( arg[4] ) ) then
513        return PreCat1GroupMorphismByGroupHomomorphisms(
514                   arg[1], arg[2], arg[3], arg[4] );
515    fi;
516    # alternatives not allowed
517    Info( InfoXMod, 2,
518          "usage: PreCat1GroupMorphism( src, rng, srchom, rnghom );" );
519    return fail;
520end );
521
522###############################################################################
523##
524#F  Cat1GroupMorphism( <src>, <rng>, <srchom>, <rnghom> )        cat1-group morphism
525##
526##  (need to extend to other sets of parameters)
527##
528InstallGlobalFunction( Cat1GroupMorphism, function( arg )
529
530    local nargs;
531
532    nargs := Length( arg );
533    # two cat1s and two homomorphisms
534    if ( ( nargs = 4 ) and IsCat1Group( arg[1] ) and IsCat1Group( arg[2])
535                       and IsGroupHomomorphism( arg[3] )
536                       and IsGroupHomomorphism( arg[4] ) ) then
537        return Cat1GroupMorphismByGroupHomomorphisms( arg[1], arg[2], arg[3], arg[4] );
538    fi;
539    # alternatives not allowed
540    Info( InfoXMod, 2, "usage: Cat1GroupMorphism( src, rng, srchom, rnghom );" );
541    return fail;
542end );
543
544##############################################################################
545##
546#M  XModMorphismByGroupHomomorphisms( <Xs>, <Xr>, <hsrc>, <hrng> )
547##  . . . make an xmod morphism
548##
549InstallMethod( XModMorphismByGroupHomomorphisms, "for 2 xmods and 2 homs",
550    true, [ IsXMod, IsXMod, IsGroupHomomorphism, IsGroupHomomorphism ], 0,
551function( src, rng, srchom, rnghom )
552
553    local mor, ok;
554
555    mor := PreXModMorphismByGroupHomomorphisms( src, rng, srchom, rnghom );
556    ok := IsXModMorphism( mor );
557    if not ok then
558        return fail;
559    fi;
560    return mor;
561end );
562
563##############################################################################
564##
565#M  InnerAutomorphismXMod( <XM>, <r> ) . . . . . . . .  conjugation of an xmod
566##
567InstallMethod( InnerAutomorphismXMod, "method for crossed modules", true,
568    [ IsPreXMod, IsMultiplicativeElementWithInverse ], 0,
569function( XM, r )
570
571    local Xrng, Xsrc, genrng, gensrc, rhom, shom, s;
572
573    Xrng := Range( XM );
574    if not ( r in Xrng ) then
575        Info( InfoXMod, 2, "conjugating element must be in the range group" );
576        return fail;
577    fi;
578    Xsrc := Source( XM );
579    gensrc := GeneratorsOfGroup( Xsrc );
580    genrng := GeneratorsOfGroup( Xrng );
581    rhom := GroupHomomorphismByImages( Xrng, Xrng, genrng,
582                List( genrng, g -> g^r ) );
583    s := ImageElm( XModAction( XM ), r );
584    shom := GroupHomomorphismByImages( Xsrc, Xsrc, gensrc,
585                List( gensrc, g -> g^s ) );
586    return XModMorphismByGroupHomomorphisms( XM, XM, shom, rhom );
587end );
588
589##############################################################################
590##
591#M  InnerAutomorphismCat1Group( <C1G>, <r> ) . . . conjugation of a cat1-group
592##
593InstallMethod( InnerAutomorphismCat1Group, "method for cat1-groups", true,
594    [ IsPreCat1Group, IsMultiplicativeElementWithInverse ], 0,
595function( C1G, r )
596
597    local Crng, Csrc, genrng, gensrc, rhom, shom, s;
598
599    Crng := Range( C1G );
600    if not ( r in Crng ) then
601        Info( InfoXMod, 2, "conjugating element must be in the range group" );
602        return fail;
603    fi;
604    Csrc := Source( C1G );
605    gensrc := GeneratorsOfGroup( Csrc );
606    genrng := GeneratorsOfGroup( Crng );
607    rhom := GroupHomomorphismByImages( Crng, Crng, genrng,
608                List( genrng, g -> g^r ) );
609    s := ImageElm( RangeEmbedding( C1G ), r );
610    shom := GroupHomomorphismByImages( Csrc, Csrc, gensrc,
611                List( gensrc, g -> g^s ) );
612    return Cat1GroupMorphismByGroupHomomorphisms( C1G, C1G, shom, rhom );
613end );
614
615#############################################################################
616##
617#M  String, ViewString, PrintString, ViewObj, PrintObj
618##  . . . . . . . . . . . . . . . . .  for a morphism of pre-crossed modules
619##
620InstallMethod( String, "method for a morphism of pre-crossed modules", true,
621    [ IsPreXModMorphism ], 0,
622function( mor )
623    return( STRINGIFY( "[", String( Source(mor) ), " => ",
624                            String( Range(mor) ), "]" ) );
625end );
626
627InstallMethod( ViewString, "method for a morphism of pre-crossed modules",
628    true, [ IsPreXModMorphism ], 0, String );
629
630InstallMethod( PrintString, "method for a morphism of pre-crossed modules",
631    true, [ IsPreXModMorphism ], 0, String );
632
633InstallMethod( ViewObj, "method for a morphism of pre-crossed modules", true,
634    [ IsPreXModMorphism ], 0,
635function( mor )
636    if HasName( mor ) then
637        Print( Name( mor ), "\n" );
638    else
639        Print( "[", Source( mor ), " => ", Range( mor ), "]" );
640    fi;
641end );
642
643InstallMethod( PrintObj, "method for a morphism of pre-crossed modules", true,
644    [ IsPreXModMorphism ], 0,
645function( mor )
646    if HasName( mor ) then
647        Print( Name( mor ), "\n" );
648    else
649        Print( "[", Source( mor ), " => ", Range( mor ), "]" );
650    fi;
651end );
652
653##############################################################################
654##
655#M  \*( <mor1>, <mor2> ) . . . . . . . . .  for 2 pre-crossed module morphisms
656##
657InstallOtherMethod( \*, "for two morphisms of pre-crossed modules",
658    IsIdenticalObj, [ IsPreXModMorphism, IsPreXModMorphism ], 0,
659function( mor1, mor2 )
660
661    local comp;
662
663    comp := CompositionMorphism( mor2, mor1 );
664    ## need to do some checks here !? ##
665    return comp;
666end );
667
668##############################################################################
669##
670#M  \^( <mor>, <int> ) . . . . . . . . . . . . . . . for a 2DimensionalMapping
671##
672InstallOtherMethod( POW, "for a 2d mapping", true,
673    [ Is2DimensionalMapping, IsInt ], 0,
674function( map, n )
675
676    local pow, i, ok;
677
678    if not ( Source( map ) = Range( map ) ) then
679        return fail;
680    elif ( n = 1 ) then
681        return map;
682    elif ( n = -1 ) then
683        ok := IsBijective( map );
684        return InverseGeneralMapping( map );
685    elif ( n < -1 ) then
686        return InverseGeneralMapping( map^(-n) );
687    fi;
688    pow := map;
689    for i in [2..n] do
690        pow := CompositionMorphism( pow, map );
691    od;
692    return pow;
693end );
694
695##############################################################################
696##
697#M  IsomorphismByIsomorphisms . . . . . . constructs isomorphic pre-cat1-group
698##
699InstallMethod( IsomorphismByIsomorphisms, "generic method for pre-cat1-groups",
700    true, [ IsPreCat1Group, IsList ], 0,
701function( PC, isos )
702
703    local G, R, t, h, e, isoG, isoR, mgiG, mgiR, invG, invR,
704          G2, R2, t2, h2, e2, PC2, mor;
705
706    G := Source( PC );
707    R := Range( PC );
708    t := TailMap( PC );
709    h := HeadMap( PC );
710    e := RangeEmbedding( PC );
711    isoG := isos[1];
712    isoR := isos[2];
713    if not ( ( Source(isoR) = R ) and ( Source(isoG) = G ) ) then
714        Error( "isomorphisms do not have G,R as source" );
715    fi;
716    G2 := Range( isoG );
717    R2 := Range( isoR );
718    mgiG := MappingGeneratorsImages( isoG );
719    invG := GroupHomomorphismByImages( G2, G, mgiG[2], mgiG[1] );
720    mgiR := MappingGeneratorsImages( isoR );
721    invR := GroupHomomorphismByImages( R2, R, mgiR[2], mgiR[1] );
722    t2 := CompositionMapping( isoR, t, invG );
723    h2 := CompositionMapping( isoR, h, invG );
724    e2 := CompositionMapping( isoG, e, invR );
725    PC2 := PreCat1GroupByTailHeadEmbedding( t2, h2, e2 );
726    mor := PreCat1GroupMorphism( PC, PC2, isoG, isoR );
727    return mor;
728end );
729
730InstallMethod( IsomorphismByIsomorphisms, "generic method for pre-xmods",
731    true, [ IsPreXMod, IsList ], 0,
732function( PM, isos )
733
734    local Psrc, Prng, Pbdy, Pact, Paut, Pautgen, siso, smgi, sinv, riso,
735          rmgi, rinv, Qsrc, Qrng, Qbdy, Qaut, Qautgen, ahom, Qact, QM, iso;
736
737    Psrc := Source( PM );
738    Prng := Range( PM );
739    Pbdy := Boundary( PM );
740    siso := isos[1];
741    Qsrc := ImagesSource( siso );
742    smgi := MappingGeneratorsImages( siso );
743    sinv := GroupHomomorphismByImages( Qsrc, Psrc, smgi[2], smgi[1] );
744    riso := isos[2];
745    Qrng := ImagesSource( riso );
746    rmgi := MappingGeneratorsImages( riso );
747    rinv := GroupHomomorphismByImages( Qrng, Prng, rmgi[2], rmgi[1] );
748    if not ( ( Psrc = Source(siso) ) and ( Prng = Source(riso) ) ) then
749        Info( InfoXMod, 2, "groups of PM not sources of isomorphisms" );
750        return fail;
751    fi;
752    Qbdy := CompositionMapping( riso, Pbdy, sinv );
753    Pact := XModAction( PM );
754    Paut := Range( Pact );
755    Pautgen := GeneratorsOfGroup( Paut );
756    Qautgen := List( Pautgen, a -> CompositionMapping( siso, a, sinv ) );
757    Qaut := Group( Qautgen );
758    ahom := GroupHomomorphismByImages( Paut, Qaut, Pautgen, Qautgen );
759    Qact := CompositionMapping( ahom, Pact, rinv );
760    QM := PreXModByBoundaryAndAction( Qbdy, Qact );
761    iso := PreXModMorphismByGroupHomomorphisms( PM, QM, siso, riso );
762    SetIsInjective( iso, true );
763    SetIsSurjective( iso, true );
764    SetImagesSource( iso, QM );
765    if ( HasIsXMod( PM ) and IsXMod( PM ) ) then
766        SetIsXMod( QM, true );
767        SetIsXModMorphism( iso, true );
768    fi;
769    return iso;
770end );
771
772##############################################################################
773##
774#M  IsomorphismPerm2DimensionalGroup . . . constructs isomorphic perm pre-xmod
775#M  IsomorphismPerm2DimensionalGroup . . . constructs isomorphic perm pre-cat1
776##
777InstallMethod( IsomorphismPerm2DimensionalGroup,
778     "generic method for pre-crossed modules", true, [ IsPreXMod ], 0,
779function( PM )
780
781    local shom, rhom, Psrc, Psgen, Qsrc, Qsgen, Prng, Prgen, Qrng, Qrgen,
782          QM, iso;
783
784    if IsPermPreXMod( PM ) then
785        return IdentityMapping( PM );
786    fi;
787    Psrc := Source( PM );
788    if IsPermGroup( Psrc ) then
789        shom := IdentityMapping( Psrc );
790    else
791        Psgen := GeneratorsOfGroup( Psrc );
792        shom := IsomorphismPermGroup( Psrc );
793        Qsrc := Image( shom );
794        shom := shom * SmallerDegreePermutationRepresentation( Qsrc );
795        Qsrc := ImagesSource( shom );
796        Qsgen := List( Psgen, s -> ImageElm( shom, s ) );
797        if HasName( Psrc ) then
798            SetName( Qsrc, Concatenation( "P", Name( Psrc ) ) );
799        fi;
800        shom := GroupHomomorphismByImages( Psrc, Qsrc, Psgen, Qsgen );
801    fi;
802    Prng := Range( PM );
803    if IsPermGroup( Prng ) then
804        rhom := IdentityMapping( Prng );
805    else
806        Prgen := GeneratorsOfGroup( Prng );
807        rhom := IsomorphismPermGroup( Prng );
808        Qrng := Image( rhom );
809        rhom := rhom * SmallerDegreePermutationRepresentation( Qrng );
810        Qrng := ImagesSource( rhom );
811        Qrgen := List( Prgen, r -> ImageElm( rhom, r ) );
812        if HasName( Prng ) then
813            SetName( Qrng, Concatenation( "P", Name( Prng ) ) );
814        fi;
815        rhom := GroupHomomorphismByImages( Prng, Qrng, Prgen, Qrgen );
816    fi;
817    iso := IsomorphismByIsomorphisms( PM, [ shom, rhom ] );
818    QM := ImagesSource( iso );
819    if HasName( PM ) then
820        SetName( QM, Concatenation( "P", Name( PM ) ) );
821    fi;
822    iso := PreXModMorphism( PM, QM, shom, rhom );
823    return iso;
824end );
825
826InstallMethod( IsomorphismPerm2DimensionalGroup,
827     "generic method for pre-cat1-groups", true, [ IsPreCat1Group ], 0,
828function( PCG )
829
830    local shom, rhom, Psrc, Psgen, Qsrc, Qsgen, Prng, Prgen, Qrng, Qrgen,
831          QCG, iso;
832
833    if IsPermPreCat1Group( PCG ) then
834        return IdentityMapping( PCG );
835    fi;
836    Psrc := Source( PCG );
837    if IsPermGroup( Psrc ) then
838        shom := IdentityMapping( Psrc );
839    else
840        Psgen := GeneratorsOfGroup( Psrc );
841        shom := IsomorphismPermGroup( Psrc );
842        Qsrc := Image( shom );
843        shom := shom * SmallerDegreePermutationRepresentation( Qsrc );
844        Qsrc := ImagesSource( shom );
845        Qsgen := List( Psgen, s -> ImageElm( shom, s ) );
846        shom := GroupHomomorphismByImages( Psrc, Qsrc, Psgen, Qsgen );
847    fi;
848    Prng := Range( PCG );
849    if IsPermGroup( Prng ) then
850        rhom := IdentityMapping( Prng );
851    else
852        Prgen := GeneratorsOfGroup( Prng );
853        if IsPreCat1GroupByEndomorphisms( PCG ) then
854            rhom := RestrictedMapping( shom, Prng );
855        else
856            rhom := IsomorphismPermGroup( Prng );
857            Qrng := Image( rhom );
858            rhom := rhom * SmallerDegreePermutationRepresentation( Qrng );
859        fi;
860        Qrng := ImagesSource( rhom );
861        Qrgen := List( Prgen, r -> ImageElm( rhom, r ) );
862        rhom := GroupHomomorphismByImages( Prng, Qrng, Prgen, Qrgen );
863    fi;
864    iso := IsomorphismByIsomorphisms( PCG, [ shom, rhom ] );
865    QCG := ImagesSource( iso );
866    if HasName( PCG ) then
867        SetName( QCG, Concatenation( "Pc", Name( PCG ) ) );
868    fi;
869    iso := PreCat1GroupMorphism( PCG, QCG, shom, rhom );
870    return iso;
871end );
872
873##############################################################################
874##
875#M  IsomorphismPc2DimensionalGroup . . . . . constructs isomorphic pc-pre-xmod
876#M  IsomorphismPc2DimensionalGroup . . . . . constructs isomorphic pc-pre-cat1
877##
878InstallMethod( IsomorphismPc2DimensionalGroup,
879     "generic method for pre-crossed modules", true, [ IsPreXMod ], 0,
880function( PM )
881
882    local shom, rhom, Psrc, Psgen, Qsrc, Qsgen, Prng, Prgen, Qrng, Qrgen,
883          QM, iso;
884
885    if IsPcPreXMod( PM ) then
886        return IdentityMapping( PM );
887    fi;
888    Psrc := Source( PM );
889    if IsPcGroup( Psrc ) then
890        shom := IdentityMapping( Psrc );
891    else
892        Psgen := GeneratorsOfGroup( Psrc );
893        shom := IsomorphismPcGroup( Psrc );
894        if ( shom = fail ) then
895            return fail;
896        fi;
897        Qsrc := ImagesSource( shom );
898        Qsgen := List( Psgen, s -> ImageElm( shom, s ) );
899        shom := GroupHomomorphismByImages( Psrc, Qsrc, Psgen, Qsgen );
900    fi;
901    Prng := Range( PM );
902    if ( HasIsNormalSubgroup2DimensionalGroup(PM)
903             and IsNormalSubgroup2DimensionalGroup(PM) ) then
904        Print( "#!  modify IsomorphismPc2DimensionalGroup to preserve the\n",
905               "#!  property of being IsNormalSubgroup2DimensionalGroup\n" );
906    fi;
907    if IsPcGroup( Prng ) then
908        rhom := IdentityMapping( Prng );
909    else
910        Prgen := GeneratorsOfGroup( Prng );
911        rhom := IsomorphismPcGroup( Prng );
912        if ( rhom = false ) then
913            return false;
914        fi;
915        Qrng := ImagesSource( rhom );
916        Qrgen := List( Prgen, r -> ImageElm( rhom, r ) );
917        rhom := GroupHomomorphismByImages( Prng, Qrng, Prgen, Qrgen );
918    fi;
919    iso := IsomorphismByIsomorphisms( PM, [ shom, rhom ] );
920    QM := ImagesSource( iso );
921    if HasName( PM ) then
922        SetName( QM, Concatenation( "Pc", Name( PM ) ) );
923    fi;
924    iso := PreXModMorphism( PM, QM, shom, rhom );
925    return iso;
926end );
927
928InstallMethod( IsomorphismPc2DimensionalGroup,
929     "generic method for pre-cat1-groups", true, [ IsPreCat1Group ], 0,
930function( PCG )
931
932    local shom, rhom, Psrc, Psgen, Qsrc, Qsgen, Prng, Prgen, Qrng, Qrgen,
933          QCG, iso;
934
935    if IsPcPreCat1Group( PCG ) then
936        return IdentityMapping( PCG );
937    fi;
938    Psrc := Source( PCG );
939    if IsPcGroup( Psrc ) then
940        shom := IdentityMapping( Psrc );
941    else
942        Psgen := GeneratorsOfGroup( Psrc );
943        shom := IsomorphismPcGroup( Psrc );
944        if ( shom = fail ) then
945            return fail;
946        fi;
947        Qsrc := ImagesSource( shom );
948        Qsgen := List( Psgen, s -> ImageElm( shom, s ) );
949        shom := GroupHomomorphismByImages( Psrc, Qsrc, Psgen, Qsgen );
950    fi;
951    Prng := Range( PCG );
952    if IsPcGroup( Prng ) then
953        rhom := IdentityMapping( Prng );
954    else
955        Prgen := GeneratorsOfGroup( Prng );
956        rhom := IsomorphismPcGroup( Prng );
957        if ( rhom = fail ) then
958            return fail;
959        fi;
960        Qrng := ImagesSource( rhom );
961        Qrgen := List( Prgen, r -> ImageElm( rhom, r ) );
962        rhom := GroupHomomorphismByImages( Prng, Qrng, Prgen, Qrgen );
963    fi;
964    iso := IsomorphismByIsomorphisms( PCG, [ shom, rhom ] );
965    QCG := ImagesSource( iso );
966    if HasName( PCG ) then
967        SetName( QCG, Concatenation( "Pc", Name( PCG ) ) );
968    fi;
969    iso := PreCat1GroupMorphism( PCG, QCG, shom, rhom );
970    return iso;
971end );
972
973##############################################################################
974##
975#M  IsomorphismFp2DimensionalGroup . . . . . constructs isomorphic fp-pre-xmod
976#M  IsomorphismFp2DimensionalGroup . . . . . constructs isomorphic fp-pre-cat1
977##
978InstallMethod( IsomorphismPc2DimensionalGroup,
979     "generic method for pre-crossed modules", true, [ IsPreXMod ], 0,
980function( PM )
981
982    local shom, rhom, Psrc, Psgen, Qsrc, Qsgen, Prng, Prgen, Qrng, Qrgen,
983          QM, iso;
984
985    if IsFpPreXMod( PM ) then
986        return IdentityMapping( PM );
987    fi;
988    Psrc := Source( PM );
989    if IsFpGroup( Psrc ) then
990        shom := IdentityMapping( Psrc );
991    else
992        Psgen := GeneratorsOfGroup( Psrc );
993        shom := IsomorphismFpGroup( Psrc );
994        if ( shom = fail ) then
995            return fail;
996        fi;
997        Qsrc := ImagesSource( shom );
998        Qsgen := List( Psgen, s -> ImageElm( shom, s ) );
999        shom := GroupHomomorphismByImages( Psrc, Qsrc, Psgen, Qsgen );
1000    fi;
1001    Prng := Range( PM );
1002    if ( HasIsNormalSubgroup2DimensionalGroup(PM)
1003             and IsNormalSubgroup2DimensionalGroup(PM) ) then
1004        Print( "#!  modify IsomorphismFp2DimensionalGroup to preserve the\n",
1005               "#!  property of being IsNormalSubgroup2DimensionalGroup\n" );
1006    fi;
1007    if IsFpGroup( Prng ) then
1008        rhom := IdentityMapping( Prng );
1009    else
1010        Prgen := GeneratorsOfGroup( Prng );
1011        rhom := IsomorphismFpGroup( Prng );
1012        if ( rhom = false ) then
1013            return false;
1014        fi;
1015        Qrng := ImagesSource( rhom );
1016        Qrgen := List( Prgen, r -> ImageElm( rhom, r ) );
1017        rhom := GroupHomomorphismByImages( Prng, Qrng, Prgen, Qrgen );
1018    fi;
1019    iso := IsomorphismByIsomorphisms( PM, [ shom, rhom ] );
1020    QM := ImagesSource( iso );
1021    if HasName( PM ) then
1022        SetName( QM, Concatenation( "Pc", Name( PM ) ) );
1023    fi;
1024    iso := PreXModMorphism( PM, QM, shom, rhom );
1025    return iso;
1026end );
1027
1028InstallMethod( IsomorphismFp2DimensionalGroup,
1029     "generic method for pre-cat1-groups", true, [ IsPreCat1Group ], 0,
1030function( PCG )
1031
1032    local shom, rhom, Psrc, Psgen, Qsrc, Qsgen, Prng, Prgen, Qrng, Qrgen,
1033          QCG, iso;
1034
1035    if IsFpPreCat1Group( PCG ) then
1036        return IdentityMapping( PCG );
1037    fi;
1038    Psrc := Source( PCG );
1039    if IsFpGroup( Psrc ) then
1040        shom := IdentityMapping( Psrc );
1041    else
1042        Psgen := GeneratorsOfGroup( Psrc );
1043        shom := IsomorphismFpGroup( Psrc );
1044        if ( shom = fail ) then
1045            return fail;
1046        fi;
1047        Qsrc := ImagesSource( shom );
1048        Qsgen := List( Psgen, s -> ImageElm( shom, s ) );
1049        shom := GroupHomomorphismByImages( Psrc, Qsrc, Psgen, Qsgen );
1050    fi;
1051    Prng := Range( PCG );
1052    if IsFpGroup( Prng ) then
1053        rhom := IdentityMapping( Prng );
1054    else
1055        Prgen := GeneratorsOfGroup( Prng );
1056        rhom := IsomorphismFpGroup( Prng );
1057        if ( rhom = fail ) then
1058            return fail;
1059        fi;
1060        Qrng := ImagesSource( rhom );
1061        Qrgen := List( Prgen, r -> ImageElm( rhom, r ) );
1062        rhom := GroupHomomorphismByImages( Prng, Qrng, Prgen, Qrgen );
1063    fi;
1064    iso := IsomorphismByIsomorphisms( PCG, [ shom, rhom ] );
1065    QCG := ImagesSource( iso );
1066    if HasName( PCG ) then
1067        SetName( QCG, Concatenation( "Fp", Name( PCG ) ) );
1068    fi;
1069    iso := PreCat1GroupMorphism( PCG, QCG, shom, rhom );
1070    return iso;
1071end );
1072
1073###############################################################################
1074##
1075#M  IsomorphismPreCat1Groups . . isomorphism between a pair of pre-cat1-groups
1076#M  IsomorphismCat1Groups  . . . isomorphism between a pair of cat1-groups
1077##
1078InstallMethod( IsomorphismPreCat1Groups, "generic method for 2 pre-cat1-groups",
1079    true, [ IsPreCat1Group, IsPreCat1Group ], 0,
1080function( C1, C2 )
1081
1082    local t1, h1, e1, t2, h2, e2, G1, G2, R1, R2, phi, psi, alpha, gamma, rho;
1083
1084    G1 := Source( C1 );
1085    G2 := Source( C2 );
1086    if not ( G1 = G2 ) then
1087        phi := IsomorphismGroups( G1, G2 );
1088    else
1089        phi := IdentityMapping( G1 );
1090    fi;
1091    if ( phi = fail ) then
1092        Info( InfoXMod, 2, "G1,G2 not isomorphic" );
1093        return fail;
1094    fi;
1095    R1 := Range( C1 );
1096    R2 := Range( C2 );
1097    if not ( R1 = R2 ) then
1098        psi := IsomorphismGroups( R1, R2 );
1099    else
1100        psi := IdentityMapping( R1 );
1101    fi;
1102    if ( psi = fail ) then
1103        Info( InfoXMod, 2, "R1,R2 not isomorphic" );
1104        return fail;
1105    fi;
1106    t1 := TailMap( C1 );
1107    h1 := HeadMap( C1 );
1108    t2 := TailMap( C2 );
1109    h2 := HeadMap( C2 );
1110    e1 := RangeEmbedding( C1 );
1111    e2 := RangeEmbedding( C2 );
1112    for alpha in AutomorphismGroup( G1 ) do
1113        gamma := alpha * phi;
1114        rho := e1 * gamma * t2;
1115        if ( ( e1*gamma = rho*e2 ) and
1116             ( gamma*h2 = h1*rho ) and
1117             ( gamma*t2 = t1*rho ) ) then
1118            return PreCat1GroupMorphismByGroupHomomorphisms(C1,C2,gamma,rho);
1119        fi;
1120    od;
1121    Info( InfoXMod, 2, "no isomorphism found" );
1122    return fail;
1123end );
1124
1125InstallMethod( IsomorphismCat1Groups, "generic method for 2 cat1-groups",
1126    true, [ IsCat1Group, IsCat1Group ], 0,
1127function( C1, C2 )
1128
1129    local iso, ok;
1130
1131    iso := IsomorphismPreCat1Groups( C1, C2 );
1132    if ( iso = fail ) then
1133        return fail;
1134    fi;
1135    ok := IsCat1GroupMorphism( iso );
1136    if not ok then
1137        Error( "found a pre-cat1 morphism which is not a cat1-morphism" );
1138    fi;
1139    return iso;
1140end );
1141
1142#############################################################################
1143##
1144#M  Name                                                       for a pre-xmod
1145##
1146InstallMethod( Name, "method for a 2d-mapping", true,
1147    [ Is2DimensionalMapping ], 0,
1148function( mor )
1149
1150    local nsrc, nrng, name;
1151
1152    if HasName( Source( mor ) ) then
1153        nsrc := Name( Source( mor ) );
1154    else
1155        nsrc := "[..]";
1156    fi;
1157    if HasName( Range( mor ) ) then
1158        nrng := Name( Range( mor ) );
1159    else
1160        nrng := "[..]";
1161    fi;
1162    name := Concatenation( "[", nsrc, " => ", nrng, "]" );
1163    SetName( mor, name );
1164    return name;
1165end );
1166
1167###############################################################################
1168##
1169#M  PreXModMorphismByGroupHomomorphisms( <P>, <Q>, <hsrc>, <hrng> )
1170##  . . . make a prexmod morphism
1171##
1172InstallMethod( PreXModMorphismByGroupHomomorphisms,
1173    "for pre-xmod, pre-xmod, homomorphism, homomorphism,", true,
1174    [ IsPreXMod, IsPreXMod, IsGroupHomomorphism, IsGroupHomomorphism ], 0,
1175function( src, rng, srchom, rnghom )
1176
1177    local filter, fam, mor, ok, nsrc, nrng, name;
1178
1179    if not ( IsGroupHomomorphism(srchom) and IsGroupHomomorphism(rnghom) ) then
1180        Info( InfoXMod, 2, "source and range mappings must be group homs" );
1181        return fail;
1182    fi;
1183    mor := Make2DimensionalGroupMorphism( [ src, rng, srchom, rnghom ] );
1184    if not IsPreXModMorphism( mor ) then
1185        Info( InfoXMod, 2, "not a morphism of pre-crossed modules.\n" );
1186        return fail;
1187    fi;
1188    if ( HasName( Source(src) ) and HasName( Range(src) ) ) then
1189        nsrc := Name( src );
1190    else
1191        nsrc := "[..]";
1192    fi;
1193    if ( HasName( Source(rng) )and HasName( Range(rng) ) ) then
1194        nrng := Name( rng );
1195    else
1196        nrng := "[..]";
1197    fi;
1198    name := Concatenation( "[", nsrc, " => ", nrng, "]" );
1199    SetName( mor, name );
1200    ok := IsXModMorphism( mor );
1201   # ok := IsSourceMorphism( mor );
1202    return mor;
1203end );
1204
1205##############################################################################
1206##
1207#M  PreCat1GroupMorphismByGroupHomomorphisms( <P>, <Q>, <hsrc>, <hrng> )
1208##
1209InstallMethod( PreCat1GroupMorphismByGroupHomomorphisms,
1210    "for pre-cat1-group, pre-cat1-group, homomorphism, homomorphism,", true,
1211    [IsPreCat1Group,IsPreCat1Group,IsGroupHomomorphism,IsGroupHomomorphism], 0,
1212function( src, rng, srchom, rnghom )
1213
1214    local filter, fam, mor, ok, nsrc, nrng, name;
1215
1216    mor := Make2DimensionalGroupMorphism( [ src, rng, srchom, rnghom ] );
1217    if not ( ( mor <> fail ) and IsPreCat1GroupMorphism( mor ) ) then
1218        Info( InfoXMod, 2, "not a morphism of pre-cat1 groups\n" );
1219        return fail;
1220    fi;
1221    if ( HasName( Source(src) ) and HasName( Range(src) ) ) then
1222        nsrc := Name( src );
1223    else
1224        nsrc := "[..]";
1225    fi;
1226    if ( HasName( Source(rng) ) and HasName( Range(rng) ) ) then
1227        nrng := Name( rng );
1228    else
1229        nrng := "[..]";
1230    fi;
1231    name := Concatenation( "[", nsrc, " => ", nrng, "]" );
1232    SetName( mor, name );
1233    ok := IsCat1GroupMorphism( mor );
1234    return mor;
1235end );
1236
1237#############################################################################
1238##
1239#M  Cat1GroupMorphismByGroupHomomorphisms( <Cs>, <Cr>, <hsrc>, <hrng> ) . . . make cat1 morphism
1240##
1241InstallMethod( Cat1GroupMorphismByGroupHomomorphisms, "for 2 cat1s and 2 homomorphisms", true,
1242    [ IsCat1Group, IsCat1Group, IsGroupHomomorphism, IsGroupHomomorphism ], 0,
1243function( src, rng, srchom, rnghom )
1244
1245    local mor, ok;
1246
1247    mor := PreCat1GroupMorphismByGroupHomomorphisms( src, rng, srchom, rnghom );
1248    ok := not ( mor = fail ) and IsCat1GroupMorphism( mor );
1249    if not ok then
1250        return fail;
1251    fi;
1252    return mor;
1253end );
1254
1255#############################################################################
1256##
1257#M  String, ViewString, PrintString, ViewObj, PrintObj
1258##  . . . . . . . . . . . . . . . . . . . . for a morphism of pre-cat1 groups
1259##
1260InstallMethod( String, "method for a morphism of pre-cat1 groups", true,
1261    [ IsPreCat1GroupMorphism ], 0,
1262function( mor )
1263    return( STRINGIFY( "[", String( Source(mor) ), " => ",
1264                            String( Range(mor) ), "]" ) );
1265end );
1266
1267InstallMethod( ViewString, "method for a morphism of pre-cat1 groups", true,
1268    [ IsPreCat1GroupMorphism ], 0, String );
1269
1270InstallMethod( PrintString, "fmethod for a morphism of pre-cat1 groups", true,
1271    [ IsPreCat1GroupMorphism ], 0, String );
1272
1273InstallMethod( ViewObj, "method for a morphism of pre-cat1 groups", true,
1274    [ IsPreCat1GroupMorphism ], 0,
1275function( mor )
1276    if HasName( mor ) then
1277        Print( Name( mor ), "\n" );
1278    else
1279        Print( "[", Source( mor ), " => ", Range( mor ), "]" );
1280    fi;
1281end );
1282
1283InstallMethod( PrintObj, "method for a morphism of pre-cat1 groups", true,
1284    [ IsPreCat1GroupMorphism ], 0,
1285function( mor )
1286    if HasName( mor ) then
1287        Print( Name( mor ), "\n" );
1288    else
1289        Print( "[", Source( mor ), " => ", Range( mor ), "]" );
1290    fi;
1291end );
1292
1293#############################################################################
1294##
1295#M  ReverseIsomorphism                                   for a pre-cat1-group
1296##
1297InstallMethod( ReverseIsomorphism, "method for a cat1-group", true,
1298    [ IsPreCat1Group ], 0,
1299function( C1G )
1300
1301    local rev, shom, rhom, src, gensrc, t, h, e, im;
1302
1303    rev := ReverseCat1Group( C1G );
1304    src := Source( C1G );
1305    gensrc := GeneratorsOfGroup( src );
1306    t := TailMap( C1G );
1307    h := HeadMap( C1G );
1308    e := RangeEmbedding( C1G );
1309    im := List( gensrc,
1310        g -> ImageElm( e, ImageElm(h,g) )*g^-1*ImageElm( e, ImageElm(t,g) ) );
1311    shom := GroupHomomorphismByImages( src, src, gensrc, im );
1312    rhom := IdentityMapping( Range( C1G ) );
1313    return PreCat1GroupMorphismByGroupHomomorphisms( C1G, rev, shom, rhom );
1314end );
1315
1316##############################################################################
1317##
1318#M  IsInjective( map ) . . . . . . . . . . . . . .  for a 2Dimensional-mapping
1319##
1320InstallOtherMethod( IsInjective,
1321    "method for a 2d-mapping", true, [ Is2DimensionalMapping ], 0,
1322    map -> (     IsInjective( SourceHom( map ) )
1323             and IsInjective( RangeHom( map ) ) )  );
1324
1325##############################################################################
1326##
1327#M  IsSurjective( map ) . . . . . . . . . . . . . . for a 2Dimensional-mapping
1328##
1329InstallOtherMethod( IsSurjective,
1330    "method for a 2d-mapping", true, [ Is2DimensionalMapping ], 0,
1331    map -> (     IsSurjective( SourceHom( map ) )
1332             and IsSurjective( RangeHom( map ) ) )  );
1333
1334##############################################################################
1335##
1336#M  IsSingleValued( map ) . . . . . . . . . . . . . for a 2Dimensional-mapping
1337##
1338InstallOtherMethod( IsSingleValued,
1339    "method for a 2d-mapping", true, [ Is2DimensionalMapping ], 0,
1340    map -> (     IsSingleValued( SourceHom( map ) )
1341             and IsSingleValued( RangeHom( map ) ) )  );
1342
1343##############################################################################
1344##
1345#M  IsTotal( map ) . . . . . . . . . . . . . . . .  for a 2Dimensional-mapping
1346##
1347InstallOtherMethod( IsTotal,
1348    "method for a 2d-mapping", true, [ Is2DimensionalMapping ], 0,
1349    map -> (     IsTotal( SourceHom( map ) )
1350             and IsTotal( RangeHom( map ) ) )  );
1351
1352##############################################################################
1353##
1354#M  IsBijective( map ) . . . . . . . . . . . . . .  for a 2Dimensional-mapping
1355##
1356InstallOtherMethod( IsBijective,
1357    "method for a 2d-mapping", true, [ Is2DimensionalMapping ], 0,
1358    map -> (     IsBijective( SourceHom( map ) )
1359             and IsBijective( RangeHom( map ) ) )  );
1360
1361##############################################################################
1362##
1363#M  IsEndomorphism2DimensionalDomain( map ) . . . . for a 2Dimensional-mapping
1364#?  temporary fix 08/01/04  ---  need to check correctness
1365#M  IsAutomorphism2DimensionalDomain( map ) . . . . for a 2Dimensional-mapping
1366##
1367InstallMethod( IsEndomorphism2DimensionalDomain,
1368    "method for a 2d-mapping", true, [ Is2DimensionalMapping ], 0,
1369    map -> IsEndoMapping( SourceHom( map ) ) and
1370           IsEndoMapping( RangeHom( map ) ) );
1371
1372InstallMethod( IsAutomorphism2DimensionalDomain,
1373    "method for a 2d-mapping", true, [ Is2DimensionalMapping ], 0,
1374    map ->  IsEndomorphism2DimensionalDomain( map ) and IsBijective( map ) );
1375
1376##############################################################################
1377##
1378#M  IsSourceMorphism( mor ) . . . . . . . . . . . . . . . for an xmod morphism
1379##
1380InstallMethod( IsSourceMorphism,
1381    "method for a morphism of crossed modules",
1382    true,
1383    [ IsXModMorphism ], 0,
1384function( mor )
1385
1386    local Srng, Rrng;
1387
1388    Srng := Range( Source( mor ) );
1389    Rrng := Range( Range( mor ) );
1390    return ( ( Srng = Rrng ) and
1391             ( RangeHom( mor ) = IdentityMapping( Srng ) ) );
1392end );
1393
1394##############################################################################
1395##
1396#M  Kernel . . . . . . of morphisms of pre-crossed modules and pre-cat1-groups
1397##
1398InstallOtherMethod( Kernel, "generic method for 2d-mappings",
1399     true, [ Is2DimensionalMapping ], 0,
1400function( map )
1401
1402    local kerS, kerR, K;
1403
1404    if HasKernel2DimensionalMapping( map ) then
1405        return Kernel2DimensionalMapping( map );
1406    fi;
1407    kerS := Kernel( SourceHom( map ) );
1408    kerR := Kernel( RangeHom( map ) );
1409    K := Sub2DimensionalGroup( Source( map ), kerS, kerR );
1410    SetKernel2DimensionalMapping( map, K );
1411    return K;
1412end );
1413
1414##############################################################################
1415##
1416#M  PreXModBySourceHom        top PreXMod from a morphism of crossed P-modules
1417##
1418InstallMethod( PreXModBySourceHom, "for a pre-crossed module morphism",
1419    true, [ IsPreXModMorphism ], 0,
1420function( mor )
1421
1422    local X1, X2, src1, rng1, src2, rng2, bdy2, y, z, S, Sbdy, Saut,
1423          gensrc1, genrng1, gensrc2, ngrng1, ngsrc2, inn, innaut,
1424          act, images, idsrc1, idrng1, isconj;
1425
1426    X1 := Source( mor );
1427    X2 := Range( mor );
1428    src1 := Source( X1 );
1429    src2 := Source( X2 );
1430    rng1 := Range( X1 );
1431    rng2 := Range( X2 );
1432    idsrc1 := InclusionMappingGroups( src1, src1 );
1433    idrng1 := InclusionMappingGroups( rng1, rng1 );
1434
1435    if   not ( rng1 = rng2 )
1436      or not ( RangeHom( mor ) = idrng1 ) then
1437        Info( InfoXMod, 2,
1438              "Not a morphism of crossed modules having a common range" );
1439        return fail;
1440    fi;
1441    gensrc1 := GeneratorsOfGroup( src1 );
1442    genrng1 := GeneratorsOfGroup( rng1 );
1443    gensrc2 := GeneratorsOfGroup( src2 );
1444    ngrng1 := Length( genrng1 );
1445    ngsrc2 := Length( gensrc2 );
1446    bdy2 := Boundary( X2 );
1447    innaut := [ ];
1448    for y in gensrc2 do
1449        z := ImageElm( bdy2, y );
1450        images := List( gensrc1, x -> x^z );
1451        inn := GroupHomomorphismByImages( src1, src1, gensrc1, images );
1452        Add( innaut, inn );
1453    od;
1454    Saut := Group( innaut, idsrc1 );
1455    act := GroupHomomorphismByImages( src2, Saut, gensrc2, innaut );
1456    S := XModByBoundaryAndAction( SourceHom( mor ), act );
1457    isconj := IsNormalSubgroup2DimensionalGroup( S );
1458    return S;
1459end );
1460
1461############################################################################
1462##
1463#M  XModMorphismOfCat1GroupMorphism
1464#M  Cat1GroupMorphismOfXModMorphism
1465##
1466InstallMethod( XModMorphismOfCat1GroupMorphism, "for a cat1-group morphism",
1467    true, [ IsCat1GroupMorphism ], 0,
1468function( phi )
1469
1470    local C1, C2, C1src, genC1src, e2, t2, proj2,
1471          X1, X2, X1src, X1rng, X2src, X2rng,
1472          genX1src, genX1rng, ek1, eksrc1, sphi, rphi, x,
1473          imrphi, imsphi, im, images, smor, mor, info1, info2;
1474
1475    C1 := Source( phi );
1476    C2 := Range( phi );
1477    C1src := Source( C1 );
1478    X1 := XModOfCat1Group( C1 );
1479    X2 := XModOfCat1Group( C2 );
1480    X1src := Source( X1 );
1481    X1rng := Range( X1 );
1482    X2src := Source( X2 );
1483    X2rng := Range( X2 );
1484    ek1 := KernelEmbedding( C1 );
1485    t2 := TailMap( C2 );
1486    e2 := RangeEmbedding( C2 );
1487    proj2 := Projection( Source( C2 ) );
1488    genC1src := GeneratorsOfGroup( C1src );
1489    genX1src := GeneratorsOfGroup( X1src );
1490    genX1rng := GeneratorsOfGroup( X1rng );
1491    sphi := SourceHom( phi );
1492    rphi := RangeHom( phi );
1493    imrphi := List( genX1rng, r -> ImageElm( rphi, r ) );
1494#    imgen := List( gensrc1, x -> SemidirectProductElement( (), (), x ) );
1495    eksrc1 := List( genX1src, s -> ImageElm( ek1, s ) );
1496    imsphi := List( eksrc1, g -> ImageElm( sphi, g ) );
1497    im := List( imsphi, x -> ImageElm( sphi, x ) );
1498    images := List( im,
1499        x -> ImageElm( proj2, ImageElm(e2,ImageElm(t2,x^-1)) * x ) );
1500    smor := GroupHomomorphismByImages( X1src, X2src, genX1src, images );
1501    mor := XModMorphismByGroupHomomorphisms( X1, X2, smor, rphi );
1502    SetXModMorphismOfCat1GroupMorphism( phi, mor );
1503    SetCat1GroupMorphismOfXModMorphism( mor, phi );
1504    return mor;
1505end );
1506
1507InstallMethod( Cat1GroupMorphismOfXModMorphism, "for an xmod morphism",
1508    true, [ IsXModMorphism ], 0,
1509function( mor )
1510
1511    local X1, X2, rec1, rec2, C1, C2, G1, G2, smor, rmor, semb1, remb1,
1512          semb2, remb2, isemb1, iremb1, geneS1, geneR1, genG1, imeS1, imeR1,
1513          imsphi, sphi, phi;
1514
1515    X1 := Source( mor );
1516    X2 := Range( mor );
1517    rec1 := PreCat1GroupOfPreXMod( X1 );
1518    rec2 := PreCat1GroupOfPreXMod( X2 );
1519    C1 := rec1.precat1;
1520    C2 := rec2.precat1;
1521    G1 := Source( C1 );
1522    G2 := Source( C2 );
1523    smor := SourceHom( mor );
1524    rmor := RangeHom( mor );
1525    semb1 := rec1.xmodSourceEmbeddingIsomorphism;
1526    remb1 := rec1.xmodRangeEmbeddingIsomorphism;
1527    semb2 := rec2.xmodSourceEmbeddingIsomorphism;
1528    remb2 := rec2.xmodRangeEmbeddingIsomorphism;
1529    isemb1 := RestrictedInverseGeneralMapping( semb1 );
1530    iremb1 := RestrictedInverseGeneralMapping( remb1 );
1531    geneS1 := GeneratorsOfGroup( rec1.xmodSourceEmbedding );
1532    geneR1 := GeneratorsOfGroup( rec1.xmodRangeEmbedding );
1533    genG1 := Concatenation( geneR1, geneS1 );
1534    imeS1 := List( geneS1, s -> ImageElm( semb2,
1535                                ImageElm( smor,
1536                                ImageElm( isemb1, s ) ) ) );
1537    imeR1 := List( geneR1, r -> ImageElm( remb2,
1538                                ImageElm( rmor,
1539                                ImageElm( iremb1, r ) ) ) );
1540    imsphi := Concatenation( imeR1, imeS1 );
1541    sphi := GroupHomomorphismByImages( G1, G2, genG1, imsphi );
1542    phi := Cat1GroupMorphismByGroupHomomorphisms( C1, C2, sphi, rmor );
1543    SetCat1GroupMorphismOfXModMorphism( mor, phi );
1544    SetXModMorphismOfCat1GroupMorphism( phi, mor );
1545    return phi;
1546end );
1547
1548##############################################################################
1549##
1550#F  SmallerDegreePerm2DimensionalGroup( <obj> )
1551##
1552InstallGlobalFunction( SmallerDegreePerm2DimensionalGroup, function( obj )
1553
1554    local src, rng, sigma, rho, mor;
1555
1556    # for a PreXMod
1557    if ( IsPreXMod( obj ) and IsPermPreXMod( obj ) ) then
1558        src := Source( obj );
1559        rng := Range( obj );
1560        sigma := SmallerDegreePermutationRepresentation( src );
1561        rho := SmallerDegreePermutationRepresentation( rng );
1562        mor := IsomorphismByIsomorphisms( obj, [ sigma, rho ] );
1563        return mor;
1564    fi;
1565    # alternatives not allowed
1566    Info( InfoXMod, 2, "at present only implemented for a PermPreXMod" );
1567    return fail;
1568end );
1569
1570##############################################################################
1571##
1572#M  IsomorphismXModByNormalSubgroup
1573##
1574InstallMethod( IsomorphismXModByNormalSubgroup,
1575    "for xmod with injective boundary", true, [ IsXMod ], 0,
1576function( X0 )
1577
1578    local S0, R, S1, bdy0, sigma, rho, ok;
1579
1580    S0 := Source( X0 );
1581    R := Range( X0 );
1582    bdy0 := Boundary( X0 );
1583    if not IsInjective( bdy0 ) then
1584        Info( InfoXMod, 2, "boundary is not injective" );
1585        return fail;
1586    fi;
1587    if IsSubgroup( S0, R ) then
1588        return IdentityMapping( X0 );
1589    else
1590        S1 := ImagesSource( bdy0 );
1591        sigma := GeneralRestrictedMapping( bdy0, S0, S1 );
1592        rho := IdentityMapping( R );
1593        ok := IsBijective( sigma ) and IsBijective( rho );
1594        return IsomorphismByIsomorphisms( X0, [ sigma, rho ] );
1595    fi;
1596end );
1597
1598##############################################################################
1599##
1600#M  Order . . . . . . . . . . . . . . . . . . . . . for a 2Dimensional-mapping
1601##
1602InstallOtherMethod( Order, "generic method for 2d-mapping",
1603    true, [ Is2DimensionalMapping ], 0,
1604function( mor )
1605    if not ( IsEndomorphism2DimensionalDomain( mor )
1606             and IsBijective( mor ) ) then
1607       Info( InfoXMod, 2, "mor is not an automorphism" );
1608       return fail;
1609    fi;
1610    return Lcm( Order( SourceHom( mor ) ), Order( RangeHom( mor ) ) );
1611end );
1612
1613#############################################################################
1614##
1615#M  ImagesSource( <mor> ) . . . . . . . . for pre-xmod and pre-cat1 morphisms
1616##
1617InstallOtherMethod( ImagesSource, "image for a pre-xmod or pre-cat1 morphism",
1618    true, [ Is2DimensionalMapping ], 0,
1619function( mor )
1620
1621    local Shom, Rhom, imS, imR, sub;
1622
1623    Shom := SourceHom( mor );
1624    Rhom := RangeHom( mor );
1625    imS := ImagesSource( Shom );
1626    imR := ImagesSource( Rhom );
1627    sub := Sub2DimensionalGroup( Range(mor), imS, imR );
1628    return sub;
1629end );
1630
1631###############################################################################
1632##
1633#M  AllCat1GroupMorphisms  . . . . . . morphisms from one cat1-group to another
1634##
1635InstallMethod( AllCat1GroupMorphisms, "for two cat1-groups", true,
1636    [ IsCat1Group, IsCat1Group ], 0,
1637function( C1G1, C1G2 )
1638
1639    local G1, R1, G2, R2, homG, homR, mors, gamma, rho, mor;
1640
1641    G1 := Source( C1G1 );
1642    R1 := Range( C1G1 );
1643    G2 := Source( C1G2 );
1644    R2 := Range( C1G2 );
1645    homG := AllHomomorphisms( G1, G2 );
1646    homR := AllHomomorphisms( R1, R2 );
1647    mors := [ ];
1648    for gamma in homG do
1649        for rho in homR do
1650            mor := PreCat1GroupMorphismByGroupHomomorphisms(
1651                        C1G1, C1G2, gamma, rho );
1652            if ( not( mor = fail ) and IsCat1GroupMorphism( mor ) ) then
1653                Add( mors, mor );
1654            fi;
1655        od;
1656    od;
1657    return mors;
1658end );
1659