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


Quelle  graveyard.g   Sprache: unbekannt

 
# Here lies some old code and presumably rests in peace...

# from .gd:

#########################
# Stabilizer Iterators: #
#########################

#
# For stabilizers Stab_{U_i}(q) for an U_i-minimal q in P_i the following
# data structure can be used to iterate through the stabilizer:
#
#  stab is a component object with the following components:
#
BindGlobal( "StabIteratorsFamily", NewFamily( "StabIteratorsFamily" ) );
DeclareCategory( "IsStabIterator", IsComponentObjectRep );
DeclareRepresentation( "IsStdStabIteratorRep", IsStabIterator,
  [ "i",     # number of the subgroup in question
    "info",  # a list of length i, at position j we have a list of elements
             # in the transversal of U_{j-1} in U_j. These elements are stored
             # as numbers indexing words in setup.trans[j].
    "pos",   # a list of length i, at position j there is a number indexing
             # an element in info[j]. This is set to all 1 when Reset
             # is called and is incremented after a call to Next
    "cache", # intermediate results to reuse, a list of length i (as above,
             # height of stabilizer, each element is again a list of length
             # k+1 (for each representation), each element 
             # in there is an intermediate result)
    "point", # list of starting points to verify whether cache is valid
  ] );
BindGlobal( "StdStabIteratorsType", 
  NewType( StabIteratorsFamily, IsStabIterator and IsStdStabIteratorRep ) );
DeclareOperation( "StabIterator", [] );   # the constructor
DeclareOperation( "Reset", [ IsStabIterator ] );
DeclareOperation( "Next", [ IsStabIterator ] );
DeclareOperation( "Next", [ IsStabIterator, IsString ] );
DeclareGlobalFunction( "ORB_ApplyStabElement" );

DeclareGlobalFunction( "ORB_Minimalize2" );

DeclareGlobalFunction( "ORB_NextStabIterator2" );
DeclareGlobalFunction( "ORB_ApplyUElement" );

DeclareGlobalFunction( "OrbitBySuborbitWithKnownSize" );


# from .gi:

InstallGlobalFunction( ORB_Minimalize,
function(p,j,i,setup,stab,w)
  # p is a point that should be minimalized. j is in 1..k+1 and indicates,
  # whether p is in P_j or in P (for j=k+1). i is in 1..k and indicates, 
  # which group U_i is used to minimalize. So only i <= j makes sense.
  # setup is a record describing the helper subgroups as defined above. 
  # Returns a U_i-minimal point q in the same U_i-orbit pU_i.
  # If stab is "false" nothing happens. If stab is a stabiterator object,
  # (usually will be "newly born" thus empty), that will
  # be filled with information for an iterator object for 
  # Stab_{U_i}(pi[j][i](q)) (see above).
  # If w is a list the word which is applied is appended.
  local m,minpoint,minstab,minstablen,minword,n,oldp,q,qq,qqq,ret,stablen,
        tempstab,v,vv,vvv,ww,www;
#Print("Mini:",j," ",i,"\n");
  oldp := p;  # to make debugging easier!
  if i = 1 then    # this is the smallest helper subgroup

    # go to P_1:
    if j > i then 
      q := setup!.pifunc[j][i](p,setup!.pi[j][i]); 
    else
      q := p;
    fi;
    v := ValueHT(setup!.info[i],q);
    if v = fail then    # we do not yet know this point
      ###Print("<\c");
      # we have to enumerate this U_1-orbit, apply all elements in trans:
      v := [];  # here we collect the stabilizer
      for m in [1..setup!.index[i]] do
        qq := ORB_ApplyWord(q,ORB_InvWord(setup!.trans[i][m]),
                        setup!.els[i],setup!.elsinv[i],setup!.op[i]);
        if q = qq then   # we found a stabilizer element:
          Add(v,m);
        else
          vv := ValueHT(setup!.info[i],qq);
          if vv = fail then    # we did not yet reach this point
            AddHT(setup!.info[i],qq,m);   # store this info
          fi;
        fi;
      od;
      AddHT(setup!.info[i],q,v);
      setup!.suborbnr[i] := setup!.suborbnr[i] + 1;
      setup!.sumstabl[i] := setup!.sumstabl[i] + Length(v);
      ###Print(Length(v),":",QuoInt(setup!.sumstabl[i],
      ###      setup!.suborbnr[i]),">   \r");

      # now p is by definition U_1-minimal
    else    # we already know this U_1-orbit:
      if IsInt(v) then   # this is the number of a word
        if IsList(w) then Append(w,setup!.trans[i][v]); fi;  # store what we do
        p := ORB_ApplyWord(p,setup!.trans[i][v],setup!.els[j],
                           setup!.elsinv[j],setup!.op[j]);
        if j > i then
          q := setup!.pifunc[j][i](p,setup!.pi[j][i]);
        else
          q := p;
        fi;
        v := ValueHT(setup!.info[i],q);
      fi; # otherwise we are already U_1-minimal:
    fi;
    if IsStabIterator(stab) then
        stab!.i := 1;
        stab!.info := [v];
        stab!.pos := [1];
    fi;
#Print("Raus\n");
    return p;

  else   # we are in some higher helper subgroup than U_1:

    # first do a U_{i-1}-minimalization:
    p := ORB_Minimalize(p,j,i-1,setup,stab,w);

    # now try to reach the minimal U_{i-1}-suborbit in the U_i-orbit:
    if j > i then
      q := setup!.pifunc[j][i](p,setup!.pi[j][i]);
    else
      q := p;
    fi;
    v := ValueHT(setup!.info[i],q);

    if v = fail then    # we do not yet know this U_{i-1}-suborbit

      ###Print("<",i,":\c");
      # first we apply all elements of the transversal of U_{i-1} in U_i,
      # U_{i-1}-minimalize them and search for the smallest stabilizer
      # to choose the U_i-minimal U_{i-1}-orbit:
      minpoint := fail;
      minword := fail;
      minstablen := -1;
      minstab := fail;
      for m in [1..setup!.index[i]] do
        tempstab := StabIterator();
        qq := ORB_ApplyWord(q,setup!.trans[i][m],setup!.els[i],
                            setup!.elsinv[i],setup!.op[i]);
        ww := ShallowCopy(setup!.trans[i][m]);
        qq := ORB_Minimalize(qq,i,i-1,setup,tempstab,ww);
        stablen := Product(tempstab!.info,Length);
        if minpoint = fail or stablen < minstablen then
          minpoint := qq;
          minstablen := stablen;
          minword := ww;
          minstab := tempstab;
        fi;
      od;
      # Now U_i-minimalize p:
      p := ORB_ApplyWord(p,minword,setup!.els[j],setup!.elsinv[j],setup!.op[j]);
      if IsList(w) then Append(w,minword); fi;
      q := minpoint;
      # in the second component we have to collect stabilizing transversal 
      # elements for subgroups U_1 to U_i:
      v := [true,List([1..i],x->[])];  
      AddHT(setup!.info[i],q,v);
                        
      # Now the U_{i-1}-orbit of the vector q is the U_i-minimal 
      # U_{i-1}-orbit and q is the U_i-minimal vector
      
      # first find all U_{i-1}-minimal elements in the U_i-minimal 
      # U_{i-1}-orbit:
      Reset(minstab);
      repeat
        ww := [];
        qq := ORB_ApplyStabElement(q,i,i-1,setup,minstab,ww);
        if qq <> q then   # some new U_{i-1}-minimal element?
          vv := ValueHT(setup!.info[i],qq);
          if vv = fail then
            AddHT(setup!.info[i],qq,[false,ORB_InvWord(ww)]);
          fi;
        else   # in this case this is an element of Stab_{U_{i-1}}(q) in P_i
          for n in [1..i-1] do
            AddSet(v[2][n],minstab!.info[n][minstab!.pos[n]]);
          od;
        fi;
      until Next(minstab);
      
      # we have to enumerate this U_i-orbit by U_{i-1}-orbits, storing
      # information for all U_{i-1}-minimal vectors:
      tempstab := StabIterator();
      for m in [1..setup!.index[i]] do
        # Apply t to find other U_{i-1}-orbits
        qq := ORB_ApplyWord(q,setup!.trans[i][m],setup!.els[i],
                            setup!.elsinv[i],setup!.op[i]);
        ww := ShallowCopy(setup!.trans[i][m]);
        qq := ORB_Minimalize(qq,i,i-1,setup,tempstab,ww);
        vv := ValueHT(setup!.info[i],qq);
        if vv <> fail and not(IsInt(vv)) then  
          # we are again in the U_i-minimal U_{i-1}-o.
          # then m has to go in the stabilizer info:
          Add(v[2][i],m);
        fi;
        if vv = fail then   # a new U_{i-1}-orbit
          # note that we now have stabilizer info in tempstab
          ret := setup!.cosetrecog[i](i,ORB_InvWord(ww),setup);
          AddHT(setup!.info[i],qq,ret);
          Reset(tempstab);
          repeat
            www := ShallowCopy(ww);
            qqq := ORB_ApplyStabElement(qq,i,i-1,setup,tempstab,www);
            vvv := ValueHT(setup!.info[i],qqq);
            if vvv = fail then
              ret := setup!.cosetrecog[i](i,ORB_InvWord(www),setup);
              AddHT(setup!.info[i],qqq,ret);
            fi;
          until Next(tempstab);
        fi;
      od;
      # now q is by definition the U_i-minimal point in the orbit and
      # v its setup!.info[i], i.e. [true,stabilizer information]
      setup!.suborbnr[i] := setup!.suborbnr[i] + 1;
      setup!.sumstabl[i] := setup!.sumstabl[i] + Product(v[2],Length);
      ###Print(Product(v[2],Length),":",
      ###      QuoInt(setup!.sumstabl[i],setup!.suborbnr[i]),">      \r");

    else   # we already knew this U_{i-1}-suborbit

      if IsInt(v) then    # this is the number of a word
        if IsList(w) then 
          Append(w,setup!.trans[i][v]);   # remember what we did
        fi; 
        p := ORB_ApplyWord(p,setup!.trans[i][v],setup!.els[j],
                           setup!.elsinv[j],setup!.op[j]);
        # we again do a U_{i-1}-minimalization:
        p := ORB_Minimalize(p,j,i-1,setup,stab,w);
        # now we are in the U_i-minimal U_{i-1}-suborbit and on a 
        # U_{i-1}-minimal element
        if j > i then
          q := setup!.pifunc[j][i](p,setup!.pi[j][i]);
        else
          q := p;
        fi;
        v := ValueHT(setup!.info[i],q);
      fi;
      if v[1] = false then    # not yet U_i-minimal 
        # we still have to apply an element of Stab_{U_{i-1}}(pi[j][i-1](p)):
        if IsList(w) then Append(w,v[2]); fi;  # remember what we did
        p := ORB_ApplyWord(p,v[2],setup!.els[j],setup!.elsinv[j],setup!.op[j]);
        if j > i then
          q := setup!.pifunc[j][i](p,setup!.pi[j][i]);
        else
          q := p;
        fi;
        v := ValueHT(setup!.info[i],q);
      fi;
      # now q is the U_i-minimal element in qU_i
      # v is now [true,stabilizer information]

    fi;

    if IsStabIterator(stab) then
        stab!.i := i;
        stab!.info := v[2];
        stab!.pos := List([1..i],x->1);
    fi;

    # now we are on the minimal element in the S-orbit
#Print("raus\n");
    return p;
  fi;
end );

