CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

Views: 418346
#############################################################################
####
##
#A  anupga.gi                   ANUPQ package                    Frank Celler
#A                                                           & Eamonn O'Brien
#A                                                           & Benedikt Rothe
##
##  Install file for p-group generation of automorphism group  functions  and
##  variables.
##
#Y  Copyright 1992-1994,  Lehrstuhl D fuer Mathematik,  RWTH Aachen,  Germany
#Y  Copyright 1992-1994,  School of Mathematical Sciences, ANU,     Australia
##

#############################################################################
##
#F  ANUPQerror( <param> ) . . . . . . . . . . . . .  report illegal parameter
##
InstallGlobalFunction( ANUPQerror, function( param )
    Error(
    "Valid Options:\n",
    "    \"ClassBound\", <bound>\n",
    "    \"OrderBound\", <order>\n",
    "    \"StepSize\", <size>\n",
    "    \"PcgsAutomorphisms\"\n",
    "    \"RankInitialSegmentSubgroups\", <rank>\n",
    "    \"SpaceEfficient\"\n",
    "    \"AllDescendants\"\n",
    "    \"Exponent\", <exponent>\n",
    "    \"Metabelian\"\n",
    "    \"SubList\"\n",
    "    \"SetupFile\", <file>\n",
    "Illegal Parameter: \"", param, "\"" );
end );

#############################################################################
##
#F  ANUPQextractArgs( <args>) . . . . . . . . . . . . . . parse argument list
##
InstallGlobalFunction( ANUPQextractArgs, function( args )
    local   CR,  i,  act,  G,  match;

    # allow to give only a prefix
    match := function( g, w )
    	return 1 < Length(g) and 
            Length(g) <= Length(w) and 
            w{[1..Length(g)]} = g;
     end;

    # extract arguments
    G  := args[1];
    CR := rec( group := G );
    i  := 2;
    while i <= Length(args)  do
        act := args[i];

        # "ClassBound", <class>
        if match( act, "ClassBound" )  then
            i := i + 1;
            CR.ClassBound := args[i];
            if CR.ClassBound <= PClassPGroup(G) then
                Error( "\"ClassBound\" must be at least ", PClassPGroup(G)+1 );
            fi;

        # "OrderBound", <order>
        elif match( act, "OrderBound" )  then
            i := i + 1;
            CR.OrderBound := args[i];

        # "StepSize", <size>
        elif match( act, "StepSize" )  then
            i := i + 1;
            CR.StepSize := args[i];

        # "PcgsAutomorphisms"
        elif match( act, "PcgsAutomorphisms" )  then
            CR.PcgsAutomorphisms := true;

        # "RankInitialSegmentSubgroups", <rank>
        elif match( act, "RankInitialSegmentSubgroups" )  then
            i := i + 1;
            CR.RankInitialSegmentSubgroups := args[i];

        # "SpaceEfficient"
        elif match( act, "SpaceEfficient" ) then
            CR.SpaceEfficient := true;

        # "AllDescendants"
        elif match( act, "AllDescendants" )  then
            CR.AllDescendants := true;

        # "Exponent", <exp>
        elif match( act, "Exponent" )  then
            i := i + 1;
            CR.Exponent := args[i];

        # "Metabelian"
        elif match( act, "Metabelian" ) then
            CR.Metabelian := true;

        # "Verbose"
        elif match( act, "Verbose" )  then
            CR.Verbose := true;

        # "SubList"
        elif match( act, "SubList" )  then
            i := i + 1;
            CR.SubList := args[i];

        # temporary directory
        elif match( act, "TmpDir" )  then
            i := i + 1;
            CR.TmpDir := args[i];

        # "SetupFile", <file>
        elif match( act, "SetupFile" )  then
            i := i + 1;
            CR.SetupFile := args[i];

        # signal an error
        else
            ANUPQerror( act );
        fi;
        i := i + 1;
    od;
    return CR;

end );

