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


Quelle  froidure-pin.gi   Sprache: unbekannt

 
Spracherkennung für: .gi vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

###########################################################################
##
##  main/froidure-pin.gi
##  Copyright (C) 2015-2022                              James D. Mitchell
##
##  Licensing information can be found in the README file of this package.
##
#############################################################################
##

# This file contains methods for accessing the kernel level version of the
# Froidure-Pin algorithm for enumerating arbitrary semigroups.

#  For some details see:
#
#  V. Froidure, and J.-E. Pin, Algorithms for computing finite semigroups.
#  Foundations of computational mathematics (Rio de Janeiro, 1997), 112-126,
#  Springer, Berlin,  1997.

InstallMethod(CanUseFroidurePin, "for a semigroup",
[IsSemigroup], S -> CanUseGapFroidurePin(S) or
                    CanUseLibsemigroupsFroidurePin(S));

InstallMethod(HasFroidurePin, "for a semigroup",
[IsSemigroup], S -> HasGapFroidurePin(S) or
                    HasLibsemigroupsFroidurePin(S));

InstallTrueMethod(CanUseFroidurePin, CanUseGapFroidurePin);

for x in [IsMatrixOverFiniteFieldSemigroup,
          IsGraphInverseSubsemigroup,
          IsMcAlisterTripleSubsemigroup,
          IsSemigroup and IsFreeBandElementCollection,
          IsPermGroup,
          IsFreeInverseSemigroupCategory] do
  InstallTrueMethod(CanUseGapFroidurePin, x);
od;
Unbind(x);

InstallMethod(CanUseGapFroidurePin, "for a semigroup",
[IsSemigroup], ReturnFalse);

InstallTrueMethod(CanUseGapFroidurePin,
IsSemigroup and HasMultiplicationTable and HasGeneratorsOfSemigroup);

InstallImmediateMethod(CanUseGapFroidurePin,
IsReesZeroMatrixSubsemigroup and HasRowsOfReesZeroMatrixSemigroup
    and HasColumnsOfReesZeroMatrixSemigroup, 0,
function(R)
  return IsPermGroup(UnderlyingSemigroup(R))
    or CanUseFroidurePin(UnderlyingSemigroup(R));
end);

InstallImmediateMethod(CanUseGapFroidurePin,
IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup, 0,
R -> CanUseFroidurePin(ParentAttr(R)));

InstallImmediateMethod(CanUseGapFroidurePin,
IsReesMatrixSubsemigroup and HasRowsOfReesMatrixSemigroup
    and HasColumnsOfReesMatrixSemigroup, 0,
function(R)
  return IsPermGroup(UnderlyingSemigroup(R))
    or CanUseFroidurePin(UnderlyingSemigroup(R));
end);

InstallImmediateMethod(CanUseGapFroidurePin,
IsReesMatrixSubsemigroup and HasGeneratorsOfSemigroup, 0,
R -> CanUseFroidurePin(ParentAttr(R)));

# The next method is supposed to catch proper subsemigroups of quotient
# semigroups
InstallImmediateMethod(CanUseGapFroidurePin,
IsAssociativeElementCollColl and HasGeneratorsOfSemigroup, 0,
function(S)
  if IsEmpty(GeneratorsOfSemigroup(S)) then
    return false;
  fi;
  return (not IsQuotientSemigroup(S))
    and IsCongruenceClass(GeneratorsOfSemigroup(S)[1]);
end);

InstallTrueMethod(CanUseGapFroidurePin,
IsSemigroupIdeal and IsReesMatrixSubsemigroup);

InstallTrueMethod(CanUseGapFroidurePin,
IsSemigroupIdeal and IsReesZeroMatrixSubsemigroup);

# Objects in IsDualSemigroupRep also CanUseGapFroidurePin but this is set
# at creation in attr/dual.gi

InstallMethod(GapFroidurePin, "for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin],
function(S)
  local data, hashlen, nrgens, nr, val, i;

  data := rec(elts := [],
              final := [],
              first := [],
              found := false,
              genslookup := [],
              left := [],
              len := 1,
              lenindex := [],
              nrrules := 0,
              parent := S,
              prefix := [],
              reduced := [[]],
              right := [],
              rules := [],
              stopper := false,
              suffix := [],
              words := []);

  hashlen         := SEMIGROUPS.OptionsRec(S).hashlen;

  data.gens := ShallowCopy(GeneratorsOfSemigroup(S));
  nrgens    := Length(data.gens);
  data.ht   := HTCreate(data.gens[1], rec(treehashsize := hashlen));
  nr        := 0;
  data.one  := false;
  data.pos  := 1;
  data.lenindex[1] := 1;
  data.genstoapply := [1 .. nrgens];

  # add the generators
  for i in data.genstoapply do
    val := HTValue(data.ht, data.gens[i]);
    if val = fail then  # new generator
      nr := nr + 1;
      HTAdd(data.ht, data.gens[i], nr);
      data.elts[nr] := data.gens[i];
      data.words[nr] := [i];
      data.first[nr] := i;
      data.final[nr] := i;
      data.prefix[nr] := 0;
      data.suffix[nr] := 0;
      data.left[nr] := EmptyPlist(nrgens);
      data.right[nr] := EmptyPlist(nrgens);
      data.genslookup[i] := nr;
      data.reduced[nr] := List([1 .. nrgens], ReturnFalse);

      if data.one = false and ForAll(data.gens,
                                     y -> data.gens[i] * y = y
                                        and y * data.gens[i] = y) then
        data.one := nr;
      fi;
    else  # duplicate generator
      data.genslookup[i] := val;
      data.nrrules := data.nrrules + 1;
      data.rules[data.nrrules] := [[i], [val]];
    fi;
  od;

  data.nr := nr;
  return data;
end);

#############################################################################
# 1. Internal methods
#############################################################################

# This is a fallback method in case we don't know any better way to check this

# InstallMethod(IsFinite,
# "for a semigroup with CanUseGapFroidurePin and known generators",
# [CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
# S -> Size(S) < infinity);

InstallMethod(AsSet,
"for a semigroup with CanUseGapFroidurePin and known generators",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
function(S)
  if not IsFinite(S) then
    ErrorNoReturn("the argument (a semigroup) is not finite");
  fi;
  return SortedList(RUN_FROIDURE_PIN(GapFroidurePin(S), -1,
                                     InfoLevel(InfoSemigroups) > 0).elts);
end);

InstallMethod(AsList,
"for a semigroup with CanUseGapFroidurePin and known generators",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
AsListCanonical);

InstallMethod(AsListCanonical,
"for a semigroup with CanUseGapFroidurePin and known generators",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
function(S)
  if not IsFinite(S) then
    ErrorNoReturn("the argument (a semigroup) is not finite");
  fi;
  return RUN_FROIDURE_PIN(GapFroidurePin(S), -1,
                          InfoLevel(InfoSemigroups) > 0).elts;
end);

# For ideals and other generatorless semigroups

InstallMethod(AsListCanonical, "for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin],
function(S)
  GeneratorsOfSemigroup(S);
  return AsListCanonical(S);
end);

InstallMethod(Enumerator,
"for a semigroup with CanUseGapFroidurePin and known generators",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
function(S)
  if (IsReesMatrixSubsemigroup(S) or IsReesZeroMatrixSubsemigroup(S))
      and HasIsWholeFamily(S) and IsWholeFamily(S) then
    TryNextMethod();
  fi;
  return EnumeratorCanonical(S);
end);

InstallMethod(EnumeratorSorted,
"for a semigroup with CanUseGapFroidurePin and known generators",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
function(S)
  if not IsFinite(S) then
    ErrorNoReturn("the argument (a semigroup) is not finite");
  fi;
  TryNextMethod();
end);

InstallMethod(EnumeratorCanonical,
"for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin],
function(S)
  local enum;

  if HasAsListCanonical(S) then
    return AsListCanonical(S);
  fi;

  enum := rec();

  # TODO Shouldn't S be stored in enum
  enum.NumberElement := {enum, x} -> PositionCanonical(S, x);

  enum.ElementNumber := function(_, nr)
    local fp;
    fp := GapFroidurePin(S);
    if not (IsBound(fp.elts) and nr < Length(fp.elts) and IsBound(fp.elts[nr]))
        then
      fp := RUN_FROIDURE_PIN(fp, nr, InfoLevel(InfoSemigroups) > 0);
    fi;

    if nr <= Length(fp.elts) and IsBound(fp.elts[nr]) then
      return fp.elts[nr];
    fi;
    return fail;
  end;

  enum.Length := enum -> Size(S);

  enum.AsList := enum -> AsListCanonical(S);

  enum.Membership := {x, enum} -> PositionCanonical(S, x) <> fail;

  enum.IsBound\[\] := {enum, nr} -> nr <= Length(enum);

  enum := EnumeratorByFunctions(S, enum);
  SetIsSemigroupEnumerator(enum, true);
  return enum;
end);

InstallMethod(IteratorCanonical,
"for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin],
S -> IteratorFiniteList(EnumeratorCanonical(S)));

InstallMethod(Iterator,
"for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin],
S -> IteratorFiniteList(Enumerator(S)));

InstallMethod(IteratorSorted,
"for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin],
S -> IteratorFiniteList(EnumeratorSorted(S)));

# different method for ideals

InstallMethod(Size,
"for a semigroup with CanUseGapFroidurePin and known generators",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
function(S)
  return Length(RUN_FROIDURE_PIN(GapFroidurePin(S), -1,
                                 InfoLevel(InfoSemigroups) > 0).elts);
end);

# different method for ideals

InstallMethod(\in,
"for mult. elt. and a semigroup with CanUseGapFroidurePin + generators",
[IsMultiplicativeElement,
 CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
{x, S} -> PositionCanonical(S, x) <> fail);

# different method for ideals

InstallMethod(Idempotents,
"for a semigroup with CanUseGapFroidurePin and known generators",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
function(S)
  if not IsFinite(S) then
    ErrorNoReturn("the argument (a semigroup) is not finite");
  fi;
  return EnumeratorCanonical(S){IdempotentsSubset(S, [1 .. Size(S)])};
end);

InstallMethod(PositionCanonical,
"for a semigroup with CanUseGapFroidurePin, generators, and mult. elt",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup,
 IsMultiplicativeElement],
function(S, x)
  local fp, ht, nr, val, limit, pos;

  if FamilyObj(x) <> ElementsFamily(FamilyObj(S)) then
    return fail;
  fi;

  fp := GapFroidurePin(S);
  ht := fp.ht;
  nr := fp.nr;
  repeat
    val := HTValue(ht, x);
    if val <> fail then
      return val;
    fi;
    limit := nr + 1;
    fp := RUN_FROIDURE_PIN(fp, limit, InfoLevel(InfoSemigroups) > 0);
    pos := fp.pos;
    nr := fp.nr;
  until pos > nr;

  return HTValue(ht, x);
end);

# Position exists so that we can call it on objects with an uninitialised data
# structure, without first having to initialise the data structure to realise
# that <x> is not in it.

# This returns the current position of x, if it is already known to belong to
# S.

InstallMethod(Position,
"for a semigroup with CanUseGapFroidurePin, mult. element, zero cyc",
[CanUseGapFroidurePin, IsMultiplicativeElement, IsZeroCyc],
PositionOp);

InstallMethod(PositionOp,
"for a semigroup with CanUseGapFroidurePin, multi. element, zero cyc",
[CanUseGapFroidurePin, IsMultiplicativeElement, IsZeroCyc],
function(S, x, _)
  if FamilyObj(x) <> ElementsFamily(FamilyObj(S)) then
    return fail;
  fi;
  return HTValue(GapFroidurePin(S).ht, x);
end);

InstallMethod(PositionSortedOp,
"for a semigroup with CanUseGapFroidurePin, generators and mult. elt.",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup,
 IsMultiplicativeElement],
function(S, x)
  if FamilyObj(x) <> ElementsFamily(FamilyObj(S)) then
    return fail;
  elif not IsFinite(S) then
    ErrorNoReturn("the 1st argument (a semigroup) is not finite");
  fi;
  return Position(AsSet(S), x);
end);

InstallMethod(IsEnumerated, "for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin],
function(S)
  local fp;
  if HasGapFroidurePin(S) then
    fp := GapFroidurePin(S);
    return fp.pos > fp.nr;
  fi;
  return false;
end);

# the main algorithm

InstallMethod(Enumerate,
"for a semigroup with CanUseGapFroidurePin and known generators and pos int",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup, IsInt],
function(S, limit)
  RUN_FROIDURE_PIN(GapFroidurePin(S), limit, InfoLevel(InfoSemigroups) > 0);
  return S;
end);

InstallMethod(Enumerate,
"for a semigroup with CanUseGapFroidurePin and known generators",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup],
S -> Enumerate(S, -1));

# same method for ideals

InstallMethod(RightCayleyGraphSemigroup,
"for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin], 3,
function(S)
  if not IsFinite(S) then
    ErrorNoReturn("the argument (a semigroup) is not finite");
  fi;
  return RUN_FROIDURE_PIN(GapFroidurePin(S), -1,
                          InfoLevel(InfoSemigroups) > 0).right;
end);

InstallMethod(RightCayleyDigraph,
"for a semigroup with CanUseGapFroidurePin rep",
[CanUseGapFroidurePin],
function(S)
  local D;
  if not IsFinite(S) then
    ErrorNoReturn("the argument (a semigroup) is not finite");
  fi;

  D := DigraphNC(MakeImmutable(RightCayleyGraphSemigroup(S)));
  SetFilterObj(D, IsCayleyDigraph);
  SetSemigroupOfCayleyDigraph(D, S);
  SetGeneratorsOfCayleyDigraph(D, GeneratorsOfSemigroup(S));
  return D;
end);

# same method for ideals

InstallMethod(LeftCayleyGraphSemigroup,
"for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin], 3,
function(S)
  if not IsFinite(S) then
    ErrorNoReturn("the argument (a semigroup) is not finite");
  fi;
  return RUN_FROIDURE_PIN(GapFroidurePin(S), -1,
                          InfoLevel(InfoSemigroups) > 0).left;
end);

InstallMethod(LeftCayleyDigraph,
"for a semigroup with CanUseGapFroidurePin rep",
[CanUseGapFroidurePin],
function(S)
  local D;
  if not IsFinite(S) then
    ErrorNoReturn("the argument (a semigroup) is not finite");
  fi;
  D := DigraphNC(MakeImmutable(LeftCayleyGraphSemigroup(S)));
  SetFilterObj(D, IsCayleyDigraph);
  SetSemigroupOfCayleyDigraph(D, S);
  SetGeneratorsOfCayleyDigraph(D, GeneratorsOfSemigroup(S));
  return D;
end);

InstallMethod(NrIdempotents, "for a semigroup with CanUseGapFroidurePin rep",
[CanUseGapFroidurePin],
function(S)
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  fi;
  return Length(Idempotents(S));
end);

InstallMethod(Factorization,
"for a semigroup with CanUseGapFroidurePin and a positive integer",
[CanUseGapFroidurePin, IsPosInt], MinimalFactorization);

InstallMethod(MinimalFactorization,
"for a semigroup with CanUseGapFroidurePin and a pos. int.",
[CanUseGapFroidurePin, IsPosInt],
function(S, i)
  local words;

  if i > Size(S) then
    ErrorNoReturn("the 2nd argument (a positive integer) is greater ",
                  "than the size of the 1st argument (a semigroup)");
  fi;

  words := RUN_FROIDURE_PIN(GapFroidurePin(S),
                            i + 1,
                            InfoLevel(InfoSemigroups) > 0).words;
  return ShallowCopy(words[i]);
end);