InstallGlobalFunction( OrbitBySuborbit,
function(p,hashlen,size,setup,percentage)
  # Enumerates the orbit of p under the group G generated by "gens" by
  # suborbits for the subgroup U described in "setup". 
  # "p" is a point
  # "hashlen" is an upper bound for the set of U-minimal points in the G-orbit
  # "size" is the group order to stop when we are ready and as upper bound
  #        for the orbit length
  # "setup" is a setup object for the iterated quotient trick,
  #         effectively enabling us to do minimalization with a subgroup
  # "percentage" is a number between 50 and 100 and gives a stopping criterium.
  #         We stop if percentage of the orbit is enumerated.
  #         Only over 50% we know that the stabilizer is correct!
  # Returns a suborbit database with additional field "words" which is
  # a list of words in gens which can be used to reach U-orbit in the G-orbit

  local k,firstgen,lastgen,stab,miniwords,db,stabgens,stabperms,stabilizer,
        fullstabsize,words,todo,i,j,x,mw,done,newperm,newword,oldtodo,sw,xx,v,
        pleaseexitnow,assumestabcomplete;

  pleaseexitnow := false;  # set this to true in a break loop to
                           # let this function exit gracefully
  assumestabcomplete := false;  # set this to true in a break loop to
                                # let this function assume that the 
                                # stabilizer is complete

  # Setup some shortcuts:
  k := setup!.k;
  firstgen := Length(setup!.els[k])+1;
  lastgen := Length(setup!.els[k+1]);

  # A security check:
  if p <> setup!.op[k+1](p,setup!.els[k+1][1]^0) then
      Error("Warning: The identity does not preserve the starting point!\n",
            "Did you normalize your vector?");
  fi;

  # First we U-minimalize p:
  stab := StabIterator();
  p := ORB_Minimalize(p,k+1,k,setup,stab,false);

  miniwords := [[]];  # here we collect U-minimalizing elements
  
  # Start a database with the first U-suborbit:
  db := SuborbitDatabase(setup,hashlen);
  StoreSuborbit(db,p,stab);

  stabgens := [];
  stabperms := [];
  stabilizer := Group(setup!.permgens[1]^0);
  if IsBound( setup!.stabchainrandom ) and setup!.stabchainrandom <> false then
      StabChain( stabilizer, rec( random := setup!.stabchainrandom ) );
  else
      StabChain(stabilizer);
  fi;
  fullstabsize := 1;
  
  words := [[]];
  todo := [[]];
  while true do

    i := 1;
    while i <= Length(todo) do
      if pleaseexitnow = true then return "didnotfinish"; fi;

      for j in [firstgen..lastgen] do
        x := setup!.op[k+1](p,setup!.els[k+1][j]);
        x := ORB_ApplyWord(x,todo[i],setup!.els[k+1],
                           setup!.elsinv[k+1],setup!.op[k+1]);
        mw := [];
        x := ORB_Minimalize(x,k+1,k,setup,stab,mw);
        v := LookupSuborbit(x,db);
        if v = fail then
          Add(words,Concatenation([j],todo[i]));
          Add(todo,Concatenation([j],todo[i]));
          Add(miniwords,mw);
          StoreSuborbit(db,x,stab);
          Print("t:",ORB_PrettyStringBigNumber(TotalLength(db)),
                " st:",ORB_PrettyStringBigNumber(fullstabsize),"       \r");
          if 2 * TotalLength(db) * fullstabsize > size and
             TotalLength(db) * fullstabsize * 100 >= size*percentage then 
            Print("\nDone!\n");
            return Objectify( StdOrbitBySuborbitsType,
                       rec(db := db,
                       words := words,
                       stabsize := fullstabsize,
                       stab := stabilizer,
                       stabwords := stabgens,
                       groupsize := size,
                       orbitlength := size/fullstabsize,
                       percentage := percentage,
                       seed := p ) );
          fi;
        else
          if assumestabcomplete = false and
             TotalLength(db) * fullstabsize * 2 <= size then
            # otherwise we know that we will not find more stabilizing els.
            # we know now that v is an integer and that
            # p*setup!.els[j]*todo[i]*U = p*words[v]*U
            # p*setup!.els[j]*todo[i]*mw is our new vector
            # p*words[v]*miniwords[v] is our old vector
            # they differ by an element in Stab_U(...)
            Reset(stab);
            done := false;
            repeat
              sw := [];
              xx := ORB_ApplyStabElement(x,k+1,k,setup,stab,sw);
              if xx = Representatives(db)[v] then  
                # we got a real stabilizer element of p
                done := true;
                newword := Concatenation([j],todo[i],mw,sw,
                            ORB_InvWord(miniwords[v]),ORB_InvWord(words[v]));
                newperm := ORB_ApplyWord(setup!.permgens[1]^0,newword,
                                 setup!.permgens,setup!.permgensinv,OnRight);
                if not(IsOne(newperm)) then
                  if not(newperm in stabilizer) then
                    Add(stabgens,newword);
                    Add(stabperms,newperm);
                    stabilizer := GroupWithGenerators(stabperms);
                    Print("\nCalculating new estimate of the stabilizer...\c");
                    if IsBound(setup!.stabchainrandom) and 
                       setup!.stabchainrandom <> false then
                        StabChain(stabilizer, 
                                  rec(random := setup!.stabchainrandom));
                    else
                        StabChain(stabilizer);
                    fi;
                    fullstabsize := Size(stabilizer);
                    Print("done.\nNew stabilizer order: ",fullstabsize,"\n");
                    if TotalLength(db) * fullstabsize * 100
                       >= size*percentage then 
                      Print("Done!\n");
                      return Objectify( StdOrbitBySuborbitsType,
                             rec(db := db,
                                 words := words,
                                 stabsize := fullstabsize,
                                 stab := stabilizer,
                                 stabwords := stabgens,
                                 groupsize := size,
                                 orbitlength := size/fullstabsize,
                                 percentage := percentage,
                                 seed := p) );
                    fi;
                  fi;
                fi;
              fi;
            until done or Next(stab);
          fi;
        fi;
      od;
      i := i + 1;
    od;
  
    oldtodo := todo;
    todo := [];
    for i in [1..Length(stabgens)] do
      Append(todo,List(oldtodo,w->Concatenation(stabgens[i],w)));
    od;
    Print("\nLength of next todo: ",Length(todo),"\n");
  od;
  # this is never reached
end );

