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


Quelle  onecohom.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Frank Celler, Alexander Hulpke.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  This file contains the methods for operations for the 1-Cohomology
##


#############################################################################
##
#F  TriangulizedGeneratorsByMatrix(<gens>,<M>,<F>)
##  triangulize and make base
##
InstallGlobalFunction(TriangulizedGeneratorsByMatrix,function (gens,M,F)
local   m, n, i, j, k, a, r,z, z0;

    gens:=ShallowCopy(gens);
    M:=ShallowCopy(M);
    # get the size of the matrix
    m:=Length(M);
    n:=Length(M[1]);

    # run through all columns of the matrix
    z0:=Zero(F);
    i :=0;
    for k in [1 .. n] do
        j:=i+1;
        while j<= m and M[j][k] = z0 do
          j:=j+1;
        od;
        if j<= m  then
            i:=i+1;
            z:=M[j][k]^-1;
            a:=gens[j]; gens[j]:=gens[i]; gens[i]:=a^IntFFE(z);
            r:=M[j];  M[j]:=M[i];  M[i]:=z*r;
            for j in [1 .. m] do
                z:=M[j][k];
                if  i<>j and z<>z0  then
                    gens[j]:=gens[j] / (gens[i]^IntFFE(z));
                    M[j]:=M[j] - z*M[i];
                fi;
            od;

        fi;
    od;

    n:=[[],[]];
    r:=0*M[1];
    for i in [1 .. m] do
        if M[i]<>r  then
            Add(n[1],gens[i]);
            Add(n[2],M[i]);
        fi;
    od;
    return n;

end);


##  For all following functions,the group is given as second argument to
##  allow dispatching after the group type


BindGlobal( "OCAddGeneratorsPcgs", function(ocr,group)
local   gens;

    if not IsBound(ocr.pcgs) then
      ocr.pcgs:=ParentPcgs(NumeratorOfModuloPcgs(ocr.modulePcgs));
    fi;

    Info(InfoCoh,2,"OCAddGenerators2: using standard generators");
    if IsBound(ocr.pPrimeSet)  then
        Info(InfoCoh,3,"OCAddGenerators2: p prime set is given ",
               "for standard generating set");
    fi;
    if IsBound(ocr.smallGeneratingSet)  then
       Info(InfoCoh,3,"OCAddGenerators2: small generating set is given ",
              "for standard generating set");
    fi;

    if not IsBound(ocr.generators) then
      Info(InfoCoh,2,"setting new generators");
      ocr.generators:=InducedPcgs(ocr.pcgs,group)
                          mod NumeratorOfModuloPcgs(ocr.modulePcgs);
    fi;

    Info(InfoCoh,2,"OCAddGenerators2: ",Length(ocr.generators),
      " generators");

    if IsBound(ocr.normalIn)  then
        if not ForAll(ocr.module,i->i in ocr.normalIn)  then
            gens:=InducedPcgs(ocr.pcgs,ocr.normalIn);
        else
            gens:=AsList(InducedPcgs(ocr.pcgs,ocr.normalIn) mod
                       ocr.modulePcgs);
        fi;
        ocr.normalGenerators:=gens;
    fi;

end );

BindGlobal( "OCAddGeneratorsGeneral", function(ocr)
local  hom,fg,fpi,fpg,nt,fam;

  if IsBound(ocr.normalIn)  then
      Error("normalizing subgroup not allowed in general case");
  fi;

  if IsBound(ocr.pPrimeSet)  then
      Error("p prime set given in general case");
  fi;

  if IsBound(ocr.factorpres) then
    # see if factor presentation is known already
    return;
  fi;

  nt:=SubgroupNC(ocr.group,NumeratorOfModuloPcgs(ocr.modulePcgs));
  if IsBound(ocr.factorfphom) and not IsBound(ocr.generators) then
    Info(InfoCoh,1,"using provided presentation");
    hom:=ocr.factorfphom;
    fpg:=FreeGeneratorsOfFpGroup(Range(hom));
    ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(hom))];
    ocr.generators:=List(GeneratorsOfGroup(Range(hom)),
                          i->PreImagesRepresentative(hom,i));

  else
    if (Index(ocr.group,nt)>Size(nt)^3
          or Index(ocr.group,nt)>500000) and
          (not KnownNaturalHomomorphismsPool(ocr.group,nt) or
          DegreeNaturalHomomorphismsPool(ocr.group,nt)>10000) then
      # computing a factor representation may be too hard
      hom:=false;
    else
      hom:=NaturalHomomorphismByNormalSubgroup(ocr.group,nt);

      fg:=Image(hom,ocr.group);
      ocr.factormap:=hom;
    fi;

    if hom<>false and (IsSolvableGroup(Range(hom))
      or (IsPermGroup(Range(hom)) and Length(MovedPoints(Range(hom)))
                             <Length(MovedPoints(ocr.group))*2)
      or (HasIsomorphismFpGroup(fg) and not IsBound(ocr.generators)))
    then
      Info(InfoCoh,1,"using factor representation");
      if IsBound(ocr.generators) then
        fpi:=IsomorphismFpGroupByGeneratorsNC(fg,List(ocr.generators,
                                                    i->Image(hom,i)),"f");
      else
        fpi:=IsomorphismFpGroup(fg:noshort:=true);
      fi;
      fpg:=FreeGeneratorsOfFpGroup(Range(fpi));
      ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi)),
                      List(GeneratorsOfGroup(Range(fpi)),
                            i->PreImagesRepresentative(fpi,i))];
      if not IsBound(ocr.generators) then
        ocr.generators:=List(ocr.factorpres[3],i->PreImagesRepresentative(hom,i));
      fi;


    elif IsBound(ocr.generators) then
      Info(InfoCoh,1,"using group representation");
      fpi:=IsomorphismFpGroupByGeneratorsNC(ocr.group,ocr.generators,"f");
#      else # old code
#       fpi:=IsomorphismFpGroup(ocr.group:noshort:=true);
#       ocr.generators:=List(MappingGeneratorsImages(fpi)[2],
#                           i->PreImagesRepresentative(fpi,i));
#      fi;
      fpg:=FreeGeneratorsOfFpGroup(Range(fpi));
      ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi))];

      # add generating system for ocr.module to obtain a presentation of the
      # factor group

      fpi:= GroupHomomorphismByImagesNC(ocr.group,
                                        FreeGroupOfFpGroup(Range(fpi)),
                                        ocr.generators,fpg);
      ocr.factorpres[2]:=Union(ocr.factorpres[2],
                      List(NumeratorOfModuloPcgs(ocr.modulePcgs),
                            i->ImagesRepresentative(fpi,i:noshort:=true)));
    else
      # build suitable pres for factor
      Info(InfoCoh,1,"using group rep and series for factor");
      fpi:=IsomorphismFpGroupByChiefSeriesFactor(ocr.group,"f",nt);
      fam:=FamilyObj(One(Range(fpi)));
      fpg:=FreeGeneratorsOfFpGroup(Range(fpi));
      ocr.generators:=List(fpg,i->PreImagesRepresentative(fpi,
         ElementOfFpGroup(fam,i)));
      ocr.factorpres:=[fpg,RelatorsOfFpGroup(Range(fpi)),ocr.generators];
    fi;
  fi;

  Info(InfoCoh,1,Length(ocr.generators)," generators,",
                 Length(ocr.factorpres[2])," relators");

