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


Quelle  homomorph.gi   Sprache: unbekannt

 
#############################################################################
##
##  homomorph.gi
##  Copyright (C) 2022                               Artemis Konstantinidi
##                                                         Chinmaya Nagpal
##
##  Licensing information can be found in the README file of this package.
##
#############################################################################
##

# This file contains various methods for representing homomorphisms between
# semigroups

InstallMethod(SemigroupHomomorphismByImages,
"for two semigroups and two lists",
[IsSemigroup, IsSemigroup, IsList, IsList],
function(S, T, gens, imgs)
  local original_gens, U, map, R, rel;

  if not ForAll(gens, x -> x in S) then
    ErrorNoReturn("the 3rd argument (a list) must consist of elements ",
                  "of the 1st argument (a semigroup)");
  elif Semigroup(gens) <> S then
    ErrorNoReturn("the 1st argument (a semigroup) is not generated by ",
                  "the 3rd argument (a list)");
  elif not ForAll(imgs, x -> x in T) then
    ErrorNoReturn("the 4th argument (a list) must consist of elements ",
                  "of the 2nd argument (a semigroup)");
  elif Size(gens) <> Size(imgs) then
    ErrorNoReturn("the 3rd argument (a list) and the 4th argument ",
                  "(a list) are not the same size");
  fi;

  # in case of different generators, do:
  # gens -> original generators (as passed to Semigroup function)
  # imgs -> images of original generators
  original_gens := GeneratorsOfSemigroup(S);
  if original_gens <> gens then
    U := Semigroup(gens);
    # Use MinimalFactorization rather than Factorization because
    # MinimalFactorization is guaranteed to return a list of positive integers,
    # but Factorization is not (i.e. if S is an inverse acting semigroup.
    # Also since we require an IsomorphismFpSemigroup, there's no additional
    # cost to using MinimalFactorization instead of Factorization.
    imgs := List(original_gens,
                 x -> EvaluateWord(imgs, MinimalFactorization(U, x)));
    gens := original_gens;
  fi;

  # maps S to a finitely presented semigroup
  map := IsomorphismFpSemigroup(S);   # S (source) -> fp semigroup (range)
  # List of relations of the above finitely presented semigroup (hence of S)
  R   := RelationsOfFpSemigroup(Range(map));

  # check that each relation is satisfied by the elements imgs
  for rel in R do
    rel := List(rel, x -> SEMIGROUPS.ExtRepObjToWord(ExtRepOfObj(x)));
    if EvaluateWord(imgs, rel[1]) <> EvaluateWord(imgs, rel[2]) then
      return fail;
    fi;
  od;

  return SemigroupHomomorphismByImages_NC(S, T, gens, imgs);
end);

InstallMethod(SemigroupHomomorphismByImages,
"for two transformation semigroups and two transformation collections",
[IsTransformationSemigroup and IsActingSemigroup,
 IsTransformationSemigroup and IsActingSemigroup,
 IsTransformationCollection and IsList,
 IsTransformationCollection and IsList],
function(S, T, gens, imgs)
  local original_gens, U, S1, T1, SxT, embS, embT, K, i;

  if not ForAll(gens, x -> x in S) then
    ErrorNoReturn("the 3rd argument (a list) must consist of elements ",
                  "of the 1st argument (a semigroup)");
  elif Semigroup(gens) <> S then
    ErrorNoReturn("the 1st argument (a semigroup) is not generated by ",
                  "the 3rd argument (a list)");
  elif not ForAll(imgs, x -> x in T) then
    ErrorNoReturn("the 4th argument (a list) must consist of elements ",
                  "of the 2nd argument (a semigroup)");
  elif Size(gens) <> Size(imgs) then
    ErrorNoReturn("the 3rd argument (a list) and the 4th argument ",
                  "(a list) are not the same size");
  fi;

  # in case of different generators, do:
  # gens -> original generators (as passed to Semigroup function)
  # imgs -> images of original generators
  original_gens := GeneratorsOfSemigroup(S);
  if original_gens <> gens then
    U := Semigroup(gens, rec(acting := true));
    # Use Factorization not MinimalFactorization because it might be quicker,
    # and there's no danger of negative numbers since S and T are both
    # transformation semigroups.
    imgs := List(original_gens, x -> EvaluateWord(imgs, Factorization(U, x)));
    gens := original_gens;
  fi;

  if not IsMonoidAsSemigroup(S) then
    S1 := Monoid(S);
  else
    S1 := S;
  fi;

  if not IsMonoidAsSemigroup(T) then
    T1 := Monoid(T);
  else
    T1 := T;
  fi;

  SxT  := DirectProduct(S1, T1);
  embS := Embedding(SxT, 1);
  embT := Embedding(SxT, 2);
  K    := [];

  for i in [1 .. Size(gens)] do
    Add(K, gens[i] ^ embS * imgs[i] ^ embT);
  od;
  K := Semigroup(K, rec(acting := true));

  # TODO(later) stop this loop as soon as K exceeds S in size:
  if Size(K) <> Size(S) then
    return fail;
  fi;
  return SemigroupHomomorphismByImages_NC(S, T, gens, imgs);
end);