InstallGlobalFunction( OrbitBySuborbitWithKnownSize,
function(p,hashlen,size,setup,randels)
  # Enumerates the orbit of p under the group G generated by "gens" by
  # suborbits for the subgroup U described in "setup". 
  #   "p" is a point
  #   "hashlen" is an upper bound for the set of U-minimal points in the G-orbit
  #   "size" is the orbit length
  #   "setup" is a record of data for the iterated quotient trick,
  #           effectively enabling us to do minimalization with a subgroup
  #   "randels" number of random elements to use for recognising half orbits
  # Returns a record with components:
  #   "db": suborbit database
  #   "words": a list of words in gens which can be used to reach 
  #            U-orbit in the G-orbit
  local k,stab,q,trans,db,l,i,Ucounter,g,j,x,y,v,ii,w,z,firstgen,lastgen;

  k := setup!.k;
  firstgen := Length(setup!.els[k])+1;
  lastgen := Length(setup!.els[k+1]);

  # First we U-minimalize p:
  stab := StabIterator();
  q := ORB_Minimalize(p,k+1,k,setup,stab,false);

  trans := [[]];    # words for getting to the U-suborbits
  
  # Start a database with the first U-suborbit:
  db := SuborbitDatabase(setup,hashlen);
  StoreSuborbit(db,q,stab);

  l := [p];
  i := 1;   # counts elements in l
  # use a stabilizer info, which describes all of U:
  Ucounter := StabIterator();
  Ucounter!.i := k;
  Ucounter!.info := List([1..k],i->[1..setup!.index[i]]);
  Ucounter!.pos := List([1..k],i->1);

  # Throw in some vectors gotten by applying random elements:
  g := GroupWithGenerators(setup!.els[k+1]{[firstgen..lastgen]});
  for j in [1..randels] do
      Print("Applying random element ",j," (",randels,") ...\n");
      x := p * PseudoRandom(g);
      y := ORB_Minimalize(x,k+1,k,setup,stab,false);
      v := LookupSuborbit(y,db);
      if v = fail then
          Add(l,x);
          Add(trans,[fail]);
          StoreSuborbit(db,y,stab);
          Print("total: ",ORB_PrettyStringBigNumber(TotalLength(db)),"     \n");
      fi;
      if TotalLength(db) >= size then 
        Print("\nDone.\n");
        return rec( db := db, words := trans ); 
      fi;
  od;
  Unbind(g);
   
  Reset(Ucounter);
  repeat
    while i <= Length(l) do
      for j in [firstgen..lastgen] do
        x := setup!.op[k+1](l[i],setup!.els[k+1][j]);
        y := ORB_Minimalize(x,k+1,k,setup,stab,false);
        v := LookupSuborbit(y,db);
        if v = fail then
          Add(trans,Concatenation(trans[i],[j]));
          Add(l,x);
          StoreSuborbit(db,y,stab);
          Print("total: ",ORB_PrettyStringBigNumber(TotalLength(db)),"     \r");
          if TotalLength(db) >= size then 
            Print("\nDone.\n");
            return rec( db := db, words := trans ); 
          fi;
        fi;
      od;
      i := i + 1;
    od;
    # now we have to to something else, perhaps applying some U elements?
    Print(".\c");
    for ii in [1..Length(l)] do
      w := [];
      z := ORB_ApplyUElement(l[ii],k+1,k,setup,Ucounter,w);
      for j in [firstgen..lastgen] do
        x := setup!.op[k+1](z,setup!.els[k+1][j]);
        y := ORB_Minimalize(x,k+1,k,setup,stab,false);
        v := LookupSuborbit(y,db);
        if v = fail then
          Add(trans,Concatenation(trans[ii],w,[j]));
          Add(l,x);
          StoreSuborbit(db,y,stab);
          Print("total: ",ORB_PrettyStringBigNumber(TotalLength(db)),"     \r");
          if TotalLength(db) >= size then 
            Print("\nDone.\n");
            return rec( db := db, words := trans ); 
          fi;
        fi;
      od;
    od;
  until Next(Ucounter,"fromabove");

  Print("Warning! Orbit not complete!!!\n");
  # this should never happen!
  return rec( db := db, words := trans );
end );