end );

#############################################################################
##
#F  OCAddGenerators(<ocr>,<group>)  . . . . . . . . . add generators,local
##
InstallGlobalFunction(OCAddGenerators,function(ocr,G)
  if IsBound(ocr.generatorsAdded) then
    return; # avoid duplicate calls
  fi;
  ocr.generatorsAdded:=true;

  # though using the method selection would be nicer,here the decisions are
  # that involved we actually have to use a dispatcher
  if IsBound(ocr.inPcComplement) # the pc complement routines interface
                                 # directly,giving generators that form an
                                 # pcgs
     or ((IsPcGroup(G) or
       (IsBound(ocr.generators) and IsGeneralPcgs(ocr.generators)))
       and not IsBound(ocr.factorpres)) then
    OCAddGeneratorsPcgs(ocr,G);
  else
    OCAddGeneratorsGeneral(ocr);
  fi;
end);


#############################################################################
##
#F  OCAddMatrices(<ocr>,<G>) . . . . . . . . add operation matrices,local
##
InstallGlobalFunction(OCAddMatrices,function(ocr,G)
local i,base;

    # If<ocr>already has a record component 'matrices',nothing is done.
    if IsBound(ocr.matrices)  then
        return;
    fi;
    Info(InfoCoh,2,"OCAddMatrices: computes linear operations");

    # Construct field and log table.
    base:=ocr.modulePcgs;

    if Length(base)=0 then
        Info(InfoCoh,2,"OCAddMatrices: module is trivial");
        return;
    else
        ocr.char :=RelativeOrderOfPcElement(base,base[1]);
        ocr.field:=GF(ocr.char);
        ocr.one:=One(ocr.field);
        ocr.zero:=Zero(ocr.field);
        # logTable is used by 'NextCentralCO'
        ocr.logTable:=[];
        for i in [1 .. ocr.char - 1] do
            ocr.logTable[LogFFE(i*One(ocr.field),
                                      PrimitiveRoot(ocr.field))+1]:=i;
        od;
    fi;

    # 'moduleMap' is constructed using 'Exponents'.
    ocr.moduleMap:=function(x)
                       x:=ExponentsOfPcElement(ocr.modulePcgs,x)* ocr.one;
                       return ImmutableVector(ocr.field,x);
                     end;
    ocr.matrices:=LinearOperationLayer(ocr.generators,ocr.modulePcgs);
    ocr.identityMatrix:=ImmutableMatrix(ocr.field,
        IdentityMat(Length(ocr.modulePcgs),ocr.field));
#    List(ocr.matrices,IsMatrix);
#    IsMatrix(ocr.identityMatrix);
#T ??

    # Do the same for the operations of 'normalIn' if present.
    if IsBound(ocr.normalIn)  then
        if not IsBound(ocr.normalMatrices)  then
            ocr.normalMatrices:=LinearOperationLayer(ocr.normalGenerators,
                ocr.modulePcgs);
#           List(ocr.normalMatrices,IsMatrix);
        fi;
    fi;

    # Construct the inverse of 'moduleMap'.
    ocr.vectorMap:=function(v)
        local   wrd, i;
        wrd:=One(ocr.modulePcgs[1]);
        for i in [1 .. Length(v)] do
            if v[i]<>ocr.zero  then
                wrd:=wrd*ocr.modulePcgs[i]^IntFFE(v[i]);
            fi;
        od;
        return wrd;
    end;

end);

#############################################################################
##
#F  OCAddToFunctions(<ocr>) . . . . . . . . . . add conversion,local
##
##
InstallGlobalFunction(OCAddToFunctions,function(ocr)
local   base, dim, gens;

    # Get the module generators.
    base:=ocr.modulePcgs;
    dim :=Length(base);

    # If 'smallGeneratingSet' is given,neither 'cocycle' nor 'list' need the
    # entries at the nongenerators.
    if not IsBound(ocr.cocycleToList)  then
        Info(InfoCoh,2,"OCAddToFunctions: adding 'cocycleToList'");
        ocr.cocycleToList:=function(c)
            local   w, i, j, k, L;
            L:=[];
            k:=0;
            for i in [1 .. Length(c) / dim] do
                w:=One(base[1]);
                for j in [1 .. dim] do
                    if c[k+j]<>ocr.zero  then
                        w:=w*base[j]^IntFFE(c[k+j]);
                    fi;
                od;
                Add(L,w);
                k:=k+dim;
            od;
            return L;
        end;
    fi;

    # 'listToCocycle' is almost trivial.
    if not IsBound(ocr.listToCocycle)  then
        Info(InfoCoh,2,"OCAddToFunctions: adding 'listToCocycle'");
        ocr.listToCocycle:=function(L)
            local   c, n;
            c:=[];
            for n in L do
                Append(c,ocr.moduleMap(n));
            od;
            #IsRowVector(c);
            ConvertToVectorRep(c,ocr.field);
            return ImmutableVector(ocr.field,c);
        end;
    fi;

    # If 'complement' is unknown,the following  function does not make sense,
    # so just return.
    if not IsBound(ocr.complement)  then
        Info(InfoCoh,2,"OCAddToFunctions: no complement,returning");
        return;
    fi;

    gens:=ocr.complementGens;

    # If  'smallGeneratingSet'  is  not present,just correct 'complement' by
    # the  list  'cocycleToList'. Otherwise we need to compute the correction
    # with the use of 'bigMatrices' and 'bigVectors'.
    if not IsBound(ocr.cocycleToComplement)  then
        Info(InfoCoh,2,"OCAddToFunctions: adding 'cocycleToComplement'");
        if not IsBound(ocr.smallGeneratingSet)  then
            ocr.cocycleToComplement:=function(c)
                local   L, i;
                L:=ocr.cocycleToList(c);
                for i in [1 .. Length(L)] do
                    L[i]:=gens[i]*L[i];
                od;
                return GroupByGenerators(L,One(base[1]));
            end;
        else

            # Get  the correcting list. The nongenerator correction are given
            # by  m_i + n_1*C_ij+... for i a nongenerator index and j a
            # generator index.  m_i  is  stored in<bigVectors>and C_ij is
            # stored in<bigMatrices>.
            ocr.cocycleToComplement:=function(c)
                local   L, i, n, j;
                L:=[];
                for i in [1 .. Length(c) / dim] do
                    n:=c{[(i-1)*dim+1 .. i*dim]};
                    L[ocr.smallGeneratingSet[i]]:=n;
                od;
                for i in [1 .. Length(gens)] do
                    if not IsBound(L[i])  then
                        n:=ocr.bigVectors[i];
                        for j in ocr.smallGeneratingSet do
                            n:=n+L[j]*ocr.bigMatrices[i][j];
                        od;
                        L[i]:=n;
                    fi;
                od;
                for i in [1 .. Length(L)] do
                    L[i]:=gens[i]*ocr.vectorMap(L[i]);
                od;
                return GroupByGenerators(L,One(base[1]));
            end;
        fi;
    fi;

    # As the IGS might be used especially here,first do not bind
    OCAddToFunctions2(ocr,ocr.generators);

end);

