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


Quelle  acting.gi   Sprache: unbekannt

 
#############################################################################
##
##  ideals/acting.gi
##  Copyright (C) 2013-2022                              James D. Mitchell
##
##  Licensing information can be found in the README file of this package.
##
#############################################################################
##

# This file contains methods for ideals of acting semigroups, and it requires
# some cleaning up.

# Attributes with better methods than the ones for
# IsActingSemigroup without IsSemigroupIdeal.

# This is here so that for regular ideals this method has higher rank than the
# method for IsSemigroup.

InstallMethod(NrDClasses, "for an inverse acting semigroup ideal rep",
[IsInverseActingSemigroupRep and IsSemigroupIdeal],
{I} -> Length(OrbSCC(LambdaOrb(I))) - 1);

InstallMethod(NrDClasses, "for a regular acting semigroup ideal rep",
[IsRegularActingSemigroupRep and IsSemigroupIdeal],
function(I)
  Enumerate(SemigroupIdealData(I));
  return Length(SemigroupIdealData(I)!.dorbit);
end);

InstallMethod(GreensDClasses, "for a regular acting semigroup ideal rep",
[IsSemigroupIdeal and IsRegularActingSemigroupRep],
function(I)
  if IsInverseActingSemigroupRep(I) then
    TryNextMethod();
  fi;
  Enumerate(SemigroupIdealData(I));
  return SemigroupIdealData(I)!.dorbit;
end);

InstallMethod(PartialOrderOfDClasses,
"for a regular acting semigroup ideal rep",
[IsSemigroupIdeal and IsRegularActingSemigroupRep],
function(I)
  local data, D;
  if IsInverseActingSemigroupRep(I) then
    TryNextMethod();
  fi;
  data := SemigroupIdealData(I);
  Enumerate(data);
  D := DigraphNC(IsMutableDigraph, data!.poset);
  DigraphRemoveLoops(D);
  MakeImmutable(D);
  return D;
end);

InstallMethod(DClassReps, "for a regular acting semigroup ideal rep",
[IsSemigroupIdeal and IsRegularActingSemigroupRep],
function(I)
  local data;
  if IsInverseActingSemigroupRep(I) then
    TryNextMethod();
  fi;
  data := SemigroupIdealData(I);
  Enumerate(data);
  return List(data!.dorbit, Representative);
end);

# the really technical stuff...

InstallMethod(SemigroupData, "for a regular acting semigroup ideal rep",
[IsRegularActingSemigroupRep and IsSemigroupIdeal],
SemigroupIdealData);

# JDM this method should become obsolete in time...
# <I> is not known to be regular if this function is invoked...

InstallMethod(SemigroupData, "for an acting semigroup ideal",
[IsActingSemigroup and IsSemigroupIdeal],
function(I)
  local data, pos, partial, classes, D, U, inj, i, j, C;
  # the maximal D-classes of the supersemigroup of <I> contained in <I>
  data := Enumerate(SemigroupIdealData(I));
  pos := [1 .. data!.genspos - 1];
  # the D-classes of the generators in positions
  # [1 .. n - 1] in data!.dorbit
  partial := data!.poset;
  classes := data!.dorbit;
  D := [];
  for i in pos do
    if not ForAny([1 .. Length(partial)], j -> j <> i and i in partial[j]) then
      Add(D, classes[i]);
    fi;
  od;

  # find generators for I...
  U := Semigroup(GeneratorsOfSemigroupIdeal(I), SEMIGROUPS.OptionsRec(I));

  for i in [1 .. Length(D)] do
    if IsRegularDClass(D[i]) then
      inj := InverseGeneralMapping(InjectionPrincipalFactor(D[i]));
      U := ClosureSemigroup(U, OnTuples(GeneratorsOfSemigroup(Source(inj)),
                                        inj));
    else
      U := ClosureSemigroup(U, D[i]);
    fi;
  od;

  i := 0;

  while Size(U) <> Size(I) do
    i := i + 1;
    j := 0;
    while Size(U) <> Size(I) and j < Length(partial[i]) do
      j := j + 1;
      if Length(partial[i]) = 1 or partial[i][j] <> i then
        C := classes[partial[i][j]];
        if IsRegularDClass(C) then
          inj := InverseGeneralMapping(InjectionPrincipalFactor(C));
          U := ClosureSemigroup(U, OnTuples(GeneratorsOfSemigroup(Source(inj)),
                                            inj));
        else
          U := ClosureSemigroup(U, AsList(C));
        fi;
      fi;
    od;
  od;

  SetGeneratorsOfSemigroup(I, GeneratorsOfSemigroup(U));
  SetLambdaOrb(I, LambdaOrb(U));
  SetRhoOrb(I, RhoOrb(U));
  # JDM: maybe more is required here to remove U from the semigroup data, like
  # replacing U with I in the first position of every entry of the data, and in
  # the different internal components of the data.
  return SemigroupData(U);
end);