InstallGlobalFunction( OrbitBySuborbitBootstrapForVectors,
function(gens,permgens,sizes,codims)
  # Returns a setup object for a list of helper subgroups
  # gens: a list of lists of generators for U_1 < U_2 < ... < U_k < G
  # permgens: the same in a faithful permutation representation
  # sizes: a list of sizes of groups U_1 < U_2 < ... < U_k
  # codims: a list of dimensions of factor modules
  # note that the basis must be changed to make projection easy!
  # That is, projection is taking the components [1..codim].

  local dim,doConversions,f,i,j,k,nrgens,nrgenssum,o,regvec,sample,setup,sum,v,
        counter,merk,neededfullspace;

  # For the old compressed matrices:
  if IsGF2MatrixRep(gens[1][1]) or Is8BitMatrixRep(gens[1][1]) then
      doConversions := true;
  else
      doConversions := false;
  fi;

  # Some preparations:
  k := Length(sizes);
  if Length(gens) <> k+1 or Length(permgens) <> k+1 or Length(codims) <> k then
      Error("Need generators for ",k+1," groups and ",k," codimensions.");
      return;
  fi;
  nrgens := List(gens,Length);
  nrgenssum := 0*nrgens;
  sum := 0;
  for i in [1..k+1] do
      nrgenssum[i] := sum;
      sum := sum + nrgens[i];
  od;
  nrgenssum[k+2] := sum;

  sample := gens[1][1][1];  # first vector of first generator

  # Do the first step:
  setup := rec(k := 1);
  setup.size := [sizes[1]];
  setup.index := [sizes[1]];
  setup.permgens := Concatenation(permgens);
  setup.permgensinv := List(setup.permgens,x->x^-1);
  setup.els := [];
  setup.els[k+1] := Concatenation(gens);
  setup.elsinv := [];
  setup.elsinv[k+1] := List(setup.els[k+1],x->x^-1);
  setup.cosetinfo := [];
  setup.cosetrecog := [];
  setup.hashlen := List([1..k+1],i->100000);
  dim := Length(gens[1][1]);
  codims[k+1] := dim;   # for the sake of completeness!
  for j in [1..k] do
      setup.els[j] := List(Concatenation(gens{[1..j]}),
                           x->ExtractSubMatrix(x,[1..codims[j]],
                                                 [1..codims[j]]));
      if doConversions then
          for i in setup.els[j] do ConvertToMatrixRep(i); od;
      fi;
      setup.elsinv[j] := List(setup.els[j],x->x^-1);
  od;
  f := BaseField(gens[1][1]);
  regvec := ZeroVector(sample,codims[1]);  
            # a new empty vector over same field
  Info(InfoOrb,1,"Looking for regular U1-orbit in factor space...");
  counter := 0;
  repeat
      counter := counter + 1;
      Randomize(regvec);
      o := Enumerate(Orb(setup.els[1],regvec,OnRight,
                         rec(hashlen := sizes[1]*2, schreier := true)));
      Info(InfoOrb,2,"Found length: ",Length(o!.orbit));
  until Length(o!.orbit) = sizes[1] or counter >= 10;
  if Length(o!.orbit) < sizes[1] then   # Bad luck, try something else:
    regvec := ZeroMutable(sample);
    Info(InfoOrb,1,"Looking for regular U1-orbit in full space...");
    counter := 0;
    repeat
        counter := counter + 1;
        Randomize(regvec);
        o := Enumerate(Orb(gens[1],regvec,OnRight,
                           rec(hashlen := sizes[1]*2, schreier := true)));
        Info(InfoOrb,2,"Found length: ",Length(o!.orbit));
    until Length(o!.orbit) = sizes[1] or counter >= 10;
    if Length(o!.orbit) < sizes[1] then   # Again bad luck, try the regular rep
        Info(InfoOrb,1,"Using the regular permutation representation...");
        o := Enumerate(Orb(gens[1],gens[1]^0,OnRight,
                                 rec(hashlen := sizes[1]*2, schreier := true)));
    fi;
  fi;
  Info(InfoOrb,2,"Found!");
  setup.trans := [List([1..Length(o!.orbit)],i->TraceSchreierTreeForward(o,i))];

  # Note that for k=1 we set codims[2] := dim
  setup.pi := [];
  setup.pifunc := [];
  for j in [2..k+1] do
      setup.pi[j] := [];
      setup.pifunc[j] := [];
      for i in [1..j-1] do
          setup.pi[j][i] := [1..codims[i]];
          setup.pifunc[j][i] := \{\};
      od;
  od;
  setup.info := [NewHT(regvec,Size(f)^(codims[1]) * 3)];
  setup.suborbnr := [0];
  setup.sumstabl := [0];
  setup.regvecs := [regvec];
  setup.op := List([1..k+1],i->OnRight);
  setup.sample := [regvec,gens[1][1][1]];

  Objectify( NewType( OrbitBySuborbitSetupFamily,
                      IsOrbitBySuborbitSetup and IsStdOrbitBySuborbitSetupRep ),
             setup );
  # From now on we can use it and it is an object!

  neededfullspace := false;

  # Now do the other steps:
  for j in [2..k] do
      # First find a vector the orbit of which identifies the U_{j-1}-cosets
      # of U_j, i.e. Stab_{U_j}(v) <= U_{j-1}, 
      # we can use the j-1 infrastructure!
      if not(neededfullspace) then
        # if we have needed the full space somewhere, we need it everywhere
        # else, because OrbitBySuborbit is only usable for big vectors!
        Info(InfoOrb,1,"Looking for U",j-1,"-coset-recognising U",j,"-orbit ",
             "in factor space...");
        regvec := ZeroVector(sample,codims[j]);
        counter := 0;
        repeat
            Randomize(regvec);
            counter := counter + 1;
            # Now U_{j-1}-minimalize it, such that the transversal-words
            # returned reach the U_{j-1}-suborbits we find next:
            regvec := ORB_Minimalize(regvec,j,j-1,setup,false,false);
            o := OrbitBySuborbit(regvec,(sizes[j]/sizes[j-1])*2+1,sizes[j],
                                 setup,100);
            Info(InfoOrb,2,"Found ",Length(Representatives(o!.db)),
                 " suborbits (need ",sizes[j]/sizes[j-1],")");
        until Length(Representatives(o!.db)) = sizes[j]/sizes[j-1] or 
              counter >= 3;
      fi;
      if neededfullspace or
         Length(Representatives(o!.db)) < sizes[j]/sizes[j-1] then
        neededfullspace := true;
        # Bad luck, try the full space:
        Info(InfoOrb,1,"Looking for U",j-1,"-coset-recognising U",j,"-orbit ",
             "in full space...");
        regvec := ZeroMutable(sample);
        counter := 0;
        # Go to the original generators, using the infrastructure for k=j-1:
        merk := [setup!.els[j],setup!.elsinv[j]];
        setup!.els[j] := Concatenation(gens{[1..j]});
        setup!.elsinv[j] := List(setup!.els[j],x->x^-1);
        setup!.sample[j] := ShallowCopy(regvec);  # now a longer vector!
        # this is corrected later on!
        repeat
            Randomize(regvec);
            counter := counter + 1;
            # Now U_{j-1}-minimalize it, such that the transversal-words
            # returned reach the U_{j-1}-suborbits we find next:
            regvec := ORB_Minimalize(regvec,j,j-1,setup,false,false);
            o := OrbitBySuborbit(regvec,(sizes[j]/sizes[j-1])*2+1,sizes[j],
                                 setup,100);
            Info(InfoOrb,2,"Found ",Length(Representatives(o!.db)),
                 " suborbits (need ",sizes[j]/sizes[j-1],")");
        until Length(Representatives(o!.db)) = sizes[j]/sizes[j-1] or
              counter >= 20;
        if Length(Representatives(o!.db)) < sizes[j]/sizes[j-1] then
            Info(InfoOrb,1,"Bad luck, did not find nice orbit, giving up.");
            return;
        fi;
        setup!.els[j] := merk[1];
        setup!.elsinv[j] := merk[2];
      fi;

      Info(InfoOrb,1,"Found U",j-1,"-coset-recognising U",j,"-orbit!");
      setup!.k := j;
      setup!.size[j] := sizes[j];
      setup!.index[j] := sizes[j]/sizes[j-1];
      setup!.trans[j] := o!.words;
      setup!.suborbnr[j] := 0;
      setup!.sumstabl[j] := 0;
      setup!.info[j] :=
            NewHT(regvec,QuoInt(Size(f)^(codims[j]),sizes[j-1])*4+1); # fixme!
      setup!.regvecs[j] := regvec;
      if not(neededfullspace) then
          setup!.cosetrecog[j] := ORB_CosetRecogGenericFactorSpace;
          setup!.cosetinfo[j] := o!.db;   # the hash table
      else
          setup!.cosetrecog[j] := ORB_CosetRecogGenericFullSpace;
          setup!.cosetinfo[j] := [o!.db,k];   # the hash table
      fi;
      setup!.sample[j] := ZeroVector(sample,codims[j]);
      setup!.sample[j+1] := sample;
  od;
  return setup;
end );

