home *** CD-ROM | disk | FTP | other *** search
/ Math Solutions 1995 October / Math_Solutions_CD-ROM_Walnut_Creek_October_1995.iso / pc / mac / discrete / lib / aghall.g < prev    next >
Encoding:
Text File  |  1993-05-05  |  20.0 KB  |  632 lines

  1. #############################################################################
  2. ##
  3. #A  aghall.g                    GAP library                      Frank Celler
  4. ##
  5. #A  @(#)$Id: aghall.g,v 3.17 1992/04/07 12:53:37 fceller Rel $
  6. ##
  7. #Y  Copyright 1990-1992,  Lehrstuhl D fuer Mathematik,  RWTH Aachen,  Germany
  8. ##
  9. ##  This files contains functions computing hall subgroups.
  10. ##
  11. #H  $Log: aghall.g,v $
  12. #H  Revision 3.17  1992/04/07  12:53:37  fceller
  13. #H  changed comparison with '0'
  14. #H
  15. #H  Revision 3.16  1992/04/03  13:10:09  fceller
  16. #H  changed 'Shifted...' into 'Sifted...'
  17. #H
  18. #H  Revision 3.15  1992/03/30  07:47:09  fceller
  19. #H  changed 'Exponents' slightly.
  20. #H
  21. #H  Revision 3.14  1992/02/10  13:45:50  fceller
  22. #H  'Order' takes two arguments: domain and element.
  23. #H
  24. #H  Revision 3.13  1992/02/07  18:11:40  fceller
  25. #H  Initial GAP 3.1 release.
  26. #H
  27. #H  Revision 3.1  1991/05/30  16:48:42  fceller
  28. #H  Initial revision
  29. ##
  30.  
  31.  
  32. #############################################################################
  33. ##
  34. #F  InfoAgGroup1( <arg> ) . . . . . . . . . . . . . . . . package information
  35. #F  InfoAgGroup2( <arg> ) . . . . . . . . . . . . . package debug information
  36. ##
  37. if not IsBound( InfoAgGroup1 )  then InfoAgGroup1 := Ignore;  fi;
  38. if not IsBound( InfoAgGroup2 )  then InfoAgGroup2 := Ignore;  fi;
  39.  
  40.  
  41. #############################################################################
  42. ##
  43.  
  44. #V  GS_LIMIT  . . . . . . . . . .  'ConjugatingWordGS' or 'ConjugatingWordCN'
  45. ##
  46. ##  If <p>  is  bigger  the  <GS_LIMIT>,  then  'ComplementConjugatingAgWord'
  47. ##  selects 'ConjugatingWordCN' instead of 'ConjugatingWordGS'.
  48. ##
  49. GS_LIMIT := 20;
  50.  
  51.  
  52. #############################################################################
  53. ##
  54. #F  ConjugatingWordGS( <N>, <U>, <V>, <K> ) . . . . . . . . . . . . . . local
  55. ##
  56. ##  Let <U> / <K> and <V> / <K> be two p-groups such  that  <U>*<N> = <V>*<N>
  57. ##  and let <N> be an elementary abelian q-group with q <> p. Then a word <n>
  58. ##  of <N> with <U> ^ <n> = <V> is returned. <K> must be normal in <U>*<N>.
  59. ##
  60. ##  It is important, that the weights of <K> are less than those of <N>.
  61. ##
  62. ConjugatingWordGS := function( N, U, V, K )
  63.     local   i, j, t, q, p, m, mm, v, x, xx;
  64.  
  65.     # If  <N>  or  <U>  / <K> is trivial, just return identity. Otherwise get
  66.     # get the canonical generating system for <U> / <K> and <V> / <K>.
  67.     U := FactorArg( U, K ).generators;
  68.     V := FactorArg( V, K ).generators;
  69.     N := Igs( N );
  70.     if U = [] or N = []  then
  71.         return K.identity;
  72.     fi;
  73.  
  74.     # The orders must be coprime.
  75.     p := RelativeOrderAgWord( U[ 1 ] );
  76.     q := RelativeOrderAgWord( N[ 1 ] );
  77.     if q = p  then
  78.         Error( "groups <U> and <N> are not coprime" );
  79.     fi;
  80.  
  81.     # Compute an integer <t> such that <t> * <p> = -1 mod <q>.
  82.     t := -Gcdex( p, q ).coeff1;
  83.     while t > q  do t := t - q;  od;
  84.     while t < 0  do t := t + q;  od;
  85.  
  86.     # Find  the  word  <n>  using the algorithm of Kantor. See S.P.Glasby and
  87.     # Michael  C.  Slattery,  "Computing  intersections  and  normalizers  in
  88.     # soluble groups", 1989.
  89.     x := K.identity;
  90.     for i  in Reversed( [ 1 .. Length( U ) ] )  do
  91.         m  := SiftedAgWord( K, ( U[ i ] ^ x ) ^ -1 * V[ i ] );
  92.         v  := K.identity;
  93.         mm := K.identity;
  94.         xx := K.identity;
  95.  
  96.         # Construct the product m^v * (m^2)^(v^2) * ... * (m^p-1)^(v^p-1).
  97.         for j  in [ 1 .. p - 1 ]  do
  98.             v  := v * V[ i ];
  99.             mm := mm * m;
  100.             xx := xx * v^-1 * mm * v;
  101.         od;
  102.         x := x * ( xx ^ t );
  103.     od;
  104.  
  105.     return x;
  106.  
  107. end;
  108.  
  109.  
  110. #############################################################################
  111. ##
  112. #F  ConjugatingWordCN( <N>, <U>, <V>, <K> ) . . . . . . . . . . . . . . local
  113. ##
  114. ##  Let <U> / <K> and <V> / <K> be two p-groups such  that  <U>*<N> = <V>*<N>
  115. ##  and let <N> be an elementary abelian q-group with q <> p. Then a word <n>
  116. ##  of <N> with <U> ^ <n> = <V> is returned. <K> must be normal in <U>*<N>.
  117. ##
  118. ConjugatingWordCN := function( N, U, V, K )
  119.     local   B, i, A, R, S, n;
  120.  
  121.     # Get generators and catch trivial cases.
  122.     U := FactorArg( U, K ).generators;
  123.     V := FactorArg( V, K ).generators;
  124.     if U = V  then
  125.         return K.identity;
  126.     fi;
  127.  
  128.     # The  following  few  lines  can  be  used  in  order to ensure that the
  129.     # returned  element  lies  in  <U>  *  <V>  and to reduce the size of the
  130.     # linear system. However 'Cgs' needs a critical amount of time.
  131.     #
  132.     # if K.generators <> []  then
  133.     #     UN := SumAgGroup( N, U );
  134.     #     UV := Cgs( UN, [ U, V ] );
  135.     #     if not IsEqualAgGroup( UN, UV )  then
  136.     #         N := NormalIntersection( N, UV );
  137.     #     fi;
  138.     # fi;
  139.     #
  140.  
  141.     N := ShallowCopy( N );
  142.     B := Igs( N );
  143.     if B = []  then
  144.         return K.identity;
  145.     fi;
  146.     N.field := GF( RelativeOrderAgWord( B[ 1 ] ) );
  147.  
  148.     # All we need are the operations ( 1 - <U> ).
  149.     A := List( B, x -> Concatenation( List( U, y -> 
  150.                   N.operations.Exponents( N, Comm(y,x), N.field ) ) ) );
  151.     R := Concatenation( List( [ 1 .. Length( U ) ], x -> 
  152.                   N.operations.Exponents( N, U[x]^-1*V[x], N.field ) ) );
  153.  
  154.     # Solve the linear system <A> * X = <R>.
  155.     S := SolutionMat( A, R );
  156.     if IsBool( S )  then
  157.         return false;
  158.     fi;
  159.  
  160.     # Get <S> back to <N>.
  161.     n := N.identity;
  162.     for i  in [ 1 .. Length( S ) ]  do
  163.         if LogVecFFE( S, i ) <> false  then
  164.             n := n * B[i] ^ Int( S[i] );
  165.         fi;
  166.     od;
  167.     return n;
  168.  
  169. end;
  170.  
  171.  
  172. #############################################################################
  173. ##
  174. #F  ComplementConjugatingAgWord( <N>, <U>, <V>, <K> ) . . . . .  find ag word
  175. ##
  176. ComplementConjugatingAgWord := function( arg )
  177.     local   N,  U,  V,  K,  cK,  cN,  x,  q,  p;
  178.  
  179.     # Check the arguments and catch trivial cases.
  180.     if Length( arg ) < 3 or Length( arg ) > 4  then
  181.         Error( "usage: ComplementConjugatingAgWord( ",
  182.                "<N>, <U>, <V> [,<K>] )" );
  183.     fi;
  184.     N := arg[ 1 ];
  185.     U := Normalized( arg[ 2 ] );
  186.     V := Normalized( arg[ 3 ] );
  187.  
  188.     InfoAgGroup1( "#I  ComplementConjugatingAgWord: ",
  189.                   "|<U>| = ", StringPP( Size( U ) ), ", ",
  190.           "|<N>| = ", StringPP( AgGroupOps.Size( N ) ), "\n" );
  191.  
  192.     if U = V  then
  193.         InfoAgGroup1( "#I  ComplementConjugatingAgWord: ",
  194.                   "returns '1' because <U> = <V>\n" );
  195.         return N.identity;
  196.     elif N.generators = []  then
  197.         InfoAgGroup1( "#I  ComplementConjugatingAgWord: ",
  198.                   "raises an error because |<N>| = 1 and <U> <> <V>",
  199.               "\n" );
  200.         x := false;
  201.     else
  202.  
  203.         # Get the prime of <N> and <U> / <K>. We must use "CN" if both have
  204.         # the  same  prime.  If not use "CN" for prime of <U> / <K> greater
  205.         # <GS_LIMIT>.
  206.         q := RelativeOrderAgWord( Igs( N )[1] );
  207.         if    Length( arg ) = 3
  208.            or ( Length( arg ) = 4 and arg[ 4 ].generators = [] )
  209.         then
  210.             K := AgSubgroup( U, [], true );
  211.             p := RelativeOrderAgWord( Igs( U )[ 1 ] );
  212.             if q = p or p > GS_LIMIT  then
  213.             InfoAgGroup2( "#I  ComplementConjugatingAgWord: ",
  214.                       "'CN' as ", q, "=", p, " or ", p, ">",
  215.                               GS_LIMIT, "\n" );
  216.                 x := ConjugatingWordCN( N, U, V, K );
  217.             else
  218.             InfoAgGroup2( "#I  ComplementConjugatingAgWord: ",
  219.                       "'GS' as ", q, "<>", p, " and ", p, "<",
  220.                               GS_LIMIT+1, "\n" );
  221.                 x := ConjugatingWordGS( N, U, V, K );
  222.             fi;
  223.         elif Length( arg ) = 4  then
  224.             K  := Normalized( arg[ 4 ] );
  225.             p  := RelativeOrderAgWord( FactorArg( U, K ).generators[ 1 ] );
  226.             cK := Igs( K );
  227.             cN := Igs( N );
  228.  
  229.             # Weights  of  K must be bigger than those of <N> in order to use
  230.             # "GS". If they are, disptach as above.
  231.             if    q = p
  232.                or p > GS_LIMIT
  233.                or ( DepthAgWord( cK[ Length(cK) ] ) >= DepthAgWord( cN[1] ) )
  234.             then
  235.             InfoAgGroup2( "#I  ComplementConjugatingAgWord: ",
  236.                       "'CN' as ", q, "=", p, ", ", p, ">",
  237.                               GS_LIMIT, " or mixed depths", "\n" );
  238.                 x := ConjugatingWordCN( N, U, V, K );
  239.             else
  240.             InfoAgGroup2( "#I  ComplementConjugatingAgWord: ",
  241.                       "'GS' as ", q, "<>", p, " and ", p, "<",
  242.                               GS_LIMIT+1, "\n" );
  243.                 x := ConjugatingWordGS( N, U, V, K );
  244.             fi;
  245.         else
  246.             Error( "usage: ComplementConjugatingAgWord(",
  247.                    " <N>, <U>, <V> [,<K>] )" );
  248.         fi;
  249.     fi;
  250.  
  251.     # If <x> is 'false' we did not find a word. Otherwise return <x>.
  252.     if IsBool( x )  then
  253.         Error( "cannot find a conjugating word" );
  254.     else
  255.         InfoAgGroup1("#I  ComplementConjugatingAgWord: found ",x,"\n");
  256.         return x;
  257.     fi;
  258.  
  259. end;
  260.  
  261.  
  262. #############################################################################
  263. ##
  264. #F  CoprimeComplement( <G>, <N> ) . . . . . . . . .  complement to <N> in <G>
  265. ##
  266. CoprimeComplement := function( arg )
  267.     return arg[1].operations.CoprimeComplement( arg );
  268. end;
  269.  
  270. AgGroupOps.CoprimeComplement := function( L )
  271.     local   G, N, M, K, U, V, x, y, o, o2, p, i;
  272.  
  273.     if Length( L ) = 2  then
  274.  
  275.         # Catch some trivial cases.
  276.         G := L[ 1 ];
  277.         N := L[ 2 ];
  278.         if N.generators = []  then
  279.             return G;
  280.         fi;
  281.         U := FactorArg( G, N ).generators;
  282.         if U = []  then
  283.             return AgSubgroup( G, [], true );
  284.         fi;
  285.         p := RelativeOrderAgWord( Igs( N )[ 1 ] );
  286.  
  287.         # Start with the lowest composition factor.
  288.         x  := U[ Length( U ) ];
  289.         o  := AgWordsOps.Order( AgWords, x );
  290.         o2 := o;
  291.         while o mod p = 0  do o := QuoInt( o, p );  od;
  292.         y  := x ^ ( o2 / o );
  293.         if LeadingExponentAgWord( x ) <> LeadingExponentAgWord( y )  then
  294.             y := y ^ ( LeadingExponentAgWord( x )
  295.                          / LeadingExponentAgWord( y )
  296.                        mod RelativeOrderAgWord( y ) );
  297.         fi;
  298.         K := AgSubgroup( G, [ y ], false );
  299.  
  300.         # Step up the composition series.
  301.         for i  in Reversed( [ 1 .. Length( U ) - 1 ] )  do
  302.  
  303.             ## if CHECK  then
  304.             ##     Print( "#I  CoprimeComplement: K = ",K.igs,"\n" );
  305.             ## fi;
  306.  
  307.             V := ConjugateSubgroup( K, U[ i ] );
  308.             x := U[ i ] * ComplementConjugatingAgWord( N, V, K );
  309.  
  310.             o  := Order( AgWords, x );
  311.             o2 := o;
  312.             while o mod p = 0  do o := QuoInt( o, p );  od;
  313.             y  := x ^ ( o2 / o );
  314.             if LeadingExponentAgWord( x ) <> LeadingExponentAgWord( y )  then
  315.                 y := y ^ ( LeadingExponentAgWord( x )
  316.                              / LeadingExponentAgWord( y )
  317.                            mod RelativeOrderAgWord( y ) );
  318.             fi;
  319.             K := AgSubgroup( G, Concatenation( [y], Igs( K ) ), false );
  320.         od;
  321.  
  322.         return K;
  323.  
  324.     else
  325.  
  326.         # Catch some trivial cases.
  327.         G := L[ 1 ];
  328.         N := L[ 2 ];
  329.         M := L[ 3 ];
  330.         if N = M  then
  331.             return G;
  332.         fi;
  333.         U := FactorArg( G, N ).generators;
  334.         if U = []  then
  335.             return M;
  336.         fi;
  337.         p := RelativeOrderAgWord( FactorArg( N, M ).generators[ 1 ] );
  338.  
  339.         # Start with the lowest composition factor.
  340.         x  := U[ Length( U ) ];
  341.         o  := AgWordsOps.Order( AgWords, x );
  342.         o2 := o;
  343.         while o mod p = 0  do o := QuoInt( o, p );  od;
  344.         y  := x ^ ( o2 / o );
  345.         if LeadingExponentAgWord( x ) <> LeadingExponentAgWord( y )  then
  346.             y := y ^ ( LeadingExponentAgWord( x )
  347.                          / LeadingExponentAgWord( y )
  348.                        mod RelativeOrderAgWord( y ) );
  349.         fi;
  350.         K := AgSubgroup( G, [ y ], false );
  351.  
  352.         # The   following  is surely  a  hack.   You   should  never  use  it
  353.         # unless    you  know what   you  do.  It   heavyly  depends  on  the
  354.         # ways 'ComplementConjugatingAgWord' works.
  355.         N := N mod M;
  356.         N.igs := N.generators;
  357.  
  358.         # Step up the composition series.
  359.         for i  in Reversed( [ 1 .. Length( U ) - 1 ] )  do
  360.  
  361.             ##  if CHECK  then
  362.             ##      Print( "#I  CoprimeComplement: K = ",K.igs,"\n" );
  363.             ##  fi;
  364.  
  365.             V  := ConjugateSubgroup( K, U[ i ] );
  366.             x  := ComplementConjugatingAgWord( N, V, K );
  367.             x  := U[ i ] * CanonicalAgWord( M, x );
  368.             o  := AgWordsOps.Order( AgWords, x );
  369.             o2 := o;
  370.             while o mod p = 0  do o := QuoInt( o, p );  od;
  371.             y  := x ^ ( o2 / o );
  372.             if LeadingExponentAgWord( x ) <> LeadingExponentAgWord( y )  then
  373.                 y := y ^ ( LeadingExponentAgWord( x )
  374.                              / LeadingExponentAgWord( y )
  375.                            mod RelativeOrderAgWord( y ) );
  376.             fi;
  377.             K := AgSubgroup( G, Concatenation( [y], K.igs ), false );
  378.         od;
  379.  
  380.         return SumAgGroup( M, K );
  381.  
  382.     fi;
  383.  
  384. end;
  385.  
  386.  
  387. #############################################################################
  388. ##
  389.  
  390. #F  HallEAS( <U>, <primes> )  . . . . . . .  hall without factorgroups, local
  391. ##
  392. HallEAS := function( U, primes )
  393.     local E, H, i, p;
  394.  
  395.     # Get the elementary abelian series of <U>.
  396.     E := ElementaryAbelianSeries( U );
  397.  
  398.     # We start with <U> / <eas>[ 2 ] and step down.
  399.     H := U;
  400.     for i  in [ 1 .. Length( E ) - 1 ]  do
  401.         p := RelativeOrderAgWord( FactorArg( E[i], E[i+1] ).generators[1] );
  402.         if not ( p in primes )  then
  403.             H := CoprimeComplement( H, E[ i ], E[ i + 1 ] );
  404.         fi;
  405.     od;
  406.  
  407.     return H;
  408.  
  409. end;
  410.  
  411.  
  412. #############################################################################
  413. ##
  414. #F  HallComposition( <G>, <primes> )  . . . . . hall with factorgroups, local
  415. ##
  416. HallComposition := function( G, primes )
  417.     local   homs, H, f, i, p;
  418.  
  419.     # Get the homomorphisms along the elementary abelian series.
  420.     homs := HomomorphismsSeries( G, ElementaryAbelianSeries(G) );
  421.  
  422.     # Start with trivial group and work down the chain.
  423.     H := homs[ 1 ].img( G );
  424.     for i  in [ 2 .. Length( homs ) ]  do
  425.         H := homs[ i ].pre( H );
  426.         p := RelativeOrderAgWord( homs[ i ].kernel.generators[ 1 ] );
  427.         if not p in primes  then
  428.             H := CoprimeComplement( H, homs[ i ].kernel );
  429.         fi;
  430.     od;
  431.  
  432.     return H;
  433.  
  434. end;
  435.  
  436.  
  437. #############################################################################
  438. ##
  439. #F  HallSubgroup( <G>, <primes> ) . . . . . . . . . . .  hall subgroup of <G>
  440. ##
  441. AgGroupOps.HallSubgroup := function( G, primes )
  442.     local   f;
  443.  
  444.     f := Set( FactorsAgGroup( G ) );
  445.  
  446.     if G.generators = []  then
  447.         return G;
  448.     elif IntersectionSet( primes, f ) = []  then
  449.         return AgSubgroup( G, [], true );
  450.     elif IsSubset( primes, f )  then
  451.         return G;
  452.     elif not IsNormalized( G )  then
  453.         G := Normalized( G );
  454.     fi;
  455.  
  456.     # 'HallEAS' is faster, so we use it instead of 'HallComposition'.
  457.     return HallEAS( G, primes );
  458.  
  459. end;
  460.  
  461. HallSubgroup := function( G, primes )
  462.  
  463.     if IsInt( primes )  then
  464.         primes := Set( Factors( primes ) );
  465.     else
  466.         primes := Set( Concatenation( List( primes, Factors ) ) );
  467.     fi;
  468.     return G.operations.HallSubgroup( G, primes );
  469.  
  470. end;
  471.  
  472. #############################################################################
  473. ##
  474. #F  HallConjugatingAgWord( <G>, <U>, <V> )  . . . . .  conjugate <U> into <V>
  475. ##
  476. HallConjugatingAgWord := function( G, V, U )
  477.     local   W,  WW,  UU,  N,  primes,  g,  n,  i,  E;
  478.  
  479.     # Get the primes of <U> and <V>.
  480.     if Size( U ) <> Size( V )  then
  481.         Error( "groups <U> and <V> have different sizes" );
  482.     fi;
  483.     primes := Set( FactorsAgGroup( U ) );
  484.     if Intersection( primes, FactorsAgGroup( G, U ) ) <> []  then
  485.         Error( "groups <U> and <V> must be hall subgroups of <G>" );
  486.     fi;
  487.  
  488.     # Conjugate stepping down the elementary abelian series of <G>.
  489.     E := ElementaryAbelianSeries( G );
  490.     g := G.identity;
  491.     W := V;
  492.     for i  in [ 2 .. Length( E ) ]  do
  493.  
  494.         # The  following is surely a hack. You should never use it unless you
  495.         # are  either (1) fc or (2) you know what you do. It  heavyly depends
  496.         # on the ways 'ComplementConjugatingAgWord' works. Until now I am not
  497.         # not convinced that it works,  but I have hope.
  498.         N := E[ i - 1 ] mod E[ i ];
  499.         N.igs := N.generators;
  500.         if not RelativeOrderAgWord( N.igs[ 1 ] ) in primes  then
  501.             WW := AgSubgroup( G, FactorArg( W, E[ i ] ).generators, false );
  502.             UU := AgSubgroup( G, FactorArg( U, E[ i ] ).generators, false );
  503.             n  := ComplementConjugatingAgWord( N, WW, UU );
  504.             W  := ConjugateSubgroup( W, n );
  505.             g  := g * n;
  506.         fi;
  507.     od;
  508.  
  509.     return g;
  510.  
  511. end;
  512.  
  513.  
  514. #############################################################################
  515. ##
  516.  
  517. #F  SylowSystem( <U> )     . . . . . . . . . . . . . . . . . sylow system of <U>
  518. ##
  519. AgGroupOps.SylowSystem := function( U )
  520.     local   sys, com, i, L, R;
  521.  
  522.     # Get  a  sylow  complement system. If it does not contain a sylow system
  523.     # compute all intersections to get it.
  524.     sys := SylowComplements( U );
  525.     if not IsBound( sys.sylowSubgroups )  then
  526.         com := sys.sylowComplements;
  527.         L := [ U ];
  528.         for i  in [ 2 .. Length( sys.primes ) ]  do
  529.             L[ i ] := NormalIntersection( L[ i - 1 ], com[ i - 1 ] );
  530.         od;
  531.         R := [];
  532.         R[ Length( sys.primes ) ] := U;
  533.         for i  in Reversed( [ 1 .. Length( sys.primes ) - 1 ] )  do
  534.             R[ i ] := NormalIntersection( R[ i + 1 ], com[ i + 1 ] );
  535.         od;
  536.         sys.sylowSubgroups := [];
  537.         for i  in [ 1 .. Length( sys.primes ) ]  do
  538.             sys.sylowSubgroups[i] := NormalIntersection( L[i], R[i] );
  539.         od;
  540.  
  541.     fi;
  542.  
  543.     return sys;
  544.  
  545. end;
  546.  
  547. SylowSystem := function( U )
  548.     return U.operations.SylowSystem( U );
  549. end;
  550.  
  551.  
  552. #############################################################################
  553. ##
  554. #F  SylowComplements( <U> ) . . . . . . . . . . . . . sylow complement system
  555. ##
  556. AgGroupOps.SylowComplements := function( U )
  557.     local   i, primes, p, com, syl, sys, K, L;
  558.  
  559.     # Catch trivial case.
  560.     if U.generators = []  then
  561.         return rec( primes := [],
  562.                     sylowSubgroups := [],
  563.                     sylowComplements := [] );
  564.     fi;
  565.  
  566.     # If  you  already  know a complement system return it. If we know just a
  567.     # sylow system, return the products.
  568.     if IsBound( U.syslowSystem )  then
  569.         if IsBound( U.syslowSystem.sylowComplements )  then
  570.             return U.syslowSystem;
  571.         elif IsBound( U.sylowSystem.sylowSubgroups )  then
  572.             com := [];
  573.             syl := U.sylowSystem.sylowSubgroups;
  574.             primes := U.sylowSystem.primes;
  575.             K := [];
  576.             L := [];
  577.             K[ 1 ] := AgSubgroup( U, [], true );
  578.             for i  in [ 2 .. Length( primes ) ]  do
  579.                 K[ i ] := SumAgGroup( K[ i - 1 ], syl[ i - 1 ] );
  580.             od;
  581.             L[ Length( primes ) ] := AgSubgroup( U, [], true );
  582.             for i  in Reversed( [ 1 .. Length( primes ) - 1 ] )  do
  583.                 L[ i ] := SumAgGroup( L[ i + 1 ], syl[ i + 1 ] );
  584.             od;
  585.             for i  in [ 1 .. Length( primes ) ]  do
  586.                 com[i] := SumAgGroup( K[ i ], L[ i ] );
  587.             od;
  588.             U.sylowSystem.sylowComplements:=com;
  589.             return U.sylowSystem;
  590.         fi;
  591.     fi;
  592.  
  593.     # Compute a hall-p'-subgroup for each prime divisor p.
  594.     primes := Set( FactorsAgGroup( U ) );
  595.     sys := rec( primes := [], sylowComplements := [] );
  596.     for p  in primes  do
  597.         K := U.operations.HallSubgroup( U, Difference( primes, [p] ) );
  598.         Add( sys.primes, p );
  599.         Add( sys.sylowComplements, K );
  600.     od;
  601.     U.sylowSystem := sys;
  602.  
  603.     return sys;
  604.  
  605. end;
  606.  
  607. SylowComplements := function( U )
  608.     return U.operations.SylowComplements( U );
  609. end;
  610.  
  611.  
  612. #############################################################################
  613. ##
  614. #F  SylowSubgroup( <G>, <p> ) . . . . . . . . . . . . . sylow subgroup of <G>
  615. ##
  616. AgGroupOps.SylowSubgroup := function( G, p )
  617.     return G.operations.HallSubgroup( G, Set( Factors( p ) ) );
  618. end;
  619.  
  620.  
  621. #############################################################################
  622. ##
  623.  
  624. #E  Emacs . . . . . . . . . . . . . . . . . . . . . . . local emacs variables
  625. ##
  626. ## Local Variables:
  627. ## mode:           outline
  628. ## outline-regexp: "#F\\|#V\\|#E"
  629. ## eval:           (hide-body)
  630. ## End:
  631. ##
  632.