Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  matrep.gi   Sprache: unbekannt

 
#############################################################################
##
#W  matrep.gi                  Polycyclic                       Werner Nickel
##

InstallGlobalFunction( "IsMatrixRepresentation",
function( G, matrices )
    local   coll,  conjugates,  d,  I,  i,  j,  conj,  rhs,  k;

    coll := Collector( G );
    conjugates := coll![PC_CONJUGATES];

    d := NumberOfGenerators( coll );

    I := matrices[1]^0;
    for i in [1..d] do
        for j in [i+1..d] do
            conj := matrices[j]^matrices[i];
            if IsBound( conjugates[j] ) and IsBound( conjugates[j][i] ) then
                rhs := I;
                for k in [1,3..Length(conjugates[j][i])-1] do
                    rhs := rhs *
                           matrices[ conjugates[j][i][k] ] ^
                           conjugates[j][i][k+1];
                od;
            else
                rhs := matrices[j];
            fi;
            if conj <> rhs then
                Error( "relation ", [j,i], " not satisfied" );
            fi;
        od;
    od;
    return true;
end );

InstallMethod( ViewObj,
        "for homomorphisms into matrix groups",
        true,
        [ IsHomomorphismIntoMatrixGroup ],
        0,
function( hom )
    local  mapi,  d;

    mapi := MappingGeneratorsImages( hom );
    View( mapi[1] );
    Print( " -> " );

    d := Length(mapi[2][1]);
    Print( "<", Length(mapi[2]), " ", d, "x", d, "-matrices>" );
    return;
end );