InstallGlobalFunction( ORB_CosetRecogGenericFactorSpace,
  function( j, w, s )
    local x;
    x := ORB_ApplyWord(s!.regvecs[j],w,s!.els[j],s!.elsinv[j],s!.op[j]);
    x := ORB_Minimalize(x,j,j-1,s,false,false);
    return LookupSuborbit(x,s!.cosetinfo[j]);
  end );

InstallGlobalFunction( ORB_CosetRecogGenericFullSpace,
  function( j, w, s )
    local x,k;
    k := s!.cosetinfo[j][2];
    x := ORB_ApplyWord(s!.regvecs[j],w,s!.els[k+1],s!.elsinv[k+1],
                       s!.op[k+1]);
    x := ORB_Minimalize(x,k+1,j-1,s,false,false);
    return LookupSuborbit(x,s!.cosetinfo[j][1]);
  end );

InstallGlobalFunction( OrbitBySuborbitBootstrapForLines,
function(gens,permgens,sizes,codims)
  # Returns a setup object for a list of helper subgroups
  # gens: a list of lists of generators for U_1 < U_2 < ... < U_k < G
  # permgens: the same in a faithful permutation representation
  # sizes: a list of sizes of groups U_1 < U_2 < ... < U_k
  # codims: a list of dimensions of factor modules
  # note that the basis must be changed to make projection easy!
  # That is, projection is taking the components [1..codim].

  local dim,doConversions,f,i,j,k,nrgens,nrgenssum,o,regvec,sample,setup,sum,v,
        counter,merk,neededfullspace,c;

  # For the old compressed matrices:
  if IsGF2MatrixRep(gens[1][1]) or Is8BitMatrixRep(gens[1][1]) then
      doConversions := true;
  else
      doConversions := false;
  fi;

  # Some preparations:
  k := Length(sizes);
  if Length(gens) <> k+1 or Length(permgens) <> k+1 or Length(codims) <> k then
      Error("Need generators for ",k+1," groups and ",k," codimensions.");
      return;
  fi;
  nrgens := List(gens,Length);
  nrgenssum := 0*nrgens;
  sum := 0;
  for i in [1..k+1] do
      nrgenssum[i] := sum;
      sum := sum + nrgens[i];
  od;
  nrgenssum[k+2] := sum;

  sample := gens[1][1][1];  # first vector of first generator

  # Do the first step:
  setup := rec(k := 1);
  setup.size := [sizes[1]];
  setup.index := [sizes[1]];
  setup.permgens := Concatenation(permgens);
  setup.permgensinv := List(setup.permgens,x->x^-1);
  setup.els := [];
  setup.els[k+1] := Concatenation(gens);
  setup.elsinv := [];
  setup.elsinv[k+1] := List(setup.els[k+1],x->x^-1);
  setup.cosetinfo := [];
  setup.cosetrecog := [];
  setup.hashlen := List([1..k+1],i->1000000);
  dim := Length(gens[1][1]);
  codims[k+1] := dim;   # for the sake of completeness!
  for j in [1..k] do
      setup.els[j] := List(Concatenation(gens{[1..j]}),
                           x->ExtractSubMatrix(x,[1..codims[j]],
                                                 [1..codims[j]]));
      if doConversions then
          for i in setup.els[j] do ConvertToMatrixRep(i); od;
      fi;
      setup.elsinv[j] := List(setup.els[j],x->x^-1);
  od;
  f := BaseField(gens[1][1]);
  regvec := ZeroVector(sample,codims[1]);  
            # a new empty vector over same field
  Info(InfoOrb,1,"Looking for regular U1-orbit in factor space...");
  counter := 0;
  repeat
      counter := counter + 1;
      Randomize(regvec);
      c := PositionNonZero( regvec );
      if c <= Length( regvec )  then
          regvec := Inverse( regvec[c] ) * regvec;
      fi;
      o := Enumerate(Orb(setup.els[1],regvec,OnLines,
                         rec(hashlen := sizes[1]*2, schreier := true)));
      Info(InfoOrb,2,"Found length: ",Length(o!.orbit));
  until Length(o!.orbit) = sizes[1] or counter >= 10;
  if Length(o!.orbit) < sizes[1] then   # Bad luck, try something else:
    regvec := ZeroMutable(sample);
    Info(InfoOrb,1,"Looking for regular U1-orbit in full space...");
    counter := 0;
    repeat
        counter := counter + 1;
        Randomize(regvec);
        c := PositionNonZero( regvec );
        if c <= Length( regvec )  then
            regvec := Inverse( regvec[c] ) * regvec;
        fi;
        o := Enumerate(Orb(gens[1],regvec,OnLines,
                                 rec(hashlen := sizes[1]*2, schreier := true)));
        Info(InfoOrb,2,"Found length: ",Length(o!.orbit));
    until Length(o!.orbit) = sizes[1] or counter >= 10;
    if Length(o!.orbit) < sizes[1] then   # Again bad luck, try the regular rep
        Info(InfoOrb,1,"Using the permutation representation...");
        o := Enumerate(Orb(permgens[1],permgens[1]^0,OnRight,
                                 rec(hashlen := sizes[1]*2, schreier := true)));
    fi;
  fi;
  Info(InfoOrb,2,"Found!");
  setup.trans := [List([1..Length(o!.orbit)],i->TraceSchreierTreeForward(o,i))];

  # Note that for k=1 we set codims[2] := dim
  setup.pi := [];
  setup.pifunc := [];
  for j in [2..k+1] do
      setup.pi[j] := [];
      setup.pifunc[j] := [];
      for i in [1..j-1] do
          setup.pi[j][i] := [1..codims[i]];
          setup.pifunc[j][i] := \{\};
      od;
  od;
  setup.info := [NewHT(regvec,Size(f)^(codims[1]) * 3)];
  setup.suborbnr := [0];
  setup.sumstabl := [0];
  setup.regvecs := [regvec];
  setup.op := List([1..k+1],i->OnLines);
  setup.sample := [regvec,gens[1][1][1]];

  Objectify( NewType( OrbitBySuborbitSetupFamily,
                      IsOrbitBySuborbitSetup and IsStdOrbitBySuborbitSetupRep ),
             setup );
  # From now on we can use it and it is an object!

  neededfullspace := false;

  # Now do the other steps:
  for j in [2..k] do
      # First find a vector the orbit of which identifies the U_{j-1}-cosets
      # of U_j, i.e. Stab_{U_j}(v) <= U_{j-1}, 
      # we can use the j-1 infrastructure!
      if not(neededfullspace) then
        # if we have needed the full space somewhere, we need it everywhere
        # else, because OrbitBySuborbit is only usable for big vectors!
        Info(InfoOrb,1,"Looking for U",j-1,"-coset-recognising U",j,"-orbit ",
             "in factor space...");
        regvec := ZeroVector(sample,codims[j]);
        counter := 0;
        repeat
            Randomize(regvec);
            c := PositionNonZero( regvec );
            if c <= Length( regvec )  then
                regvec := Inverse( regvec[c] ) * regvec;
            fi;
            # Now U_{j-1}-minimalize it, such that the transversal-words
            # returned reach the U_{j-1}-suborbits we find next:
            regvec := ORB_Minimalize(regvec,j,j-1,setup,false,false);
            counter := counter + 1;
            o := OrbitBySuborbit(regvec,(sizes[j]/sizes[j-1])*2+1,sizes[j],
                                 setup,100);
            Info(InfoOrb,2,"Found ",Length(Representatives(o!.db)),
                 " suborbits (need ",sizes[j]/sizes[j-1],")");
        until Length(Representatives(o!.db)) = sizes[j]/sizes[j-1] or 
              counter >= 3;
      fi;
      if neededfullspace or
         Length(Representatives(o!.db)) < sizes[j]/sizes[j-1] then
        neededfullspace := true;
        # Bad luck, try the full space:
        Info(InfoOrb,1,"Looking for U",j-1,"-coset-recognising U",j,"-orbit ",
             "in full space...");
        regvec := ZeroMutable(sample);
        counter := 0;
        # Go to the original generators, using the infrastructure for k=j-1:
        merk := [setup!.els[j],setup!.elsinv[j]];
        setup!.els[j] := Concatenation(gens{[1..j]});
        setup!.elsinv[j] := List(setup!.els[j],x->x^-1);
        setup!.sample[j] := ShallowCopy(regvec);  # now a longer vector
        # this will be corrected later on
        repeat
            Randomize(regvec);
            c := PositionNonZero( regvec );
            if c <= Length( regvec )  then
                regvec := Inverse( regvec[c] ) * regvec;
            fi;
            # Now U_{j-1}-minimalize it, such that the transversal-words
            # returned reach the U_{j-1}-suborbits we find next:
            regvec := ORB_Minimalize(regvec,j,j-1,setup,false,false);
            counter := counter + 1;
            o := OrbitBySuborbit(regvec,(sizes[j]/sizes[j-1])*2+1,sizes[j],
                                 setup,100);
            Info(InfoOrb,2,"Found ",Length(Representatives(o!.db)),
                 " suborbits (need ",sizes[j]/sizes[j-1],")");
        until Length(Representatives(o!.db)) = sizes[j]/sizes[j-1] or
              counter >= 20;
        if Length(Representatives(o!.db)) < sizes[j]/sizes[j-1] then
            Info(InfoOrb,1,"Bad luck, did not find nice orbit, giving up.");
            return;
        fi;
        setup!.els[j] := merk[1];
        setup!.elsinv[j] := merk[2];
      fi;

      Info(InfoOrb,2,"Found U",j-1,"-coset-recognising U",j,"-orbit!");
      setup!.k := j;
      setup!.size[j] := sizes[j];
      setup!.index[j] := sizes[j]/sizes[j-1];
      setup!.trans[j] := o!.words;
      setup!.suborbnr[j] := 0;
      setup!.sumstabl[j] := 0;
      setup!.info[j] :=
            NewHT(regvec,QuoInt(Size(f)^(codims[j]),sizes[j-1])*4+1); # fixme!
      setup!.regvecs[j] := regvec;
      if not(neededfullspace) then
          setup!.cosetrecog[j] := ORB_CosetRecogGenericFactorSpace;
          setup!.cosetinfo[j] := o!.db;   # the hash table
      else
          setup!.cosetrecog[j] := ORB_CosetRecogGenericFullSpace;
          setup!.cosetinfo[j] := [o!.db,k];   # the hash table
      fi;
      setup!.sample[j] := ZeroVector(sample,codims[j]);
      setup!.sample[j+1] := sample;
  od;
  return setup;
end );