InstallMethod(MinimalFactorization,
"for a semigroup with CanUseGapFroidurePin and a multiplicative element",
[CanUseGapFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    ErrorNoReturn("the 2nd argument (a mult. elt.) is not an element ",
                  "of the 1st argument (a semigroup)");
  fi;
  return Factorization(S, PositionCanonical(S, x));
end);

InstallMethod(Factorization,
"for a semigroup with CanUseGapFroidurePin and a multiplicative element",
[CanUseGapFroidurePin, IsMultiplicativeElement], MinimalFactorization);

InstallMethod(RulesOfSemigroup,
"for a semigroup with CanUseGapFroidurePin",
[CanUseGapFroidurePin],
function(S)
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  fi;
  return RUN_FROIDURE_PIN(GapFroidurePin(S), -1,
                          InfoLevel(InfoSemigroups) > 0).rules;
end);

InstallMethod(IdempotentsSubset,
"for a semigroup with CanUseGapFroidurePin + known generators, hom. list",
[CanUseGapFroidurePin and HasGeneratorsOfSemigroup,
 IsHomogeneousList],
function(S, list)
  local fp, left, final, prefix, elts, out, i, j, pos;

  fp := RUN_FROIDURE_PIN(GapFroidurePin(S),
                         Maximum(list) + 1,
                         InfoLevel(InfoSemigroups) > 0);
  left   := fp.left;
  final := fp.final;
  prefix := fp.prefix;
  elts := fp.elts;

  out := [];
  for pos in list do
    i := pos;
    j := pos;
    repeat
      j := left[j][final[i]];
      i := prefix[i];
    until i = 0;
    if j = pos then
      Add(out, pos);
    fi;
  od;
  return out;
end);

InstallMethod(FirstLetter,
"for a semigroup with CanUseGapFroidurePin and a pos. int.",
[CanUseGapFroidurePin, IsPosInt],
function(S, i)
  local fp;

  if i > Size(S) then
    ErrorNoReturn("the 2nd argument (a positive integer) is greater ",
                  "than the size of the 1st argument (a semigroup)");
  fi;

  fp := RUN_FROIDURE_PIN(GapFroidurePin(S),
                         i + 1,
                         InfoLevel(InfoSemigroups) > 0);
  return fp.first[i];
end);

InstallMethod(FirstLetter,
"for a semigroup with CanUseGapFroidurePin and a multiplicative element",
[CanUseGapFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    ErrorNoReturn("the 2nd argument (a mult. elt.) is not an element ",
                  "of the 1st argument (a semigroup)");
  fi;
  return FirstLetter(S, PositionCanonical(S, x));
end);

InstallMethod(FinalLetter,
"for a semigroup with CanUseGapFroidurePin and a pos. int.",
[CanUseGapFroidurePin, IsPosInt],
function(S, i)
  local fp;

  if i > Size(S) then
    ErrorNoReturn("the 2nd argument (a positive integer) is greater ",
                  "than the size of the 1st argument (a semigroup)");
  fi;

  fp := RUN_FROIDURE_PIN(GapFroidurePin(S),
                         i + 1,
                         InfoLevel(InfoSemigroups) > 0);
  return fp.final[i];
end);

InstallMethod(FinalLetter,
"for a semigroup with CanUseGapFroidurePin and a multiplicative element",
[CanUseGapFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    ErrorNoReturn("the 2nd argument (a mult. elt.) is not an element ",
                  "of the 1st argument (a semigroup)");
  fi;
  return FinalLetter(S, PositionCanonical(S, x));
end);

InstallMethod(Prefix,
"for a semigroup with CanUseGapFroidurePin and a pos. int.",
[CanUseGapFroidurePin, IsPosInt],
function(S, i)
  local fp;

  if i > Size(S) then
    ErrorNoReturn("the 2nd argument (a positive integer) is greater ",
                  "than the size of the 1st argument (a semigroup)");
  fi;

  fp := RUN_FROIDURE_PIN(GapFroidurePin(S),
                         i + 1,
                         InfoLevel(InfoSemigroups) > 0);
  return fp.prefix[i];
end);

InstallMethod(Prefix,
"for a semigroup with CanUseGapFroidurePin and a multiplicative element",
[CanUseGapFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    ErrorNoReturn("the 2nd argument (a mult. elt.) is not an element ",
                  "of the 1st argument (a semigroup)");
  fi;
  return Prefix(S, PositionCanonical(S, x));
end);

InstallMethod(Suffix,
"for a semigroup with CanUseGapFroidurePin and a pos. int.",
[CanUseGapFroidurePin, IsPosInt],
function(S, i)
  local fp;

  if i > Size(S) then
    ErrorNoReturn("the 2nd argument (a positive integer) is greater ",
                  "than the size of the 1st argument (a semigroup)");
  fi;

  fp := RUN_FROIDURE_PIN(GapFroidurePin(S),
                         i + 1,
                         InfoLevel(InfoSemigroups) > 0);
  return fp.suffix[i];
end);

InstallMethod(Suffix,
"for a semigroup with CanUseGapFroidurePin and a multiplicative element",
[CanUseGapFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    ErrorNoReturn("the 2nd argument (a mult. elt.) is not an element ",
                  "of the 1st argument (a semigroup)");
  fi;
  return Suffix(S, PositionCanonical(S, x));
end);

[ Dauer der Verarbeitung: 0.42 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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