InstallMethod(OCAddToFunctions2,"pc group",true,[IsRecord,IsModuloPcgs],
  2,function(ocr,pcgs)
local  gens;

  gens:=ocr.complementGens;


  if not IsBound(ocr.complementToCocycle)  then

      ocr.origgens:=ocr.generators;
      Info(InfoCoh,2,"OCAddToFunctions: adding 'complementToCocycle'");
      if not IsBound(ocr.smallGeneratingSet)  then
          ocr.complementToCocycle:=function(K)
              local   L, i;
              # get the generators corresponding to the pcgs
              L:=CorrespondingGeneratorsByModuloPcgs(ocr.origgens,
                                                     GeneratorsOfGroup(K));
              for i in [1 .. Length(gens)] do
                  L[i]:=LeftQuotient(gens[i],L[i]);
              od;
              return ocr.listToCocycle(L);
          end;
      else
          Error("not yet implemented");
          ocr.complementToCocycle:=function(K)
              local   L, S, i, j;
              L:=CanonicalPcgs(InducedPcgsByGenerators(ocr.generators,
                               GeneratorsOfGroup(K)));
              S:=[];
              for i in [1 .. Length(ocr.smallGeneratingSet)] do
                  j:=ocr.smallGeneratingSet[i];
                  S[i] :=LeftQuotient(gens[j],L[j]);
              od;
              return ocr.listToCocycle(S);
          end;
      fi;
  fi;

end);

InstallMethod(OCAddToFunctions2,"generic",true,[IsRecord,IsList],0,
function(ocr,gens)
local Ngens;

  gens:=ocr.complementGens;

  if not IsBound(ocr.complementToCocycle)  then
      Info(InfoCoh,2,"OCAddToFunctions: adding 'complementToCocycle'");
      if not IsBound(ocr.smallGeneratingSet)  then
          Ngens:=NumeratorOfModuloPcgs(ocr.modulePcgs);
          ocr.complementToCocycle:=function(K)
          local   L,i,hom;
            # create a homomorphism to decompose into generators
            hom:= GroupHomomorphismByImagesNC(ocr.group,K,
                   Concatenation(GeneratorsOfGroup(K),Ngens),
                   Concatenation(GeneratorsOfGroup(K),List(Ngens,i->One(K))));

            L:=[];
            for i in [1 .. Length(gens)] do
                L[i]:=LeftQuotient(gens[i],
                            ImagesRepresentative(hom,gens[i]));
            od;
            return ocr.listToCocycle(L);
          end;
      else
         Error("this should not happen");
      fi;
  fi;

end);

#############################################################################
##
#F  OCAddCentralizer(<ocr>,<B>)  . . . . . . . add centralizer by base<B>
##
BindGlobal( "OCAddCentralizer", function(ocr,B)
    ocr.centralizer:=GroupByGenerators(List(B,ocr.vectorMap),
                                          One(ocr.group));
end );


#############################################################################
##
#F  OCOneCoboundaries(<ocr>)    . . . . . . . . . . one cobounds main routine
##
InstallGlobalFunction(OCOneCoboundaries,function(ocr)
local   B, S, L, T, i, j;

    # Add the important record components for coboundaries.
    if IsBound(ocr.oneCoboundaries)  then
        return ocr.oneCoboundaries;
    fi;

    Info(InfoCoh,1,"OCOneCoboundaries: coboundaries and centralizer");
    OCAddGenerators(ocr,ocr.group);
    OCAddMatrices(ocr,ocr.generators);

    # Construct (1 - M[1], ...,1 - M[n]).
    if IsBound(ocr.smallGeneratingSet)  then
        S:=ocr.smallGeneratingSet;
    else
        S:=[1 .. Length(ocr.generators)];
    fi;
    L:=[];
    T:=ocr.identityMatrix;
    for i in [1 .. Length(T)] do
        L[i]:=[];
        for j in S do
            Append(L[i],T[i] - ocr.matrices[j][i]);
        od;
    od;
    IsMatrix(L);

    # If there are no equations,return.
    if Length(S) = 0  then
        Info(InfoCoh,1,"OCOneCoboundaries: group is trivial");
        ocr.oneCoboundaries:=FullRowSpace(ocr.field,0);
        ocr.centralizer:=SubgroupNC(ocr.group,ocr.modulePcgs);
        return ocr.oneCoboundaries;
    fi;

    # Find a base for the one coboundaries.
    B:=TriangulizedGeneratorsByMatrix(ocr.modulePcgs ,L,ocr.field);
    ocr.oneCoboundaries:=VectorSpace(ocr.field,B[2],Zero(ocr.field)*L[1]);

    ocr.triangulizedBase:=B[1];
    Info(InfoCoh,1,"OCOneCoboundaries: |B^1| = ",ocr.char,
               "^",Dimension(ocr.oneCoboundaries));
    ocr.heads:=[];
    j:=1;
    i:=1;
    while i<= Length(B[2]) and j<= Length(B[2][1]) do
        if B[2][i][j]<>ocr.zero  then
            ocr.heads[i]:=j;
            i:=i+1;
        fi;
        j:=j+1;
    od;

    # Now get the nullspace, this is the centralizer.
    OCAddCentralizer(ocr,NullspaceMat(L));
    Info(InfoCoh,1,"OCOneCoboundaries: |C| = ",ocr.char,
               "^",Length(GeneratorsOfGroup(ocr.centralizer)));
    OCAddToFunctions(ocr);
    return ocr.oneCoboundaries;

end);


#############################################################################
##
#F  OCConjugatingWord(<ocr>,<c1>,<c2>)  . . . . . . . . . . . . . . local
##
##  Compute a Word n in<ocr.module>such that<c1>^ n =<c2>.
##
InstallGlobalFunction(OCConjugatingWord,function(ocr,c1,c2)
local   B, w, v, j;

    B:=ocr.triangulizedBase;
    w:=One(ocr.modulePcgs[1]);
    v:=c2 - c1;
    for j in [1 .. Length(ocr.heads)] do
        #if IntFFE(v[ocr.heads[j]])<>false  then
        w:=w*B[j]^IntFFE(v[ocr.heads[j]]);
        #fi;
    od;
    return w;

end);