#############################################################################
##
#F  ANUPQauto( <G>, <gens>, <imgs> )  . . . . . . . .  construct automorphism
##
InstallGlobalFunction( ANUPQauto, function( G, gens, images )
   local   f;

   f := GroupHomomorphismByImagesNC( G, G, gens, images );
   SetIsBijective( f, true );
   SetKernelOfMultiplicativeGeneralMapping( f, TrivialSubgroup(G) );

   return f;
end );

#############################################################################
##
#F  ANUPQautoList( <G>, <gens>, <L> ) . . . . . . . construct a list of autos
##
InstallGlobalFunction( ANUPQautoList, function( G, gens, automs )
    local   D,  g,  igs,  auts,  i;

    # construct direct product elements
    D := [];
    for g  in [ 1 .. Length(gens) ]  do
	Add( D, DirectProductElement( automs{[1..Length(automs)]}[g] ) );
    od;

    # and compute the abstract igs simultaneously
    igs := InducedPcgsByGeneratorsWithImages( Pcgs(G), gens, D );
    gens := igs[1];
    D := igs[2];


    # construct the automorphisms
    auts := [];
    for i in [ 1 .. Length(automs) ]  do
	Add( auts, ANUPQauto( G, gens, D{[1..Length(gens)]}[i] ) );
    od;

    # and then the automorphisms
    return auts;

end );

#############################################################################
##
#F  ANUPQSetAutomorphismGroup( <G>, <gens>, <automs>, <isSoluble> ) 
##
InstallGlobalFunction( ANUPQSetAutomorphismGroup, 
function( G, gens, centralAutos, otherAutos, relativeOrders, isSoluble )

    SetANUPQAutomorphisms( G, 
            rec( gens := gens, 
                 centralAutos   := centralAutos, 
                 otherAutos     := otherAutos, 
                 relativeOrders := relativeOrders,
                 isSoluble      := isSoluble ) );

    return;

end );

#############################################################################
##
#F  PqSupplementInnerAutomorphisms( <G> ) 
##
##  returns   a   record   analogous   to   what   is   returned    by    the
##  `AutomorphismGroupPGroup' function of the {\AutPGrp} package, except that
##  only  the  fields  `agAutos',  `agOrder'  and  `glAutos'  are  set.   The
##  automorphisms generate a subgroup of the automorphism  group  of  the  pc
##  group <D> that supplements the inner automorphism group  of  <D>  in  the
##  whole automorphism group of <D>. The group of automorphisms returned  may
##  be a proper subgroup of the full automorphism group. The  descendant  <D>
##  must   have   been   computed    by    the    function    `PqDescendants'
##  (see~"PqDescendants").
##

##!!  Muss angepasst werden auf die jetzt besser verstandenen Anforderungen
##!!  an Automorphismen, n�mlich der Unterscheideung zwischen solchen, die
##!!  auf der Frattinigruppe treu operieren und solche, die dies nicht tuen.

InstallGlobalFunction( "PqSupplementInnerAutomorphisms",
function( G )
    local   gens,  automs,  A, centralAutos, otherAutos;

#Print( "Attention: the function PqSupplementInnerAutomorphisms()",
#       " is outdated and dangerous\n" );

    if not HasANUPQAutomorphisms( G ) then
        return Error( "group does not carry automorphism information" );
    fi;

    automs := ANUPQAutomorphisms( G );

    gens := automs.gens;

    centralAutos := ANUPQautoList( G, gens, automs.centralAutos );
    otherAutos   := ANUPQautoList( G, gens, automs.otherAutos );
    
    return rec( agAutos := centralAutos,
                agOrder := automs.relativeOrders,
                glAutos := otherAutos );

end );

#############################################################################
##
#F  ANUPQprintExps( <pqi>, <lst> ) . . . . . . . . . . .  print exponent list
##
InstallGlobalFunction( ANUPQprintExps, function( pqi, lst )
    local   first,  l,  j;

    l := Length(lst);
    first := true;
    for j  in [1 .. l]  do
        if lst[j] <> 0  then
          if not first  then
              AppendTo( pqi, "*" );
          fi;
          first := false;
          AppendTo( pqi, "g", j, "^", lst[j] );
        fi;
    od;
end );