InstallMethod(SemigroupHomomorphismByImages, "for two semigroups and one list",
[IsSemigroup, IsSemigroup, IsList],
{S, T, imgs}
-> SemigroupHomomorphismByImages(S, T, GeneratorsOfSemigroup(S), imgs));

InstallMethod(SemigroupHomomorphismByImages, "for two semigroups",
[IsSemigroup, IsSemigroup],
function(S, T)
  return SemigroupHomomorphismByImages(S,
                                       T,
                                       GeneratorsOfSemigroup(S),
                                       GeneratorsOfSemigroup(T));
end);

InstallMethod(SemigroupHomomorphismByImages, "for a semigroup and two lists",
[IsSemigroup, IsList, IsList],
{S, gens, imgs}
-> SemigroupHomomorphismByImages(S, Semigroup(imgs), gens, imgs));

InstallMethod(SemigroupIsomorphismByImages, "for two semigroup and two lists",
[IsSemigroup, IsSemigroup, IsList, IsList],
function(S, T, gens, imgs)
  local hom;
  # TODO(Homomorph): we could check for other isomorphism invariants here, like
  # we require that gens, and imgs are duplicate free for example, and that S
  # and T have the same size etc
  hom := SemigroupHomomorphismByImages(S, T, gens, imgs);
  if hom <> fail and IsBijective(hom) then
    return hom;
  fi;
  return fail;
end);

InstallMethod(SemigroupIsomorphismByImagesNC, "for two semigroup and two lists",
[IsSemigroup, IsSemigroup, IsList, IsList],
function(S, T, gens, imgs)
  local iso;
  iso := Objectify(NewType(GeneralMappingsFamily(ElementsFamily(FamilyObj(S)),
                                               ElementsFamily(FamilyObj(T))),
                           IsSemigroupHomomorphismByImages and IsBijective),
                           rec());
  SetSource(iso, S);
  SetRange(iso, T);
  SetMappingGeneratorsImages(iso, [Immutable(gens), Immutable(imgs)]);
  return iso;
end);

InstallMethod(SemigroupIsomorphismByImages, "for two semigroups and one list",
[IsSemigroup, IsSemigroup, IsList],
{S, T, imgs}
-> SemigroupIsomorphismByImages(S, T, GeneratorsOfSemigroup(S), imgs));

InstallMethod(SemigroupIsomorphismByImages, "for two semigroups",
[IsSemigroup, IsSemigroup],
function(S, T)
  return SemigroupIsomorphismByImages(S,
                                      T,
                                      GeneratorsOfSemigroup(S),
                                      GeneratorsOfSemigroup(T));
end);

InstallMethod(SemigroupIsomorphismByImages, "for a semigroup and two lists",
[IsSemigroup, IsList, IsList],
{S, gens, imgs}
-> SemigroupIsomorphismByImages(S, Semigroup(imgs), gens, imgs));

InstallMethod(SemigroupHomomorphismByImages_NC,
"for two semigroups and two lists",
[IsSemigroup, IsSemigroup, IsList, IsList],
function(S, T, gens, imgs)
  local hom;

  hom := Objectify(NewType(GeneralMappingsFamily(ElementsFamily(FamilyObj(S)),
                                                 ElementsFamily(FamilyObj(T))),
                           IsSemigroupHomomorphismByImages), rec());
  SetSource(hom, S);
  SetRange(hom, T);
  SetMappingGeneratorsImages(hom, [Immutable(gens), Immutable(imgs)]);

  return hom;
end);

InstallMethod(SemigroupHomomorphismByFunctionNC,
"for semigroup, semigroup, and function",
[IsSemigroup, IsSemigroup, IsFunction],
function(S, T, f)
  local hom;
  hom := Objectify(NewType(GeneralMappingsFamily(ElementsFamily(FamilyObj(S)),
                                                 ElementsFamily(FamilyObj(T))),
                           IsSemigroupHomomorphismByFunction), rec(fun := f));
  SetSource(hom, S);
  SetRange(hom, T);
  return hom;
end);

InstallMethod(SemigroupHomomorphismByFunction,
"for two semigroups and a function",
[IsSemigroup, IsSemigroup, IsFunction],
function(S, T, f)
  local map;
  map := MappingByFunction(S, T, f);
  if not RespectsMultiplication(map) then
    return fail;
  fi;
  SetFilterObj(map, IsSemigroupHomomorphismByFunction);
  return map;
end);

InstallMethod(SemigroupIsomorphismByFunction,
"for two semigroups and two functions",
[IsSemigroup, IsSemigroup, IsFunction, IsFunction],
function(S, T, f, g)
  local map, inv;
  map := SemigroupHomomorphismByFunction(S, T, f);
  if map = fail or not IsBijective(map) then
    return fail;
  fi;
  inv := SemigroupHomomorphismByFunction(T, S, g);
  if inv = fail or not IsBijective(inv) then
    return fail;
  elif CompositionMapping(map, inv)
      <> SemigroupHomomorphismByFunctionNC(T, T, IdFunc) then
    return fail;
  fi;

  return SemigroupIsomorphismByFunctionNC(S, T, f, g);
end);

InstallMethod(SemigroupIsomorphismByFunctionNC,
"for two semigroups and two functions",
[IsSemigroup, IsSemigroup, IsFunction, IsFunction],
function(S, T, f, g)
  local iso;
  iso := Objectify(NewType(GeneralMappingsFamily(ElementsFamily(FamilyObj(S)),
                                                 ElementsFamily(FamilyObj(T))),
                           IsSemigroupIsomorphismByFunction),
                           rec(fun    := f,
                               invFun := g));
  SetSource(iso, S);
  SetRange(iso, T);
  return iso;
end);

InstallMethod(InverseGeneralMapping,
"for a semigroup isomorphism by function",
[IsSemigroupIsomorphismByFunction],
function(map)
  local inv;
  inv := SemigroupIsomorphismByFunctionNC(Range(map),
                                          Source(map),
                                          map!.invFun,
                                          map!.fun);
  TransferMappingPropertiesToInverse(map, inv);
  return inv;
end);

# The next method applies when we create a homomorphism using
# SemigroupHomomorphismByFunction and so invFun is not available.

InstallMethod(InverseGeneralMapping,
"for a bijective semigroup homomorphism by function",
[IsSemigroupHomomorphismByFunction and IsBijective],
function(map)
  local inv;
  inv := SemigroupIsomorphismByFunctionNC(Range(map),
                                          Source(map),
                                          x -> First(Source(map),
                                                     y -> y ^ map = x),
                                          map!.fun);
  TransferMappingPropertiesToInverse(map, inv);
  return inv;
end);

# methods for converting between SHBI and SHBF
InstallMethod(AsSemigroupHomomorphismByImages,
"for a semigroup homomorphism by function",
[IsSemigroupHomomorphismByFunction],
function(hom)
  local S, T, gens, imgs;
  S    := Source(hom);
  T    := Range(hom);
  gens := GeneratorsOfSemigroup(S);
  imgs := List(gens, x -> x ^ hom);
  return SemigroupHomomorphismByImages(S, T, gens, imgs);
end);

InstallMethod(AsSemigroupHomomorphismByFunction,
"for a semigroup homomorphism by images",
[IsSemigroupHomomorphismByImages],
hom -> SemigroupHomomorphismByFunctionNC(Source(hom),
                                         Range(hom),
                                         x -> ImageElm(hom, x)));

InstallMethod(AsSemigroupIsomorphismByFunction,
"for a semigroup homomorphism by images",
[IsSemigroupHomomorphismByImages],
hom -> SemigroupIsomorphismByFunctionNC(Source(hom),
                                        Range(hom),
                                        x -> ImageElm(hom, x),
                                        y -> PreImages(hom, y)));

# Methods for SHBI/SIBI/SHBF
InstallMethod(IsSurjective, "for a semigroup homomorphism",
[IsSemigroupHomomorphismByImagesOrFunction],
{hom} -> Size(ImagesSource(hom)) = Size(Range(hom)));

InstallMethod(IsInjective, "for a semigroup homomorphism",
[IsSemigroupHomomorphismByImagesOrFunction],
{hom} -> Size(Source(hom)) = Size(ImagesSource(hom)));

InstallMethod(ImagesSet, "for a semigroup homom. and list of elements",
[IsSemigroupHomomorphismByImagesOrFunction, IsList],
{hom, elms} -> List(elms, x -> ImageElm(hom, x)));

InstallMethod(ImageElm, "for a semigroup homom. by images and element",
[IsSemigroupHomomorphismByImages, IsMultiplicativeElement],
function(hom, x)
  if not x in Source(hom) then
    ErrorNoReturn("the 2nd argument (a mult. elt.) is not an element ",
                  "of the source of the 1st argument (semigroup homom. by ",
                  "images)");
  fi;
  # Use MinimalFactorization rather than Factorization because
  # MinimalFactorization is guaranteed to return a list of positive integers,
  # but Factorization is not (i.e. if S is an inverse acting semigroup.
  # Also since we require an IsomorphismFpSemigroup, there's no additional
  # cost to using MinimalFactorization instead of Factorization.
  return EvaluateWord(MappingGeneratorsImages(hom)[2],
                      MinimalFactorization(Source(hom), x));
end);

InstallMethod(ImagesSource, "for SHBI",
[IsSemigroupHomomorphismByImages],
hom -> Semigroup(MappingGeneratorsImages(hom)[2]));

InstallMethod(PreImagesRepresentative,
"for a semigroup homom. by images and an element in the range",
[IsSemigroupHomomorphismByImages, IsMultiplicativeElement],
function(hom, x)
  if not x in Range(hom) then
    ErrorNoReturn("the 2nd argument is not an element of the range of the ",
                  "1st argument (semigroup homom. by images)");
  elif not x in ImagesSource(hom) then
    return fail;
  fi;
  # Use MinimalFactorization rather than Factorization because
  # MinimalFactorization is guaranteed to return a list of positive integers,
  # but Factorization is not (i.e. if S is an inverse acting semigroup.
  # Also since we require an IsomorphismFpSemigroup, there's no additional
  # cost to using MinimalFactorization instead of Factorization.
  return EvaluateWord(MappingGeneratorsImages(hom)[1],
                      MinimalFactorization(ImagesSource(hom), x));
end);

InstallMethod(ImagesRepresentative,
"for a semigroup homom. by images and an element in the source",
[IsSemigroupHomomorphismByImages, IsMultiplicativeElement],
function(hom, x)
  if not x in Source(hom) then
    ErrorNoReturn("the 2nd argument is not an element of the source of the ",
                  "1st argument (semigroup homom. by images)");
  fi;
  # Use MinimalFactorization rather than Factorization because
  # MinimalFactorization is guaranteed to return a list of positive integers,
  # but Factorization is not (i.e. if S is an inverse acting semigroup.
  # Also since we require an IsomorphismFpSemigroup, there's no additional
  # cost to using MinimalFactorization instead of Factorization.
  return EvaluateWord(MappingGeneratorsImages(hom)[2],
                      MinimalFactorization(Source(hom), x));
end);

InstallMethod(ImagesElm, "for a semigroup homom. by images and an element",
[IsSemigroupHomomorphismByImages, IsMultiplicativeElement],
{hom, x} -> [ImageElm(hom, x)]);

InstallMethod(PreImagesElm,
"for a semigroup homom. by images and an element in the range",
[IsSemigroupHomomorphismByImages, IsMultiplicativeElement],
function(hom, x)
  local preim, y;
  if not x in Range(hom) then
    ErrorNoReturn("the 2nd argument is not an element of the range of the ",
                  "1st argument (semigroup homom. by images)");
  elif not x in ImagesSource(hom) then
    ErrorNoReturn("the 2nd argument is not mapped to by the 1st argument ",
                  "(semigroup homom. by images)");
  fi;
  preim := [];
  for y in Source(hom) do
    if ImageElm(hom, y) = x then
      Add(preim, y);
    fi;
  od;
  return preim;
end);

InstallMethod(KernelOfSemigroupHomomorphism, "for a semigroup homomorphism",
[IsSemigroupHomomorphismByImagesOrFunction],
function(hom)
  local S, cong, enum, x, y, pairs, i, j;

  if IsQuotientSemigroup(Range(hom)) then
    return QuotientSemigroupCongruence(Range(hom));
  fi;

  S := Source(hom);
  if IsBijective(hom) then
    return SemigroupCongruence(S, []);
  elif Size(ImagesSource(hom)) = 1 then
    return UniversalSemigroupCongruence(S);
  fi;

  cong := SemigroupCongruence(S, []);
  enum := EnumeratorCanonical(S);
  for i in [1 .. Size(S) - 1] do
    x := enum[i];
    for j in [i + 1 .. Size(S)] do
      y := enum[j];
      if x ^ hom = y ^ hom then
        if not [x, y] in cong then
          pairs := ShallowCopy(GeneratingPairsOfSemigroupCongruence(cong));
          Add(pairs, [x, y]);
          cong := SemigroupCongruence(S, pairs);
          if NrEquivalenceClasses(cong) = Size(ImagesSource(hom)) then
            return cong;
          fi;
        fi;
      fi;
    od;
  od;
  return cong;
end);

InstallMethod(String, "for a semigroup homom. by images",
[IsSemigroupHomomorphismByImages],
function(hom)
  local mapi;
  if UserPreference("semigroups", "ViewObj") <> "semigroups-pkg" then
    TryNextMethod();
  fi;
  mapi := MappingGeneratorsImages(hom);
  return Concatenation("SemigroupHomomorphismByImages( ",
                       String(Source(hom)),
                       ", ",
                       String(Range(hom)),
                       ", ",
                       String(mapi[1]),
                       ", ",
                       String(mapi[2]),
                       " )");
end);

InstallMethod(PrintObj, "for a semigroup homom. by images",
[IsSemigroupHomomorphismByImages],
function(hom)
  Print(String(hom));
  return;
end);

InstallMethod(String, "for a semigroup isom. by images",
[IsSemigroupHomomorphismByImages and IsBijective],
function(iso)
  local mapi, str;
  if UserPreference("semigroups", "ViewObj") <> "semigroups-pkg" then
    TryNextMethod();
  fi;
  mapi := MappingGeneratorsImages(iso);
  str := Concatenation("SemigroupIsomorphismByImages( ",
                       String(Source(iso)),
                       ", ",
                       String(Range(iso)),
                       ", ",
                       String(mapi[1]),
                       ", ",
                       String(mapi[2]),
                       " )");
  # print empty lists with two spaces for consistency
  # see https://github.com/gap-system/gap/pull/5418
  return ReplacedString(str, "[ ]", "[  ]");
end);

InstallMethod(\=, "compare homom. by images", IsIdenticalObj,
[IsSemigroupHomomorphismByImages, IsSemigroupHomomorphismByImages],
function(hom1, hom2)
  local i;
  if Source(hom1) <> Source(hom2)
      or Range(hom1) <> Range(hom2)
      or PreImagesRange(hom1) <> PreImagesRange(hom2)
      or ImagesSource(hom1) <> ImagesSource(hom2) then
    return false;
  fi;
  hom1 := MappingGeneratorsImages(hom1);
  return hom1[2] = List(hom1[1], i -> ImageElm(hom2, i));
end);

InstallMethod(ViewObj, "for SHBI/SHBF",
[IsSemigroupHomomorphismByImagesOrFunction],
2,  # to beat method for mapping by function with inverse
function(hom)
  if UserPreference("semigroups", "ViewObj") <> "semigroups-pkg" then
    TryNextMethod();
  fi;
  Print("\>");
  ViewObj(Source(hom));
  Print("\< \>->\< \>");
  ViewObj(Range(hom));
  Print("\<");
end);

InstallMethod(String, "for a semigroup homom. by function",
[IsSemigroupHomomorphismByFunction],
function(hom)
  if UserPreference("semigroups", "ViewObj") <> "semigroups-pkg" then
    TryNextMethod();
  fi;
  return Concatenation("SemigroupHomomorphismByFunction( ",
                       String(Source(hom)),
                       ", ",
                       String(Range(hom)),
                       ", ",
                       String(hom!.fun),
                       " )");
end);

InstallMethod(PrintObj, "for a semigroup homom. by function",
[IsSemigroupHomomorphismByFunction],
function(hom)
  if UserPreference("semigroups", "ViewObj") <> "semigroups-pkg" then
    TryNextMethod();
  fi;
  Print(String(hom));
  return;
end);

InstallMethod(String, "for a semigroup isom. by function",
[IsSemigroupIsomorphismByFunction],
function(iso)
  if UserPreference("semigroups", "ViewObj") <> "semigroups-pkg" then
    TryNextMethod();
  fi;
  return Concatenation("SemigroupIsomorphismByFunction( ",
                       String(Source(iso)),
                       ", ",
                       String(Range(iso)),
                       ", ",
                       String(iso!.fun),
                       ", ",
                       String(iso!.invFun),
                       " )");
end);

InstallMethod(PrintObj, "for a semigroup isom. by function",
[IsSemigroupIsomorphismByFunction],
function(iso)
  if UserPreference("semigroups", "ViewObj") <> "semigroups-pkg" then
    TryNextMethod();
  fi;
  Print(String(iso));
  return;
end);

[ 0.40Quellennavigators  Projekt   ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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