#############################################################################
##
#F  OCAddRelations(<ocr>,<gens>) . . . . . . . . . . .  add relations,local
##
InstallMethod(OCAddRelations,"pc group",true,[IsRecord,IsModuloPcgs],0,
function(ocr,gens )
local   p, w, r, i, j, k,mpcgs;


    # If<ocr>has a  record component 'relators',nothing is done.
    if IsBound(ocr.relators)  then
        return;
    fi;
    Info(InfoCoh,2,"OCAddRelations: computes pc-presentation");

    # Construct the factor pcgs

    mpcgs :=ocr.generators;

    # Start  with the power-relations. If g1^p = g2^3*g4^5*g5,then
    # the  relator  g1 ^ -p * g2 ^ 3 *g4^5*g5 is used,because it
    # contains only one negative exponent.
    ocr.relators:=[];
    for i in [1 .. Length(mpcgs)] do
        p:=RelativeOrders(mpcgs)[i];
        r:=rec(generators:=[i],powers:=[-p] );
        w:=ExponentsOfRelativePower(mpcgs,i);
        for j in [1 .. Length(w)] do
            if w[j]<>0  then
                Add(r.generators,j);
                Add(r.powers,w[j]);
            fi;
        od;
        r.usedGenerators:=Set(r.generators);
        Add(ocr.relators,r);
    od;

    # Now  compute  the  conjugated words. If g1^g2 = g3^5*g4^2,then
    # the  relator (g1^-1)^g2*g3^5*g4^2 is used,as it contains
    # only two negative exponents.
    for i in [1 .. Length(mpcgs) - 1] do
        for j in [i+1 .. Length(mpcgs)] do
            r:=rec(generators:=[i,j,i],powers:=[-1,-1,1]);
            w:=mpcgs[j]^mpcgs[i];
            w:=ExponentsOfPcElement(mpcgs,w);
            for k in [1 .. Length(w)] do
                if w[k]<>0  then
                    Add(r.generators,k);
                    Add(r.powers,w[k]);
                fi;
            od;
            r.usedGenerators:=Set(r.generators);
            Add(ocr.relators,r);
        od;
    od;

end);

InstallMethod(OCAddRelations,"perm group",true,[IsRecord,IsList],0,
function(ocr,gens )
local   r,rel,i,j,w;

  # If<ocr>has a  record component 'relators',nothing is done.
  if IsBound(ocr.relators)  then
      return;
  fi;
  Info(InfoCoh,2,"OCAddRelations: fetch presentation");

  # it is not the right place to get a presentation here,as we may have
  # chosen the wrong generators before. So we just fetch it.

  r:=ocr.factorpres[2];

  # now rewrite the relators into the OC form

  ocr.relators:=[];

  for i in r do
    rel:=rec(generators:=[],powers:=[]);

    w:=ExtRepOfObj(i);
    j:=1;
    while j<Length(w) do
      Add(rel.generators,w[j]);
      Add(rel.powers,w[j+1]);
      j:=j+2;
    od;

    rel.usedGenerators:=Set(rel.generators);
    Add(ocr.relators,rel);
  od;

end);

BindGlobal("OCTestRelations",function(ocr,gens)
local i,j,e,g;
  g:=GroupByGenerators(NumeratorOfModuloPcgs(ocr.modulePcgs));
  for i in ocr.relators do
    e:=One(gens[1]);
    for j in [1..Length(i.generators)] do
      e:=e*gens[i.generators[j]]^i.powers[j];
    od;
    if not e in g then
      Error("relator wrong");
    fi;
  od;
  return true;
end);

#############################################################################
##
#M  NormalRelations(<ocr>,<G>,<gens>)  . .  rels for normal complements,local
##
InstallMethod(OCNormalRelations,"pc group",
  true,[IsRecord,IsPcGroup,IsListOrCollection],0,
function(ocr,G,gens)
local   i,j,k,
        relations,
        r,
        w,mpcgs;

    Info(InfoCoh,2,"computes rels for normal complements");

    Error("this still has to be fixed!");

    mpcgs:=InducedPcgsByGeneratorsNC(ocr.pcgs,
               Concatenation(ocr.generators,ocr.modulePcgs)) mod
               ocr.modulePcgs;
    # Compute  g_i^s_j for all generators s_j in 'normalGenerators' and all
    # i in<generators>.
    relations:=[];
    for i in [1 .. Length(gens)] do
        for j in [1 .. Length(ocr.normalGenerators)] do
            r:=rec(generators:=[],
                      powers    :=[],
                      conjugated:=[i,j]);
            w:=ocr.generators[gens[i]]^ocr.normalGenerators[j];
            w:=ExponentsOfPcElement(mpcgs,w);
            for k in [1 .. Length(w)] do
                if w[k]<>0  then
                    Add(r.generators,k);
                    Add(r.powers,w[k]);
                fi;
            od;
            r.usedGenerators:=Set(r.generators);
            Add(relations,r);
        od;
    od;
    return relations;

end);


#############################################################################
##
#M  OCAddSumMatrices(<ocr>,<gens>)  . . . . . . . . . . . add sums,local
##
InstallMethod(OCAddSumMatrices,"pc group",true,[IsRecord,IsPcgs],0,
function(ocr,pcgs)
local   i, j;

    if not IsBound(ocr.maximalPowers)  then
        Info(InfoCoh,2,"maximal powers = relative orders");
        ocr.maximalPowers:=List(ocr.generators,
          i->RelativeOrderOfPcElement(pcgs,i));
    fi;

    # At  first  add  all  powers, such  that  powerMatrices[ i ][ j] is
    # matrices[ i ] ^j for j = 1 ... p,if p is the maximal power for the
    # i.th generator.
    if not IsBound(ocr.powerMatrices)  then
        Info(InfoCoh,2,"AddSumMatrices: adding power matrices");
        ocr.powerMatrices:=[];
        for i in [1 .. Length(ocr.matrices)] do
            ocr.powerMatrices[i]:=[ocr.matrices[i]];
            for j in [2 .. ocr.maximalPowers[i]] do
                ocr.powerMatrices[i][j] :=
                    ocr.powerMatrices[i][j - 1]*ocr.matrices[i];
            od;
        od;
    fi;

    # Now  all  sums, such  that sumMatrices[i][j] is the sum from k = 0
    # up to j - 1 over matrices[i]^k for j = 1 ... p.
    if not IsBound(ocr.sumMatrices)  then
        Info(InfoCoh,2,"AddSumMatrices: adding sum matrices");
        ocr.sumMatrices:=[];
        for i in [1 .. Length(ocr.matrices)] do
            ocr.sumMatrices[i]:=[ocr.identityMatrix];
            for j in [2 .. ocr.maximalPowers[i]] do
                ocr.sumMatrices[i][j] :=
                    ocr.sumMatrices[i][j-1]+ocr.powerMatrices[i][j-1];
            od;
        od;
    fi;

end);