#############################################################################
##
#V  ANUPGAGlobalVariables
##
InstallValue( ANUPGAGlobalVariables,
              [ "ANUPQgroups", 
                "ANUPQautos", 
                "ANUPQmagic" ] );

#############################################################################
##
#F  PqList( <file> [: SubList := <sub>]) . . . . .  get a list of descendants
##
InstallGlobalFunction( PqList, function( file )
    local   var,  lst,  groups,  autos,  sublist,  func;

    PQ_OTHER_OPTS_CHK("PqList", false);
    # check arguments
    if not IsString(file) then
        Error( "usage: PqList( <file> [: SubList := <sub>])\n" );
    fi;

    for var in ANUPGAGlobalVariables do
        HideGlobalVariables( var );
    od;

    # try to read <file>
    if not READ( file ) or not IsBoundGlobal( "ANUPQmagic" )  then

        for var in ANUPGAGlobalVariables do
            UnhideGlobalVariables( var );
        od;
        return false;
    fi;

    # <lst> will hold the groups
    lst := [];
    if IsBoundGlobal( "ANUPQgroups" ) then
        groups := ValueGlobal( "ANUPQgroups" );
        if IsBoundGlobal( "ANUPQautos" ) then
            autos := ValueGlobal( "ANUPQautos" );
        fi;

        sublist := VALUE_PQ_OPTION("SubList", [ 1 .. Length( groups ) ]);
        if not IsList(sublist) then
            sublist := [ sublist ];
        fi;

        for func  in sublist  do
            groups[func](lst);
            if IsBound( autos) and IsBound( autos[func] )  then
                autos[func]( lst[Length(lst)] );
            fi;
        od;
    fi;
    
    for var in ANUPGAGlobalVariables do
        UnhideGlobalVariables( var );
    od;

    # return the groups
    return lst;

end );

#############################################################################
##
#F  PqLetterInt( <n> ) . . . . . . . . . . . . . . . 
##
InstallGlobalFunction( PqLetterInt, function ( n )
    local  letters, str, x, d;
    letters := [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", 
        "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" ]
     ;
    if n < 1  then
        Error( "number must be positive" );
    elif n <= Length( letters )  then
        return letters[n];
    fi;
    str := "";
    n := n - 1;
    d := 1;
    repeat
        x := n mod Length( letters ) + d;
        str := Concatenation( letters[x], str );
        n := QuoInt( n, Length( letters ) );
        if n < 26  then
            d := 0;
        fi;
    until n < 1;
    return str;
end );