InstallGlobalFunction( IsVectorInOrbitBySuborbitList,
function(v,obsol)
  local i,j,k,res,s,x;
  s := obsol.setup;
  k := s!.k;
  for j in [1..obsol.nrrandels] do
      x := s!.op[k+1](v,obsol.randels[j]);
      x := ORB_Minimalize(x,k+1,k,s,false,false);
      for i in [1..Length(obsol.obsos)] do
          res := LookupSuborbit(x,obsol.obsos[i]!.db);
          if res <> fail then  # we know this N-orbit
              return i;  # is in orbit number i
          fi;
      od;
  od;
  return fail;
end );


InstallGlobalFunction( ORB_ApplyStabElement,
function(p,j,i,setup,stab,w)
  local ww,www;
  while true do
    if i > 1 and IsBound(stab!.point[i][j]) and p = stab!.point[i][j] then
      if IsList(w) then Append(w,stab!.cache[i][j][1]); fi;
      p := stab!.cache[i][j][2];
    else
      stab!.point[i][j] := p;

      ww := ShallowCopy(setup!.trans[i][stab!.info[i][stab!.pos[i]]]);
      if IsList(w) then Append(w,ww); fi;
      p := ORB_ApplyWord(p,ww,setup!.els[j],setup!.elsinv[j],setup!.op[j]);
      if i = 1 then
        return p;
      fi;
      www := [];
      p := ORB_Minimalize(p,j,i,setup,false,www);
      Append(ww,www);
      if IsList(w) then Append(w,www); fi;

      stab!.cache[i][j] := [ww,p];
    fi;
    i := i - 1;
  od;
  # never comes here
end );

