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


Quelle  reesmat.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include J. D. Mitchell.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  This file contains the implementation of Rees matrix semigroups.
##

# Notes: there are essentially 3 types of semigroups here:
# 1) the whole family Rees matrix semigroup (notice that the matrix used to
# define the semigroup may contain rows or columns consisting entirely of 0s
# so it is not guaranteed that the resulting semigroup is 0-simple)
# 2) subsemigroups U of 1), which defined by a generating set and are Rees matrix
# semigroups, i.e. U=I'xG'xJ' where the whole family if IxGxJ and I', J' subsets
# of I, J and G' a subsemigroup of G.
# 3) subsemigroups of 1) obtained by removing an index or element of the
# underlying semigroup, and hence are also Rees matrix semigroups.
# 4) subsemigroups of 1) defined by generating sets which are not
# simple/0-simple.

# So, the methods with filters IsRees(Zero)MatrixSemigroup and
# HasGeneratorsOfSemigroup only apply to subsemigroups of type 2).
# Subsemigroups of type 3 already know the values of Rows, Columns,
# UnderlyingSemigroup, and Matrix.

# a Rees matrix semigroup over a semigroup <S> is simple if and only if <S> is
# simple.

InstallImmediateMethod(IsFinite, IsReesZeroMatrixSubsemigroup, 0,
function(R)
  if IsBound(ElementsFamily(FamilyObj(R))!.IsFinite) then
    if HasIsWholeFamily(R) and IsWholeFamily(R) then
      return ElementsFamily(FamilyObj(R))!.IsFinite;
    elif ElementsFamily(FamilyObj(R))!.IsFinite then
      return true;
    fi;
  fi;
  TryNextMethod();
end);

InstallImmediateMethod(IsFinite, IsReesMatrixSubsemigroup, 0,
function(R)
  if IsBound(ElementsFamily(FamilyObj(R))!.IsFinite) then
    if HasIsWholeFamily(R) and IsWholeFamily(R) then
      return ElementsFamily(FamilyObj(R))!.IsFinite;
    elif ElementsFamily(FamilyObj(R))!.IsFinite then
      return true;
    fi;
  fi;
  TryNextMethod();
end);

InstallMethod(IsFinite, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup],
function(R)
  if HasIsFinite(ParentAttr(R)) and IsFinite(ParentAttr(R))then
    return true;
  fi;
  TryNextMethod();
end);

InstallMethod(IsFinite, "for a Rees matrix subsemigroup",
[IsReesMatrixSubsemigroup],
function(R)
  if HasIsFinite(ParentAttr(R)) and IsFinite(ParentAttr(R)) then
    return true;
  fi;
  TryNextMethod();
end);

#

InstallMethod(IsIdempotent, "for a Rees 0-matrix semigroup element",
[IsReesZeroMatrixSemigroupElement],
function(x)
  local matrix_entry, g;

  if x![1] = 0 then
    # <x> is the 0 element of the family
    return true;
  fi;

  matrix_entry := x![4][x![3]][x![1]];

  if matrix_entry = 0 then
    return false;
  fi;

  g := UnderlyingElementOfReesZeroMatrixSemigroupElement(x);
  return g * matrix_entry * g = g;
end);

#

InstallTrueMethod(IsRegularSemigroup,
IsReesMatrixSemigroup and IsSimpleSemigroup);

#

InstallMethod(IsRegularSemigroup, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSemigroup],
function(R)
  local mat;

  mat := Matrix(R);
  if HasIsGroupAsSemigroup(UnderlyingSemigroup(R))
      and IsGroupAsSemigroup(UnderlyingSemigroup(R)) then
    return ForAll(Rows(R), i -> ForAny(Columns(R), j -> mat[j,i]<>0))
      and ForAll(Columns(R), j -> ForAny(Rows(R), i -> mat[j,i]<>0));
  else
    TryNextMethod();
  fi;
end);

#

InstallMethod(IsSimpleSemigroup,
"for a subsemigroup of a Rees matrix semigroup with an underlying semigroup",
[IsReesMatrixSubsemigroup and HasUnderlyingSemigroup],
R-> IsSimpleSemigroup(UnderlyingSemigroup(R)));

# This next method for `IsSimpleSemigroup` additionally requires the filter
# `IsFinite`, but is otherwise identical.  In the Semigroups package, there are
# some more general methods installed for `IsSimpleSemigroup` which include the
# filter `IsFinite`. When the rank of `IsFinite` is sufficiently large, these
# methods can beat the above method. The above method is a more specific method
# and should always be the one chosen for Rees matrix subsemigroups with known
# underlying semigroup, whether finite or infinite.

InstallMethod(IsSimpleSemigroup,
"for finite subsemigroup of a Rees matrix semigroup with underlying semigroup",
[IsReesMatrixSubsemigroup and HasUnderlyingSemigroup and IsFinite],
R -> IsSimpleSemigroup(UnderlyingSemigroup(R)));

# check that the matrix has no rows or columns consisting entirely of 0s
# and that the underlying semigroup is simple

InstallMethod(IsZeroSimpleSemigroup, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSemigroup],
function(R)
  local i, mat;

  mat := Matrix(R);
  if ForAny(Columns(R), j -> ForAll(Rows(R), i -> mat[j,i] = 0))
      or ForAny(Rows(R), i -> ForAll(Columns(R), j -> mat[j,i] = 0)) then
    return false;
  fi;
  return IsSimpleSemigroup(UnderlyingSemigroup(R));
end);

#

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

#