InstallMethod(GeneratorsOfSemigroup, "for an acting semigroup ideal",
[IsActingSemigroup and IsSemigroupIdeal],
function(I)
  local data, pos, partial, classes, D, U, inj, i, j;

  if not IsRegularActingSemigroupRep(I) then
    return SemigroupData(I)!.gens;
  fi;

  Info(InfoWarning, 2, "finding a generating set of a semigroup ideal!");
  data := SemigroupIdealData(I);
  Enumerate(data, infinity, ReturnFalse);
  pos := [1 .. data!.genspos - 1];
  # the D-classes of the generators in positions
  # [1..n-1] in data!.dorbit
  partial := data!.poset;
  classes := data!.dorbit;
  D := [];
  for i in pos do
    Add(D, classes[i]);
  od;

  # find generators for I...
  U := Semigroup(GeneratorsOfSemigroupIdeal(I));

  for i in [1 .. Length(D)] do
    inj := InverseGeneralMapping(InjectionPrincipalFactor(D[i]));
    U := ClosureSemigroup(U, OnTuples(GeneratorsOfSemigroup(Source(inj)),
                                      inj));
  od;

  i := 0;
  classes := data!.dorbit;

  while Size(U) <> Size(I) do
    i := i + 1;
    j := 0;
    while Size(U) <> Size(I) and j < Length(partial[i]) do
      j := j + 1;
      if Length(partial[i]) = 1 or partial[i][j] <> i then
        inj := InjectionPrincipalFactor(classes[partial[i][j]]);
        inj := InverseGeneralMapping(inj);
        U := ClosureSemigroup(U, OnTuples(GeneratorsOfSemigroup(Source(inj)),
                                          inj));
      fi;
    od;
  od;

  return GeneratorsOfSemigroup(U);
end);

# Don't think that this applies to semigroups of matrices over finite fields,
# so this doesn't require us to use ConvertToInternalElement
# TODO(FixExtremeTests): check that this is really correct

InstallMethod(GeneratorsOfSemigroup,
"for an inverse acting semigroup rep ideal",
[IsInverseActingSemigroupRep and IsSemigroupIdeal],
function(I)
  local U, partial, D, pos, inj, i, j, C, gens;

  Info(InfoWarning, 2, "finding a generating set of a semigroup ideal!");

  # find generators for I...
  U := InverseSemigroup(MinimalIdealGeneratingSet(I));
  partial := OutNeighbours(PartialOrderOfDClasses(I));
  D := GreensDClasses(I);

  # positions of the D-classes containing generators of the ideal...
  pos := Set(GeneratorsOfSemigroupIdeal(I),
             x -> OrbSCCLookup(LambdaOrb(I))[Position(LambdaOrb(I),
                                                      LambdaFunc(I)(x))] - 1);

  for i in pos do
    inj := InverseGeneralMapping(InjectionPrincipalFactor(D[i]));
    U := ClosureInverseSemigroup(U,
                                 OnTuples(GeneratorsOfSemigroup(Source(inj)),
                                          inj));
  od;

  i := 0;
  while Size(U) <> Size(I) do
    i := i + 1;
    j := 0;
    while Size(U) <> Size(I) and j < Length(partial[i]) do
      j := j + 1;
      if Length(partial[i]) = 1 or partial[i][j] <> i then
        C := D[partial[i][j]];
        inj := InverseGeneralMapping(InjectionPrincipalFactor(C));
        gens := GeneratorsOfSemigroup(Source(inj));
        U := ClosureInverseSemigroup(U, OnTuples(gens, inj));
      fi;
    od;
  od;

  return GeneratorsOfSemigroup(U);
end);

InstallMethod(GeneratorsOfInverseSemigroup,
"for an inverse acting semigroup ideal rep",
[IsInverseActingSemigroupRep and IsSemigroupIdeal],
function(I)
  local U, i, partial, D, pos, inj, gens, j, C;

  if HasGeneratorsOfSemigroup(I) then
    return GeneratorsOfSemigroup(I);
  fi;

  Info(InfoWarning, 2, "finding a generating set of a semigroup ideal!");

  # find generators for I...
  U := InverseSemigroup(GeneratorsOfSemigroupIdeal(I));
  partial := OutNeighbours(PartialOrderOfDClasses(I));
  D := GreensDClasses(I);

  # positions of the D-classes containing generators of the ideal...
  pos := Set(GeneratorsOfSemigroupIdeal(I),
             x -> OrbSCCLookup(LambdaOrb(I))[Position(LambdaOrb(I),
                                                      LambdaFunc(I)(x))] - 1);

  for i in pos do
    inj := InverseGeneralMapping(InjectionPrincipalFactor(D[i]));
    gens := GeneratorsOfSemigroup(Source(inj));
    U := ClosureInverseSemigroup(U, OnTuples(gens, inj));
  od;

  i := 0;

  while Size(U) <> Size(I) do
    i := i + 1;
    j := 0;
    while Size(U) <> Size(I) and j < Length(partial[i]) do
      j := j + 1;
      if Length(partial[i]) = 1 or partial[i][j] <> i then
        C := D[partial[i][j]];
        inj := InverseGeneralMapping(InjectionPrincipalFactor(C));
        gens := GeneratorsOfSemigroup(Source(inj));
        U := ClosureInverseSemigroup(U, OnTuples(gens, inj));
      fi;
    od;
  od;

  return GeneratorsOfInverseSemigroup(U);
end);

# this could be simpler for ideals which know they are regular a priori.

InstallMethod(SemigroupIdealData, "for an acting semigroup ideal",
[IsActingSemigroup and IsSemigroupIdeal],
function(I)
  local S, gens, data, filt;

  S := SupersemigroupOfIdeal(I);
  gens := GeneratorsOfSemigroup(S);
  if IsActingSemigroup(S) then
    gens := List(gens, x -> ConvertToInternalElement(S, x));
  fi;

  data := rec();
  data.gens := gens;
  data.parent := I;
  data.log := [1];
  data.genspos := 0;
  data.ht := HTCreate(gens[1], rec(treehashsize :=
                                   SEMIGROUPS.OptionsRec(I).hashlen));
  data.pos := 0;
  data.init := false;
  data.reps := [];
  data.repslookup := [];
  data.orblookup1 := [];
  data.orblookup2 := [];
  data.rholookup := [fail];
  data.lenreps := [0];
  data.orbit := [fail];
  data.dorbit := [];
  data.repslens := [];
  data.lambdarhoht := [];
  data.regular := [];
  data.genstoapply := [1 .. Length(gens)];
  data.stopper := false;
  data.poset := [];
  data.scc_lookup := [];

  if HasIsRegularSemigroup(I) and IsRegularSemigroup(I) then
    filt := IsRegularIdealData;
  else
    filt := IsSemigroupIdealData;
  fi;
  Objectify(NewType(FamilyObj(I), filt), data);

  return data;
end);

InstallMethod(SemigroupIdealData,
"for an inverse acting semigroup rep ideal",
[IsInverseActingSemigroupRep and IsSemigroupIdeal],
ReturnFail);

InstallMethod(ViewObj, [IsSemigroupIdealData],
function(data)
  Print("<");
  if IsClosedData(data) then
    Print("closed ");
  else
    Print("open ");
  fi;
  Print("semigroup ideal ");

  Print("data with ", Length(data!.orbit) - 1, " reps, ",
        Length(LambdaOrb(data!.parent)) - 1, " lambda-values, ",
        Length(RhoOrb(data!.parent)) - 1, " rho-values>");
  return;
end);

InstallMethod(Enumerate, "for semigroup ideal data, limit, looking function",
[IsSemigroupIdealData, IsCyclotomic, IsFunction],
{data, limit, lookfunc} -> Enumerate(data, limit, rec(lookfunc := lookfunc)));

# We concentrate on the case when nothing is known about the parent of the
# ideal.

# we make the R-class centered data structure as in SemigroupIdealData but at
# the same time have an additional "orbit" consisting of D-class reps.

InstallMethod(Enumerate,
"for semigroup ideal data, limit, and record",
[IsSemigroupIdealData, IsCyclotomic, IsRecord],
function(data, limit, record)
  local lookfunc, looking, lambdalookfunc, lambdalooking, rholookfunc,
  rholooking, ht, orb, nr_r, d, nr_d, reps, repslens, lenreps, lambdarhoht,
  repslookup, orblookup1, orblookup2, rholookup, stopper, gens, genstoapply, I,
  lambda, lambdao, lambdaoht, lambdalookup, lambdascc, lenscc, lambdaperm, rho,
  rhoo, rhooht, rhoolookup, rhoscc, act, htadd, htvalue, drel, dtype, poset,
  datalookup, log, tester, regular, UpdateSemigroupIdealData, idealgens, i, x,
  rreps, pos, j, k, z;

  if IsBound(record.lookfunc) and not record.lookfunc <> ReturnFalse then
    lookfunc := record.lookfunc;
    looking := true;
    data!.found := false;
  else
    looking := false;
  fi;

  if IsBound(record.lambdalookfunc) then
    lambdalookfunc := record.lambdalookfunc;
    lambdalooking := true;
  else
    lambdalookfunc := ReturnFalse;
    lambdalooking := false;
  fi;

  if IsBound(record.rholookfunc) then
    rholookfunc := record.rholookfunc;
    rholooking := true;
  else
    rholookfunc := ReturnFalse;
    rholooking := false;
  fi;

  if IsClosedData(data) then
    if looking then
      data!.found := false;
    fi;
    return data;
  fi;

  data!.looking := looking;

  ht   := data!.ht;      # so far found R-reps
  orb  := data!.orbit;   # the so far found R-reps data
  nr_r := Length(orb);
  d    := data!.dorbit;  # the so far found D-classes
  nr_d := Length(d);
  reps := data!.reps;    # reps grouped by equal lambda-scc-index and
                         # rho-value-index

  repslens := data!.repslens;  # Length(reps[m][i])=repslens[m][i]
  lenreps := data!.lenreps;    # lenreps[m]=Length(reps[m])

  lambdarhoht := data!.lambdarhoht;
  # HTValue(lambdarhoht, [m,l])=position in reps[m]
  # of R-reps with lambda-scc-index=m and
  # rho-value-index=l

  repslookup := data!.repslookup;  # Position(orb, reps[m][i][j])
                                   # = repslookup[m][i][j]
                                   # = HTValue(ht, reps[m][i][j])

  orblookup1 := data!.orblookup1;  # orblookup1[i] position in reps[m]
                                   # containing orb[i][4] (the R-rep)

  orblookup2 := data!.orblookup2;  # orblookup2[i] position in
                                   # reps[m][orblookup1[i]]
                                   # containing orb[i][4] (the R-rep)

  rholookup := data!.rholookup;    # rholookup[i]=rho-value-index of orb[i][4]

  stopper := data!.stopper;        # stop at this place in the orbit

  # generators
  gens := data!.gens;  # generators of the parent semigroup
  genstoapply := data!.genstoapply;

  I := data!.parent;

  # lambda
  lambda := LambdaFunc(I);
  lambdao := LambdaOrb(I);
  lambdaoht := lambdao!.ht;
  lambdalookup := lambdao!.scc_lookup;
  lambdascc := OrbSCC(lambdao);
  lenscc := Length(lambdascc);

  lambdaperm := LambdaPerm(I);

  # rho
  rho := RhoFunc(I);
  rhoo := RhoOrb(I);
  rhooht := rhoo!.ht;
  rhoolookup := rhoo!.scc_lookup;
  rhoscc := OrbSCC(rhoo);

  act := StabilizerAction(I);

  if IsBoundGlobal("ORBC") then
    htadd := HTAdd_TreeHash_C;
    htvalue := HTValue_TreeHash_C;
  else
    htadd := HTAdd;
    htvalue := HTValue;
  fi;

  # new stuff
  drel := GreensDRelation(I);
  dtype := DClassType(I);

  poset := data!.poset;  # the D-class poset
  datalookup := data!.scc_lookup;

  log := data!.log;
  # log[i+1] is the last position in orb=data!.orbit where the R-class reps
  # of d[i] appear...

  tester := IdempotentTester(I);
  regular := data!.regular;

  #############################################################################

  # the function which checks if x is already R/D-related to something in the
  # data and if not adds it in the appropriate place

  UpdateSemigroupIdealData := function(x, pos, gen, idealpos)
    local new, xx, l, m, mm, schutz, mults, cosets, y, n, z, ind, val;
    new := false;

    # check, update, rectify the lambda value
    xx := lambda(x);
    l := htvalue(lambdaoht, xx);
    if l = fail then
      l := UpdateIdealLambdaOrb(lambdao, xx, x, pos, gen, idealpos,
                                lambdalookfunc);

      # update the lists of reps
      for n in [lenscc + 1 .. lenscc + Length(lambdascc)] do
        reps[n] := [];
        repslookup[n] := [];
        repslens[n] := [];
        lenreps[n] := 0;
        lenscc := Length(lambdascc);
      od;
      new := true;  # x is a new R-rep
    fi;
    m := lambdalookup[l];
    if l <> lambdascc[m][1] then
      x := x * LambdaOrbMult(lambdao, m, l)[2];
    fi;

    # check if x is identical to one of the known R-reps
    if not new then
      val := htvalue(ht, x);
      if val <> fail then
        if pos <> fail then  # we are multiplying the <i>th D-rep by a generator
          AddSet(poset[i], datalookup[val]);
        fi;
        return;  # x is one of the old R-reps
      fi;
    fi;

    # check, update, rectify the rho value
    xx := rho(x);
    l := htvalue(rhooht, xx);
    if l = fail then
      l := UpdateIdealRhoOrb(rhoo, xx, x, pos, gen, idealpos, rholookfunc);
      new := true;  # x is a new R-rep
    fi;
    schutz := LambdaOrbStabChain(lambdao, m);

    # check if x is R-related to one of the known R-reps
    if not new and schutz <> false and IsBound(lambdarhoht[l])
        and IsBound(lambdarhoht[l][m]) then
       # if schutz=false or these are not bound, then x is a new R-rep

      ind := lambdarhoht[l][m];
      if schutz = true then
        if pos <> fail then
          AddSet(poset[i], datalookup[repslookup[m][ind][1]]);
        fi;
        return;
      fi;

      for n in [1 .. repslens[m][ind]] do
        if SchutzGpMembership(I)(schutz, lambdaperm(reps[m][ind][n], x)) then
          if pos <> fail then
            AddSet(poset[i], datalookup[repslookup[m][ind][n]]);
          fi;
          return;  # x is on of the old R-reps
        fi;
      od;
    fi;

    # if we reach here, then x is a new R-rep, and hence a new D-rep
    mm := rhoolookup[l];
    if l <> rhoscc[mm][1] then
      x := RhoOrbMult(rhoo, mm, l)[2] * x;
    fi;

    nr_d := nr_d + 1;
    d[nr_d] := rec(rep := x);
    ObjectifyWithAttributes(d[nr_d], dtype,
                            ParentAttr, I,
                            EquivalenceClassRelation, drel,
                            IsGreensClassNC, false,
                            Representative, ConvertToExternalElement(I, x),
                            LambdaOrb, lambdao,
                            LambdaOrbSCCIndex, m,
                            RhoOrb, rhoo,
                            RhoOrbSCCIndex, mm,
                            RhoOrbSCC, rhoscc[mm]);
    regular[nr_d] := false;

    # install the point in the poset

    if pos <> fail  then
      AddSet(poset[i], nr_d);
    fi;

    # install the R-class reps of the new D-rep
    mults := RhoOrbMults(rhoo, mm);
    cosets := RhoCosets(d[nr_d]);

    for l in rhoscc[mm] do  # install the R-class reps
      if not IsBound(lambdarhoht[l]) then
        lambdarhoht[l] := [];
      fi;
      if not IsBound(lambdarhoht[l][m]) then
        lenreps[m] := lenreps[m] + 1;
        ind := lenreps[m];
        lambdarhoht[l][m] := ind;
        repslens[m][ind] := 0;
        reps[m][ind] := [];
        repslookup[m][ind] := [];
      else
        ind := lambdarhoht[l][m];
        if not HasIsRegularSemigroup(I) then
          SetIsRegularSemigroup(I, false);
        fi;
      fi;
      if not HasIsRegularSemigroup(I) and not regular[nr_d] then
        regular[nr_d] := tester(lambdao[lambdascc[m][1]], rhoo[l]);
      fi;
      y := mults[l][1] * x;

      for z in cosets do
        nr_r := nr_r + 1;

        repslens[m][ind] := repslens[m][ind] + 1;
        reps[m][ind][repslens[m][ind]] := act(y, z ^ -1);
        repslookup[m][ind][repslens[m][ind]] := nr_r;
        orblookup1[nr_r] := ind;
        orblookup2[nr_r] := repslens[m][ind];
        rholookup[nr_r] := l;
        datalookup[nr_r] := nr_d;

        orb[nr_r] := [I, m, lambdao, reps[m][ind][repslens[m][ind]],
                      false, nr_r];
        htadd(ht, reps[m][ind][repslens[m][ind]], nr_r);

        if looking then
          # did we find it?
          if lookfunc(data, orb[nr_r]) then
            data!.found := nr_r;
          fi;
        fi;

      od;
    od;
    log[nr_d + 1] := nr_r;
  end;
  #############################################################################

  # initialise the data if necessary
  if data!.init = false then
    # add the generators of the ideal...
    idealgens := List(GeneratorsOfSemigroupIdeal(I),
                      x -> ConvertToInternalElement(I, x));
    for i in [1 .. Length(idealgens)] do
      UpdateSemigroupIdealData(idealgens[i], fail, fail, i);
    od;

    data!.init := true;
    data!.genspos := nr_d + 1;
  fi;

  i := data!.pos;  # points in orb in position at most i have descendants

  while nr_d <= limit and i < nr_d and i <> stopper do
    i := i + 1;  # advance in the dorb
    poset[i] := [];
    x := Representative(d[i]);

    # left multiply the R-class reps by the generators of the semigroup
    rreps := [];
    pos := Position(lambdao, lambda(x));
    for j in [log[i] + 1 .. log[i + 1]] do  # the R-class reps of d[i]
      rreps[j - log[i]] := orb[j][4];
      for k in genstoapply do
        UpdateSemigroupIdealData(gens[k] * orb[j][4], pos, k, fail);
        if (looking and data!.found <> false)
            or (lambdalooking and lambdao!.found <> false)
            or (rholooking and rhoo!.found <> false) then
          data!.pos := i - 1;
          return data;
        fi;
      od;
    od;
    SetRClassReps(d[i], rreps);

    # right multiply the L-class reps by the generators of the semigroup
    pos := Position(rhoo, rho(x));
    for z in LClassReps(d[i]) do
      for k in genstoapply do
        UpdateSemigroupIdealData(z * gens[k], pos, k, fail);
        if (looking and data!.found <> false)
            or (lambdalooking and lambdao!.found <> false)
            or (rholooking and rhoo!.found <> false) then
          data!.pos := i - 1;
          return data;
        fi;
      od;
    od;
  od;

  # for the data-orbit
  data!.pos := i;

  if nr_d = i then
    SetFilterObj(lambdao, IsClosedOrbit);
    SetFilterObj(rhoo, IsClosedOrbit);
    SetFilterObj(data, IsClosedData);
    if not HasIsRegularSemigroup(I) then
      SetIsRegularSemigroup(I, ForAll(regular, x -> x));
    fi;
    if IsRegularSemigroup(I) then
      SetFilterObj(I, IsRegularActingSemigroupRep);
      SetGreensDClasses(I, d);
    fi;
  fi;
  return data;
end);

# TODO(FixExtremeTests): use ConvertToInternalElement here

InstallMethod(\in,
"for a multiplicative element and regular acting semigroup ideal",
[IsMultiplicativeElement,
 IsSemigroupIdeal and IsRegularActingSemigroupRep],
function(x, I)
  local data, ht, xx, o, l, lookfunc, m, lambdarhoht,
        schutz, ind, reps;

  if IsInverseActingSemigroupRep(I) then
    TryNextMethod();
  elif ElementsFamily(FamilyObj(I)) <> FamilyObj(x)
      or (IsActingSemigroupWithFixedDegreeMultiplication(I)
          and ActionDegree(x) <> ActionDegree(I))
      or (ActionDegree(x) > ActionDegree(I)) then
    return false;
  elif ActionRank(I)(x) >
      MaximumList(List(Generators(I), y -> ActionRank(I)(y))) then
    Info(InfoSemigroups, 2, "element has larger rank than any element of ",
         "semigroup.");
    return false;
  elif HasMinimalIdeal(I) then
    if ActionRank(I)(x) < ActionRank(I)(Representative(MinimalIdeal(I))) then
      Info(InfoSemigroups, 2, "element has smaller rank than any element of ",
           "semigroup.");
      return false;
    fi;
  fi;

  data := SemigroupIdealData(I);
  ht := data!.ht;

  # look for lambda!
  xx := LambdaFunc(I)(x);
  o := LambdaOrb(I);

  l := Position(o, xx);

  if l = fail then
    if IsClosedOrbit(o) then
      return false;
    fi;

    # this function checks if <pt> has the same lambda-value as x
    lookfunc := {lambdao, pt} -> pt = xx;
    Enumerate(data, infinity, rec(lambdalookfunc := lookfunc));
    l := PositionOfFound(o);

    # rho is not found, so f not in s
    if l = false then
      return false;
    fi;
    l := Position(o, xx);
  fi;

  # strongly connected component of lambda orb
  m := OrbSCCLookup(o)[l];

  # make sure lambda of <x> is in the first place of its scc
  if l <> OrbSCC(o)[m][1] then
    x := x * LambdaOrbMult(o, m, l)[2];
  fi;

  schutz := LambdaOrbStabChain(o, m);

  # check if <x> is an existing R-rep
  if HTValue(ht, x) <> fail then
    return true;
  elif schutz = false then
    # If <x> in <I> and the Schutz gp is trivial, then <x> is an R-class rep.
    # Since we have found the D-class containing an element of <I> with the
    # same lambda-val as <x>, we have found all of the R-class reps of <I>
    # with the same lambda-val as <x>, and so we should have found <x>. We
    # didn't and so <x> is not in <I>.
    return false;
  fi;

  # look for rho!
  o := RhoOrb(I);
  l := Position(o, RhoFunc(I)(x));

  if l = fail then
    Assert(1, IsClosedOrbit(o));
    # Because I is regular once we have found the lambda-val we have found the
    # (unique) D-class of I containing something with the same lambda-val. If x
    # in I, then the D-class we've found must contain x and so we already know
    # the rho-val. So, if l = fail, then x is not in I.
    return false;
  fi;

  lambdarhoht := data!.lambdarhoht;

  # look for the R-class rep
  if not IsBound(lambdarhoht[l]) or not IsBound(lambdarhoht[l][m]) then
    # lambda-rho-combination not yet seen
    if IsClosedData(data) then
      return false;
    fi;

    lookfunc := {d, x} -> IsBound(lambdarhoht[l])
                          and IsBound(lambdarhoht[l][m]);
    data := Enumerate(data, infinity, lookfunc);
    if not IsBound(lambdarhoht[l]) or not IsBound(lambdarhoht[l][m]) then
      return false;
    fi;
  fi;

  ind := lambdarhoht[l][m];
  # the index of the list of reps with same lambda-rho value as <x>.
  # Note that since <I> is regular, there is only one such rep at most.

  reps := data!.reps;

  # if the Schutzenberger group is the symmetric group, then <x> in <I>!
  if schutz = true then
    return true;
  fi;
  Assert(1, schutz <> false);
  return SchutzGpMembership(I)(schutz, LambdaPerm(I)(reps[m][ind][1], x));
end);