InstallMethod( StoreSuborbit, 
  "for a suborbit database, a point, a stabiterator, and a setup object",
  [ IsSuborbitDatabase and IsStdSuborbitDbRep, IsObject, IsStabIterator ],
  function(db,p,stab)
  # "db" must be a suborbit database
  # "p" must be a U-minimal element, which is not yet known
  # "stab" must be stabilizer information coming from minimalization
  # all U-minimal elements in the same orbit are calculated and stored
  # in the hash, in addition "p" is appended as representative to
  # "suborbits" and the orbit length is calculated and appended to
  # "lengths".
  local setup, k, firstgen, lastgen, li, i, j, pp, vv, nrmins, length,stabsize;
        
  setup := db!.setup;
  k := setup!.k;
  Add(db!.reps,p);
  AddHT(db!.mins,p,Length(db!.reps));
  ###Print("[",Product(stab.info,Length),"\c");
  if Size(stab) = setup!.size[k] then
    # better use a standard orbit algorithm:
    if k = 1 then
      firstgen := 1;
    else
      firstgen := Length(setup!.els[k-1])+1;
    fi;
    lastgen := Length(setup!.els[k]);
    li := [p];
    i := 1;
    while i <= Length(li) do
      for j in [firstgen..lastgen] do
        pp := setup!.op[k+1](li[i],setup!.els[k+1][j]);  # ???
        vv := ValueHT(db!.mins,pp);
        if vv = fail then
          AddHT(db!.mins,pp,Length(db!.reps));
          Add(li,pp);
        fi;
      od;
      i := i + 1;
    od;
    nrmins := Length(li);
    length := nrmins;
  else
    Reset(stab);
    nrmins := 1;
    stabsize := 0;
    repeat
      pp := ORB_ApplyStabElement(p,k+1,k,setup,stab,false);
      if p = pp then  # we got a real stabilizer element of p
        stabsize := stabsize + 1;
      else  # we could have stepped to some other U-minimal element
        vv := ValueHT(db!.mins,pp);
        if vv = fail then
          AddHT(db!.mins,pp,Length(db!.reps));
          nrmins := nrmins+1;
        fi;
      fi;
    until Next(stab);
    length := setup!.size[k] / stabsize;
  fi;
  Add(db!.lengths,length);
  db!.totallength := db!.totallength + length;
  ###Print("]\r");
  Print("\r#",Length(db!.reps),
        ",S:",ORB_PrettyStringBigNumber(length),",\c");
  Print("M:",nrmins,"  \c");
  return length;
end );

InstallMethod( SuborbitDatabase, "for an orbit by suborbit setup object",
  [ IsOrbitBySuborbitSetup, IsPosInt ],
  function( setup, hashlen )
    # i is the number of subgroups used for the trick, i>=1
    local r;
    r := rec( reps := [], lengths := [], setup := setup, totallength := 0,
              i := setup!.k, j := setup!.k+1 );
    r.mins := NewHT( setup!.sample[setup!.k+1], hashlen );
    Objectify( StdSuborbitDatabasesType, r );
    return r;
  end );

#########################
# Stabilizer Iterators: #
#########################

InstallMethod( StabIterator, "without arguments", [],  
  function( )
    local stab;
    stab := rec();
    Objectify( StdStabIteratorsType, stab );
    return stab;
  end );

InstallMethod( ViewObj, "for a stab iterator", 
  [ IsStabIterator and IsStdStabIteratorRep ],
  function( stab )
    if not(IsBound(stab!.i)) then
        Print("<newly born stab iterator>");
    else
        Print("<stabiterator size=",stab!.info," position=",stab!.pos,">");
    fi;
  end );

InstallMethod( Reset, "for a stab iterator",
  [ IsStabIterator and IsStdStabIteratorRep ],
function(stab)
  if not(IsBound(stab!.i)) then
      Error("StabIterator is not yet initialized");
      return;
  fi;
  stab!.pos := List(stab!.info,x->1);
  stab!.point := List([1..stab!.i],x->[]);
  stab!.cache := List([1..stab!.i],x->[]);
end );

InstallOtherMethod( Size, "for a std stab iterator",
  [ IsStabIterator and IsStdStabIteratorRep ],
  function( stab )
    return Product( stab!.info, Length );
  end );

InstallMethod( Next, "for a stab iterator",
  [ IsStabIterator and IsStdStabIteratorRep ],
function(stab)
  local i;
  i := 1;
  while true do
    if i > Length(stab!.pos) then
      return true;   # finished with this iterator
    fi;
    stab!.pos[i] := stab!.pos[i]+1;
    stab!.point[i] := [];    # this is no longer valid
    if stab!.pos[i] <= Length(stab!.info[i]) then
      return false;  # next element found
    fi;
    stab!.pos[i] := 1;
    i := i + 1;
  od;
  # this is never reached
end );

InstallMethod( Next, "for a stab iterator and a string",
  [ IsStabIterator and IsStdStabIteratorRep, IsString ],
function(stab,st)
  local i;
  i := stab!.i;
  while true do
    if i < 1 then
      return true;   # finished with this iterator
    fi;
    stab!.pos[i] := stab!.pos[i]+1;
    stab!.point[i] := [];
    if stab!.pos[i] <= Length(stab!.info[i]) then
      return false;  # next element found
    fi;
    stab!.pos[i] := 1;
    i := i - 1;
  od;
  # this is never reached
end );


InstallGlobalFunction( OrbitsFromSeedsToOrbitList,
function( obsol, li, hashsize, grpsize )
  local o,orb,v;
  for v in li do
      orb := IsVectorInOrbitBySuborbitList(v,obsol);
      if orb = fail then
          o := OrbitBySuborbit(v,hashsize,grpsize,obsol.setup,50);
          if o <> "didnotfinish" then
              Add(obsol.obsos,o);
              Print("New suborbit:\n");
              ViewObj(o);
              Print("\nHave now ",Length(obsol.obsos),
                    " orbits with a total of ",
                    ORB_PrettyStringBigNumber(Sum(obsol.obsos,Size)),
                    " elements.\n");
          fi;
      else
          Info(InfoOrb,2,"Already know orbit ",orb);
      fi;
  od;
end );