InstallMethod(IsReesMatrixSemigroup,
"for a Rees matrix subsemigroup with generators",
[IsReesMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  local gens, I, J;

  if IsWholeFamily(R) then
    return true;
  fi;

  # it is still possible that <R> is a Rees matrix semigroup, if, for example,
  # we have a subsemigroup specified by generators which equals a subsemigroup
  # obtained by removing a row, in the case that <R> is not simple.
  gens:=GeneratorsOfSemigroup(R);
  I:=Set(gens, x-> x![1]);
  J:=Set(gens, x-> x![3]);

  return ForAll(GeneratorsOfReesMatrixSemigroupNC(ParentAttr(R), I,
    Semigroup(List(AsSSortedList(R), x-> x![2])), J), x-> x in R);
end);

#

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

#

InstallMethod(IsReesZeroMatrixSemigroup,
"for a Rees 0-matrix subsemigroup with generators",
[IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  local gens, pos, elts, I, J;

  if IsWholeFamily(R) then
    return true;
  fi;

  # it is still possible that <R> is a Rees 0-matrix semigroup, if, for
  # example, we have a subsemigroup specified by generators which equals a
  # subsemigroup obtained by removing a row, in the case that <R> is not simple.

  if MultiplicativeZero(R)<>MultiplicativeZero(ParentAttr(R)) then
    return false; #Rees 0-matrix semigroups always contain the 0.
  fi;

  gens := Unique(GeneratorsOfSemigroup(R));
  pos:=Position(gens, MultiplicativeZero(R));
  if pos<>fail then
    if Size(gens) = 1 then
      return false;
    fi;
    gens:=ShallowCopy(gens);
    Remove(gens, pos);
  fi;

  elts:=ShallowCopy(AsSSortedList(R));
  RemoveSet(elts, MultiplicativeZero(R));

  I:=Set(gens, x-> x![1]);
  J:=Set(gens, x-> x![3]);

  return ForAll(GeneratorsOfReesZeroMatrixSemigroupNC(ParentAttr(R), I,
    Semigroup(List(elts, x-> x![2])), J), x-> x in R);
end);

#

InstallMethod(ReesMatrixSemigroup, "for a semigroup and a rectangular table",
[IsSemigroup, IsRectangularTable],
function(S, mat)
  local fam, R, type, x;

  for x in mat do
    if ForAny(x, s-> not s in S) then
      ErrorNoReturn("the entries of the second argument (a rectangular ",
                    "table) must belong to the first argument (a semigroup)");
    fi;
  od;

  fam := NewFamily( "ReesMatrixSemigroupElementsFamily",
          IsReesMatrixSemigroupElement);

  if HasIsFinite(S) then
    fam!.IsFinite := IsFinite(S);
  fi;

  # create the Rees matrix semigroup
  R := Objectify( NewType( CollectionsFamily( fam ), IsWholeFamily and
   IsReesMatrixSubsemigroup and IsAttributeStoringRep ), rec() );

  # store the type of the elements in the semigroup
  type:=NewType(fam, IsReesMatrixSemigroupElement and IsPositionalObjectRep);

  fam!.type:=type;
  SetTypeReesMatrixSemigroupElements(R, type);
  SetReesMatrixSemigroupOfFamily(fam, R);

  SetMatrixOfReesMatrixSemigroup(R, mat);
  SetUnderlyingSemigroup(R, S);
  SetRowsOfReesMatrixSemigroup(R, [1..Length(mat[1])]);
  SetColumnsOfReesMatrixSemigroup(R, [1..Length(mat)]);

  if HasIsSimpleSemigroup(S) and IsSimpleSemigroup(S) then
    SetIsSimpleSemigroup(R, true);
  fi;

  if HasIsFinite(S) then
    SetIsFinite(R, IsFinite(S));
  fi;

  SetIsZeroSimpleSemigroup(R, false);
  return R;
end);

#

InstallMethod(ReesZeroMatrixSemigroup, "for a semigroup and a dense list",
[IsSemigroup, IsDenseList],
function(S, mat)
  local fam, R, type, x;

  if IsEmpty(mat) or not ForAll(mat, x -> IsDenseList(x) and not IsEmpty(x)
                                          and Length(x) = Length(mat[1])) then
    ErrorNoReturn("the second argument must be a non-empty list, whose ",
                  "entries are non-empty lists of equal length");
  fi;

  for x in mat do
    if ForAny(x, s -> not (s = 0 or s in S)) then
      ErrorNoReturn("the entries of the second argument must be 0 or belong ",
                    "to the first argument (a semigroup)");
    fi;
  od;

  fam := NewFamily("ReesZeroMatrixSemigroupElementsFamily",
                   IsReesZeroMatrixSemigroupElement);

  if HasIsFinite(S) then
    fam!.IsFinite := IsFinite(S);
  fi;

  # create the Rees matrix semigroup
  R := Objectify(NewType(CollectionsFamily(fam),
                 IsWholeFamily
                 and IsReesZeroMatrixSubsemigroup
                 and IsAttributeStoringRep), rec());

  # store the type of the elements in the semigroup
  type := NewType(fam, IsReesZeroMatrixSemigroupElement and IsPositionalObjectRep);

  fam!.type := type;
  SetTypeReesMatrixSemigroupElements(R, type);
  SetReesMatrixSemigroupOfFamily(fam, R);

  SetMatrixOfReesZeroMatrixSemigroup(R, mat);
  SetUnderlyingSemigroup(R, S);
  SetRowsOfReesZeroMatrixSemigroup(R, [1 .. Length(mat[1])]);
  SetColumnsOfReesZeroMatrixSemigroup(R, [1 .. Length(mat)]);
  SetMultiplicativeZero(R,
                        Objectify(TypeReesMatrixSemigroupElements(R), [0]));

  # cannot set IsZeroSimpleSemigroup to be <true> here since the matrix may
  # contain a row or column consisting entirely of 0s!
  # WW Also S might not be a simple semigroup (which is necessary)!
  if IsGroup(S) or (HasIsFinite(S) and IsFinite(S)) then
    GeneratorsOfSemigroup(R);
  fi;
  SetIsSimpleSemigroup(R, false);
  return R;
end);

InstallMethod(ViewObj, "for a Rees matrix semigroup",
[IsReesMatrixSemigroup], 3, #to beat the next method
function(R)
  Print("\>\><Rees matrix semigroup \>", Length(Rows(R)), "x",
      Length(Columns(R)), "\< over \<");
  View(UnderlyingSemigroup(R));
  Print(">\<");
  return;
end);

#

InstallMethod(ViewObj, "for a subsemigroup of a Rees matrix semigroup",
[IsReesMatrixSubsemigroup], PrintObj);

#

InstallMethod(PrintObj, "for a subsemigroup of a Rees matrix semigroup",
[IsReesMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  Print("\><subsemigroup of \>",
        Length(Rows(ParentAttr(R))), "x", Length(Columns(ParentAttr(R))),
        "\< Rees matrix semigroup \>with ",
        Pluralize(Length(GeneratorsOfSemigroup(R)), "generator"), "\<>\<");
  return;
end);

#

InstallMethod(ViewObj, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSemigroup], 3, #to beat the next method
function(R)
  Print("\>\><Rees 0-matrix semigroup \>", Length(Rows(R)), "x",
      Length(Columns(R)), "\< over \<");
  View(UnderlyingSemigroup(R));
  Print(">\<");
  return;
end);

#

InstallMethod(ViewObj, "for a subsemigroup of a Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup], PrintObj);

InstallMethod(PrintObj, "for a subsemigroup of a Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  Print("\><subsemigroup of \>",
        Length(Rows(ParentAttr(R))), "x", Length(Columns(ParentAttr(R))),
        "\< Rees 0-matrix semigroup \>with ",
        Pluralize(Length(GeneratorsOfSemigroup(R)), "generator"), "\<>\<");
  return;
end);

#

InstallMethod(PrintObj, "for a Rees matrix semigroup",
[IsReesMatrixSemigroup and IsWholeFamily], 2,
function(R)
  Print("ReesMatrixSemigroup( ");
  Print(UnderlyingSemigroup(R));
  Print(", ");
  Print(Matrix(R));
  Print(" )");
end);

#

InstallMethod(PrintObj, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSemigroup and IsWholeFamily], 2,
function(R)
  Print("ReesZeroMatrixSemigroup( ");
  Print(UnderlyingSemigroup(R));
  Print(", ");
  Print(Matrix(R));
  Print(" )");
end);

#

InstallMethod(Size, "for a Rees matrix semigroup",
[IsReesMatrixSemigroup],
function(R)
  if Size(UnderlyingSemigroup(R))=infinity then
    return infinity;
  fi;

  return Length(Rows(R))*Size(UnderlyingSemigroup(R))*Length(Columns(R));
end);

#

InstallMethod(Size, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSemigroup],
function(R)
  if Size(UnderlyingSemigroup(R))=infinity then
    return infinity;
  fi;

  return Length(Rows(R))*Size(UnderlyingSemigroup(R))*Length(Columns(R))+1;
end);

#

InstallMethod(Representative,
"for a subsemigroup of Rees matrix semigroup with generators",
[IsReesMatrixSubsemigroup and HasGeneratorsOfSemigroup], 2,
# to beat the other method
function(R)
  return GeneratorsOfSemigroup(R)[1];
end);

#

InstallMethod(Representative, "for a Rees matrix semigroup",
[IsReesMatrixSemigroup],
function(R)
  return Objectify(TypeReesMatrixSemigroupElements(R),
   [Rows(R)[1], Representative(UnderlyingSemigroup(R)), Columns(R)[1],
    Matrix(R)]);
end);

#

InstallMethod(Representative,
"for a subsemigroup of Rees 0-matrix semigroup with generators",
[IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup], 2,
# to beat the other method
function(R)
  return GeneratorsOfSemigroup(R)[1];
end);

#

InstallMethod(Representative, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSemigroup],
function(R)
  return Objectify(TypeReesMatrixSemigroupElements(R),
   [Rows(R)[1], Representative(UnderlyingSemigroup(R)), Columns(R)[1],
    Matrix(R)]);
end);


#

InstallMethod(Enumerator, "for a Rees matrix semigroup",
[IsReesMatrixSemigroup],
function( R )

  return EnumeratorByFunctions(R, rec(

    enum:=EnumeratorOfCartesianProduct(Rows(R),
       Enumerator(UnderlyingSemigroup(R)), Columns(R), [Matrix(R)]),

    NumberElement:=function(enum, x)
      if FamilyObj(x) <> ElementsFamily(FamilyObj(R)) then
        return fail;
      fi;
      return Position(enum!.enum, [x![1], x![2], x![3], x![4]]);
    end,

    ElementNumber:=function(enum, n)
      return Objectify(TypeReesMatrixSemigroupElements(R), enum!.enum[n]);
    end,

    Length:=enum-> Length(enum!.enum),

    PrintObj:=function(enum)
      Print("<enumerator of Rees matrix semigroup>");
      return;
    end));
end);

#

InstallMethod(Enumerator, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSemigroup and HasUnderlyingSemigroup],
function( R )

  return EnumeratorByFunctions(R, rec(

    enum:=EnumeratorOfCartesianProduct(Rows(R),
       Enumerator(UnderlyingSemigroup(R)), Columns(R), [Matrix(R)]),

    NumberElement:=function(enum, x)
      local pos;

      if FamilyObj(x) <> ElementsFamily(FamilyObj(R)) then
        return fail;
      elif IsMultiplicativeZero(R, x) then
        return 1;
      fi;

      pos:=Position(enum!.enum, [x![1], x![2], x![3], x![4]]);
      if pos=fail then
        return fail;
      fi;
      return pos+1;
    end,

    ElementNumber:=function(enum, n)
      if n=1 then
        return MultiplicativeZero(R);
      fi;
      return Objectify(TypeReesMatrixSemigroupElements(R), enum!.enum[n-1]);
    end,

    Length:=enum-> Length(enum!.enum)+1,

    PrintObj:=function(enum)
      Print("<enumerator of Rees 0-matrix semigroup>");
      return;
    end));
end);

# these methods (Matrix, Rows, Columns, UnderlyingSemigroup) should only apply
# to subsemigroups defined by a generating set, which happen to be
# simple/0-simple.