#############################################################################
##
#F  PQ_DESCENDANTS( <args> ) . . . . . . . . . construct descendants of group
##
InstallGlobalFunction( PQ_DESCENDANTS, function( args )
    local   datarec, p, class, G, ndescendants;

    datarec := ANUPQ_ARG_CHK("PqDescendants", args);
    if datarec.calltype = "interactive" and IsBound(datarec.descendants) then
        Info(InfoANUPQ, 1, 
             "`PqDescendants' should not be called more than once for the");
        Info(InfoANUPQ, 1, 
             "same process ... returning previously computed descendants.");
        return datarec.descendants;
    elif datarec.calltype = "GAP3compatible" then
        # ANUPQ_ARG_CHK calls PQ_DESCENDANTS itself in this case
        # (so datarec.descendants has already been computed)
        return datarec.descendants;
    fi;

    PQ_AUT_GROUP(datarec.group); # make sure we have the aut. grp.

    # if <G> is not capable and we want to compute something, return
    if HasIsCapable(datarec.group) and not IsCapable(datarec.group) and 
       VALUE_PQ_OPTION("SetupFile") = fail then
        datarec.descendants := [];
        return datarec.descendants;
    fi;

    PushOptions(rec(nonuser := true));
    p     := PrimePGroup(datarec.group);
    class := PClassPGroup(datarec.group);
    if not( IsBound(datarec.pQuotient) and 
            p = PrimePGroup(datarec.pQuotient) and
            class = datarec.class or
            IsBound(datarec.pCover) and
            p = PrimePGroup(datarec.pCover) and
            IsBound(datarec.pcoverclass) and 
            class = datarec.pcoverclass - 1 ) then
        PQ_PC_PRESENTATION( datarec, "pQ" : Prime := p, ClassBound := class );
    fi;
    if not( IsBound(datarec.pCover) and p = PrimePGroup(datarec.pCover) and
            class = datarec.pcoverclass - 1 ) then
        PQ_P_COVER( datarec );
    fi;
    PQ_PG_SUPPLY_AUTS( datarec, "pG" );
    ndescendants := PQ_PG_CONSTRUCT_DESCENDANTS( datarec );
    PopOptions();

    if datarec.calltype = "non-interactive" then
        PQ_COMPLETE_NONINTERACTIVE_FUNC_CALL(datarec);
        if IsBound( datarec.setupfile ) then
            return true;
        fi;
    fi;
        
    if ndescendants = 0 then
        datarec.descendants := [];
        return datarec.descendants;
    fi;

    datarec.descendants 
        := PqList( Filename( ANUPQData.tmpdir, "GAP_library" ) : recursive );
    for G in datarec.descendants do
        if not HasIsCapable(G)  then
            SetIsCapable( G, false );
        fi;
        SetIsPGroup( G, true );
        SetPrimePGroup( G, p );
    od;

    return datarec.descendants;
end );

#############################################################################
##
#F  PqDescendants( <G> ... )  . . . . . . . . .  construct descendants of <G>
#F  PqDescendants( <i> )
#F  PqDescendants()
##
InstallGlobalFunction( PqDescendants, function( arg )
    return PQ_DESCENDANTS(arg);
end );

#############################################################################
##
#F  PqSetPQuotientToGroup( <i> ) . . . set p-quotient as the group of process
#F  PqSetPQuotientToGroup()
##
InstallGlobalFunction( PqSetPQuotientToGroup, function( arg )
local datarec;
    ANUPQ_IOINDEX_ARG_CHK(arg);
    datarec := ANUPQData.io[ ANUPQ_IOINDEX(arg) ];
    if not IsBound(datarec.pQuotient) then
        Error( "p-quotient has not yet been calculated!\n" );
    fi;
    datarec.group := datarec.pQuotient;
end );

