home *** CD-ROM | disk | FTP | other *** search
- #############################################################################
- ##
- #A lattperm.g GAP library J\"urgen Mnich
- ##
- #A @(#)$Id: lattperm.g,v 3.4 1993/02/09 14:25:55 martin Rel $
- ##
- #Y Copyright 1990-1992, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany
- ##
- ## This file contains the permutation group specifications for calculating
- ## the lattice of subgroups.
- ##
- #H $Log: lattperm.g,v $
- #H Revision 3.4 1993/02/09 14:25:55 martin
- #H made undefined globals local
- #H
- #H Revision 3.3 1992/03/17 12:31:20 jmnich
- #H minor style changes, more bug fixes
- #H
- #H Revision 3.2 1992/02/29 13:25:11 jmnich
- #H general library review, some bug fixes
- #H
- #H Revision 3.1 1992/02/12 15:37:22 martin
- #H initial revision under RCS
- #H
- ##
-
-
- #############################################################################
- ##
- #F PermGroupOps.Zuppos( <group> ) . . . . . . . . . . . . . compute zuppos
- ##
- ## This functions handles the special case for zuppo calculation when the
- ## given group is a permutation group. In this case there is an internal
- ## function 'SmallestGeneratorPerm' that is used here.
- ##
- PermGroupOps.Zuppos := function( group )
- local zuppos, zuppo_gens, zuppo_powers, zuppo_primes, zuppo_exponents,
- nz, zg, elems, pos, cyc, known, order, forder, good, bad, x, p;
-
- if IsParent( group ) then
-
- # initialize the calculated data
-
- nz := 0;
- zuppos := [];
- zuppo_gens := [ false ];
- zuppo_powers := [];
- zuppo_primes := [];
- zuppo_exponents := [];
-
- # remember good and bad orders
-
- good := [];
- bad := [ 1 ];
-
- # sorry, but we will loop over all elements
-
- elems := Elements( group );
-
- for pos in [1..Length( elems )] do
-
- order := OrderPerm( elems[pos] );
-
- # check whether it yields a zuppo
-
- if not (order in good or order in bad) then
- if IsPrimePowerInt( order ) then
- AddSet( good, order );
- else
- AddSet( bad, order );
- fi;
- fi;
-
- if order in good then
-
- zg := SmallestGeneratorPerm( elems[pos] );
-
- if zg = elems[pos] then
-
- # we have found a new zuppo.
-
- forder := Factors( order );
-
- nz := nz + 1;
- zg := nz;
- AddSet( zuppos, elems[pos] );
- zuppo_primes[nz] := forder[1];
- zuppo_exponents[nz] := Length( forder );
- if zuppo_exponents[nz] = 1 then
- zuppo_powers[nz] := 1;
- else
- zuppo_powers[nz] := Position( elems, elems[pos] ^ forder[1] );
- fi;
-
- else
-
- zg := Position( zuppos, zg );
-
- fi;
-
- zuppo_gens[pos] := zg;
- fi;
- od;
-
- # correct the values in zuppo_powers to contain 'zuppos' elements
-
- for x in [1..nz] do
- zuppo_powers[x] := zuppo_gens[zuppo_powers[x]];
- od;
-
- group.zuppos := zuppos;
- group.zuppo_generators := zuppo_gens;
- group.zuppo_powers := zuppo_powers;
- group.zuppo_primes := zuppo_primes;
- group.zuppo_exponents := zuppo_exponents;
- group.conjugateZuppoBlist := BlistList( zuppos, [] );
-
- else
-
- zuppos := Intersection( Zuppos( Parent( group ) ), Elements( group ) );
-
- fi;
-
- Unbind( group.elements );
-
- return zuppos;
- end;
-
-
- PermGroupOps.PlainZuppos := function( group )
- local zuppos, zuppo_gens, zuppo_powers, zuppo_primes, zuppo_exponents,
- nz, zg, elems, pos, cyc, known, order, forder, good, bad, x, p;
-
- # initialize the calculated data
-
- nz := 0;
- zuppos := [];
- zuppo_gens := [ false ];
- zuppo_powers := [];
- zuppo_primes := [];
- zuppo_exponents := [];
-
- # remember good and bad orders
-
- good := [];
- bad := [ 1 ];
-
- # sorry, but we will loop over all elements
-
- elems := Elements( group );
-
- for pos in [1..Length( elems )] do
-
- order := OrderPerm( elems[pos] );
-
- # check whether it yields a zuppo
-
- if not (order in good or order in bad) then
- if IsPrimePowerInt( order ) then
- AddSet( good, order );
- else
- AddSet( bad, order );
- fi;
- fi;
-
- if order in good then
-
- zg := SmallestGeneratorPerm( elems[pos] );
-
- if zg = elems[pos] then
-
- # we have found a new zuppo.
-
- forder := Factors( order );
-
- nz := nz + 1;
- zg := nz;
- AddSet( zuppos, elems[pos] );
- zuppo_primes[nz] := forder[1];
- zuppo_exponents[nz] := Length( forder );
- if zuppo_exponents[nz] = 1 then
- zuppo_powers[nz] := 1;
- else
- zuppo_powers[nz] := Position( elems, elems[pos] ^ forder[1] );
- fi;
-
- else
-
- zg := Position( zuppos, zg );
-
- fi;
-
- zuppo_gens[pos] := zg;
- fi;
- od;
-
- # correct the values in zuppo_powers to contain 'zuppos' elements
-
- for x in [1..nz] do
- zuppo_powers[x] := zuppo_gens[zuppo_powers[x]];
- od;
-
- group.zuppos := zuppos;
- group.zuppo_generators := zuppo_gens;
- group.zuppo_powers := zuppo_powers;
- group.zuppo_primes := zuppo_primes;
- group.zuppo_exponents := zuppo_exponents;
- group.conjugateZuppoBlist := BlistList( zuppos, [] );
-
- Unbind( group.elements );
-
- return zuppos;
- end;
-
-
- PermGroupOps.SylowZuppos := function( group )
- local zuppos, zuppo_gens, zuppo_powers, zuppo_primes, zuppo_exponents,
- g, p, S, Szup, zuporb, N, T, t, i;
-
- zuppos := [];
- zuppo_gens := [ false ];
- zuppo_powers := [];
- zuppo_primes := [];
- zuppo_exponents := [];
-
- for p in Set( Factors( Size( group ) ) ) do
-
- InfoLattice1( "#I Prime ", p, "\n" );
-
- S := SylowSubgroup( group, p );
- Szup := S.operations.PlainZuppos( S );
- zuporb := [];
-
- InfoLattice1( "#I ", Length( Szup ), " Zuppos\n" );
-
- for g in Szup do
-
- # Zuppos of S may be conjugate, so test first if g is new
-
- if not g in zuporb then
-
- N := group.operations.Normalizer( group,
- Subgroup( group, [ g ] ) );
- MakeStabChain( N, group.operations.Base( group ) );
- ExtendStabChain( N, group.operations.Base( group ) );
- T := group.operations.RightCosetRepsStab( group, N );
-
- InfoLattice1( "#I ", Length( T ), " conjugates\n" );
-
- for t in T do
- AddSet( zuporb, SmallestGeneratorPerm( g ^ t ) );
- od;
- fi;
- od;
-
- UniteSet( zuppos, zuporb );
- od;
-
- InfoLattice1( "#I calculating powers...\n" );
-
- zuppo_powers := ShallowCopy( zuppos );
- for i in [1..Length( zuppos )] do
- p := Factors( OrderPerm( zuppos[i] ) )[1];
- g := zuppos[i] ^ p;
- if g <> group.identity then
- zuppo_powers[i] := Position( zuppos, SmallestGeneratorPerm( g ) );
- else
- zuppo_powers[i] := false;
- fi;
- od;
-
- InfoLattice1( "#I ...done\n" );
-
- group.zuppos := zuppos;
- group.zuppo_generators := zuppo_gens;
- group.zuppo_powers := zuppo_powers;
- group.zuppo_primes := zuppo_primes;
- group.zuppo_exponents := zuppo_exponents;
- group.conjugateZuppoBlist := BlistList( zuppos, [] );
-
- return zuppos;
- end;
-
-
- #############################################################################
- ##
- #F PermGroupOps.ZuppoBlist( <group> ) . . . . . . . compute blist of zuppos
- ##
- ## This functions computes the zuppos of a group represented as a blist on
- ## the zuppos of the parent group.
- ##
- PermGroupOps.ZuppoBlist := function( group )
- local zuppob, rng;
-
- if IsParent( group ) then
- rng := [1 .. Length( Zuppos( group ) )];
- zuppob := BlistList( rng, rng );
- elif IsBound( group.zuppos ) then
- zuppob := BlistList( Zuppos( Parent( group ) ), group.zuppos );
- else
- zuppob := BlistList( Zuppos( Parent( group ) ), Elements( group ) );
- Unbind( group.elements );
- fi;
-
- return zuppob;
- end;
-
-
- #############################################################################
- ##
- #F PermGroupOps.GeneratorZuppos . . . . . . determine zuppos for generators
- ##
- PermGroupOps.GeneratorZuppos := function( H )
- local g, facord, prm, coprm, p, gzup;
-
- gzup := [];
- for g in H.generators do
- facord := Factors( OrderPerm( g ) );
- for prm in Set( facord ) do
- coprm := 1;
- for p in facord do if p <> prm then coprm := coprm * p; fi; od;
- Add( gzup, SmallestGeneratorPerm( g ^ coprm ) );
- od;
- od;
- return gzup;
- end;
-
-
- #############################################################################
- ##
- #F PermGroupOps.GeneratorZuppoBlist . . determine zuppoblist for generators
- ##
- PermGroupOps.GeneratorZuppoBlist := function( H )
- local g, facord, prm, coprm, p, gzup, zuppos;
-
- zuppos := Zuppos( Parent( H ) );
- gzup := BlistList( zuppos, [] );
- for g in H.generators do
- facord := Factors( OrderPerm( g ) );
- for prm in Set( facord ) do
- coprm := 1;
- for p in facord do if p <> prm then coprm := coprm * p; fi; od;
- gzup[Position( zuppos, SmallestGeneratorPerm( g ^ coprm ) )] := true;
- od;
- od;
- return gzup;
- end;
-
-
- #############################################################################
- ##
- #F PermGroupOps.ConjugateZuppos( <group>, <conjugand> ) . . . . . . . . . .
- #F . . . . . . . . . . . . . . . . . . . . compute blist of conjugate zuppos
- ##
- ##
- ##
- PermGroupOps.ConjugateZuppos := function( H, g )
- local zuppos, zuppop, i;
-
-
- if g = H.identity then
- return Zuppos( H );
- fi;
-
- zuppop := Zuppos( Parent( H ) );
- zuppos := ShallowCopy( Zuppos( H ) );
- for i in [1..Length( zuppos )] do
- zuppos[i] := SmallestGeneratorPerm( zuppos[i] ^ g );
- od;
-
- return Set( zuppos );
- end;
-
-
- #############################################################################
- ##
- #F PermGroupOps.ConjugateZuppoBlist( <group>, <conjugand> ) . . . . . . . .
- #F . . . . . . . . . . . . . . . . . . . . compute blist of conjugate zuppos
- ##
- ##
- ##
- PermGroupOps.ConjugateZuppoBlist := function( H, g )
- local zuppob, zuppop, x;
-
- if g = H.identity then
- return ZuppoBlist( H );
- fi;
-
- zuppop := Zuppos( Parent( H ) );
- zuppob := Parent( H ).conjugateZuppoBlist;
- SubtractBlist( zuppob, zuppob );
- for x in Zuppos( H ) do
- zuppob[Position( zuppop, SmallestGeneratorPerm( x ^ g ) )] := true;
- od;
-
- return zuppob;
- end;
-
-
- #############################################################################
- ##
- #F PermGroupOps.SetLatticeStatus( <L>, <object>, <status> ) . . . . . . . .
- #F . . . . . . . . . . . . . . . . . . . . . . set status of lattice objects
- ##
- ## returns
- ##
- ## [ <class>, <conjugand>, <isnew> ]
- ##
- ##
- PermGroupOps.SetLatticeStatus := function( L, H, status )
- local G, CH, N, CN, C, CC, T, equals, qequals, subs, sups,
- hzup, czup, gzup, isnew, issup, size, nelem, pos, t, i, x;
-
-
- G := L.group;
-
- # the first step is to convert H to a conjugacy class of subgroups
- # if it is a group.
-
- if IsGroup( H ) then
-
- # determine its layer
-
- CH := ConjugacyClassSubgroups( G, H );
- size := Size( H );
-
- if size = 1 then CH.layer := 0;
- else CH.layer := Length( Factors( size ) );
- fi;
-
- CH.status := "0 new";
-
- else
-
- CH := H;
- H := CH.representative;
- size := Size( H );
-
- if not IsBound( CH.status ) then
- if size = 1 then CH.layer := 0;
- else CH.layer := Length( Factors( size ) );
- fi;
-
- CH.status := "0 new";
- fi;
-
- fi;
-
- InfoLattice2( "#I setstatus ", H, ", size ", size, " to ", status,
- "in layer ", CH.layer, "\n" );
-
- # if the status of the class is higher than the requested one,
- # return it itself.
-
- if CH.status >= status then
- return [ CH, G.identity, false ];
- fi;
-
- # find list of possibly equal classes
-
- if IsBound( CH.equalClasses ) then
-
- # this has been done already
-
- equals := CH.equalClasses;
-
- elif CH.status >= "2 class" then
-
- # there is no need to test for equality if the class has already
- # been added to the lattice.
-
- equals := [];
-
- else
-
- # o.k. now, go through the list of classes and have a look.
-
- gzup := GeneratorZuppoBlist( H );
- equals := [];
- for CC in L.classes do
- C := CC.representative;
- if C.size = size then
- if IsSubsetBlist( ZuppoBlist( C ), gzup ) then
-
- # we were able to identify the representative
-
- L.statistics.equalGroups := L.statistics.equalGroups + 1;
- if IsBound( CH.normalsubgroups ) then
- for x in CH.normalsubgroups do
- x.normalizerLattice := [ CC, G.identity ];
- od;
- fi;
- InfoLattice2( "#I ...found in lattice\n" );
- return [ CC, G.identity, false ];
-
- else
- Add( equals, CC );
- fi;
- fi;
- od;
- fi;
-
- # now go on and improve the objects status one by one.
- # first: shall we add the group to the queue ?
-
- if status = "1 group" then
-
- # make sure H is not already in the queue
-
- gzup := GeneratorZuppoBlist( H );
-
- for i in [1..Length( L.queue )] do
- if IsBound( L.queue[i] ) then
- CC := L.queue[i];
- C := CC.representative;
- if C.size = size then
- if IsSubsetBlist( ZuppoBlist( C ), gzup ) then
-
- # oh, yes. there is a queue group equal to ours.
-
- L.statistics.equalGroups := L.statistics.equalGroups + 1;
- if IsBound( CH.normalsubgroups ) then
- if not IsBound( CC.normalsubgroups ) then
- CC.normalsubgroups := [];
- fi;
- for x in CH.normalsubgroups do
- x.normalizerLattice := [ CC, G.identity ];
- Add( CC.normalsubgroups, x );
- od;
- fi;
- InfoLattice2( "#I ...found in queue\n" );
- return [ CC, G.identity, false ];
-
- fi;
- fi;
- fi;
- od;
-
- InfoLattice1( "#I ...added to queue\n" );
-
- CH.status := "1 group";
- CH.equalClasses := equals;
-
- Add( L.queue, CH );
-
- return [ CH, G.identity, false ];
- fi;
-
- # the class will have higher status than being a queue group so
- # remove the list of possibly equal classes.
-
- Unbind( CH.equalClasses );
-
- # second: shall we add the group to the lattice ?
-
- if CH.status < "2 class" and status >= "2 class" then
-
- # if we have to create the class we need the normalizer of H
- # and its (right) transversal in G.
-
- InfoLattice2( "#I calculating normalizer of H\n" );
-
- N := G.operations.Normalizer( G, H );
- CN := ConjugacyClassSubgroups( G, N );
- T := G.operations.RightTransversal( G, N );
-
- L.statistics.normalizers := L.statistics.normalizers + 1;
-
- CN.normalsubgroups := [ CH ];
- CH.normalizerLattice := [ CN, G.identity ];
- CH.conjugands := T;
- CH.size := Length( T );
-
- if Size( N ) <> size then
-
- InfoLattice2( "#I handling normalizer\n" );
-
- isnew := SetLatticeStatus( L, CN, L.calculatedGroups );
- CH.normalizerLattice := [ isnew[1], isnew[2] ];
- isnew := isnew[3];
-
- else
-
- InfoLattice2( "#I group is selfnormal -- no handling\n" );
-
- CH.normalizerLattice := [ CH, G.identity ];
- isnew := false;
-
- fi;
-
- # if H's normalizer wasn't known before, H itself must be new.
-
- if isnew then
- equals := [];
- fi;
-
- # we continue with the determination of possible subgroups...
-
- subs := [];
- for CC in L.classes do
- C := CC.representative;
- if CC.layer = CH.layer - 1 and CC.status = "3 extending"
- and size mod C.size = 0 then
- Add( subs, CC );
- fi;
- od;
-
- # ... and the possibly equal queue groups
-
- gzup := GeneratorZuppoBlist( H );
- qequals := [];
- for i in [1..Length( L.queue )] do
- if IsBound( L.queue[i] ) then
- CC := L.queue[i];
- C := CC.representative;
- if C.size = size then
- if IsSubsetBlist( ZuppoBlist( C ), gzup ) then
-
- # oh, there is a group in the queue equal to ours.
-
- L.statistics.equalGroups := L.statistics.equalGroups + 1;
- if IsBound( CC.normalsubgroups ) then
- if not IsBound( CH.normalsubgroups ) then
- CH.normalsubgroups := [];
- fi;
- for x in CC.normalsubgroups do
- x.normalizerLattice := [ CH, G.identity ];
- Add( CH.normalsubgroups, x );
- od;
- fi;
- InfoLattice2( "#I ...found in queue\n" );
- Unbind( L.queue[i] );
-
- else
- Add( qequals, i );
- fi;
- fi;
- fi;
- od;
-
- # is there anything to do with the conjugates so far ?
-
- if equals = [] and qequals = [] and subs = [] then
- T := [];
- fi;
-
- # generate each conjugate, i.e. its zuppos one after the other,
- # performing all necessary actions with each zuppo blist right
- # here.
-
- InfoLattice2( "#I conjugating H\n" );
-
- for t in T do
-
- czup := H.operations.ConjugateZuppoBlist( H, t );
- L.statistics.conjugateZuppos := L.statistics.conjugateZuppos + 1;
-
- # first check whether this conjugate is the representative of a
- # known class of subgroups
-
- for CC in equals do
- C := CC.representative;
- if ZuppoBlist( C ) = czup then
-
- # in fact there is a class that contains the conjugate
-
- L.statistics.equalGroups := L.statistics.equalGroups + 1;
- if IsBound( CH.normalsubgroups ) then
- for x in CH.normalsubgroups do
- x.normalizerLattice := [ CC, t^-1 * x.normalizerLattice[2] ];
- od;
- fi;
- InfoLattice2( "#I ...found in lattice\n" );
- return [ CC, t^-1, false ];
-
- fi;
- od;
-
- # next check whether this group is a member of the queue
-
- for i in qequals do
- if IsBound( L.queue[i] ) then
- CC := L.queue[i];
- C := CC.representative;
- if ZuppoBlist( C ) = czup then
-
- # bingo, we found a group in the queue equal to the
- # conjugate of H.
-
- L.statistics.equalGroups := L.statistics.equalGroups + 1;
- if IsBound( CC.normalsubgroups ) then
- if not IsBound( CH.normalsubgroups ) then
- CH.normalsubgroups := [];
- fi;
- for x in CC.normalsubgroups do
- x.normalizerLattice := [ CH, t ];
- Add( CH.normalsubgroups, x );
- od;
- fi;
- InfoLattice2( "#I identified queue group\n" );
- Unbind( L.queue[i] );
-
- fi;
- fi;
- od;
-
- # next reduce the extendingZuppos blists of those classes that are
- # yet to be extended and whose representative may be a subgroup
- # of this conjugate.
-
- for CC in subs do
- C := CC.representative;
- if IsSubsetBlist( czup, ZuppoBlist( C ) ) then
- InfoLattice2( "#I found a subgroup\n" );
- SubtractBlist( CC.extendingZuppos, czup );
- fi;
- od;
- od;
-
- # the group survived this step, so it is new
-
- CH.status := "2 class";
-
- Unbind( CH.normalsubgroups );
- #T Unbind( CH.conjugands );
- Add( L.classes, CH );
-
- InfoLattice1( "#I Class of size ", size, " and length ", CH.size, " added\n" );
- fi;
-
- # third: shall the extendingZuppos blist of the class be created ?
-
- if CH.status < "3 extending" and status >= "3 extending"
- and not LatticeBreak then
-
- # initialize the extendingZuppos blist
-
- CH.extendingZuppos := ShallowCopy(
- CH.normalizerLattice[1].representative.operations.ConjugateZuppoBlist(
- CH.normalizerLattice[1].representative,
- CH.normalizerLattice[2]
- )
- );
- SubtractBlist( CH.extendingZuppos, ZuppoBlist( H ) );
- L.statistics.conjugateZuppos := L.statistics.conjugateZuppos + 1;
-
- # change it to reflect the proper list of extending zuppos.
-
- gzup := GeneratorZuppos( H );
-
- for CC in L.classes do
- C := CC.representative;
- if CC.layer = CH.layer + 1 and C.size mod size = 0 then
- T := CC.conjugands;
- czup := ZuppoBlist( C );
- for t in T do
- issup := true;
- i := Length( gzup );
- x := t ^ -1;
- while issup and i > 0 do
- issup := czup[Position( G.zuppos, SmallestGeneratorPerm( gzup[i]^x ) )];
- i := i - 1;
- od;
- if issup then
- InfoLattice2( "#I supergroup found\n" );
- SubtractBlist( CH.extendingZuppos, C.operations.ConjugateZuppoBlist( C, t ) );
- L.statistics.conjugateZuppos := L.statistics.conjugateZuppos + 1;
- fi;
- od;
- fi;
- od;
-
- CH.status := "3 extending";
- fi;
-
- # fourth: shall we calculate all cyclic extensions of H ?
-
- if CH.status < "4 extended" and status >= "4 extended"
- and not LatticeBreak then
-
- InfoLattice2( "#I calculating extensions of H\n" );
-
- hzup := ZuppoBlist( H );
- pos := Position( CH.extendingZuppos, true );
-
- while pos <> false and not LatticeBreak do
-
- # is the zuppo generator of prime index over H ?
-
- if G.zuppo_powers[pos] = false or hzup[G.zuppo_powers[pos]] then
-
- # put everything we know into N
-
- N := G.operations.Subgroup( G, Concatenation( H.generators, [ G.zuppos[pos] ] ) );
- CN := ConjugacyClassSubgroups( G, N );
- CN.equalClasses := [];
-
- # finally, add it to the lattice
-
- SetLatticeStatus( L, CN, L.extensionGroups );
- L.statistics.extensions := L.statistics.extensions + 1;
- fi;
-
- CH.extendingZuppos[pos] := false;
- pos := Position( CH.extendingZuppos, true, pos );
- od;
-
- if not LatticeBreak then
-
- # cleanup H
-
- CH.status := "4 extended";
- Unbind( CH.extendingZuppos );
- Unbind( H.generatorZuppos );
- Unbind( H.generatorZuppoBlist );
- Unbind( H.elements );
-
- if not IsParent( H ) then
- Unbind( H.zuppos );
- Unbind( H.stabilizer );
- Unbind( H.orbit );
- Unbind( H.transversal );
- fi;
-
- InfoLattice2( "#I extensions of H done\n" );
- fi;
- fi;
-
- return [ CH, G.identity, true ];
- end;
-
-
- #############################################################################
- ##
- #F PermGroupOps.RightTransversal( <G>, <H> ) . determine a right transversal
- ##
- ## returns
- ##
- ## <list>
- ##
- PermGroupOps.RightTransversal := function( G, H )
-
- MakeStabChain( H, G.operations.Base( G ) );
- ExtendStabChain( H, G.operations.Base( G ) );
- return G.operations.RightCosetRepsStab( G, H );
- end;
-
-
- #############################################################################
- ##
- #E Emacs . . . . . . . . . . . . . . . . . . . . . . . local emacs variables
- ##
- ## Local Variables:
- ## mode: outline
- ## outline-regexp: "#F\\|#V\\|#E"
- ## fill-column: 73
- ## fill-prefix: "## "
- ## eval: (hide-body)
- ## End:
- ##
-