# JDM; this method could be removed later...

InstallMethod(Size, "for an acting semigroup ideal",
[IsActingSemigroup and IsSemigroupIdeal],
function(s)
  local data, lenreps, repslens, o, scc, size, n, m, i;

  data := Enumerate(SemigroupIdealData(s), infinity, ReturnFalse);
  lenreps := data!.lenreps;
  repslens := data!.repslens;
  o := LambdaOrb(s);
  scc := OrbSCC(o);

  size := 0;

  for m in [2 .. Length(scc)] do
    n := Size(LambdaOrbSchutzGp(o, m)) * Length(scc[m]);
    for i in [1 .. lenreps[m]] do
      size := size + n * repslens[m][i];
    od;
  od;

  return size;
end);

InstallMethod(Enumerate,
"for regular ideal data, limit, and func",
[IsRegularIdealData, IsCyclotomic, IsRecord],
function(data, limit, record)
  local lookfunc, looking, lambdalookfunc, lambdalooking, rholookfunc,
  rholooking, ht, orb, nr_r, d, nr_d, reps, repslens, lenreps, lambdarhoht,
  repslookup, orblookup1, orblookup2, rholookup, stopper, gens, genstoapply, I,
  lambda, lambdao, lambdaoht, lambdalookup, lambdascc, lenscc, rho, rhoo,
  rhooht, rhoolookup, rhoscc, rholen, htadd, htvalue, drel, dtype, poset,
  datalookup, log, UpdateSemigroupIdealData, idealgens, i, x, rreps, pos, j, k,
  z;

  if IsBound(record.lookfunc) and record.lookfunc <> ReturnFalse then
    lookfunc := record.lookfunc;
    looking := true;
    data!.found := false;
  else
    looking := false;
  fi;

  if IsBound(record.lambdalookfunc) then
    lambdalookfunc := record.lambdalookfunc;
    lambdalooking := true;
  else
    lambdalookfunc := ReturnFalse;
    lambdalooking := false;
  fi;

  if IsBound(record.rholookfunc) then
    rholookfunc := record.rholookfunc;
    rholooking := true;
  else
    rholookfunc := ReturnFalse;
    rholooking := false;
  fi;

  if IsClosedData(data) then
    if looking then
      data!.found := false;
    fi;
    return data;
  fi;

  data!.looking := looking;

  ht := data!.ht;       # so far found R-reps
  orb := data!.orbit;   # the so far found R-reps data
  nr_r := Length(orb);
  d := data!.dorbit;    # the so far found D-classes
  nr_d := Length(d);
  reps := data!.reps;
  # reps grouped by equal lambda-scc-index and rho-value-index

  repslens := data!.repslens;       # Length(reps[m][i])=repslens[m][i]
  lenreps := data!.lenreps;         # lenreps[m]=Length(reps[m])

  lambdarhoht := data!.lambdarhoht;
                                  # HTValue(lambdarhoht, [m,l])=position in
                                  # reps[m] of R-reps with lambda-scc-index=m
                                  # and rho-value-index=l

  repslookup := data!.repslookup;  # Position(orb, reps[m][i][j])
                                  # = repslookup[m][i][j]
                                  # = HTValue(ht, reps[m][i][j])

  orblookup1 := data!.orblookup1;  # orblookup1[i] position in reps[m]
                                  # containing orb[i][4] (the R-rep)

  orblookup2 := data!.orblookup2;  # orblookup2[i] position in
                                  # reps[m][orblookup1[i]]
                                  # containing orb[i][4] (the R-rep)

  rholookup := data!.rholookup;   # rholookup[i]=rho-value-index of orb[i][4]

  stopper := data!.stopper;       # stop at this place in the orbit

  # generators
  gens := data!.gens;  # generators of the parent semigroup
  genstoapply := data!.genstoapply;

  I := data!.parent;

  # lambda
  lambda := LambdaFunc(I);
  lambdao := LambdaOrb(I);
  lambdaoht := lambdao!.ht;
  lambdalookup := lambdao!.scc_lookup;
  lambdascc := OrbSCC(lambdao);
  lenscc := Length(lambdascc);

  # rho
  rho := RhoFunc(I);
  rhoo := RhoOrb(I);
  rhooht := rhoo!.ht;
  rhoolookup := rhoo!.scc_lookup;
  rhoscc := OrbSCC(rhoo);
  rholen := Length(rhoo);

  if IsBoundGlobal("ORBC") then
    htadd := HTAdd_TreeHash_C;
    htvalue := HTValue_TreeHash_C;
  else
    htadd := HTAdd;
    htvalue := HTValue;
  fi;

  # new stuff
  drel := GreensDRelation(I);
  dtype := DClassType(I);

  poset := data!.poset;  # the D-class poset
  datalookup := data!.scc_lookup;

  log := data!.log;
  # log[i+1] is the last position in orb=data!.orbit where the
  # R-class reps of d[i] appear...

  #############################################################################

  # the function which checks if x is already R/D-related to something in the
  # data and if not adds it in the appropriate place

  UpdateSemigroupIdealData := function(x, pos, gen, idealpos)
    local new, xx, l, m, mm, schutz, mults, y, n, ind, val;
    new := false;

    # check, update, rectify the lambda value
    xx := lambda(x);
    l := htvalue(lambdaoht, xx);
    if l = fail then
      l := UpdateIdealLambdaOrb(lambdao, xx, x, pos, gen, idealpos,
                                lambdalookfunc);

      # update the lists of reps
      for n in [lenscc + 1 .. lenscc + Length(lambdascc)] do
        reps[n] := [];
        repslookup[n] := [];
        repslens[n] := [];
        lenreps[n] := 0;
        lenscc := Length(lambdascc);
      od;
      new := true;  # x is a new R-rep
    fi;
    m := lambdalookup[l];
    if l <> lambdascc[m][1] then
      x := x * LambdaOrbMult(lambdao, m, l)[2];
    fi;

    # check if x is identical to one of the known R-reps
    if not new then
      val := htvalue(ht, x);
      if val <> fail then
        if pos <> fail then  # we are multiplying the <i>th D-rep by a generator
          AddSet(poset[i], datalookup[val]);
        fi;
        return;  # x is one of the old R-reps
      fi;
    fi;

    # check, update, rectify the rho value
    xx := rho(x);
    l := htvalue(rhooht, xx);
    if l = fail then
      l := UpdateIdealRhoOrb(rhoo, xx, x, pos, gen, idealpos, rholookfunc);
      for n in [rholen + 1 .. rholen + Length(rhoo)] do
        lambdarhoht[n] := [];
      od;
      rholen := Length(rhoo);
      new := true;  # x is a new R-rep
    fi;
    schutz := LambdaOrbStabChain(lambdao, m);

    # check if x is R-related to one of the known R-reps
    if not new and schutz <> false and IsBound(lambdarhoht[l][m]) then
      ind := lambdarhoht[l][m];
      if pos <> fail then
        AddSet(poset[i], datalookup[repslookup[m][ind][1]]);
      fi;
      return;
    fi;

    # if we reach here, then x is a new R-rep, and hence a new D-rep
    mm := rhoolookup[l];
    if l <> rhoscc[mm][1] then
      x := RhoOrbMult(rhoo, mm, l)[2] * x;
    fi;

    nr_d := nr_d + 1;
    d[nr_d] := rec(rep := x);
    ObjectifyWithAttributes(d[nr_d], dtype,
                            ParentAttr, I,
                            EquivalenceClassRelation, drel,
                            IsGreensClassNC, false,
                            Representative, ConvertToExternalElement(I, x),
                            LambdaOrb, lambdao,
                            LambdaOrbSCCIndex, m,
                            RhoOrb, rhoo,
                            RhoOrbSCCIndex, mm,
                            RhoOrbSCC, rhoscc[mm]);

    # install the point in the poset
    if pos <> fail  then
      AddSet(poset[i], nr_d);
    fi;

    # install the R-class reps of the new D-rep
    mults := RhoOrbMults(rhoo, mm);

    for l in rhoscc[mm] do  # install the R-class reps
      nr_r := nr_r + 1;
      y := mults[l][1] * x;
      orb[nr_r] := [I, m, lambdao, y, false, nr_r];
      htadd(ht, y, nr_r);

      lenreps[m] := lenreps[m] + 1;
      ind := lenreps[m];
      lambdarhoht[l][m] := ind;  # this can't have been seen before
      reps[m][ind] := [y];
      repslookup[m][ind] := [nr_r];
      repslens[m][ind] := 1;
      orblookup1[nr_r] := ind;
      orblookup2[nr_r] := 1;
      rholookup[nr_r] := l;
      datalookup[nr_r] := nr_d;

      if looking then
        # did we find it?
        if lookfunc(data, orb[nr_r]) then
          data!.found := nr_r;
        fi;
      fi;

    od;
    log[nr_d + 1] := nr_r;
  end;
  #############################################################################

  # initialise the data if necessary
  if data!.init = false then
    # add the generators of the ideal...
    idealgens := List(GeneratorsOfSemigroupIdeal(I),
                      x -> ConvertToInternalElement(I, x));
    for i in [1 .. Length(idealgens)] do
      UpdateSemigroupIdealData(idealgens[i], fail, fail, i);
    od;

    data!.init := true;
    data!.genspos := nr_d + 1;
  fi;

  i := data!.pos;       # points in orb in position at most i have descendants

  while nr_d <= limit and i < nr_d and i <> stopper do
    i := i + 1;  # advance in the dorb
    poset[i] := [];
    x := Representative(d[i]);

    # left multiply the R-class reps by the generators of the semigroup
    rreps := [];
    pos := Position(lambdao, lambda(x));
    for j in [log[i] + 1 .. log[i + 1]] do  # the R-class reps of d[i]
      rreps[j - log[i]] := orb[j][4];
      for k in genstoapply do
        UpdateSemigroupIdealData(gens[k] * orb[j][4], pos, k, fail);
        if (looking and data!.found <> false)
            or (lambdalooking and lambdao!.found <> false)
            or (rholooking and rhoo!.found <> false) then
          data!.pos := i - 1;
          return data;
        fi;
      od;
    od;
    SetRClassReps(d[i], rreps);

    # right multiply the L-class reps by the generators of the semigroup
    pos := Position(rhoo, rho(x));
    for z in LClassReps(d[i]) do
      for k in genstoapply do
        UpdateSemigroupIdealData(z * gens[k], pos, k, fail);
        if (looking and data!.found <> false)
            or (lambdalooking and lambdao!.found <> false)
            or (rholooking and rhoo!.found <> false) then
          data!.pos := i - 1;
          return data;
        fi;
      od;
    od;
  od;

  # for the data-orbit
  data!.pos := i;

  if nr_d = i then
    SetFilterObj(lambdao, IsClosedOrbit);
    SetFilterObj(rhoo, IsClosedOrbit);
    SetFilterObj(data, IsClosedData);
  fi;

  return data;
end);

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