InstallMethod(OCAddSumMatrices,"perm group",true,[IsRecord,IsList],0,
function(ocr,gens)
local   i,j;

    if not IsBound(ocr.maximalPowers)  then
        Info(InfoCoh,2,"AddSumMatrices: maximal power = 1");
        ocr.maximalPowers:=List(ocr.generators,x->1);
    fi;

    # At  first  add  all  powers, such  that  powerMatrices[ i ][ j] is
    # matrices[ i ] ^j for j = 1 ... p,if p is the maximal power for the
    # i.th generator.
    if not IsBound(ocr.powerMatrices)  then
        Info(InfoCoh,2,"AddSumMatrices: adding power matrices");
        ocr.powerMatrices:=[];
        for i in [1 .. Length(ocr.matrices)] do
            ocr.powerMatrices[i]:=[ocr.matrices[i]];
            for j in [2 .. ocr.maximalPowers[i]] do
                ocr.powerMatrices[i][j] :=
                    ocr.powerMatrices[i][j - 1]*ocr.matrices[i];
            od;
        od;
    fi;

    # Now  all  sums, such  that sumMatrices[i][j] is the sum from k = 0
    # up to j - 1 over matrices[i]^k for j = 1 ... p.
    if not IsBound(ocr.sumMatrices)  then
        Info(InfoCoh,2,"AddSumMatrices: adding sum matrices");
        ocr.sumMatrices:=[];
        for i in [1 .. Length(ocr.matrices)] do
            ocr.sumMatrices[i]:=[ocr.identityMatrix];
            for j in [2 .. ocr.maximalPowers[i]] do
                ocr.sumMatrices[i][j] :=
                    ocr.sumMatrices[i][j-1]+ocr.powerMatrices[i][j-1];
            od;
        od;
    fi;

end);

#############################################################################
##
#F  OCEquationMatrix(<ocr>,<r>,<n>)  . . . . . . . . . . . . . . .  local
##
InstallGlobalFunction(OCEquationMatrix,function(ocr,r,n)
local   mat, i, j, v, vv;

    Info(InfoCoh,3,"OCEquationMatrix: matrix number ",n);
    mat:=ocr.identityMatrix - ocr.identityMatrix;
    if not n in r.usedGenerators  then return mat;  fi;

    #  For j:=generators[i], v:=powers[i], M operations:
    #
    #    if j = n and v>0,then
    #           mat = mat*M[j]^v+sum_{k=0}^{v-1} M[j]^k
    #    if j = n and v<0,then
    #           mat = (mat - sum_{k=0}^{-v-1} M[j]^k)*M[j]^v
    #    if j<>n,then
    #           mat = mat*M[j]^v
    #
    for i in [1 .. Length(r.generators)] do
        j :=r.generators[i];
        vv:=r.powers[i];

        # Repeat,until we used up all powers.
        while vv<>0 do
            if AbsInt(vv)>AbsInt(ocr.maximalPowers[j])  then
                v :=SignInt(vv)*ocr.maximalPowers[j];
                vv:=vv - v;
            else
                v :=vv;
                vv:=0;
            fi;
            if j = n and v>0   then
                mat:=mat*ocr.powerMatrices[j][v]+ocr.sumMatrices[j][v];
            elif j = n and v<0  then
                mat:=  (mat - ocr.sumMatrices[j][-v])
                      *(ocr.powerMatrices[j][-v]^-1);
            elif j<>n and v>0  then
                mat:=mat*ocr.powerMatrices[j][v];
            elif j<>n and v<0  then
                mat:=mat*(ocr.powerMatrices[j][-v]^-1);
            else
                Info(InfoCoh,2,"OCEquationMatrix: zero power");
            fi;
        od;
    od;

    # if<r>  has an entry   'conjugated'  the records  is  no relator for a
    # presentation,but belongs to relation
    #         (g_i n_i)^s_j = r
    # which is used to determinate  normal  complements.  [i,j]  is bound  to
    # 'conjugated'.  If i<><n>,we can  forget about it,but otherwise -s_j
    # must be added.
    if IsBound(r.conjugated) and r.conjugated[1] = n  then
        mat:=mat - ocr.normalMatrices[r.conjugated[2]];
    fi;
    return mat;

end);


#############################################################################
##
#M  OCAddBigMatrices(<ocr>,<generators>)   . . . . . . . . . . . . . local
##
InstallMethod(OCAddBigMatrices,"general",true,[IsRecord,IsList],0,
function(ocr,G)
local   i, j, n, w, small, nonSmall;

    # If no small generating set is known simply return.
    if not IsBound(ocr.smallGeneratingSet)  then
        Info(InfoCoh,2,"AddBigMatrices: no small generating set");
        return;
    fi;
    small:=ocr.smallGeneratingSet;
    nonSmall:=Difference([1 .. Length(ocr.generators)],small);
    if not IsBound(ocr.bigMatrices)  then
        ocr.bigMatrices:=List([1 .. Length(ocr.generators)],x->[]);
        Info(InfoCoh,2,"AddBigMatrices: adding bigMatrices");
        for i in nonSmall do
            for j in small do
                ocr.bigMatrices[i][j]:=OCEquationMatrix(ocr,
                    ocr.generatorsInSmall[i],j);
            od;
        od;
    fi;

    # Compute n_(i) for non small generators i.
    if not IsBound(ocr.bigVectors)  then
        Info(InfoCoh,2,"AddBigMatricesOC: adding bigVectors");
        ocr.bigVectors:=[];
        for i in nonSmall do
            n:=ocr.generators[i]^-1;
            w:=ocr.generatorsInSmall[i];
            for j in [1 .. Length(w.generators)] do
                n:=n*ocr.generators[w.generators[j]]^w.powers[j];
            od;
            ocr.bigVectors[i]:=ocr.moduleMap(n);
        od;
    fi;

end);