#### Willem's code ##########################################################
##
BindGlobal( "ExtendRep", function( col, new, mats)


    # Here `col' is a from-the-left collector. Let G be the group defined
    # by `col' and H the subgroup generated by the generators with indices
    # `new+1'...`nogens'. Then we assume that the list `mats' defines a
    # representation of H (`new+1' is represented by `mats[1]' and so on.
    # This function extends the representation of the subgroup H to the
    # subgroup generated by H together with the element with index `new'.

    # Elements of `H' are represented as words. For example [ 0, 0, 1, 2 ]
    # is u_3*u_4^2. The length of these words is equal to the number of
    # polycyclic generators of G. So the first entries of such a word
    # will be zero (to be precise: the entries until and including `new').


    local   MakeWord,  EvaluateFunction,  TriangulizeRows,  nogen,
            nulev,  dim,  commutes,  i,  ev,  M,  exrep,  k,  l,
            asbas,  last_inds,  hdeg,  sp,  deg,  ready,  le,  j,  m,
            cc,  cf,  inds,  mons,  tup,  ff,  vecs,  f,  vec,  vecs1,
            B,  B1,  finished,  cls,  done,  changeocc,  vv,  m1,
            num,  isrep,  newmons;

    MakeWord:= function( p )

        # Represents the element `p' of `H' in the form [ ind, exp, ...]
        # e.g., [ 1,0,0,2] is transformed to [1,1,4,2].

        local p1,i;

         p1:=[];
         for i in [1..Length(p)] do
             if p[i]<>0 then Append(p1,[i,p[i]]); fi;
         od;
         return p1;
    end;


    EvaluateFunction:=function( f, a )

        # Here `f' is an element of the dual space of the group algebra of `H'.
        # So it is represented as [ [ i, j ], k ].
        # `a' is a monomial in the group algebra of `H'. We evaluate
        # `f(a)'.

        local p, wd, j, of, M;

        p:= a;

        if f[2] <> 0 then

           # we calculate new^{-f[2]}*a*new^{f[2]}:

           p:= List( [1..NumberOfGenerators( col )], x -> 0 );
           wd:= [ new, -f[2] ];
           for j in [1..Length(a)] do
               if a[j]<>0 then Append( wd, [ j, a[j] ] ); fi;
           od;
           Append( wd, [ new,f[2] ] );
           CollectWordOrFail( col, p, wd );
        fi;

        # We calculate the matrix corresponding to `p'.

        of:= Length(mats)-NumberOfGenerators( col );
        M:= IdentityMat( Length(mats[1]) );
        for j in [1..Length(p)] do
            if of+j >= 1 then
               if p[j] <> 0 then
                  M:= M*(mats[of+j]^p[j]);
               fi;
            fi;
        od;

        # We return the correct entry of the matrix.

        return M[f[1][2]][f[1][1]];

    end;

    TriangulizeRows:= function( vecs )

       # Here `vecs' is a list of integer vectors. This function
       # returns a list of integer vectors spanning the same space
       # over the integers (i.e., the same lattice), in triangular form.
       # The algorithm is similar to the one for Hermite normal form:
       # Suppose we have already taken care of the rows 1..k-1, and suppose that
       # we are dealing with column `col' (here col >= k, and the inequality
       # may be strict because there can be zero columns that do not contribute).
       # Then we look for the minimal entry in column `col' on and below position
       # `k'. We swap the corresponding row to position `k', and subtract it
       # as many times as possible from the rows below. If this produces
       # zeros everywehere then we are happy, and move on. If not then
       # we do this again: move the minimal entry to position `k' etc.
       #
       # The output of this function also contains a second list, in bijection
       # with the rowvectors in the output. The k-th entry of this list contains
       # the position of the first nonzero entry in the k-th row.

       local col, k, i, pos, fac, cols, v, min, c;

       col:=1;
       k:=1;
       cols:= [ ];
       while k <= Length(vecs) do

          # We look for the minimal nonzero element in column `col', where we
          # run through the rows with index >= k.

          min:= 0;
          i:= k-1;

          # First we get the first nonzero entry...
          while min = 0 and i < Length( vecs ) do
             i:=i+1; min:= vecs[i][col];
          od;

          if min = 0 then
             pos:= fail;
          else

             if min < 0 then min:= -min; fi;

             pos:= i;
             while i < Length(vecs) do
                i:=i+1;
                c:= vecs[i][col];
                if c < 0 then c:= -c; fi;
                if c < min and c <> 0 then min:= c; pos:= i; fi;
             od;
          fi;

          if pos = fail then

             # there is no nonzero entry in this column, that means that it
             # will not contribute to the triangular form, we move one column.

             col:= col+1;

          else

             if pos <> k then

                # We swap rows `k' and `pos', so that the minimal value will be
                # in row `k'.

                v:= vecs[k];
                vecs[k]:= vecs[pos];
                vecs[pos]:= v;

             fi;

             # Subtract row `k' as many times as possible.

             for i in [k+1..Length(vecs)] do
                 fac:= (vecs[i][col]-
                              (vecs[i][col] mod vecs[k][col]))/vecs[k][col];
                 vecs[i]:=vecs[i]-fac*vecs[k];
             od;

             # If all entries in the column `col' below position `k' are zero,
             # then we are done. Otherwise we just go through the process again.
             if ForAll( List( [k+1..Length(vecs)], x-> vecs[x][col] ),
                                                             IsZero ) then
                Add( cols, col );
                col:=col+1; k:=k+1;
             fi;

             # Get rid of zero rows...
             vecs:= Filtered( vecs, x -> x <> 0*x );

          fi;

       od;

       return [vecs,cols];

    end;

    nogen:= NumberOfGenerators( col );
    nulev:= List([1..nogen],x->0);
    dim:= Length( mats[1] );

    # We check whether the generator with index `new' commutes with all
    # elements of `H'. In that case we can easily extend the representation.

    commutes:= true;
    for i in [new+1..nogen] do
      ev:= ShallowCopy( nulev );
      CollectWordOrFail( col, ev, [i,-1,new,-1,i,1,new,1] );
      if ev<>0*ev then commutes:= false; break; fi;
    od;

    if commutes then

        # We represent the generator with index `new' by the matrix
        #
        #      / I 0      \
        #      \ 0 E_{12} /
        #
        # where I is the dim x dim identity matrix, and E_{12}
        # is the 2x2 matrix with ones on the diagonal, and a one on pos. (1,2).
        # A generator with index `new+i' is represented by the matrix
        #
        #     / mats[i] 0   \
        #     \   0     I_2 /
        #
        # where I_2 is the 2x2 identity matrix.

      M:= IdentityMat( dim+2 );
      M[dim+1][dim+2]:=1;
      exrep:= [ M ];
      for i in [1..Length(mats)] do
        M:= NullMat( dim+2, dim+2 );
        for k in [1..dim] do
          for l in [1..dim] do
             M[k][l]:=mats[i][k][l];
          od;
        od;
        M[dim+1][dim+1]:=1; M[dim+2][dim+2]:=1;
        Add( exrep, M );
      od;
      return exrep;
    fi;

    # In the other case we compute the space spanned by C_{\rho}. This is
    # the space spanned by the coefficient-functions on the matrix space
    # spanned by all products
    #
    #          mats[1]^k1...mats[s]^ks
    #
    # where k_i\in \Z. So first we calculate a basis of this space.

    asbas:=[ IdentityMat( dim ) ];  # The basis to be.

    last_inds:= [ 1 ];
    # `last_inds' is an array in bijection with `asbas'.
    # If `last_inds[i]=k' then the last letter in the word that defines
    # `asbas[i]' is `k'. (So we only need to multiply with higher
    # elements in order to (maybe) get new basis elements).
    # We basically loop through `asbas' and multiply each element in there
    # with elements with the same or a higher index. If all such products
    # are in `asbas' then we have found our basis. Of course, we only have
    # to try the elements added in the previous round. So `hdeg' is the
    # index where the first of thoses elements is in `asbas'.
    # `deg' will record the maximum degree of a word corresponding to a
    # basis element (for later use).

    hdeg:= 1;
    sp:= MutableBasis( Rationals, asbas );
    deg:= 0;
    ready:= false;
    while not ready do
      deg:= deg + 1;
      i:= hdeg;
      le:= Length( asbas );
      ready:= true;
      while i <= le do

        for j in [ last_inds[i]..Length( mats )] do
          m:= asbas[i]*mats[j];
          if not IsContainedInSpan( sp, m ) then
            ready:= false;
            Add( asbas, m );
            Add( last_inds, j );
            CloseMutableBasis( sp, m );
          fi;
        od;

        i:= i+1;
      od;
      hdeg:= le+1;
    od;

    deg:= deg - 1;

    # Compute the functions. A coefficient function m -> m[j][i] is represented
    # by [i,j]. `cc' will be the list of all such functions.
    # We note that the elements of `asbas' form a discriminating set for
    # the coefficient space. So we represent the coefficcients as vectors using
    # the set `asbas'.

    cc:=[ ];
    sp:= MutableBasis( Rationals, [ List(asbas,m->0)] );

    for i in [1..dim] do
      for j in [1..dim] do

        cf:= List( asbas, m -> m[j][i] );
        if not IsContainedInSpan( sp, cf ) then
          Add( cc, [i,j] );
          CloseMutableBasis( sp, cf );
        fi;
      od;
    od;


    # 'mons' will be a list of all monomials in the group H up to degree 'deg'.

    inds:=[ new+1 .. nogen ];
    mons:=[ ShallowCopy( nulev ) ];
    for i in [1..deg] do
      tup:= UnorderedTuples( inds, i );
      for j in [1..Length(tup)] do
        ev:= ShallowCopy( nulev );
        for k in tup[j] do
          ev[k]:= ev[k]+1;
        od;
        Add( mons, ev );
      od;
    od;

    # 'ff' will be a basis of the subspace of ZH^* spanned by the functions.
    # A function is either coefficient function or new^k applied to a coefficient
    # function. So we represent a function as a list [ [i,j], k].
    # 'vecs' will contain the vectorial representation of the elements of 'ff'
    # relative to the monomials in 'mons'.

    ff:=[]; vecs:=[];
    for i in [1..Length(cc)] do
      f:= [ cc[i], 0 ];
      vec:= List( mons, a -> EvaluateFunction( f, a ) );
      Add( ff, f ); Add( vecs, ShallowCopy( vec ) );
    od;


    while true do

        # We determine the module generated by C_{\rho} (as a subspace
        # of the dual of the vector space spanned by the monomials in `mons').
        # This module is generated by all new^k.f for f\in ff.
        #
        # `vecs1' will be a set of vectors spanning the module over the
        # integers, wheras `vecs' spans the module over the rationals,
        # and `vecs[i]' corresponds exactly to the function `ff[i]' (so we
        # need to keep this information as we
        # do not allow for linear combinations of functions in `ff').

        vecs1:= ShallowCopy( List( vecs, ShallowCopy ) );
        sp:= VectorSpace( Rationals, vecs );
        B:= Basis( sp, vecs );
        k:= 1;
        le:= Length( ff );
        B1:= Basis( sp, vecs1 );

        while k <= le do
            f:= List( ff[k], ShallowCopy );
            finished:= false;
            while not finished do
                f[2]:= f[2]+1; # we let `new' act by increasing
                               # `f[2]' by 1.


                if not f in ff then
                    vec:= List( mons, a -> EvaluateFunction( f, a ) );
                    cf:= Coefficients( B1, vec );
                    if cf <> fail then

                        if not ForAll( cf, IsInt ) then
                            # `vec' lies in the space `sp'
                            # but not in the space over the
                            # integers spanned by `vecs1'.
                            # So we add it, triangularize
                            # and then we get a new basis
                            # `vecs1' that spans the whole
                            # space over the integers.

                            Add( vecs1, vec );
                            vecs1:=TriangulizeRows(vecs1)[1];
                            B1:= Basis( sp, vecs1 );

                        fi;
                        finished:= true;
                        # we are finished with letting `new' act on `f'.
                    else  # we add the new vector, function etc...

                        Add( ff, List( f, ShallowCopy ) );
                        Add( vecs, ShallowCopy( vec ) );
                        Add( vecs1, ShallowCopy( vec ) );
                        sp:= VectorSpace( Rationals, vecs );
                        B1:= Basis( sp, vecs1 );

                    fi;
                else
                    finished:= true;
                fi;

            od;
            k:= k+1;
        od;

        # Now we determine a list of monomials sufficient to "distinguish" the
        # functions. It is of length equal to the dimension of the module.
        # It consists of the monomials corresponding to the columns that
        # come from a call to TriangularizeRows.

        cls:= TriangulizeRows( vecs1 )[2];
        mons:= mons{cls};
        vecs:= List( vecs, u -> u{cls} );
        vecs1:= List( vecs1, u -> u{cls} );

        # We calculate the action of the generators of the group, starting with
        # the new element. `exrep' will contain the matrices of the action.

        # It is possible that the Z-module spanned by `vecs1' is not closed
        # under the action of `new', *over Z*, i.e., that `new.f' is not
        # a Z-linear combination of the elements of `vecs1'. In that case we
        # add the vector we get, triangularize and start again. For that
        # we need the rather complicated loop `while not done do..' etc.

        sp:= VectorSpace( Rationals, vecs );
        B:= Basis( sp, vecs );
        done:= false;

        while not done do

            changeocc:= false;
            B1:= Basis( sp, vecs1 );
            exrep:= [ ];
            M:= [ ];
            for j in [1..Length(vecs1)] do
                vv:= [ ];
                for m in mons do

                    # `ev' will be the element new^{-1}.m.new

                    m1:= [new,-1];
                    Append( m1, MakeWord(m) ); Append( m1, [new,1] );
                    ev:= ShallowCopy( nulev );
                    CollectWordOrFail( col, ev, m1 );

                # Now we calculate the vector corresponding to the function
                # new.f, where f is the function corresponding to the vector
                # vecs1[j]. Now this vector is a linear combination of vectors
                # in `vecs1', i.e., the function is a linear combination of
                # elementary functions (i.e., fcts of the form new^k.c_{ij}).
                # So when evaluating we have to loop over the elements of this
                # linear combination.

                    cf:= Coefficients( B, vecs1[j] );
                    num:= 0;
                    for i in [1..Length(cf)] do
                        if cf[i]<>0 then
                            num:= num +
                                  cf[i]*EvaluateFunction( ff[i], ev );
                        fi;
                    od;
                    Add(vv,num);
                od;

                cf:= Coefficients( B1, vv );
                if not ForAll( cf, x -> IsInt( x ) ) then
                    Add( vecs1, vv );
                    vecs1:= TriangulizeRows(vecs1)[1];
                    changeocc:= true;
                    break;
                else
                    Add( M, Coefficients( B1, vv ) );
                fi;

            od;

            if not changeocc then
                Add( exrep, TransposedMat( M ) );

        # We calculate the action of the "old" generators. Basically works the
        # same as the code for the "new" generator.

                for i in [new+1..nogen] do
                    if changeocc then break; fi;
                    M:= [ ];
                    for j in [1..Length(vecs1)] do
                        vv:= [ ];
                        cf:= Coefficients( B, vecs1[j] );
                        for m in mons do
                            m1:= MakeWord( m ); Append( m1, [i,1] );
                            ev:= ShallowCopy( nulev );
                            CollectWordOrFail( col, ev, m1 );
                            num:= 0;
                            for l in [1..Length(cf)] do
                                if cf[l]<>0 then
                                    num:= num + cf[l]*
                                          EvaluateFunction( ff[l], ev );
                                fi;
                            od;
                            Add(vv,num);
                        od;

                        cf:= Coefficients( B1, vv );
                        if not ForAll( cf, x -> IsInt( x ) ) then
                            Add( vecs1, vv );
                            vecs1:= TriangulizeRows(vecs1)[1];
                            changeocc:= true;
                            break;
                        else
                            Add( M, Coefficients( B1, vv ) );
                        fi;

                    od;

                    Add( exrep, TransposedMat( M ) );

                od;
            fi;

            if not changeocc then done:= true; fi;

        od;


        # If the representation we get is a group representation, then we are
        # happy, if not then we increase the degree.

        isrep:= true;

        for i in [new..nogen] do
            if not isrep then break; fi;
            for j in [i+1..nogen] do

                # We calculate `ev' such that
                # u_j*u_i = u_i*u_j*ev, and we check whether the matrices
                # satisfy this relation.
                ev:= List( [1..nogen], x -> 0 );
                CollectWordOrFail( col, ev, [j,-1,i,-1,j,1,i,1] );
                M:= exrep[1]^0;
                for k in [new..Length(ev)] do
                    if ev[k] <> 0 then
                       M:= M*( exrep[k-new+1]^ev[k] );
                    fi;
                od;
                M:= exrep[j-new+1]*M; M:= exrep[i-new+1]*M;
                if M <> exrep[j-new+1]*exrep[i-new+1] then
                   isrep:= false; break;
                fi;
            od;
        od;

        if not isrep then

           # We increase the degree and compute our new guess for a
           # discriminating set.
           deg:=deg+1;
           newmons:= [];
           tup:= UnorderedTuples( inds, deg );
           for j in [1..Length(tup)] do
               ev:= ShallowCopy( nulev );
               for k in [1..Length(tup[j])] do
                   ev[tup[j][k]]:= ev[tup[j][k]]+1;
               od;
               Add( newmons, ShallowCopy(ev) );
           od;

           for i in [1..Length(vecs)] do
               Append( vecs[i], List( newmons, w
                            -> EvaluateFunction( ff[i], w ) ) );
           od;

           Append( mons, newmons );

        else
           return exrep;
        fi;

    od;  # end of big loop `while true ..etc'

end );