InstallGlobalFunction( OrbitBySuborbit2,
function(setup,p,j,l,i,percentage)
  # Enumerates the orbit of p under the group U_j (with G=U_{k+1}) by
  # suborbits for the subgroup U_i described in "setup". 
  # "setup" is a setup object for the iterated quotient trick,
  #         effectively enabling us to do minimalization with a subgroup
  # "p" is a point
  # "l", "j" and "i" are integers with k+1 >= j >= l > i >= 1
  # "j" indicates in which representation we work,
  # "i" indicates how many helper subgroups we use
  # "l" indicates which group we enumerate
  # "percentage" is a number between 50 and 100 and gives a stopping criterium.
  #         We stop if percentage of the orbit is enumerated.
  #         Only over 50% we know that the stabilizer is correct!
  # Returns a suborbit database with additional field "words" which is
  # a list of words in gens which can be used to reach U-orbit in the G-orbit
  local assumestabcomplete,db,firstgen,fullstabsize,ii,lastgen,m,miniwords,
        mw,newperm,newword,o,oldtodo,pleaseexitnow,stab,stabg,stabgens,
        stabilizer,stabperms,sw,todo,v,words,x;

  Info(InfoOrb,2,"Entering OrbitBySuborbit2 j=",j," l=",l," i=",i);

  if not(j >= l and l > i and i >= 1) then
      Error("Need j >= l > i >= 1");
      return;
  fi;

  pleaseexitnow := false;  # set this to true in a break loop to
                           # let this function exit gracefully
  assumestabcomplete := false;  # set this to true in a break loop to
                                # let this function assume that the 
                                # stabilizer is complete

  # Setup some shortcuts:
  firstgen := Length(setup!.els[l-1])+1;
  lastgen := Length(setup!.els[l]);

  # A security check:
  if p <> setup!.op[j](p,setup!.els[j][1]^0) then
      Error("Warning: The identity does not preserve the starting point!\n",
            "Did you normalize your vector?");
  fi;

  # First we U_i-minimalize p:
  stab := rec();
  p := ORB_Minimalize(p,j,i,setup,stab,false);

  miniwords := [[]];  # here we collect U-minimalizing elements
  
  # Start a database with the first U-suborbit:
  db := SuborbitDatabase2(setup,j,l,i);
  StoreSuborbit(db,p,stab,1);

  stabgens := [];
  stabperms := [];
  stabilizer := Group(setup!.permgens[l][1]^0);
  if IsBound( setup!.stabchainrandom ) and setup!.stabchainrandom <> false then
      StabChain( stabilizer, rec( random := setup!.stabchainrandom ) );
  else
      StabChain(stabilizer);
  fi;
  fullstabsize := 1;
  
  words := [[]];
  todo := [[]];
  while true do

    ii := 1;
    while ii <= Length(todo) do
      if pleaseexitnow = true then 
          return ["didnotfinish",db,fullstabsize]; 
      fi;

      for m in [firstgen..lastgen] do
        x := setup!.op[j](p,setup!.els[j][m]);
        x := ORB_ApplyWord(x,todo[ii],setup!.els[j],
                           setup!.elsinv[j],setup!.op[j]);
        mw := [];
        x := ORB_Minimalize(x,j,i,setup,stab,mw);
        v := LookupSuborbit(x,db);
        if v = fail then   # a new suborbit
          Add(words,Concatenation([m],todo[ii]));
          Add(todo,Concatenation([m],todo[ii]));
          Add(miniwords,mw);
          StoreSuborbit(db,x,stab,fullstabsize);
          if 2 * TotalLength(db) * fullstabsize > setup!.size[l] and
             TotalLength(db) * fullstabsize * 100 >= 
                             setup!.size[l]*percentage then 
            Info(InfoOrb,2,"Leaving OrbitBySuborbit2");
            return Objectify( StdOrbitBySuborbitsType,
                       rec(db := db,
                       words := words,
                       stabsize := fullstabsize,
                       stab := stabilizer,
                       stabwords := stabgens,
                       groupsize := setup!.size[l],
                       orbitlength := setup!.size[l]/fullstabsize,
                       percentage := percentage,
                       seed := p ) );
          fi;
        else
          if assumestabcomplete = false and
             TotalLength(db) * fullstabsize * 2 <= setup!.size[l] then
            # otherwise we know that we will not find more stabilizing els.
            # we know now that v is an integer and that
            # p*setup!.els[m]*todo[ii]*U = p*words[v]*U
            # p*setup!.els[m]*todo[ii]*mw is our new vector
            # p*words[v]*miniwords[v] is our old vector
            # they differ by an element in Stab_U(...)
            stabg := List(stab.gens,
                          w->ORB_ApplyWord(setup!.els[j][1]^0,w,setup!.els[j],
                                           setup!.elsinv[j], OnRight ));
            o := Enumerate(Orb(stabg,x,setup!.op[j],
                   rec( hashlen := setup!.hashlen[j],
                        lookingfor := [Representatives(db)[v]],
                        schreier := true )));
            sw := TraceSchreierTreeForward(o,o!.found);
            sw := Concatenation( stab.gens{sw} );
            newword := Concatenation([m],todo[ii],mw,sw,
                            ORB_InvWord(miniwords[v]),ORB_InvWord(words[v]));
            Print("[\c");
            newperm := ORB_ApplyWord(setup!.permgens[l][1]^0,newword,
                            setup!.permgens[l],setup!.permgensinv[l],OnRight);
            if not(IsOne(newperm)) then
              Print(".\c");
              if not(newperm in stabilizer) then
                Print(".\c");
                Add(stabgens,newword);
                Add(stabperms,newperm);
                stabilizer := GroupWithGenerators(stabperms);
                Info(InfoOrb,1,"Calculating new estimate of the stabilizer...");
                if IsBound(setup!.stabchainrandom) and
                   setup!.stabchainrandom <> false then
                    StabChain(stabilizer, 
                              rec(random := setup!.stabchainrandom));
                else
                    StabChain(stabilizer);
                fi;
                fullstabsize := Size(stabilizer);
                Info(InfoOrb,1,"New stabilizer order: ",fullstabsize);
                if TotalLength(db) * fullstabsize * 100
                   >= setup!.size[l]*percentage then 
                  Info(InfoOrb,2,"Leaving OrbitBySuborbit2");
                  return Objectify( StdOrbitBySuborbitsType,
                         rec(db := db,
                             words := words,
                             stabsize := fullstabsize,
                             stab := stabilizer,
                             stabwords := stabgens,
                             groupsize := setup!.size[l],
                             orbitlength := setup!.size[l]/fullstabsize,
                             percentage := percentage,
                             seed := p) );
                fi;
              fi;
            fi;
            Print("]\c");
          fi;
        fi;
      od;   # for m in [firstgen..lastgen]
      ii := ii + 1;
    od;
  
    oldtodo := todo;
    todo := [];
    for ii in [1..Length(stabgens)] do
      Append(todo,List(oldtodo,w->Concatenation(stabgens[ii],w)));
    od;
    Info(InfoOrb,1,"Length of next todo: ",Length(todo));
  od;
  # this is never reached
end );


InstallGlobalFunction( ORB_ApplyUElement,
function(p,j,i,setup,stab,w)
  local ww;
  while i >= 1 do
    ww := ShallowCopy(setup!.trans[i][stab!.info[i][stab!.pos[i]]]);
    if IsList(w) then Append(w,ww); fi;
    p := ORB_ApplyWord(p,ww,setup!.els[j],setup!.elsinv[j],setup!.op[j]);
    i := i - 1;
  od;
  return p;
end );


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