#############################################################################
##
#F  OCSmallEquationMatrix(<ocr>,<r>,<n>)  . . . . . . . . . . . . . local
##
InstallGlobalFunction(OCSmallEquationMatrix,function(ocr,r,n)
local   mat, i, j, v, vv;

    Info(InfoCoh,3,"OCSmallEquationMatrix: matrix number ",n);
    mat:=ocr.identityMatrix - ocr.identityMatrix;

    #<n>must a small generator.
    if not n in ocr.smallGeneratingSet  then
      Error("<n> is no small generator");
    fi;

    # Warning: if<n>is not in <r.usedGenerators>we cannot  return,as the
    # nonsmall generators may yield a result.

    # For j:=generators[i], v:=powers[i], M operations:
    #
    # If j is a small generator,everything is as usual.
    #
    #    if j = n and v>0, then
    #          mat = mat*M[j]^v+sum_{k=0}^{v-1} M[j]^k
    #    if j = n and v<0, then
    #          mat = (mat - sum_{k=0}^{-v-1} M[j]^k)*M[j]^v
    #    if j<>n,then
    #          mat = mat*M[j]^v
    #
    # If j is not  a small generator, then j<>n.   But  we need to correct
    #<mat>using the<bigMatrices>:
    #
    #   n_j = n_(j)+...+n_n^C_jn+...
    #
    #   if v>0,then
    #         mat = mat*M[j]^v+C_jn*sum_{k=0}^{v-1} M[j]^k
    #   If v<0,then
    #         mat = (mat - C_jn*sum_{k=0}^{-v-1} M[j]^k)*M[j]^v
    #
    for i in [1 .. Length(r.generators)] do
        j :=r.generators[i];
        vv:=r.powers[i];
        while vv<>0 do
            if AbsInt(vv)>AbsInt(ocr.maximalPowers[j])  then
                v :=SignInt(vv)*ocr.maximalPowers[j];
                vv:=vv - v;
            else
                v :=vv;
                vv:=0;
            fi;
            if j in ocr.smallGeneratingSet  then
                if j = n and v>0   then
                    mat:=mat*ocr.powerMatrices[j][v]
                          +ocr.sumMatrices[j][v];
                elif j = n and v<0  then
                    mat:=(mat - ocr.sumMatrices[j][-v])
                          *(ocr.powerMatrices[j][-v]^-1);
                elif j<>n and v>0  then
                    mat:=mat*ocr.powerMatrices[j][v];
                elif j<>n and v<0  then
                    mat:=mat*(ocr.powerMatrices[j][-v]^-1);
                else
                    Info(InfoCoh,2,"EquationMatrixOC: zero power");
                fi;
            else
                if v>0  then
                    mat:=mat*ocr.powerMatrices[j][v]
                          +ocr.bigMatrices[j][n]*ocr.sumMatrices[j][v];
                elif v<0  then
                    mat:=(mat-ocr.bigMatrices[j][n]*ocr.sumMatrices[j][-v])
                          *(ocr.powerMatrices[j][-v]^-1);
                else
                    Info(InfoCoh,2,"EquationMatrixOC: zero power");
                fi;
            fi;
        od;
    od;

    # If<r>  has an entry  <conjugated> the records  is  no relator for a
    # presentation,but belongs to relation
    #         (g_i n_i)^s_j =<r>
    # which is  used to determinate  normal complements.   [i,j] is  bound to
    # 'conjugated'.  If i<><n>,we can  forget about it,but  otherwise s_j
    # must be added. i is always a small generator.
    if IsBound(r.conjugated) and r.conjugated[1] = n  then
        mat:=mat - ocr.normalMatrices[r.conjugated[2]];
    fi;
    return mat;

end);


#############################################################################
##
#F  OCEquationVector(<ocr>,<r>)  . . . . . . . . . . . . . . . . . . local
##
InstallGlobalFunction(OCEquationVector,function(ocr,r)
local n,i;

  # If <r> has   an entry 'conjugated'   the records is  no relator  for  a
  # presentation,but belongs to relation
  #       (g_i n_i)^s_j =<r>
  # which is  used to determinate  normal  complements.   [i,j] is bound to
  # <conjugated>.
  if IsBound(r.conjugated)  then
    n:=(ocr.generators[r.conjugated[1]]
           ^ocr.normalGenerators[r.conjugated[2]])^-1;
  else
    n:=ocr.identity;
  fi;

  for i in [1 .. Length(r.generators)] do
    n:=n*ocr.generators[r.generators[i]]^r.powers[i];
  od;

  Assert(1,n in GroupByGenerators(NumeratorOfModuloPcgs(ocr.modulePcgs)));

  return ShallowCopy(ocr.moduleMap(n));

end);


#############################################################################
##
#F  OCSmallEquationVector(<ocr>,<r>)    . . . . . . . . . . . . . . . . local
##
InstallGlobalFunction(OCSmallEquationVector,function(ocr,r)
local   n, a, i, nonSmall, v, vv, j;

    # if<r>has  an entry 'conjugated'  the  records  is no relator   for  a
    # presentation,but belongs to relation
    #     (g_i n_i)^s_j =<r>
    # which is used to determinate normal complements.  [i,j] is bound  to
    # 'conjugated'. i is always a small generator.
    if IsBound(r.conjugated)  then
        n:=(ocr.generators[r.conjugated[1]]
              ^ocr.normalGenerators[r.conjugated[2]])^-1;
    else
        n:=ocr.identity;
    fi;

    # At first the vector of the relator itself.
    for i in [1 .. Length(r.generators)] do
        n:=n*ocr.generators[r.generators[i]]^r.powers[i];
    od;
    n:=ocr.moduleMap(n);

    # Each  non  small generators in<r>gives an additional vector. It
    # must be shifted through the relator.
    nonSmall:=Difference([1 .. Length(ocr.generators)],
                            ocr.smallGeneratingSet);
    a:=n - n;
    for i in [1 .. Length(r.generators)] do
        j :=r.generators[i];
        vv:=r.powers[i];
        while vv<>0 do
            if AbsInt(vv)>AbsInt(ocr.maximalPowers[j])  then
                v :=SignInt(vv)*ocr.maximalPowers[j];
                vv:=vv - v;
            else
                v :=vv;
                vv:=0;
            fi;

            if j in nonSmall  then
                if v>0  then
                    a:=a*ocr.powerMatrices[j][v]+ocr.bigVectors[j]
                        *ocr.sumMatrices[j][v];
                elif v<0  then
                    a:=(a - ocr.bigVectors[j]
                        *ocr.sumMatrices[j][-v])
                        *(ocr.powerMatrices[j][-v]^-1);
                else
                    Info(InfoCoh,2,"OCSmallEquationVector: zero power");
                fi;
            else
                if v>0  then
                    a:=a*ocr.powerMatrices[j][v];
                elif v<0  then
                    a:=a*(ocr.powerMatrices[j][-v]^-1);
                else
                    Info(InfoCoh,2,"OCSmallEquationVector: zero power");
                fi;
            fi;
        od;
    od;

    return ShallowCopy(n+a);

end);


#############################################################################
##
#F  OCAddComplement(<ocr>,<K>) . . . . . . . . . . . . . . . . . . . local
##
InstallMethod(OCAddComplement,"pc group",true,
  [IsRecord,IsPcGroup,IsListOrCollection],0,
function(ocr,G,K)
    ocr.complementGens:=K;
    Assert(1,ForAll([1..Length(ocr.complementGens)],i->
             ExponentsOfPcElement(ocr.generators,ocr.complementGens[i])
             =ExponentsOfPcElement(ocr.generators,ocr.generators[i])));

    K:=InducedPcgsByGeneratorsNC(NumeratorOfModuloPcgs(ocr.generators),K);
    ocr.complement:=SubgroupNC(ocr.group,K);
end);

InstallMethod(OCAddComplement,"generic",true,
  [IsRecord,IsGroup,IsListOrCollection],0,
function(ocr,G,K)
    ocr.complement:=SubgroupNC(ocr.group,K);
    ocr.complementGens:=K;
end);


#############################################################################
##
#F  OCOneCocycles(<ocr>,<onlySplit>) . . . . . . one cocycles main routine
##
##  If<onlySplit>,'OCOneCocycles' returns 'false' as soon  as  possibly  if
##  the extension does not split.
##
InstallGlobalFunction(OCOneCocycles,function(ocr,onlySplit)
local   cobounds,cocycles,    # base of one coboundaries and cocycles
        dim,                # dimension of module
        gens,               # generator numbers
        len,                # number of generators
        K,                  # list of complement generators
        L0,                 # null vector
        S, R,               # linear system and right hand side
        rels,               # relations
        RS, RR,             # rel linear system and right hand side
        isSplit,            # is split extension
        N,                  # correct
        row,                # one row
        tmp,i,g,j,k,n;

    # If we know our cocycles return them.
    if IsBound(ocr.oneCocycles)  then
        return ocr.oneCocycles;
    fi;

    # Assume it does split. This may change later.
    isSplit:=true;

    ocr.identity:=One(ocr.modulePcgs[1]);
    Info(InfoCoh,1,"OCOneCocycles: computes cocycles and cobounds");

    # We  need the generators of the factorgroup with relations,all matrices
    # and  the  cobounds.  If  the 'smallGeneratingSet' is given,get the big
    # matrices and vectors.
    cobounds:=BasisVectors(Basis(OCOneCoboundaries(ocr)));

    # If  we  are only want normal complements,the group of cobounds must be
    # trivial,  otherwise  there  are  no  normal  ones  as  the  conjugated
    # complements correspond with the cobounds.
    if IsBound(ocr.normalIn) and cobounds<>[]  then
        Info(InfoCoh,1,"OneCocyclesCO: no normal complements");
        return false;
    fi;

    # Initialize the relations and sum/big matrices.
    OCAddRelations(ocr,ocr.generators);
    Assert(1,OCTestRelations(ocr,ocr.generators)=true);

    OCAddSumMatrices(ocr,ocr.generators);
    if IsBound(ocr.smallGeneratingSet)  then
        OCAddBigMatrices(ocr,ocr.generators);
    fi;

    # Now initialize  a  matrix  with  will  hold the triangulized system of
    # linear  equations.  If  'smallGeneratingSet'  is  given  use  this, if
    # 'pPrimeSet' is given do not use those.
    dim:=Length(ocr.modulePcgs);
    if IsBound(ocr.smallGeneratingSet)  then
        gens:=ocr.smallGeneratingSet;
        len :=Length(ocr.smallGeneratingSet);
        K   :=ShallowCopy(ocr.generators);
    elif IsBound(ocr.pPrimeSet)  then
        Info(InfoCoh,2,"OCOneCocycles: computing coprime complement");
        gens:=Difference([1 .. Length(ocr.generators)],ocr.pPrimeSet);
        gens:=Set(gens);
        len :=Length(ocr.generators) - Length(ocr.pPrimeSet);
        K   :=OCCoprimeComplement(ocr,ocr.generators);
        ocr.generators:=ShallowCopy(K);
    else
        len :=Length(ocr.generators);
        gens:=[1 .. len];
        K   :=ShallowCopy(ocr.generators);
    fi;
    Info(InfoCoh,2,"OCOneCocycles: ",len," generators");

    # Initialize system.
    tmp:=ocr.moduleMap(ocr.identity);
    L0 :=Concatenation(List([1 .. len],x->tmp));
    L0:=ImmutableVector(ocr.field,L0);
    S:=List([1 .. len*dim],x->L0);
    #R:=List([1 .. len*dim],x->Zero(ocr.field));
    R:=ListWithIdenticalEntries(len*dim,Zero(ocr.field));

    # Get  the  linear  system  for one relation and append it to the already
    # triangulized system.
    Info(InfoCoh,2,"OCOneCocycles: constructing linear equations: ");

    # Get all relations.
    if IsBound(ocr.normalIn)  then
        rels:=Concatenation(ocr.relators,
                               OCNormalRelations(ocr,ocr.group,gens));
    else
        rels:=ocr.relators;
    fi;

    for i in [1 .. Length(rels)] do
        Info(InfoCoh,2,"  relation ",i," (",Length(rels),")");
        RS:=[];
        if IsBound(ocr.smallGeneratingSet)  then
            for g in gens do
                Append(RS,OCSmallEquationMatrix(ocr,rels[i],g));
            od;
            RR:=OCSmallEquationVector(ocr,rels[i]);
            MultVector(RR,-One(ocr.field));

        else
            for g in gens do
                Append(RS,OCEquationMatrix(ocr,rels[i],g));
            od;
            RR:=OCEquationVector(ocr,rels[i]);
            MultVector(RR,-One(ocr.field));

        fi;

        # The is a system for x M = v so transpose.
        RS:=MutableTransposedMat(RS);

        # Now append this to the triangulized system.
        for j in [1 .. Length(RS)] do
            k:=1;
            while RS[j]<>L0 do
                while RS[j][k] = ocr.zero do
                    k:=k+1;
                od;
                if S[k][k]<>ocr.zero  then
                    RR[j]:=RR[j] - RS[j][k]*R[k];
                    RS[j]:=RS[j] - RS[j][k]*S[k];
                else
                    R[k]:=RS[j][k]^-1*RR[j];
                    S[k]:=RS[j][k]^-1*RS[j];
                    RS[j]:=L0;
                    RR[j]:=0*RR[j];
                fi;
            od;
            if RR[j] <>ocr.zero  then
                Info(InfoCoh,1,"OCOneCocycles: no split extension");
                isSplit:=false;
                if onlySplit  then
                    return isSplit;
                fi;
            fi;
        od;
        IsMatrix(RS);
    od;

    # Now remove all  entries above the  diagonal.  Let's see  if a  solution
    # exist.  As system <S> is triangulized all we have to do,is to check if
    # right side <R> is null,where the diagonal is null.
    Info(InfoCoh,2,"OCOneCocycles: computing nullspace and solution");
    for i in [1 .. Length(S)] do
        if S[i][i]<>ocr.zero  then
            for k in [1 .. i-1] do
                if S[k][i]<>ocr.zero  then
                    R[k]:=R[k] - S[k][i]*R[i];
                    S[k]:=S[k] - S[k][i]*S[i];
                fi;
            od;
        else
            if R[i]<>ocr.zero  then
                Info(InfoCoh,1,"OCOneCocycles: no split extension");
                isSplit:=false;
                if onlySplit  then
                    return isSplit;
                fi;
            fi;
        fi;
    od;

    # As <system>is triangulized,the right side is now the solution. So if
    # 'smallGeneratingSet'   is  not  given, we  only  need  to  modify  the
    #<complement> generators, which  are  not in 'pPrimeSet'. Otherwise we
    # must  blow  up  the  cocycle to cover all generators not only the small
    # ones.
    if isSplit  then
        if not IsBound(ocr.smallGeneratingSet)  then
            N:=ocr.cocycleToList(R);
            for i in [1 .. Length(N)] do
                K[gens[i]]:=K[gens[i]]*N[i];
            od;
        else
            N:=[];
            for i in [1 .. Length(R) / dim] do
                n:= R{ [(i-1)*dim+1 .. i*dim] };
                N[ocr.smallGeneratingSet[i]]:=n;
            od;
            for i in [1 .. Length(K)] do
                if not IsBound(N[i])  then
                    n:=ocr.bigVectors[i];
                    for j in ocr.smallGeneratingSet do
                        n:=n+N[j]*ocr.bigMatrices[i][j];
                    od;
                else
                    n:=N[i];
                fi;
                K[i]:=K[i]*ocr.vectorMap(n);
            od;
        fi;
        OCAddComplement(ocr,ocr.group,K);
        OCAddToFunctions(ocr);
    fi;

    # System<S>is triangulized, get the nullspace.
    cocycles:=[];
    for i in [1 .. Length(S[1])] do
        if  S[i][i] = ocr.zero  then
            row:=ShallowCopy(L0);
            for k in [1 .. i-1] do
                row[k]:=S[k][i];
            od;
            row[i]:=- One(ocr.field);
            Add(cocycles,row);
        fi;
    od;
    IsMatrix(cocycles);

    # If  'pPrimeSet'  is  given, we  need  to  add  zeros to cocycle at the
    # positions  of  the pPrimeGenerators. Then the cobounds must be added in
    # order to get all cocycles.
    if IsBound(ocr.pPrimeSet)  then
        tmp:=ocr.moduleMap(ocr.identity);
        for j in [1 .. Length(cocycles)] do
            k:=0;
            row:=[];
            for i in [1 .. Length(ocr.generators)] do
                if not i in ocr.pPrimeSet  then
                    n:=cocycles[j]{ [k*dim+1 .. (k+1)*dim] };
                    Append(row,n);
                    k:=k+1;
                else
                    Append(row,tmp);
                fi;
            od;
            #IsRowVector(row);
            cocycles[j]:=ImmutableVector(ocr.field,row);
        od;
        Append(cocycles,cobounds);
        if cocycles<>[]  then
            cocycles:=BaseMat(cocycles);
        fi;
    else
        if cocycles<>[]  then
            TriangulizeMat(cocycles);
        fi;
    fi;
    ocr.oneCocycles:=VectorSpace(ocr.field,cocycles,
                              Zero(ocr.oneCoboundaries));
    Info(InfoCoh,1,"OCOneCocycles: order of cocycles ",ocr.char,
               "^",Dimension(ocr.oneCocycles));
    return ocr.oneCocycles;

end);