BindGlobal( "RepresentationForPcpCollector", function( col )

  local n,m,mats,i;

  n:= NumberOfGenerators( col );
  m:=IdentityMat(2);
  m[1][2]:=1;
  mats:=[m];
  for i in [2..n] do
    mats:= ExtendRep( col, n-i+1, mats );
  od;
  return mats;
end );

##
##
#### End of Willem's code ###################################################

InstallMethod( UnitriangularMatrixRepresentation,
        "for torsion free fin. gen. nilpotent pcp-groups",
        true,
        [ IsPcpGroup and IsNilpotentGroup ],
        0,
function( tgroup )
    local  coll,  mats,  mgroup,  phi;

    ## Does the group have power relations?
    if not IsTorsionFree( tgroup ) then
        Error("there are power relations in the collector of the pcp-group");
        ## Here we could compute the upper central series and construct an
        ## isomorphism to a group defined along the upper central series.
    fi;

    coll := Collector( tgroup );
    mats := LowerUnitriangularForm( RepresentationForPcpCollector( coll ) );

    mgroup := Group( mats, mats[1]^0 );
    UseIsomorphismRelation( tgroup, mgroup );

    phi := GroupHomomorphismByImagesNC( tgroup, mgroup,
                   GeneratorsOfGroup(tgroup),
                   GeneratorsOfGroup(mgroup) );
    SetIsBijective( phi, true );
    SetIsHomomorphismIntoMatrixGroup( phi, true );
    # FIXME: IsHomomorphismIntoMatrixGroup should perhaps be
    # a plain filter not a property. Especially since no methods
    # for it are installed.

    return phi;
end );

[ Dauer der Verarbeitung: 0.6 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge