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


SSL froidure-pin.gi   Sprache: unbekannt

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

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

# We have the following loop instead of IsMatrixOverSemiringSemigroup because
# semigroups of matrices over a finite field below to
# IsMatrixOverSemiringSemigroup, but cannot compute LibsemigroupsFroidurePin

InstallTrueMethod(CanUseFroidurePin, CanUseLibsemigroupsFroidurePin);

for x in [IsFpSemigroup,
          IsFpMonoid,
          IsTransformationSemigroup,
          IsBooleanMatSemigroup,
          IsIntegerMatrixSemigroup,
          IsIntegerMatrixMonoid,
          IsMaxPlusMatrixSemigroup,
          IsMinPlusMatrixSemigroup,
          IsTropicalMinPlusMatrixSemigroup,
          IsTropicalMaxPlusMatrixSemigroup,
          IsNTPMatrixSemigroup,
          IsProjectiveMaxPlusMatrixSemigroup,
          IsBipartitionSemigroup,
          IsPBRSemigroup,
          IsTransformationSemigroup,
          IsPartialPermSemigroup] do
  InstallTrueMethod(CanUseLibsemigroupsFroidurePin,
                    x and HasGeneratorsOfSemigroup);
  InstallTrueMethod(CanUseLibsemigroupsFroidurePin,
                    x and IsSemigroupIdeal);
od;

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

InstallImmediateMethod(CanUseLibsemigroupsFroidurePin,
IsQuotientSemigroup and HasQuotientSemigroupCongruence, 0,
Q -> CanUseLibsemigroupsCongruence(QuotientSemigroupCongruence(Q)));

###########################################################################
## Function for getting the correct record from the `libsemigroups` record.
###########################################################################

DeclareOperation("FroidurePinMemFnRec", [IsSemigroup]);
DeclareOperation("FroidurePinMemFnRec",
                 [IsSemigroup, IsListOrCollection]);

InstallMethod(FroidurePinMemFnRec, "for a semigroup",
[IsSemigroup], S -> FroidurePinMemFnRec(S, []));

InstallMethod(FroidurePinMemFnRec, "for a semigroup",
[IsSemigroup, IsListOrCollection], {S, coll} -> FroidurePinMemFnRec(S));

InstallMethod(FroidurePinMemFnRec,
"for a transformation semigroup and list or coll.",
[IsTransformationSemigroup, IsListOrCollection],
function(S, coll)
  local N;
  N := DegreeOfTransformationSemigroup(S);
  if IsTransformationCollection(coll) then
    N := Maximum(N, DegreeOfTransformationCollection(coll));
  elif not IsEmpty(coll) then
    Error("Expected a transf. coll. or empty list, found ",
          TNAM_OBJ(coll));
  fi;
  if N <= 16
      and IsBound(LIBSEMIGROUPS_HPCOMBI_ENABLED) then
    return libsemigroups.FroidurePinTransf16;
  elif N <= 2 ^ 16 then
    return libsemigroups.FroidurePinTransfUInt2;
  elif N <= 2 ^ 32 then
    return libsemigroups.FroidurePinTransfUInt4;
  else
    # Cannot currently test the next line
    Error("transformation degree is too high!");
  fi;
end);

InstallMethod(FroidurePinMemFnRec,
"for a partial perm. semigroup and list or coll.",
[IsPartialPermSemigroup, IsListOrCollection],
function(S, coll)
  local N;
  N := Maximum(DegreeOfPartialPermSemigroup(S),
               CodegreeOfPartialPermSemigroup(S));
  if IsPartialPermCollection(coll) then
    N := Maximum(N,
                 DegreeOfPartialPermCollection(coll),
                 CodegreeOfPartialPermCollection(coll));
  elif not IsEmpty(coll) then
    Error("Expected a partial perm. coll. or empty list, found ",
          TNAM_OBJ(coll));
  fi;
  if N <= 16 and IsBound(LIBSEMIGROUPS_HPCOMBI_ENABLED) then
    return libsemigroups.FroidurePinPPerm16;
  elif N <= 2 ^ 16 then
    return libsemigroups.FroidurePinPPermUInt2;
  elif N <= 2 ^ 32 then
    return libsemigroups.FroidurePinPPermUInt4;
  else
    # Cannot currently test the next line
    Error("partial perm degree is too high!");
  fi;
end);

InstallMethod(FroidurePinMemFnRec, "for a boolean matrix semigroup",
[IsBooleanMatSemigroup],
function(S)
  local N;
  N := DimensionOfMatrixOverSemiring(Representative(S));
  if N <= 8 then
    return libsemigroups.FroidurePinBMat8;
  else
    return libsemigroups.FroidurePinBMat;
  fi;
end);

InstallMethod(FroidurePinMemFnRec, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> libsemigroups.FroidurePinBipart);

InstallMethod(FroidurePinMemFnRec, "for an integer matrix semigroup",
[IsIntegerMatrixSemigroup], S -> libsemigroups.FroidurePinIntMat);

InstallMethod(FroidurePinMemFnRec, "for an integer matrix monoid",
[IsIntegerMatrixMonoid], S -> libsemigroups.FroidurePinIntMat);

InstallMethod(FroidurePinMemFnRec, "for an max-plus matrix semigroup",
[IsMaxPlusMatrixSemigroup], S -> libsemigroups.FroidurePinMaxPlusMat);

InstallMethod(FroidurePinMemFnRec, "for an min-plus matrix semigroup",
[IsMinPlusMatrixSemigroup], S -> libsemigroups.FroidurePinMinPlusMat);

InstallMethod(FroidurePinMemFnRec, "for a tropical max-plus matrix semigroup",
[IsTropicalMaxPlusMatrixSemigroup],
S -> libsemigroups.FroidurePinMaxPlusTruncMat);

InstallMethod(FroidurePinMemFnRec, "for a tropical min-plus matrix semigroup",
[IsTropicalMinPlusMatrixSemigroup],
S -> libsemigroups.FroidurePinMinPlusTruncMat);

InstallMethod(FroidurePinMemFnRec, "for an ntp matrix semigroup",
[IsNTPMatrixSemigroup], S -> libsemigroups.FroidurePinNTPMat);

InstallMethod(FroidurePinMemFnRec,
"for a projective max-plus matrix semigroup",
[IsProjectiveMaxPlusMatrixSemigroup],
S -> libsemigroups.FroidurePinProjMaxPlusMat);

InstallMethod(FroidurePinMemFnRec, "for a pbr semigroup",
[IsPBRSemigroup], S -> libsemigroups.FroidurePinPBR);

InstallMethod(FroidurePinMemFnRec, "for an fp semigroup",
[IsFpSemigroup], S -> libsemigroups.FroidurePinBase);

InstallMethod(FroidurePinMemFnRec, "for an fp monoid",
[IsFpMonoid], S -> libsemigroups.FroidurePinBase);

InstallMethod(FroidurePinMemFnRec, "for quotient semigroup",
[IsQuotientSemigroup], S -> libsemigroups.FroidurePinBase);

BindGlobal("_GetElement",
function(coll, x)
  Assert(1, IsMultiplicativeElementCollection(coll) or IsMatrixObj(x));
  Assert(1, IsMultiplicativeElement(x) or IsMatrixObj(x));
  if IsPartialPermCollection(coll) then
    return [x, Maximum(DegreeOfPartialPermCollection(coll),
                       CodegreeOfPartialPermCollection(coll))];
  elif IsTransformationCollection(coll) then
    return [x, DegreeOfTransformationCollection(coll)];
  elif IsElementOfFpSemigroupCollection(coll) then
    return SEMIGROUPS.ExtRepObjToWord(ExtRepOfObj(x)) - 1;
  elif IsElementOfFpMonoidCollection(coll) then
    if IsOne(x) then
      return [0];
    fi;
    return SEMIGROUPS.ExtRepObjToWord(ExtRepOfObj(x));
  fi;
  return x;
end);

###########################################################################
## Constructor - constructs a libsemigroups LibsemigroupsFroidurePin object, #
## and adds the generators of the semigroup to that.
###########################################################################

InstallMethod(HasLibsemigroupsFroidurePin,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  return IsBound(S!.LibsemigroupsFroidurePin)
      and IsValidGapbind14Object(S!.LibsemigroupsFroidurePin);
end);

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