#############################################################################
##
#F  SavePqList( <file>, <lst> ) . . . . . . . . .  save a list of descendants
##
InstallGlobalFunction( SavePqList, function( file, list )
    local   appendExp,  l,  G,  pcgs,  p,  i,  w,  str,  word,  j,  
            automorphisms,  r;

    # function to add exponent vector
    appendExp := function( str, word )
        local   first, s, oldLen, i, w;

        first  := true;
        s      := str;
        oldLen := 0;
        for i  in [ 1 .. Length (word) ]  do
            if word[i] <> 0 then
                w := Concatenation( "G.", String (i) );
                if word[i] <> 1  then
                    w := Concatenation( w, "^", String(word[i]) );
                fi;
                if not first  then
                    w := Concatenation( "*", w );
                fi;
                if Length(s)+Length(w)-oldLen >= 77  then
                    s := Concatenation( s, "\n" );
                    oldLen := Length(s);
                fi;
                s := Concatenation( s, w );
                first := false;
            fi;
        od;
        if first  then
            s := Concatenation( s, "G.1^0" );
        fi;
        return s;
    end;

    # print head of file
    PrintTo(  file, "ANUPQgroups := [];\n"    );
    AppendTo( file, "Unbind(ANUPQautos);\n\n" );

    # run through all groups in <list>
    for l  in [ 1 .. Length(list) ]  do
        G    := list[l];
        pcgs := PcgsPCentralSeriesPGroup( G );
        p    := PrimePGroup( G );
        AppendTo( file, "## group number: ", l, "\n"                     );
        AppendTo( file, "ANUPQgroups[", l, "] := function( L )\n"        );
        AppendTo( file, "local   G,  A,  B;\n"                           );
        AppendTo( file, "G := FreeGroup( IsSyllableWordsFamily,\n"       );
        AppendTo( file, "                ", Length(pcgs), ", \"G\" );\n" );
        AppendTo( file, "G := G / [\n"                                   );

        # at first the power relators
        for i in [ 1 .. Length(pcgs) ]  do
            if 1 < i  then
                AppendTo( file, ",\n" );
            fi;
            w   := pcgs[i]^p;
            str := Concatenation( "G.", String(i), "^", String(p) );
            if w <> One(G) then
                word := ExponentsOfPcElement( pcgs, w );
                str  := Concatenation( str, "/(" );
                str  := appendExp( str,word );
                str  := Concatenation( str, ")" );
            fi;
            AppendTo( file, str );
        od;

        # and now the commutator relators
        for i  in [ 1 .. Length(pcgs)-1 ]  do
            for j  in [ i+1 .. Length(pcgs) ]  do
                w := Comm( pcgs[j], pcgs[i] );
                if w <> One(G) then
                    word := ExponentsOfPcElement( pcgs, w );
                    str  := Concatenation(
                                ",\nComm( G.", String(j),
                                ", G.", String(i), " )/(" );
                    str := appendExp( str, word );
                    AppendTo( file, str, ")" );
                fi;
            od;
        od;
        AppendTo( file, "];\n" );

        # convert group into an ag group, save presentation
        AppendTo( file, "G := PcGroupFpGroupNC(G);\n"              );

        # add automorphisms
        if HasAutomorphismGroup(G) then
            AppendTo( file, "A := [];\nB := [" );
    	    for r  in [ 1 .. RankPGroup(G) ]  do
                AppendTo( file, "G.", r );
                if r <> RankPGroup(G)  then
                    AppendTo( file, ", " );
    	    	else
    	    	    AppendTo( file, "];\n" );
                fi;
            od;
            automorphisms := GeneratorsOfGroup( AutomorphismGroup( G ) );
            for j  in [ 1 .. Length(automorphisms) ]  do
                AppendTo( file, "A[", j, "] := [");
                for r  in [ 1 .. RankPGroup(G) ]  do
                    word := Image( automorphisms[j], pcgs[r] );
                    word := ExponentsOfPcElement( pcgs, word );
                    AppendTo( file, appendExp( "", word ) );
                    if r <> RankPGroup(G)  then
                        AppendTo (file, ", \n");
                    fi;
                od;
                AppendTo( file, "]; \n");
            od;
    	    AppendTo( file, "ANUPQSetAutomorphismGroup( G, B, A, " );
            if HasIsSolvableGroup( AutomorphismGroup(G) ) then
                AppendTo( file, IsSolvableGroup( G ), " );\n" );
            else
                AppendTo( file, false, " );\n" );
            fi;
        fi;

        if HasNuclearRank( G ) then
            AppendTo( file, "SetNuclearRank( G, ", NuclearRank(G), " );\n" );
        fi;
        if HasIsCapable( G ) then
            AppendTo( file, "SetIsCapable( G, ", IsCapable(G), " );\n" );
        fi;
        if HasANUPQIdentity( G ) then
            AppendTo( file, "SetANUPQIdentity( G, ", 
                    ANUPQIdentity(G), " );\n" );
        fi;

        AppendTo( file, "Add( L, G );\n" );
        AppendTo( file, "end;\n\n\n"     );
    od;

    # write a magic string to the files
    AppendTo( file, "ANUPQmagic := \"groups saved to file\";\n" );
end );

#E  anupga.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here