InstallMethod(MatrixOfReesMatrixSemigroup, "for a Rees matrix semigroup with generators",
[IsReesMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  if not IsReesMatrixSemigroup(R) then
    return fail;
  fi;
  return MatrixOfReesMatrixSemigroup(ParentAttr(R));
end);

InstallMethod(MatrixOfReesZeroMatrixSemigroup, "for a Rees 0-matrix semigroup with generators",
[IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  if not IsReesZeroMatrixSemigroup(R) then
    return fail;
  fi;
  return MatrixOfReesZeroMatrixSemigroup(ParentAttr(R));
end);

# for convenience and backwards compatibility
InstallOtherMethod(Matrix, [IsReesMatrixSubsemigroup], MatrixOfReesMatrixSemigroup);
InstallOtherMethod(Matrix, [IsReesZeroMatrixSubsemigroup], MatrixOfReesZeroMatrixSemigroup);

#

InstallMethod(RowsOfReesMatrixSemigroup, "for a Rees matrix semigroup with generators",
[IsReesMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  if not IsReesMatrixSemigroup(R) then
    return fail;
  fi;
  return SetX(GeneratorsOfSemigroup(R), x-> x![1]);
end);

InstallMethod(RowsOfReesZeroMatrixSemigroup, "for a Rees 0-matrix semigroup with generators",
[IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  local out;
  if not IsReesZeroMatrixSemigroup(R) then
    return fail;
  fi;
  out:=SetX(GeneratorsOfSemigroup(R), x-> x![1]);
  if out[1]=0 then
    Remove(out, 1);
  fi;
  return out;
end);

#

InstallMethod(ColumnsOfReesMatrixSemigroup, "for a Rees matrix semigroup with generators",
[IsReesMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  if not IsReesMatrixSemigroup(R) then
    return fail;
  fi;
  return SetX(GeneratorsOfSemigroup(R), x-> x![3]);
end);

InstallMethod(ColumnsOfReesZeroMatrixSemigroup, "for a Rees 0-matrix semigroup with generators",
[IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  local out, x;

  if not IsReesZeroMatrixSemigroup(R) then
    return fail;
  fi;

  out:=[];
  for x in GeneratorsOfSemigroup(R) do
    if x![1]<>0 then
      AddSet(out, x![3]);
    fi;
  od;

  return out;
end);

# these methods only apply to subsemigroups which happen to be Rees matrix
# semigroups

InstallMethod(UnderlyingSemigroup,
"for a Rees matrix semigroup with generators",
[IsReesMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  local gens, i, S, U;

  if not IsReesMatrixSemigroup(R) then
    return fail;
  fi;

  gens:=List(AsSSortedList(R), x-> x![2]);

  if IsGeneratorsOfMagmaWithInverses(gens) then
    i:=1;
    S:=UnderlyingSemigroup(ParentAttr(R));
    U:=Group(gens[1]);
    while Size(U)<Size(S) and i<Length(gens) do
      i:=i+1;
      U:=ClosureGroup(U, gens[i]);
    od;
  else
    U:=Semigroup(gens);
  fi;

  SetIsSimpleSemigroup(U, true);
  return U;
end);

# these methods only apply to subsemigroups which happen to be Rees matrix
# semigroups

InstallMethod(UnderlyingSemigroup,
"for a Rees 0-matrix semigroup with generators",
[IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
  local gens, i, S, U;

  if not IsReesZeroMatrixSemigroup(R) then
    return fail;
  fi;

  #remove the 0
  gens:=Filtered(AsSSortedList(R), x-> x![1]<>0);
  Apply(gens, x-> x![2]);
  gens := Set(gens);

  if IsGeneratorsOfMagmaWithInverses(gens) then
    i:=1;
    S:=UnderlyingSemigroup(ParentAttr(R));
    U:=Group(gens[1]);
    while Size(U)<Size(S) and i<Length(gens) do
      i:=i+1;
      U:=ClosureGroup(U, gens[i]);
    od;
  else
    U:=Semigroup(gens);
  fi;

  return U;
end);

# again only for subsemigroups defined by generators...

InstallMethod(TypeReesMatrixSemigroupElements,
"for a subsemigroup of Rees matrix semigroup",
[IsReesMatrixSubsemigroup],
R -> TypeReesMatrixSemigroupElements(ParentAttr(R)));

InstallMethod(TypeReesMatrixSemigroupElements,
"for a subsemigroup of Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup],
R -> TypeReesMatrixSemigroupElements(ParentAttr(R)));

# Elements...

InstallGlobalFunction(RMSElement,
function(R, i, s, j)
  local out;

  if not (IsReesMatrixSubsemigroup(R)
     or IsReesZeroMatrixSubsemigroup(R)) then
    ErrorNoReturn("the first argument must be a Rees matrix semigroup",
                  " or Rees 0-matrix semigroup");
  fi;

  if (HasIsReesMatrixSemigroup(R) and IsReesMatrixSemigroup(R)) or
    (HasIsReesZeroMatrixSemigroup(R) and IsReesZeroMatrixSemigroup(R)) then
    if not i in Rows(R) then
      ErrorNoReturn("the second argument (a positive integer) does not ",
                    "belong to the rows of the first argument (a Rees ",
                    "(0-)matrix semigroup)");
    elif not j in Columns(R) then
      ErrorNoReturn("the fourth argument (a positive integer) does not ",
                    "belong to the columns of the first argument (a Rees ",
                    "(0-)matrix semigroup)");
    elif not s in UnderlyingSemigroup(R) then
      ErrorNoReturn("the second argument does not belong to the",
                    "underlying semigroup of the first argument (a Rees ",
                    "(0-)matrix semgiroup)");
    fi;
    return Objectify(TypeReesMatrixSemigroupElements(R), [i, s, j, Matrix(R)]);
  fi;

  out:=Objectify(TypeReesMatrixSemigroupElements(R),
   [i, s, j, Matrix(ParentAttr(R))]);

  if not out in R then # for the case R is defined by a generating set
    ErrorNoReturn("the arguments do not describe an element of the first ",
                  "argument (a Rees (0-)matrix semigroup)");
  fi;
  return out;
end);

#

InstallMethod(RowOfReesMatrixSemigroupElement,
"for a Rees matrix semigroup element", [IsReesMatrixSemigroupElement],
x-> x![1]);

#

InstallMethod(RowOfReesZeroMatrixSemigroupElement,
"for a Rees 0-matrix semigroup element", [IsReesZeroMatrixSemigroupElement],
function(x)
  if x![1] = 0 then
    return fail;
  fi;
  return x![1];
end);

#

InstallMethod(UnderlyingElementOfReesMatrixSemigroupElement,
"for a Rees matrix semigroup element", [IsReesMatrixSemigroupElement],
x-> x![2]);

#

InstallMethod(UnderlyingElementOfReesZeroMatrixSemigroupElement,
"for a Rees 0-matrix semigroup element", [IsReesZeroMatrixSemigroupElement],
function(x)
  if x![1] = 0 then
    return fail;
  fi;
  return x![2];
end);

#

InstallMethod(ColumnOfReesMatrixSemigroupElement,
"for a Rees matrix semigroup element", [IsReesMatrixSemigroupElement],
x-> x![3]);

#

InstallMethod(ColumnOfReesZeroMatrixSemigroupElement,
"for a Rees 0-matrix semigroup element", [IsReesZeroMatrixSemigroupElement],
function(x)
  if x![1] = 0 then
    return fail;
  fi;
  return x![3];
end);

#

InstallMethod(PrintObj, "for a Rees matrix semigroup element",
[IsReesMatrixSemigroupElement],
function(x)
  Print("RMSElement(",
        ReesMatrixSemigroupOfFamily(FamilyObj(x)),
        ", ", x![1], ", ", x![2], ", ", x![3], ")");
end);

#

InstallMethod(PrintObj, "for a Rees 0-matrix semigroup element",
[IsReesZeroMatrixSemigroupElement],
function(x)
  if x![1]=0 then
    Print("MultiplicativeZero(",
          ReesMatrixSemigroupOfFamily(FamilyObj(x)),
          ")");
    return;
  fi;
  Print("RMSElement(",
        ReesMatrixSemigroupOfFamily(FamilyObj(x)),
        ", ", x![1], ", ", x![2], ", ", x![3], ")");
end);

InstallMethod(ViewString, "for a Rees matrix semigroup element",
[IsReesMatrixSemigroupElement],
function(x)
  return PRINT_STRINGIFY("\>(", ViewString(x![1]), ",", ViewString(x![2]), ",",
                         ViewString(x![3]), ")\<");
end);

#

InstallMethod(ViewString, "for a Rees 0-matrix semigroup element",
[IsReesZeroMatrixSemigroupElement],
function(x)
  if x![1] = 0 then
    return "0";
  fi;
  return PRINT_STRINGIFY("\>(", ViewString(x![1]), ",", ViewString(x![2]), ",",
                         ViewString(x![3]), ")\<");
end);

#

InstallMethod(ELM_LIST, "for a Rees matrix semigroup element",
[IsReesMatrixSemigroupElement, IsPosInt],
function(x, i)
  if i > 3 then
    ErrorNoReturn("the second argument must be 1, 2, or 3");
  fi;
  return x![i];
end);

#

InstallMethod(ELM_LIST, "for a Rees 0-matrix semigroup element",
[IsReesZeroMatrixSemigroupElement, IsPosInt],
function(x, i)
  if x![1] = 0 then
    ErrorNoReturn("the first argument (an element of a Rees 0-matrix ",
                  "semigroup) must be non-zero");
  elif i > 3 then
    ErrorNoReturn("the second argument must be 1, 2, or 3");
  fi;
  return x![i];
end);

#

InstallMethod(ZeroOp, "for a Rees matrix semigroup element",
[IsReesMatrixSemigroupElement], ReturnFail);

#

InstallMethod(ZeroOp, "for a Rees 0-matrix semigroup element",
[IsReesZeroMatrixSemigroupElement],
function(x)
  return MultiplicativeZero(ReesMatrixSemigroupOfFamily(FamilyObj(x)));
end);

#

InstallMethod(MultiplicativeZeroOp, "for a Rees matrix semigroup",
[IsReesMatrixSemigroup], ReturnFail);

#

InstallMethod(\*, "for elements of a Rees matrix semigroup",
IsIdenticalObj,
[IsReesMatrixSemigroupElement, IsReesMatrixSemigroupElement],
function(x, y)
  return Objectify(FamilyObj(x)!.type,
   [x![1], x![2]*x![4][x![3]][y![1]]*y![2], y![3], x![4]]);
end);

#

InstallMethod(\*, "for elements of a Rees 0-matrix semigroup",
IsIdenticalObj,
[IsReesZeroMatrixSemigroupElement, IsReesZeroMatrixSemigroupElement],
function(x, y)
  local p;

  if x![1]=0 then
    return x;
  elif y![1]=0 then
    return y;
  fi;

  p:=x![4][x![3]][y![1]];
  if p=0 then
    return Objectify(FamilyObj(x)!.type, [0]);
  fi;
  return Objectify(FamilyObj(x)!.type, [x![1], x![2]*p*y![2], y![3], x![4]]);
end);

#

InstallMethod(\<, "for elements of a Rees matrix semigroup",
IsIdenticalObj,
[IsReesMatrixSemigroupElement, IsReesMatrixSemigroupElement],
function(x, y)
  return x![1]<y![1] or (x![1]=y![1] and x![2]<y![2])
    or (x![1]=y![1] and x![2]=y![2] and x![3]<y![3]);
end);

# 0 is less than everything!

InstallMethod(\<, "for elements of a Rees 0-matrix semigroup",
IsIdenticalObj,
[IsReesZeroMatrixSemigroupElement, IsReesZeroMatrixSemigroupElement],
function(x, y)
  if x![1]=0 then
    return y![1]<>0;
  elif y![1]=0 then
    return false;
  fi;

  return x![1]<y![1] or (x![1]=y![1] and x![2]<y![2])
    or (x![1]=y![1] and x![2]=y![2] and x![3]<y![3]);
end);

#

InstallMethod(\=, "for elements of a Rees matrix semigroup",
IsIdenticalObj,
[IsReesMatrixSemigroupElement, IsReesMatrixSemigroupElement],
function(x, y)
  return x![1]=y![1] and x![2]=y![2] and x![3]=y![3];
end);

#

InstallMethod(\=, "for elements of a Rees 0-matrix semigroup",
IsIdenticalObj,
[IsReesZeroMatrixSemigroupElement, IsReesZeroMatrixSemigroupElement],
function(x, y)
  if x![1]=0 then
    return y![1]=0;
  fi;
  return x![1]=y![1] and x![2]=y![2] and x![3]=y![3];
end);

#

InstallMethod(ParentAttr, "for a subsemigroup of a Rees matrix semigroup",
[IsReesMatrixSubsemigroup],
function(R)
  return ReesMatrixSemigroupOfFamily(FamilyObj(Representative(R)));
end);

#

InstallMethod(ParentAttr, "for a subsemigroup of a Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup],
function(R)
  return ReesMatrixSemigroupOfFamily(FamilyObj(Representative(R)));
end);

#

InstallMethod(IsWholeFamily, "for a subsemigroup of a Rees matrix semigroup",
[IsReesMatrixSubsemigroup],
function(R)
  local S;

  if Size(R)=Size(ReesMatrixSemigroupOfFamily(ElementsFamily(FamilyObj(R))))
   then
    if not HasMatrixOfReesMatrixSemigroup(R) then # <R> is defined by generators
      S:=ParentAttr(R);
      SetMatrixOfReesMatrixSemigroup(R, Matrix(S));
      SetUnderlyingSemigroup(R, UnderlyingSemigroup(S));
      SetRowsOfReesMatrixSemigroup(R, Rows(S));
      SetColumnsOfReesMatrixSemigroup(R, Columns(S));
    fi;
    return true;
  else
    return false;
  fi;
end);

#

InstallMethod(IsWholeFamily, "for a subsemigroup of a Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup],
function(R)
  local S;

  if Size(R)=Size(ReesMatrixSemigroupOfFamily(ElementsFamily(FamilyObj(R))))
   then
    if not HasMatrixOfReesZeroMatrixSemigroup(R) then # <R> is defined by generators
      S:=ParentAttr(R);
      SetMatrixOfReesZeroMatrixSemigroup(R, Matrix(S));
      SetUnderlyingSemigroup(R, UnderlyingSemigroup(S));
      SetRowsOfReesZeroMatrixSemigroup(R, Rows(S));
      SetColumnsOfReesZeroMatrixSemigroup(R, Columns(S));
    fi;
    return true;
  else
    return false;
  fi;
end);

# generators for the subsemigroup generated by <IxUxJ>, when <R> is a Rees
# matrix semigroup (and not only a subsemigroup).

InstallGlobalFunction(GeneratorsOfReesMatrixSemigroupNC,
function(R, I, U, J)
  local P, type, i, j, gens, u;

  P:=Matrix(R);   type:=TypeReesMatrixSemigroupElements(R);

  if IsGroup(U) then
    i:=I[1];   j:=J[1];
    if IsTrivial(U) then
      gens:=[Objectify(type, [i, P[j][i]^-1, j, P])];
    else
      gens:=List(GeneratorsOfGroup(U), x->
       Objectify( type, [i, x*P[j][i]^-1, j, P]));
    fi;

    if Length(I)>Length(J) then
      for i in [2..Length(J)] do
        Add(gens, Objectify(type, [I[i], One(U), J[i], P]));
      od;
      for i in [Length(J)+1..Length(I)] do
        Add(gens, Objectify(type, [I[i], One(U), J[1], P]));
      od;
    else
      for i in [2..Length(I)] do
        Add(gens, Objectify(type, [I[i], One(U), J[i], P]));
      od;
      for i in [Length(I)+1..Length(J)] do
        Add(gens, Objectify(type, [I[1], One(U), J[i], P]));
      od;
    fi;
  else
    gens:=[];
    for i in I do
      for u in U do
        for j in J do
          Add(gens, Objectify(type, [i, u, j, P]));
        od;
      od;
    od;
  fi;
  return gens;
end);

# generators for the subsemigroup generated by <IxUxJ>, when <R> is a Rees
# matrix semigroup (and not only a subsemigroup).

InstallGlobalFunction(GeneratorsOfReesZeroMatrixSemigroupNC,
function(R, I, U, J)
  local P, type, i, j, gens, k, u;

  P:=Matrix(R);   type:=TypeReesMatrixSemigroupElements(R);
  i:=I[1];        j:=First(J, j-> P[j][i]<>0);

  if IsGroup(U) and IsRegularSemigroup(R) and not j=fail then
    if IsTrivial(U) then
      gens:=[Objectify(type, [i, P[j][i]^-1, j, P])];
    else
      gens:=List(GeneratorsOfGroup(U), x->
        Objectify(type, [i, x*P[j][i]^-1, j, P]));
    fi;

    for k in J do
      if k<>j then
        Add(gens, Objectify(type, [i, One(U), k, P]));
      fi;
    od;

    for k in I do
      if k<>i then
        Add(gens, Objectify(type, [k, One(U), j, P]));
      fi;
    od;
  else
    gens:=[];
    for i in I do
      for u in U do
        for j in J do
          Add(gens, Objectify(type, [i, u, j, P]));
        od;
      od;
    od;
  fi;
  return gens;
end);

# you can't do this operation on arbitrary subsemigroup of Rees matrix
# semigroups since they don't have to be simple and so don't have to have rows,
# columns etc.

# generators for the subsemigroup generated by <IxUxJ>, when <R> is a Rees
# matrix semigroup (and not only a subsemigroup).

InstallMethod(GeneratorsOfReesMatrixSemigroup,
"for a Rees matrix subsemigroup, rows, semigroup, columns",
[IsReesMatrixSubsemigroup, IsList, IsSemigroup, IsList],
function(R, I, U, J)

  if not IsReesMatrixSemigroup(R) then
    ErrorNoReturn("the first argument must be a Rees matrix semigroup");
  elif not IsSubset(Rows(R), I) or IsEmpty(I) then
    ErrorNoReturn("the second argument must be a non-empty subset of the ",
                  "rows of the first argument (a Rees matrix semigroup)");
  elif not IsSubsemigroup(UnderlyingSemigroup(R), U) then
    ErrorNoReturn("the third argument must be a subsemigroup of the ",
                  "underlying semigroup of the first argument (a Rees matrix ",
                  "semigroup)");
  elif not IsSubset(Columns(R), J) or IsEmpty(J) then
    ErrorNoReturn("the fourth argument must be a non-empty subset of the ",
                  "columns of the first argument (a Rees matrix semigroup)");
  fi;

  return GeneratorsOfReesMatrixSemigroupNC(R, I, U, J);
end);

# you can't do this operation on arbitrary subsemigroup of Rees matrix
# semigroups since they don't have to be simple and so don't have to have rows,
# columns etc.

# generators for the subsemigroup generated by <IxUxJ>, when <R> is a Rees
# matrix semigroup (and not only a subsemigroup).

InstallMethod(GeneratorsOfReesZeroMatrixSemigroup,
"for a Rees 0-matrix semigroup, rows, semigroup, columns",
[IsReesZeroMatrixSubsemigroup, IsList, IsSemigroup, IsList],
function(R, I, U, J)

  if not IsReesZeroMatrixSemigroup(R) then
    ErrorNoReturn("the first argument must be a Rees 0-matrix semigroup");
  elif not IsSubset(Rows(R), I) or IsEmpty(I) then
    ErrorNoReturn("the second argument must be a non-empty subset of the ",
                  "rows of the first argument (a Rees 0-matrix semigroup)");
  elif not IsSubsemigroup(UnderlyingSemigroup(R), U) then
    ErrorNoReturn("the third argument must be a subsemigroup of the ",
                  "underlying semigroup of the first argument (a Rees ",
                  "0-matrix semigroup)");
  elif not IsSubset(Columns(R), J) or IsEmpty(J) then
    ErrorNoReturn("the fourth argument must be a non-empty subset of the ",
                  "columns of the first argument (a Rees 0-matrix semigroup)");
  fi;

  return GeneratorsOfReesZeroMatrixSemigroupNC(R, I, U, J);
end);

#

InstallMethod(GeneratorsOfSemigroup, "for a Rees matrix semigroup",
[IsReesMatrixSemigroup],
function(R)
  return GeneratorsOfReesMatrixSemigroupNC(R, Rows(R), UnderlyingSemigroup(R),
   Columns(R));
end);

#

InstallMethod(GeneratorsOfSemigroup, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSemigroup],
function(R)
  local gens;

  gens:=GeneratorsOfReesZeroMatrixSemigroupNC(R, Rows(R),
   UnderlyingSemigroup(R), Columns(R));
  if ForAll(Rows(R), i-> ForAll(Columns(R), j-> Matrix(R)[j][i]<>0)) then
    Add(gens, MultiplicativeZero(R));
  fi;
  return gens;
end);

# Note that it is possible that the rows and columns of the matrix only contain
# the zero element, if the resulting semigroup were taken to be in
# IsReesMatrixSemigroup then it would belong to IsReesMatrixSemigroup and
# IsReesZeroMatrixSubsemigroup, so that its elements belong to
# IsReesZeroMatrixSemigroupElement but not to IsReesMatrixSemigroupElement
# (since this makes reference to the whole family used to create the
# semigroups). On the other hand, if we simply exclude the 0, then every method
# for IsReesZeroMatrixSemigroup is messed up because we assume that they always
# contain the 0.
#
# Hence we always include the 0 element, even if all the matrix
# entries corresponding to I and J are non-zero.

InstallMethod(ReesZeroMatrixSubsemigroup,
"for a Rees 0-matrix semigroup, rows, semigroup, columns",
[IsReesZeroMatrixSubsemigroup, IsList, IsSemigroup, IsList],
function(R, I, U, J)

  if not IsReesZeroMatrixSemigroup(R) then
    ErrorNoReturn("the first argument must be a Rees 0-matrix semigroup");
  elif not IsSubset(Rows(R), I) or IsEmpty(I) then
    ErrorNoReturn("the second argument must be a non-empty subset of the ",
                  "rows of the first argument (a Rees 0-matrix semigroup)");
  elif not IsSubsemigroup(UnderlyingSemigroup(R), U) then
    ErrorNoReturn("the third argument must be a subsemigroup of the ",
                  "underlying semigroup of the first argument (a Rees ",
                  "0-matrix semigroup)");
  elif not IsSubset(Columns(R), J) or IsEmpty(J) then
    ErrorNoReturn("the fourth argument must be a non-empty subset of the ",
                  "columns of the first argument (a Rees 0-matrix semigroup)");
  fi;

  return ReesZeroMatrixSubsemigroupNC(R, I, U, J);
end);

InstallGlobalFunction(ReesZeroMatrixSubsemigroupNC,
function(R, I, U, J)
  local S;

  if U=UnderlyingSemigroup(R) and ForAny(Matrix(R){J}{I}, x-> 0 in x) then
    S:=Objectify( NewType( FamilyObj(R),
     IsReesZeroMatrixSubsemigroup and IsAttributeStoringRep ), rec() );
    SetTypeReesMatrixSemigroupElements(S, TypeReesMatrixSemigroupElements(R));

    SetMatrixOfReesZeroMatrixSemigroup(S, Matrix(R));
    SetUnderlyingSemigroup(S, UnderlyingSemigroup(R));
    SetRowsOfReesZeroMatrixSemigroup(S, I);
    SetColumnsOfReesZeroMatrixSemigroup(S, J);
    SetParentAttr(S, R);

    #it might be that all the matrix entries corresponding to I and J are zero
    #and so we can't set IsZeroSimpleSemigroup here.
    SetMultiplicativeZero(S, MultiplicativeZero(R));
    SetIsSimpleSemigroup(S, false);
    SetIsReesZeroMatrixSemigroup(S, true);
    return S;
  fi;

  return Semigroup(GeneratorsOfReesZeroMatrixSemigroupNC(R, I, U, J));
end);

#

InstallMethod(ReesMatrixSubsemigroup,
"for a Rees matrix semigroup, rows, semigroup, columns",
[IsReesMatrixSubsemigroup, IsList, IsSemigroup, IsList],
function(R, I, U, J)

  if not IsReesMatrixSemigroup(R) then
    ErrorNoReturn("the first argument must be a Rees matrix semigroup");
  elif not IsSubset(Rows(R), I) or IsEmpty(I) then
    ErrorNoReturn("the second argument must be a non-empty subset of the ",
                  "rows of the first argument (a Rees matrix semigroup)");
  elif not IsSubsemigroup(UnderlyingSemigroup(R), U) then
    ErrorNoReturn("the third argument must be a subsemigroup of the ",
                  "underlying semigroup of the first argument (a Rees ",
                  "matrix semigroup)");
  elif not IsSubset(Columns(R), J) or IsEmpty(J) then
    ErrorNoReturn("the fourth argument must be a non-empty subset of the ",
                  "columns of the first argument (a Rees matrix semigroup)");
  fi;

  return ReesMatrixSubsemigroupNC(R, I, U, J);
end);

#

InstallGlobalFunction(ReesMatrixSubsemigroupNC,
function(R, I, U, J)
  local S;

  if U=UnderlyingSemigroup(R) then
    S:=Objectify( NewType( FamilyObj(R),
      IsReesMatrixSubsemigroup and IsAttributeStoringRep ), rec() );
    SetTypeReesMatrixSemigroupElements(S, TypeReesMatrixSemigroupElements(R));

    SetMatrixOfReesMatrixSemigroup(S, Matrix(R));
    SetUnderlyingSemigroup(S, UnderlyingSemigroup(R));
    SetRowsOfReesMatrixSemigroup(S, I);
    SetColumnsOfReesMatrixSemigroup(S, J);
    SetParentAttr(S, R);

    if HasIsSimpleSemigroup(R) and IsSimpleSemigroup(R) then
      SetIsSimpleSemigroup(S, true);
    fi;
    SetIsReesMatrixSemigroup(S, true);
    SetIsZeroSimpleSemigroup(S, false);
    return S;
  fi;
  return Semigroup(GeneratorsOfReesMatrixSemigroupNC(R, I, U, J));
end);

#

BindGlobal("_InjectionPrincipalFactor",
function(D, constructor)
  local map, inv, G, mat, rep, R, L, x, RR, LL, rms, iso, hom, i, j;

  map := IsomorphismPermGroup(GroupHClassOfGreensDClass(D));
  inv := InverseGeneralMapping(map);

  G := Range(map);
  mat := [];

  rep := Representative(GroupHClassOfGreensDClass(D));
  L := List(GreensHClasses(GreensRClassOfElement(Parent(D), rep)),
            Representative);
  R := List(GreensHClasses(GreensLClassOfElement(Parent(D), rep)),
            Representative);

  for i in [1 .. Length(L)] do
    mat[i] := [];
    for j in [1 .. Length(R)] do
      x := L[i] * R[j];
      if x in D then
        mat[i,j] := x ^ map;
      else
        mat[i,j] := 0;
      fi;
    od;
  od;

  RR := EmptyPlist(Length(R));
  LL := EmptyPlist(Length(L));

  for j in [1 .. Length(R)] do
    for i in [1 .. Length(L)] do
      if mat[i,j] <> 0 then
        RR[j] := ((mat[i,j] ^ -1) ^ inv) * L[i];
        break;
      fi;
    od;
  od;

  for i in [1 .. Length(L)] do
    for j in [1 .. Length(R)] do
      if mat[i,j] <> 0 then
        LL[i] := R[j] * (mat[i,j] ^ -1) ^ inv;
        break;
      fi;
    od;
  od;

  rms := constructor(G, mat);

  iso := function(x)
    i := PositionProperty(R, y -> y in GreensRClassOfElement(Parent(D), x));
    j := PositionProperty(L, y -> y in GreensLClassOfElement(Parent(D), x));

    if i = fail or j = fail then
      return fail;
    fi;
    return Objectify(TypeReesMatrixSemigroupElements(rms),
                     [i, (rep * RR[i] * x * LL[j]) ^ map, j, mat]);
  end;

  hom := MappingByFunction(D, rms, iso,
                           function(x)
                             if x![1] = 0 then
                               return fail;
                             fi;
                             return R[x![1]] * (x![2] ^ inv) * L[x![3]];
                           end);
  SetIsInjective(hom, true);
  SetIsTotal(hom, true);
  return hom;
end);

InstallMethod(IsomorphismReesMatrixSemigroup, "for a D-class",
[IsGreensDClass],
function(D)
  if Number(D, IsIdempotent) <> Length(GreensHClasses(D)) then
    ErrorNoReturn("the argument (a Green's D-class) is not a subsemigroup");
  fi;
  return _InjectionPrincipalFactor(D, ReesMatrixSemigroup);
end);

InstallMethod(IsomorphismReesMatrixSemigroup,
"for a finite simple", [IsSemigroup],
function(S)
  local rep, inj;

  if not (IsSimpleSemigroup(S) and IsFinite(S)) then
    ErrorNoReturn("the argument must be a finite simple semigroup");
  fi;

  rep := Representative(S);
  inj := _InjectionPrincipalFactor(GreensDClassOfElement(S, rep),
                                   ReesMatrixSemigroup);

  return MagmaIsomorphismByFunctionsNC(S, Range(inj),
                                       x -> x ^ inj,
                                       x -> x ^ InverseGeneralMapping(inj));
end);

InstallMethod(IsomorphismReesZeroMatrixSemigroup,
"for a finite 0-simple", [IsSemigroup],
function(S)
  local D, map, inj, inv;

  if not (IsZeroSimpleSemigroup(S) and IsFinite(S)) then
    ErrorNoReturn("the argument must be a finite 0-simple semigroup");
  fi;

  D := First(GreensDClasses(S),
             x -> not IsMultiplicativeZero(S, Representative(x)));

  map := _InjectionPrincipalFactor(D, ReesZeroMatrixSemigroup);

  # the below is necessary since map is not defined on the zero of S
  inj := function(x)
    if x = MultiplicativeZero(S) then
      return MultiplicativeZero(Range(map));
    fi;
    return x ^ map;
  end;

  inv := function(x)
    if x = MultiplicativeZero(Range(map)) then
      return MultiplicativeZero(S);
    fi;
    return x ^ InverseGeneralMapping(map);
  end;

  return MagmaIsomorphismByFunctionsNC(S,
                                       Range(map),
                                       inj,
                                       inv);
end);

#

InstallMethod(AssociatedReesMatrixSemigroupOfDClass,
"for a Green's D-class of a semigroup",
[IsGreensDClass],
function(D)

  if not IsFinite(Parent(D)) then
    TryNextMethod();
  fi;

  if not IsRegularDClass(D) then
    ErrorNoReturn("the argument should be a regular D-class");
  fi;

  if Length(GreensHClasses(D)) = Number(D, IsIdempotent) then
    return Range(IsomorphismReesMatrixSemigroup(D));
  fi;
  return Range(_InjectionPrincipalFactor(D, ReesZeroMatrixSemigroup));
end);

# so that we can find Green's relations etc

InstallMethod(MonoidByAdjoiningIdentity, [IsReesMatrixSubsemigroup],
function(R)
  local M;
  M:=Monoid(List(GeneratorsOfSemigroup(R), MonoidByAdjoiningIdentityElt));
  SetUnderlyingSemigroupOfMonoidByAdjoiningIdentity(M, R);
  return M;
end);

# so that we can find Green's relations etc

InstallMethod(MonoidByAdjoiningIdentity, [IsReesZeroMatrixSubsemigroup],
function(R)
  local M;
  M:=Monoid(List(GeneratorsOfSemigroup(R), MonoidByAdjoiningIdentityElt));
  SetUnderlyingSemigroupOfMonoidByAdjoiningIdentity(M, R);
  return M;
end);

# the next two methods by Michael Torpey and Thomas Bourne.

InstallMethod(IsomorphismReesZeroMatrixSemigroup,
"for a Rees 0-matrix subsemigroup", [IsReesZeroMatrixSubsemigroup],
function(U)
  local V, iso, inv;

  if not IsReesZeroMatrixSemigroup(U) then
    TryNextMethod();
  elif IsWholeFamily(U) then
    return MagmaIsomorphismByFunctionsNC(U, U, IdFunc, IdFunc);
  fi;

  V:=ReesZeroMatrixSemigroup(UnderlyingSemigroup(U),
                             Matrix(U){Columns(U)}{Rows(U)});

  iso := function(u)
    if u = MultiplicativeZero(U) then
      return MultiplicativeZero(V);
    fi;
    return RMSElement(V,
                      Position(Rows(U),u![1]),
                      u![2],
                      Position(Columns(U),u![3]));
  end;

  inv := function(v)
    if v = MultiplicativeZero(V) then
      return MultiplicativeZero(U);
    fi;
    return RMSElement(U, Rows(U)[v![1]], v![2], Columns(U)[v![3]]);
  end;

  return MagmaIsomorphismByFunctionsNC(U, V, iso, inv);
end);

InstallMethod(IsomorphismReesMatrixSemigroup, "for a Rees matrix subsemigroup",
[IsReesMatrixSubsemigroup],
function(U)
  local V, iso, inv;

    if not IsReesMatrixSemigroup(U) then
      TryNextMethod();
    elif IsWholeFamily(U) then
      return MagmaIsomorphismByFunctionsNC(U, U, IdFunc, IdFunc);
    fi;

    V:=ReesMatrixSemigroup(UnderlyingSemigroup(U),
     List(Matrix(U){Columns(U)}, x-> x{Rows(U)}));
   #JDM doing Matrix(U){Columns(U)}{Rows(U)} the resulting object does not know
   #IsRectangularTable, and doesn't store this after it is calculated.

    iso := function(u)
      return RMSElement(V, Position(Rows(U),u![1]), u![2],
       Position(Columns(U),u![3]));
    end;

    inv := function(v)
      return RMSElement(U, Rows(U)[v![1]], v![2], Columns(U)[v![3]]);
    end;

    return MagmaIsomorphismByFunctionsNC(U, V, iso, inv);
end);

#EOF

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