InstallGlobalFunction(LibsemigroupsFroidurePin,
function(S)
  local C, record, T, add_generator, coll, x;
  Assert(1, IsSemigroup(S));
  Assert(1, CanUseLibsemigroupsFroidurePin(S));
  if HasLibsemigroupsFroidurePin(S) then
    return S!.LibsemigroupsFroidurePin;
  elif IsFpSemigroup(S) or IsFpMonoid(S) then
    C := LibsemigroupsCongruence(UnderlyingCongruence(S));
    return libsemigroups.Congruence.quotient_froidure_pin(C);
  elif IsQuotientSemigroup(S) then
    C := QuotientSemigroupCongruence(S);
    if not HasGeneratingPairsOfMagmaCongruence(C) then
      GeneratingPairsOfMagmaCongruence(C);
    fi;
    C := LibsemigroupsCongruence(C);
    return libsemigroups.Congruence.quotient_froidure_pin(C);
  fi;
  Unbind(S!.LibsemigroupsFroidurePin);
  record := FroidurePinMemFnRec(S);
  T  := record.make();
  add_generator := record.add_generator;
  coll := GeneratorsOfSemigroup(S);
  for x in coll do
    add_generator(T, _GetElement(coll, x));
  od;
  S!.LibsemigroupsFroidurePin := T;
  return T;
end);

###########################################################################
## Size/IsFinite
###########################################################################

InstallMethod(Size, "for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  if not IsFinite(S) then
    return infinity;
  fi;
  return FroidurePinMemFnRec(S).size(LibsemigroupsFroidurePin(S));
end);

InstallMethod(IsFinite, "for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  if IsFpSemigroup(S) or IsFpMonoid(S) or IsQuotientSemigroup(S) then
    TryNextMethod();
  fi;
  return FroidurePinMemFnRec(S).size(LibsemigroupsFroidurePin(S)) < infinity;
end);

###########################################################################
## AsSet/AsList etc
###########################################################################

InstallMethod(AsSet, "for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local result, sorted_at, T, i;
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  elif IsPartialPermSemigroup(S) or IsFpSemigroup(S) or IsFpMonoid(S)
      or IsQuotientSemigroup(S) then
    # Special case required because < for libsemigroups PartialPerms and < for
    # GAP partial perms are different; and also for IsFpSemigroup and
    # IsFpMonoid and IsQuotientSemigroup because there's no sorted_at
    return AsSet(AsList(S));
  fi;
  result := EmptyPlist(Size(S));
  sorted_at := FroidurePinMemFnRec(S).sorted_at;
  T := LibsemigroupsFroidurePin(S);
  for i in [1 .. Size(S)] do
    result[i] := sorted_at(T, i - 1);
  od;
  SetIsSSortedList(result, true);
  return result;
end);

InstallMethod(AsListCanonical,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local result, at, T, i;
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  elif IsFpSemigroup(S) or IsFpMonoid(S) or IsQuotientSemigroup(S) then
    at := {T, i} -> EvaluateWord(GeneratorsOfSemigroup(S),
                     FroidurePinMemFnRec(S).factorisation(T, i) + 1);
  else
    at := FroidurePinMemFnRec(S).at;
  fi;
  result := EmptyPlist(Size(S));
  T := LibsemigroupsFroidurePin(S);
  for i in [1 .. Size(S)] do
    result[i] := at(T, i - 1);
  od;
  return result;
end);

InstallMethod(AsList,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin], AsListCanonical);

###########################################################################
## Position etc
###########################################################################

InstallMethod(PositionCanonical,
"for a semigroup with CanUseLibsemigroupsFroidurePin and mult. element",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsMultiplicativeElement],
function(S, x)
  local T, record, word, pos, C;

  if IsPartialPermSemigroup(S) then
    if DegreeOfPartialPermSemigroup(S) < DegreeOfPartialPerm(x)
        or CodegreeOfPartialPermSemigroup(S) < CodegreeOfPartialPerm(x) then
      return fail;
    fi;
  elif IsTransformationSemigroup(S) then
    if DegreeOfTransformationSemigroup(S) < DegreeOfTransformation(x) then
      return fail;
    fi;
  elif IsFpSemigroup(S) or IsFpMonoid(S) then
    if not x in S then
      return fail;
    fi;
    T := LibsemigroupsFroidurePin(S);
    record := FroidurePinMemFnRec(S);
    word := _GetElement(S, x);
    pos := record.current_position(T, word);
    while pos < 0 do
      record.enumerate(T, record.current_size(T) + 1);
      pos := record.current_position(T, word);
    od;
    return pos + 1;
  elif IsQuotientSemigroup(S) then
    T := QuotientSemigroupPreimage(S);
    C := QuotientSemigroupCongruence(S);
    return CongruenceWordToClassIndex(C, Factorization(T, Representative(x)));
  fi;
  pos := FroidurePinMemFnRec(S).position(LibsemigroupsFroidurePin(S),
                                         _GetElement(S, x));
  if pos < 0 then
    return fail;
  fi;
  return pos + 1;
end);

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

InstallMethod(PositionOp,
"for a semigroup with CanUseLibsemigroupsFroidurePin, mult. element, and zero",
[IsSemigroup and CanUseLibsemigroupsFroidurePin,
 IsMultiplicativeElement,
 IsZeroCyc],
function(S, x, _)
  local pos;
  if IsPartialPermSemigroup(S) then
    if DegreeOfPartialPermSemigroup(S) < DegreeOfPartialPerm(x)
        or CodegreeOfPartialPermSemigroup(S) < CodegreeOfPartialPerm(x) then
      return fail;
    fi;
  elif IsTransformationSemigroup(S) then
    if DegreeOfTransformationSemigroup(S) < DegreeOfTransformation(x) then
      return fail;
    fi;
  fi;

  pos := FroidurePinMemFnRec(S).current_position(LibsemigroupsFroidurePin(S),
                                                 _GetElement(S, x));
  if pos < 0 then
    return fail;
  else
    return pos + 1;
  fi;
end);

InstallMethod(PositionSortedOp,
"for a semigroup with CanUseLibsemigroupsFroidurePin and mult. element",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsMultiplicativeElement],
function(S, x)
  local pos;
  if not IsFinite(S) then
    Error("the 1st argument (a semigroup) is not finite");
  elif IsPartialPermSemigroup(S) then
    if DegreeOfPartialPermSemigroup(S) < DegreeOfPartialPerm(x)
        or CodegreeOfPartialPermSemigroup(S) < CodegreeOfPartialPerm(x) then
      return fail;
    fi;
    # Special case required because < for libsemigroups PartialPerms and < for
    # GAP partial perms are different.
    return Position(AsSet(S), x);
  elif IsTransformationSemigroup(S) then
    if DegreeOfTransformationSemigroup(S) < DegreeOfTransformation(x) then
      return fail;
    fi;
  fi;
  pos := FroidurePinMemFnRec(S).sorted_position(LibsemigroupsFroidurePin(S),
                                                _GetElement(S, x));
  if pos < 0 then
    return fail;
  else
    return pos + 1;
  fi;
end);

###########################################################################
## Membership
###########################################################################

InstallMethod(\in,
"for mult. element and a semigroup with CanUseLibsemigroupsFroidurePin",
[IsMultiplicativeElement, IsSemigroup and CanUseLibsemigroupsFroidurePin],
{x, S} -> PositionCanonical(S, x) <> fail);

###########################################################################
## NrIdempotents
###########################################################################

InstallMethod(NrIdempotents,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local F;
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  elif IsFpSemigroup(S) or IsFpMonoid(S) or IsQuotientSemigroup(S) then
    return Length(IdempotentsSubset(S, [1 .. Size(S)]));
  fi;
  F := LibsemigroupsFroidurePin(S);
  return FroidurePinMemFnRec(S).number_of_idempotents(F);
end);

InstallMethod(Idempotents,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  fi;
  return FroidurePinMemFnRec(S).idempotents(LibsemigroupsFroidurePin(S));
end);

###########################################################################
## MinimalFactorization
###########################################################################

InstallMethod(MinimalFactorization,
"for a semigroup with CanUseLibsemigroupsFroidurePin and pos. int",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsPosInt],
function(S, i)
  local F;
  F := LibsemigroupsFroidurePin(S);
  return FroidurePinMemFnRec(S).factorisation(F, i - 1) + 1;
end);

InstallMethod(MinimalFactorization,
"for a semigroup with CanUseLibsemigroupsFroidurePin and mult. element",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    Error("the 2nd argument (a mult. elt.) must belong to the ",
          "1st argument (a semigroup)");
  fi;
  return MinimalFactorization(S, PositionCanonical(S, x));
end);

InstallMethod(Factorization,
"for a semigroup with CanUseLibsemigroupsFroidurePin and pos. int",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsPosInt],
MinimalFactorization);

InstallMethod(Factorization,
"for a semigroup with CanUseLibsemigroupsFroidurePin and mult. element",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsMultiplicativeElement],
MinimalFactorization);

###########################################################################
## Prefixes, Suffixes, etc.
###########################################################################

InstallMethod(FirstLetter,
"for a semigroup with CanUseLibsemigroupsFroidurePin and pos. int",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsPosInt],
function(S, i)
  local F;
  F := LibsemigroupsFroidurePin(S);
  return FroidurePinMemFnRec(S).first_letter(F, i - 1) + 1;
end);

InstallMethod(FirstLetter,
"for a semigroup with CanUseLibsemigroupsFroidurePin and mult. element",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    Error("the 2nd argument (a mult. elt.) must belong to the ",
          "1st argument (a semigroup)");
  fi;
  return FirstLetter(S, PositionCanonical(S, x));
end);

InstallMethod(FinalLetter,
"for a semigroup with CanUseLibsemigroupsFroidurePin and pos. int",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsPosInt],
function(S, i)
  local F;
  F := LibsemigroupsFroidurePin(S);
  return FroidurePinMemFnRec(S).final_letter(F, i - 1) + 1;
end);

InstallMethod(FinalLetter,
"for a semigroup with CanUseLibsemigroupsFroidurePin and mult. element",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    Error("the 2nd argument (a mult. elt.) must belong to the ",
          "1st argument (a semigroup)");
  fi;
  return FinalLetter(S, PositionCanonical(S, x));
end);

InstallMethod(Prefix,
"for a semigroup with CanUseLibsemigroupsFroidurePin and pos. int",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsPosInt],
function(S, i)
  local F;
  F := LibsemigroupsFroidurePin(S);
  return FroidurePinMemFnRec(S).prefix(F, i - 1) + 1;
end);

InstallMethod(Prefix,
"for a semigroup with CanUseLibsemigroupsFroidurePin and mult. element",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    Error("the 2nd argument (a mult. elt.) must belong to the ",
          "1st argument (a semigroup)");
  fi;
  return Prefix(S, PositionCanonical(S, x));
end);

InstallMethod(Suffix,
"for a semigroup with CanUseLibsemigroupsFroidurePin and pos. int",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsPosInt],
function(S, i)
  local F;
  F := LibsemigroupsFroidurePin(S);
  return FroidurePinMemFnRec(S).suffix(F, i - 1) + 1;
end);

InstallMethod(Suffix,
"for a semigroup with CanUseLibsemigroupsFroidurePin and mult. element",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsMultiplicativeElement],
function(S, x)
  if not x in S then
    Error("the 2nd argument (a mult. elt.) must belong to the ",
          "1st argument (a semigroup)");
  fi;
  return Suffix(S, PositionCanonical(S, x));
end);

###########################################################################
## Enumerate
###########################################################################

InstallMethod(Enumerate,
"for a semigroup with CanUseLibsemigroupsFroidurePin and pos int",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsInt],
function(S, n)
  FroidurePinMemFnRec(S).enumerate(LibsemigroupsFroidurePin(S), n);
  return S;
end);

InstallMethod(Enumerate,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  FroidurePinMemFnRec(S).enumerate(LibsemigroupsFroidurePin(S), -1);
  return S;
end);

InstallMethod(IsEnumerated,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
S -> FroidurePinMemFnRec(S).finished(LibsemigroupsFroidurePin(S)));

###########################################################################
## Cayley graphs etc
###########################################################################

InstallMethod(LeftCayleyGraphSemigroup,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local F;
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  fi;
  F := LibsemigroupsFroidurePin(S);
  return FroidurePinMemFnRec(S).left_cayley_graph(F) + 1;
end);

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

InstallMethod(RightCayleyGraphSemigroup,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local F;
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  fi;
  F := LibsemigroupsFroidurePin(S);
  return FroidurePinMemFnRec(S).right_cayley_graph(F) + 1;
end);

InstallMethod(RightCayleyDigraph,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local D;
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  fi;
  D := DigraphNC(RightCayleyGraphSemigroup(S));
  SetFilterObj(D, IsCayleyDigraph);
  SetSemigroupOfCayleyDigraph(D, S);
  SetGeneratorsOfCayleyDigraph(D, GeneratorsOfSemigroup(S));
  return D;
end);

########################################################################
## Enumerators
########################################################################

InstallMethod(EnumeratorSorted,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local sorted_at, T, enum;

  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  elif IsPartialPermSemigroup(S) or IsFpSemigroup(S) or IsFpMonoid(S)
      or IsQuotientSemigroup(S) then
    # Special case required because < for libsemigroups ParialPerms and < for
    # GAP partial perms are different.
    return AsSet(S);
  fi;

  sorted_at := FroidurePinMemFnRec(S).sorted_at;
  T := LibsemigroupsFroidurePin(S);

  enum := rec();

  enum.NumberElement := {enum, x} -> PositionSortedOp(S, x);

  enum.ElementNumber := {enum, nr} -> sorted_at(T, nr - 1);

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

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

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

  enum := EnumeratorByFunctions(S, enum);
  SetIsSemigroupEnumerator(enum, true);
  SetIsSSortedList(enum, true);

  return enum;
end);

InstallMethod(Enumerator,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin], 6, EnumeratorCanonical);

InstallMethod(EnumeratorCanonical,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local T, enum, factorisation, at;

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

  T := LibsemigroupsFroidurePin(S);

  enum := rec();

  enum.NumberElement := {enum, x} -> PositionCanonical(S, x);

  if IsFpSemigroup(S) or IsFpMonoid(S) or IsQuotientSemigroup(S) then
    factorisation := FroidurePinMemFnRec(S).minimal_factorisation;
    enum.ElementNumber := function(enum, nr)
      if nr > Length(enum) then
        return fail;
      fi;
      return EvaluateWord(GeneratorsOfSemigroup(S),
                          factorisation(T, nr - 1) + 1);
    end;
  else
    at := FroidurePinMemFnRec(S).at;
    enum.ElementNumber := function(enum, nr)
      if nr > Length(enum) then
        return fail;
      else
        return at(T, nr - 1);
      fi;
    end;
  fi;

  # TODO shouldn't S be stored in enum?
  enum.Length := function(_)
    if not IsFinite(S) then
      return infinity;
    else
      return Size(S);
    fi;
  end;

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

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

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

  return enum;
end);

# The next method is necessary since it does not necessarily involve
# enumerating the entire semigroup in the case that the semigroup is partially
# enumerated and <list> only contains indices that are within the so far
# enumerated range. The default methods in the library do, because they require
# the length of the enumerator to check that the list of positions is valid.

InstallMethod(ELMS_LIST, "for a semigroup enumerator and a list",
[IsSemigroupEnumerator, IsList],
function(enum, list)
  local S, result, factorisation, at, T, i;

  S := UnderlyingCollection(enum);
  if not CanUseLibsemigroupsFroidurePin(S) then
    TryNextMethod();
  fi;
  result := EmptyPlist(Length(list));
  if IsFpSemigroup(S) or IsFpMonoid(S) or IsQuotientSemigroup(S) then
    factorisation := FroidurePinMemFnRec(S).minimal_factorisation;
    at := {T, nr} -> EvaluateWord(GeneratorsOfSemigroup(S),
                                  factorisation(T, nr) + 1);
  else
    at := FroidurePinMemFnRec(S).at;
  fi;
  T := LibsemigroupsFroidurePin(S);
  for i in list do
    Add(result, at(T, i - 1));
  od;
  return result;
end);

########################################################################
## Iterators
########################################################################

InstallMethod(IteratorCanonical,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
S -> IteratorList(EnumeratorCanonical(S)));

InstallMethod(Iterator,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin], IteratorCanonical);

InstallMethod(IteratorSorted,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
S -> IteratorList(EnumeratorSorted(S)));

########################################################################
## MultiplicationTable
########################################################################

InstallMethod(MultiplicationTable,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  local N, result, pos_to_pos_sorted, product, T, next, k, i, j;

  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  fi;
  N      := Size(S);
  result := List([1 .. N], x -> EmptyPlist(N));
  T := LibsemigroupsFroidurePin(S);
  if IsFpSemigroup(S) or IsFpMonoid(S) or IsQuotientSemigroup(S) then
    pos_to_pos_sorted := {T, i} -> i;
    product := FroidurePinMemFnRec(S).product_by_reduction;
    FroidurePinMemFnRec(S).enumerate(T, N + 1);
  else
    pos_to_pos_sorted := FroidurePinMemFnRec(S).position_to_sorted_position;
    product := FroidurePinMemFnRec(S).fast_product;
  fi;
  for i in [0 .. N - 1] do
    next := result[pos_to_pos_sorted(T, i) + 1];
    for j in [0 .. N - 1] do
      k := pos_to_pos_sorted(T, j) + 1;
      next[k] := pos_to_pos_sorted(T, product(T, i, j)) + 1;
    od;
  od;
  return result;
end);

########################################################################
## ClosureSemigroupOrMonoidNC
########################################################################

# TODO(later) require a ClosureSemigroupDestructive that uses closure directly,
# not copy then closure.

InstallMethod(ClosureSemigroupOrMonoidNC,
"for fn, CanUseLibsemigroupsFroidurePin, finite list, and record",
[IsFunction,
 IsSemigroup and CanUseLibsemigroupsFroidurePin,
 IsFinite and IsList,
 IsRecord],
function(Constructor, S, coll, opts)
  local n, R, M, N, CppT, add_generator, generator, T, x, i;

  # opts must be copied and processed before calling this function
  # coll must be copied before calling this function
  if ForAll(coll, x -> x in S) then
    # To avoid copying unless necessary!
    return S;
  fi;

  if not IsMutable(coll) then
    coll := ShallowCopy(coll);
  fi;

  coll := Shuffle(coll);
  if IsGeneratorsOfActingSemigroup(coll) then
    n := ActionDegree(coll);
    Sort(coll, {x, y} -> ActionRank(x, n) > ActionRank(y, n));
  elif Length(coll) < 120 then
    Sort(coll, IsGreensDGreaterThanFunc(Semigroup(coll)));
  fi;

  R := FroidurePinMemFnRec(S, coll);

  # Perform the closure
  if IsPartialPermSemigroup(S) or IsTransformationSemigroup(S) then
    if IsPartialPermSemigroup(S) then
      M := Maximum(DegreeOfPartialPermCollection(coll),
                   CodegreeOfPartialPermCollection(coll));
      N := Maximum(DegreeOfPartialPermSemigroup(S),
                   CodegreeOfPartialPermSemigroup(S));
    else
      M := DegreeOfTransformationCollection(coll);
      N := DegreeOfTransformationSemigroup(S);
    fi;
    if M > N then
      # Can't use closure, TODO(later) use copy_closure
      CppT  := R.make();
      add_generator := R.add_generator;
      for x in GeneratorsOfSemigroup(S) do
        add_generator(CppT, [x, M]);
      od;
      R.closure(CppT, List(coll, x -> [x, M]));
    else
      CppT := R.copy(LibsemigroupsFroidurePin(S));
      R.closure(CppT, List(coll, x -> [x, N]));
    fi;
  else
    CppT := R.copy(LibsemigroupsFroidurePin(S));
    R.closure(CppT, coll);
  fi;

  generator := R.generator;

  # Recover the new generating set from the closure
  coll := EmptyPlist(R.number_of_generators(CppT));
  for i in [1 .. R.number_of_generators(CppT)] do
    Add(coll, generator(CppT, i - 1));
  od;
  # Construct new semigroup so as to reset all attributes
  T := Constructor(coll, opts);
  T!.LibsemigroupsFroidurePin := CppT;
  return T;
end);

########################################################################
## New in v4
########################################################################

InstallMethod(RulesOfSemigroup,
"for a semigroup with CanUseLibsemigroupsFroidurePin",
[IsSemigroup and CanUseLibsemigroupsFroidurePin],
function(S)
  if not IsFinite(S) then
    Error("the argument (a semigroup) is not finite");
  fi;
  Enumerate(S);
  return FroidurePinMemFnRec(S).rules(LibsemigroupsFroidurePin(S)) + 1;
end);

InstallMethod(IdempotentsSubset,
"for a semigroup with CanUseLibsemigroupsFroidurePin and hom. list",
[IsSemigroup and CanUseLibsemigroupsFroidurePin, IsHomogeneousList],
function(S, list)
  local product_by_reduction, is_idempotent, T;
  if not IsFinite(S) then
    Error("the 1st argument (a semigroup) is not finite");
  elif IsFpSemigroup(S) or IsFpMonoid(S) or IsQuotientSemigroup(S) then
    product_by_reduction := FroidurePinMemFnRec(S).product_by_reduction;
    is_idempotent := {T, x} -> product_by_reduction(T, x, x) = x;
  else
    is_idempotent := FroidurePinMemFnRec(S).is_idempotent;
  fi;
  T := LibsemigroupsFroidurePin(S);
  return Filtered(list, x -> is_idempotent(T, x - 1));
end);

[ Verzeichnis aufwärts0.61unsichere Verbindung  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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