#############################################################################
##
#M  OneCoboundaries(<G>,<M>)    . . . . . . . . . . one cobounds of<G>/<M>
##
InstallGlobalFunction(OneCoboundaries,function(G,M)
local ocr;


  if not IsList(M) then
    if not IsElementaryAbelian(M) then
      Error("<M> must be elementary abelian");
    fi;
    M:=InducedPcgsWrtHomePcgs(M);
  fi;

  ocr:=rec(modulePcgs:=M);
  if IsGroup(G) then
    ocr.group:=G;
  else
    ocr.group:= GroupByGenerators(G);
    ocr.generators:=G;
  fi;

  OCOneCoboundaries(ocr);

  return rec(
      oneCoboundaries:=ocr.oneCoboundaries,
      generators     :=ocr.generators,
      cocycleToList  :=ocr.cocycleToList,
      listToCocycle  :=ocr.listToCocycle);

end);


#############################################################################
##
#F  OneCocycles(<G>,<M>) . . . . . . . . . . . . one cocycles of<G>/<M>
##
InstallGlobalFunction(OneCocycles,function(G,M)
local   ocr,erg;

  if not IsList(M) then
    if not IsElementaryAbelian(M) then
      Error("<M> must be elementary abelian");
    fi;
    M:=InducedPcgsWrtHomePcgs(M);
  fi;

  ocr:=rec(modulePcgs:=M);
  if IsGroup(G) then
    ocr.group:=G;
  else
    ocr.group:= GroupByGenerators(G);
    ocr.generators:=G;
  fi;

  OCOneCocycles(ocr,false);

  if IsBound(ocr.complement)  then
      erg:=rec(
          oneCoboundaries    :=ocr.oneCoboundaries,
          oneCocycles        :=ocr.oneCocycles,
          generators         :=ocr.generators,
          isSplitExtension   :=true,
          complement         :=ocr.complement,
          complementGens     :=ocr.complementGens,
          cocycleToList      :=ocr.cocycleToList,
          listToCocycle      :=ocr.listToCocycle,
          cocycleToComplement:=ocr.cocycleToComplement,
          factorGens         :=ocr.generators);
      if IsBound(ocr.complementToCocycle) then
        erg.complementToCocycle:=ocr.complementToCocycle;
      fi;
      return erg;
  else
      return rec(
          oneCoboundaries    :=ocr.oneCoboundaries,
          oneCocycles        :=ocr.oneCocycles,
          generators         :=ocr.generators,
          cocycleToList      :=ocr.cocycleToList,
          listToCocycle      :=ocr.listToCocycle,
          isSplitExtension   :=false);
  fi;

end);


#############################################################################
##
#F  ComplementClassesRepresentativesEA(<G>,<N>) . complement classes to el.ab. N by 1-Cohom.
##
InstallGlobalFunction(ComplementClassesRepresentativesEA,function(g,n)
local oc,l;
  if Size(g)=Size(n) then
    return TrivialSubgroup(g);
  fi;
  oc:=OneCocycles(g,n);
  if not oc.isSplitExtension  then
    return [];
  else
    if Dimension(oc.oneCocycles)=Dimension(oc.oneCoboundaries) then
      return [oc.complement];
    else
      l:=BaseSteinitzVectors(BasisVectors(Basis(oc.oneCocycles)),
                             BasisVectors(Basis(oc.oneCoboundaries)));
      l:=List(VectorSpace(LeftActingDomain(oc.oneCocycles),l.factorspace,
                          Zero(oc.oneCocycles)),
              i->oc.cocycleToComplement(i));
      return l;
    fi;
  fi;
end);

[ Dauer der Verarbeitung: 0.34 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