|
###########################################################################
##
## main/setup.gi
## Copyright (C) 2013-2022 James D. Mitchell
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##
###############################################################################
# Setup - install the basic things required for specific acting semigroups #
###############################################################################
# IsGeneratorsOfActingSemigroup
InstallMethod(IsGeneratorsOfActingSemigroup, "for a list or collection",
[IsListOrCollection], ReturnFalse);
# In the below can't do ReturnTrue, since GAP insists that we use
# InstallTrueMethod.
#
# InstallTrueMethod(IsGeneratorsOfActingSemigroup, IsTransformationCollection);
#
# can't do InstallTrueMethod for the above since this is not picked up
# if Semigroups is loaded after any transformation semigroup has been created.
# It seems that since IsTransformationCollection has had its implied filters
# installed, if we add an additional implied filter
# IsGeneratorsOfActingSemigroup, then this is ignored. I think this is a bug.
InstallMethod(IsGeneratorsOfActingSemigroup, "for a transformation collection",
[IsTransformationCollection], x -> true); # gaplint: disable=W036
InstallMethod(IsGeneratorsOfActingSemigroup, "for a partial perm collection",
[IsPartialPermCollection], x -> true); # gaplint: disable=W036
InstallMethod(IsGeneratorsOfActingSemigroup, "for a bipartition collection",
[IsBipartitionCollection], x -> true); # gaplint: disable=W036
InstallMethod(IsGeneratorsOfActingSemigroup,
"for a Rees 0-matrix semigroup element collection",
[IsReesZeroMatrixSemigroupElementCollection],
function(coll)
local R;
R := ReesMatrixSemigroupOfFamily(FamilyObj(Representative(coll)));
return IsPermGroup(UnderlyingSemigroup(R)) and IsRegularSemigroup(R);
end);
InstallMethod(IsGeneratorsOfActingSemigroup,
"for a McAlister triple element collection",
[IsMcAlisterTripleSemigroupElementCollection],
function(coll)
return
IsPermGroup(McAlisterTripleSemigroupGroup(MTSEParent(Representative(coll))));
end);
InstallMethod(IsGeneratorsOfActingSemigroup,
"for an ffe coll coll coll",
# TODO(MatrixObj-later) is this the best way to recognise a collection of
# MatrixObj?
[IsFFECollCollColl],
function(coll)
return IsGeneratorsOfSemigroup(coll)
and (IsEmpty(coll) or ForAll(coll, IsMatrixObjOverFiniteField));
end);
InstallTrueMethod(IsGeneratorsOfActingSemigroup,
IsMatrixOverFiniteFieldSemigroup);
# the largest point involved in the action
InstallMethod(ActionDegree, "for a transformation",
[IsTransformation], DegreeOfTransformation);
InstallMethod(ActionDegree, "for a partial perm",
[IsPartialPerm], x -> Maximum(DegreeOfPartialPerm(x),
CodegreeOfPartialPerm(x)));
InstallMethod(ActionDegree, "for a bipartition",
[IsBipartition], DegreeOfBipartition);
InstallMethod(ActionDegree, "for a Rees 0-matrix semigroup element",
[IsReesZeroMatrixSemigroupElement],
function(x)
if x![1] = 0 then
return 0;
fi;
return NrMovedPoints(x![2]) + 1;
end);
InstallMethod(ActionDegree, "for a McAlister semigroup element",
[IsMcAlisterTripleSemigroupElement],
x -> 0);
InstallMethod(ActionDegree, "for a matrix obj", [IsMatrixObj],
function(m)
if not IsMatrixObjOverFiniteField(m) then
TryNextMethod();
fi;
return NrRows(m);
end);
InstallMethod(ActionDegree, "for a transformation collection",
[IsTransformationCollection], DegreeOfTransformationCollection);
InstallMethod(ActionDegree, "for a partial perm collection",
[IsPartialPermCollection], x -> Maximum(DegreeOfPartialPermCollection(x),
CodegreeOfPartialPermCollection(x)));
InstallMethod(ActionDegree, "for a bipartition collection",
[IsBipartitionCollection], DegreeOfBipartitionCollection);
InstallMethod(ActionDegree, "for a Rees 0-matrix semigroup element collection",
[IsReesZeroMatrixSemigroupElementCollection],
function(coll)
local R;
if ForAny(coll, x -> x![1] <> 0) then
R := ReesMatrixSemigroupOfFamily(FamilyObj(Representative(coll)));
return NrMovedPoints(UnderlyingSemigroup(R)) + 1;
fi;
return 0;
end);
InstallMethod(ActionDegree, "for a ffe coll coll coll",
[IsFFECollCollColl],
function(coll)
Assert(1, ForAll(coll, IsMatrixObjOverFiniteField));
return NrRows(Representative(coll));
end);
InstallMethod(ActionDegree, "for a McAlister semigroup element collection",
[IsMcAlisterTripleSemigroupElementCollection],
coll -> MaximumList(List(coll, ActionDegree)));
InstallMethod(ActionDegree, "for a transformation semigroup",
[IsTransformationSemigroup], DegreeOfTransformationSemigroup);
InstallMethod(ActionDegree, "for a partial perm semigroup",
[IsPartialPermSemigroup], x -> Maximum(DegreeOfPartialPermSemigroup(x),
CodegreeOfPartialPermSemigroup(x)));
InstallMethod(ActionDegree, "for a partial perm inverse semigroup",
[IsPartialPermSemigroup and IsInverseSemigroup], DegreeOfPartialPermSemigroup);
InstallMethod(ActionDegree, "for a bipartition semigroup",
[IsBipartitionSemigroup], DegreeOfBipartitionSemigroup);
InstallMethod(ActionDegree, "for a Rees 0-matrix subsemigroup with generators",
[IsReesZeroMatrixSubsemigroup and HasGeneratorsOfSemigroup],
function(R)
local parent;
if ForAny(GeneratorsOfSemigroup(R), x -> x![1] <> 0) then
parent := ReesMatrixSemigroupOfFamily(ElementsFamily(FamilyObj(R)));
return NrMovedPoints(UnderlyingSemigroup(parent)) + 1;
fi;
return 0;
end);
InstallMethod(ActionDegree, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
S -> 0);
InstallMethod(ActionDegree, "for a matrix over finite field semigroup",
[IsMatrixOverFiniteFieldSemigroup],
S -> ActionDegree(Representative(S)));
# the number of points in the range of the action
InstallMethod(ActionRank, "for a transformation and integer",
[IsTransformation, IsInt], RANK_TRANS_INT);
InstallMethod(ActionRank, "for a transformation semigroup",
[IsTransformationSemigroup],
S -> f -> RANK_TRANS_INT(f, DegreeOfTransformationSemigroup(S)));
InstallMethod(ActionRank, "for a partial perm and integer",
[IsPartialPerm, IsInt],
{f, n} -> RankOfPartialPerm(f));
InstallMethod(ActionRank, "for a partial perm semigroup",
[IsPartialPermSemigroup],
S -> RankOfPartialPerm);
InstallMethod(ActionRank, "for a bipartition and integer",
[IsBipartition, IsInt], BIPART_RANK);
InstallMethod(ActionRank, "for a bipartition semigroup",
[IsBipartitionSemigroup],
S -> RankOfBipartition);
InstallMethod(ActionRank,
"for a Rees 0-matrix semigroup element and integer",
[IsReesZeroMatrixSemigroupElement, IsInt],
function(f, _)
local parent;
if f![1] = 0 then
return 0;
fi;
parent := ReesMatrixSemigroupOfFamily(FamilyObj(f));
return NrMovedPoints(UnderlyingSemigroup(parent)) + 1;
end);
InstallMethod(ActionRank, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup],
function(R)
return function(x)
local parent;
if x![1] = 0 then
return 0;
else
parent := ReesMatrixSemigroupOfFamily(ElementsFamily(FamilyObj(R)));
return NrMovedPoints(UnderlyingSemigroup(parent)) + 1;
fi;
end;
end);
InstallMethod(ActionRank, "for a McAlister triple semigroup element and int",
[IsMcAlisterTripleSemigroupElement, IsInt],
{f, n} -> f[1]);
InstallMethod(ActionRank, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
S -> x -> ActionDegree(S));
InstallMethod(ActionRank, "for a matrix object and integer",
[IsMatrixObj, IsInt],
function(x, _)
if not IsMatrixObjOverFiniteField(x) then
TryNextMethod();
fi;
return Rank(RowSpaceBasis(x));
end);
InstallMethod(ActionRank, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup],
S -> x -> Rank(RowSpaceBasis(x)));
# the minimum possible rank of an element
InstallMethod(MinActionRank, "for a transformation semigroup",
[IsTransformationSemigroup], x -> 1);
InstallMethod(MinActionRank, "for a partial perm semigroup",
[IsPartialPermSemigroup], x -> 0);
InstallMethod(MinActionRank, "for a bipartition semigroup",
[IsBipartitionSemigroup], x -> 0);
InstallMethod(MinActionRank, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], x -> 0);
InstallMethod(MinActionRank, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], x -> 1);
InstallMethod(MinActionRank, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], x -> 0);
# options passed to LambdaOrb(S) when it is created
InstallMethod(LambdaOrbOpts, "for a transformation semigroup",
[IsTransformationSemigroup], S -> rec(forflatplainlists := true));
InstallMethod(LambdaOrbOpts, "for a partial perm semigroup",
[IsPartialPermSemigroup], S -> rec(forflatplainlists := true));
InstallMethod(LambdaOrbOpts, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> rec());
InstallMethod(LambdaOrbOpts, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S -> rec());
InstallMethod(LambdaOrbOpts, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S -> rec());
InstallMethod(LambdaOrbOpts, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S -> rec());
InstallMethod(RhoOrbOpts, "for a transformation semigroup",
[IsTransformationSemigroup], S -> rec(forflatplainlists := true));
InstallMethod(RhoOrbOpts, "for a partial perm semigroup",
[IsPartialPermSemigroup], S -> rec(forflatplainlists := true));
InstallMethod(RhoOrbOpts, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> rec());
InstallMethod(RhoOrbOpts, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S -> rec());
InstallMethod(RhoOrbOpts, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S -> rec());
InstallMethod(RhoOrbOpts, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S -> rec());
# the lambda and rho acts
InstallMethod(LambdaAct, "for a transformation semigroup",
[IsTransformationSemigroup],
S -> {set, f} -> OnPosIntSetsTrans(set, f, DegreeOfTransformationSemigroup(S)));
InstallMethod(LambdaAct, "for a partial perm semigroup",
[IsPartialPermSemigroup], x -> OnPosIntSetsPartialPerm);
InstallMethod(LambdaAct, "for a bipartition semigroup",
[IsBipartitionSemigroup], x -> BLOCKS_RIGHT_ACT);
InstallMethod(LambdaAct, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], x -> function(pt, x)
if x![1] = 0 or pt = 0 then
return 0;
elif pt = -1 or x![4][pt][x![1]] <> 0 then
return x![3];
else
return 0;
fi;
end);
InstallMethod(LambdaAct, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
function(S)
local act, digraph;
S := MTSEParent(Representative(S));
act := McAlisterTripleSemigroupAction(S);
digraph := McAlisterTripleSemigroupPartialOrder(S);
return
function(pt, x)
if pt = 0 then
return act(x[1], x[2] ^ -1);
fi;
return PartialOrderDigraphJoinOfVertices(digraph,
act(pt, x[2] ^ -1),
act(x[1], x[2] ^ -1));
end;
end);
InstallMethod(LambdaAct, "for a matrix over finite field semigroup",
[IsMatrixOverFiniteFieldSemigroup],
S -> {vsp, mat} -> MatrixOverFiniteFieldRowSpaceRightAction(S, vsp, mat));
InstallMethod(RhoAct, "for a transformation semigroup",
[IsTransformationSemigroup],
S ->
{set, f} -> ON_KERNEL_ANTI_ACTION(set, f, DegreeOfTransformationSemigroup(S)));
InstallMethod(RhoAct, "for a partial perm semigroup",
[IsPartialPermSemigroup], S ->
{set, f} -> OnPosIntSetsPartialPerm(set, f ^ -1));
InstallMethod(RhoAct, "for a partial perm semigroup",
[IsBipartitionSemigroup], x -> BLOCKS_LEFT_ACT);
InstallMethod(RhoAct, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], x -> function(pt, x)
if x![1] = 0 or pt = 0 then
return 0;
elif pt = -1 or x![4][x![3]][pt] <> 0 then
return x![1];
else
return 0;
fi;
end);
InstallMethod(RhoAct, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
function(S)
local act, digraph;
S := MTSEParent(Representative(S));
act := McAlisterTripleSemigroupAction(S);
digraph := McAlisterTripleSemigroupPartialOrder(S);
return
function(pt, x)
if pt = 0 then
return x[1];
fi;
return PartialOrderDigraphJoinOfVertices(digraph,
act(pt, x[2]),
x[1]);
end;
end);
InstallMethod(RhoAct, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup],
S -> {vsp, mat} -> LambdaAct(S)(vsp, TransposedMat(mat)));
# the seed or dummy start point for LambdaOrb
InstallMethod(LambdaOrbSeed, "for a transformation semigroup",
[IsTransformationSemigroup], S -> [0]);
InstallMethod(LambdaOrbSeed, "for a partial perm semigroup",
[IsPartialPermSemigroup], S -> [0]);
InstallMethod(LambdaOrbSeed, "for a bipartition semigroup",
[IsBipartitionSemigroup],
S -> BLOCKS_NC([[1 .. DegreeOfBipartitionSemigroup(S) + 1]]));
InstallMethod(LambdaOrbSeed, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S -> -1);
InstallMethod(LambdaOrbSeed, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S -> 0);
InstallMethod(LambdaOrbSeed,
"for a matrix over finite field semigroup",
[IsMatrixOverFiniteFieldSemigroup],
function(S)
local deg;
deg := NrRows(Representative(S)) + 2;
return NewRowBasisOverFiniteField(IsPlistRowBasisOverFiniteFieldRep,
BaseDomain(S),
NullMat(deg, deg, BaseDomain(S)));
end);
# the seed or dummy start point for RhoOrb
InstallMethod(RhoOrbSeed, "for a transformation semigroup",
[IsTransformationSemigroup], S -> [0]);
InstallMethod(RhoOrbSeed, "for a partial perm semigroup",
[IsPartialPermSemigroup], S -> [0]);
InstallMethod(RhoOrbSeed, "for a bipartition semigroup",
[IsBipartitionSemigroup],
S -> BLOCKS_NC([[1 .. DegreeOfBipartitionSemigroup(S) + 1]]));
InstallMethod(RhoOrbSeed, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S -> -1);
InstallMethod(RhoOrbSeed, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S -> 0);
InstallMethod(RhoOrbSeed, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], LambdaOrbSeed);
# the function calculating the lambda or rho value of an element
InstallMethod(LambdaFunc, "for a transformation semigroup",
[IsTransformationSemigroup],
S -> f -> IMAGE_SET_TRANS_INT(f, DegreeOfTransformationSemigroup(S)));
InstallMethod(LambdaFunc, "for a partial perm semigroup",
[IsPartialPermSemigroup], x -> IMAGE_SET_PPERM);
InstallMethod(LambdaFunc, "for a bipartition semigroup",
[IsBipartitionSemigroup], x -> BIPART_RIGHT_BLOCKS);
InstallMethod(LambdaFunc, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], R -> function(x)
if x![1] <> 0 then
return x![3];
fi;
return 0;
end);
InstallMethod(LambdaFunc, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
function(S)
local act;
act := McAlisterTripleSemigroupAction(MTSEParent(Representative(S)));
return x -> act(x[1], x[2] ^ -1);
end);
# a function that returns the row space
InstallMethod(LambdaFunc, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S -> RowSpaceBasis);
InstallMethod(RhoFunc, "for a transformation semigroup",
[IsTransformationSemigroup],
S -> f -> FLAT_KERNEL_TRANS_INT(f, DegreeOfTransformationSemigroup(S)));
InstallMethod(RhoFunc, "for a partial perm semigroup",
[IsPartialPermSemigroup], x -> DOMAIN_PPERM);
InstallMethod(RhoFunc, "for a bipartition semigroup",
[IsBipartitionSemigroup], x -> BIPART_LEFT_BLOCKS);
InstallMethod(RhoFunc, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], R -> x -> x![1]);
InstallMethod(RhoFunc, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S -> x -> x[1]);
# a function that returns the column space
InstallMethod(RhoFunc, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup],
S -> mat -> LambdaFunc(S)(TransposedMat(mat)));
# The function used to calculate the rank of lambda or rho value
InstallMethod(LambdaRank, "for a transformation semigroup",
[IsTransformationSemigroup], x -> Length);
InstallMethod(LambdaRank, "for a partial perm semigroup",
[IsPartialPermSemigroup], x -> Length);
InstallMethod(LambdaRank, "for a bipartition semigroup",
[IsBipartitionSemigroup], x -> BLOCKS_RANK);
InstallMethod(LambdaRank, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], R ->
function(x)
local parent;
if x = 0 then
return 0;
else
parent := ReesMatrixSemigroupOfFamily(ElementsFamily(FamilyObj(R)));
return NrMovedPoints(UnderlyingSemigroup(parent)) + 1;
fi;
end);
InstallMethod(LambdaRank, "for a McAlister subsemigroup",
[IsMcAlisterTripleSubsemigroup], S ->
function(x)
local T;
if x = 0 then
return 0;
fi;
T := MTSEParent(Representative(S));
return ActionRank(MTSE(T, x, One(McAlisterTripleSemigroupGroup(T))), 0);
end);
# Why are there row spaces and matrices passed in here?
InstallMethod(LambdaRank, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], x -> Rank);
InstallMethod(RhoRank, "for a transformation semigroup",
[IsTransformationSemigroup], S -> function(x)
if IsEmpty(x) then
return 0;
else
return MaximumList(x);
fi;
end);
InstallMethod(RhoRank, "for a partial perm semigroup",
[IsPartialPermSemigroup], x -> Length);
InstallMethod(RhoRank, "for a bipartition semigroup",
[IsBipartitionSemigroup], x -> BLOCKS_RANK);
InstallMethod(RhoRank, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], LambdaRank);
InstallMethod(RhoRank, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], LambdaRank);
InstallMethod(RhoRank, "for a McAlister subsemigroup",
[IsMcAlisterTripleSubsemigroup], LambdaRank);
# if g=LambdaInverse(X, f) and X^f=Y, then Y^g=X and g acts on the right
# like the inverse of f on Y.
InstallMethod(LambdaInverse, "for a transformation semigroup",
[IsTransformationSemigroup], S -> INV_LIST_TRANS);
InstallMethod(LambdaInverse, "for a partial perm semigroup",
[IsPartialPermSemigroup], S -> {x, f} -> f ^ -1);
InstallMethod(LambdaInverse, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S -> {x, f} -> f ^ -1);
InstallMethod(LambdaInverse, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> BLOCKS_INV_RIGHT);
InstallMethod(LambdaInverse, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S ->
function(k, x)
local i;
if x![1] = 0 or k = 0 then
return x;
fi;
i := First([1 .. Length(x![4][x![3]])], i -> x![4][x![3]][i] <> 0);
return Objectify(FamilyObj(x)!.type,
[i,
(x![4][k][x![1]] * x![2] * x![4][x![3]][i]) ^ -1,
k,
x![4]]);
end);
# if g = RhoInverse(X, f) and f ^ X = Y (this is a left action), then
# g ^ Y = X and g acts on the left like the inverse of f on Y.
InstallMethod(LambdaInverse, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S ->
{rsp, mat} -> MatrixOverFiniteFieldLocalRightInverse(S, rsp, mat));
InstallMethod(RhoInverse, "for a transformation semigroup",
[IsTransformationSemigroup], S -> INV_KER_TRANS);
InstallMethod(RhoInverse, "for a partial perm semigroup",
[IsPartialPermSemigroup], S ->
{dom, f} -> f ^ -1);
InstallMethod(RhoInverse, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S -> {x, f} -> f ^ -1);
# JDM better method for this!!
InstallMethod(RhoInverse, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S ->
function(k, x)
local i;
if x![1] = 0 or k = 0 then
return x;
fi;
i := First([1 .. Length(x![4])], i -> x![4][i][x![1]] <> 0);
return Objectify(FamilyObj(x)!.type,
[k,
(x![4][i][x![1]] * x![2] * x![4][x![3]][k]) ^ -1,
i,
x![4]]);
end);
InstallMethod(RhoInverse, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> BLOCKS_INV_LEFT);
InstallMethod(RhoInverse, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S ->
function(rsp, mat)
return TransposedMat(MatrixOverFiniteFieldLocalRightInverse(S,
rsp, TransposedMat(mat)));
end);
SEMIGROUPS.DefaultLambdaBound := _ ->
function(r)
if r < 100 then
return Factorial(r);
else
return infinity;
fi;
end;
InstallMethod(LambdaBound, "for a transformation semigroup",
[IsTransformationSemigroup], SEMIGROUPS.DefaultLambdaBound);
InstallMethod(RhoBound, "for a transformation semigroup",
[IsTransformationSemigroup], LambdaBound);
InstallMethod(LambdaBound, "for a partial perm semigroup",
[IsPartialPermSemigroup], SEMIGROUPS.DefaultLambdaBound);
InstallMethod(RhoBound, "for a partial perm semigroup",
[IsPartialPermSemigroup], LambdaBound);
InstallMethod(LambdaBound, "for a bipartition semigroup",
[IsBipartitionSemigroup], SEMIGROUPS.DefaultLambdaBound);
InstallMethod(RhoBound, "for a bipartition semigroup",
[IsBipartitionSemigroup], LambdaBound);
InstallMethod(LambdaBound, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup], SEMIGROUPS.DefaultLambdaBound);
InstallMethod(RhoBound, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup], LambdaBound);
InstallMethod(LambdaBound, "for a McAlister subsemigroup",
[IsMcAlisterTripleSubsemigroup], S ->
function(r)
local G;
G := McAlisterTripleSemigroupGroup(MTSEParent(Representative(S)));
return Size(Stabilizer(G, r, McAlisterTripleSemigroupAction(S)));
end);
InstallMethod(RhoBound, "for a McAlister subsemigroup",
[IsMcAlisterTripleSubsemigroup], LambdaBound);
InstallMethod(LambdaBound, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S ->
function(r)
if r = 0 then
return 1;
elif r < 100 then
return Size(GL(NrRows(Representative(S)), BaseDomain(S)));
else
return infinity;
fi;
end);
InstallMethod(RhoBound, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], LambdaBound);
# LamdaIdentity(S) returns a function that returns
# the identity element of the Schutzenberger group
# elements produced by LambdaPerm
# TODO(later) these functions don't need the argument <r> any more
InstallMethod(LambdaIdentity, "for a transformation semigroup",
[IsTransformationSemigroup],
S -> r -> ());
InstallMethod(RhoIdentity, "for a transformation semigroup",
[IsTransformationSemigroup],
S -> r -> ());
InstallMethod(LambdaIdentity, "for a partial perm semigroup",
[IsPartialPermSemigroup],
S -> r -> ());
InstallMethod(RhoIdentity, "for a partial perm semigroup",
[IsPartialPermSemigroup],
S -> r -> ());
InstallMethod(LambdaIdentity, "for a bipartition semigroup",
[IsBipartitionSemigroup],
S -> r -> ());
InstallMethod(RhoIdentity, "for a bipartition semigroup",
[IsBipartitionSemigroup],
S -> r -> ());
InstallMethod(LambdaIdentity, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup],
S -> r -> ());
InstallMethod(RhoIdentity, "for a Rees 0-matrix semigroup",
[IsReesZeroMatrixSubsemigroup],
S -> r -> ());
InstallMethod(LambdaIdentity, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
S -> r -> ());
InstallMethod(RhoIdentity, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], LambdaIdentity);
InstallMethod(LambdaIdentity, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S ->
r -> IdentityMat(r, BaseDomain(Representative(S))));
InstallMethod(RhoIdentity, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S ->
r -> IdentityMat(r, BaseDomain(Representative(S))));
# LambdaPerm(S) returns a permutation from two acting semigroup elements with
# equal LambdaFunc and RhoFunc. This is required to check if one of the two
# elements belongs to the schutz gp of a lambda orb.
InstallMethod(LambdaPerm, "for a transformation semigroup",
[IsTransformationSemigroup], S -> PermLeftQuoTransformationNC);
InstallMethod(LambdaPerm, "for a partial perm semigroup",
[IsPartialPermSemigroup], S -> PERM_LEFT_QUO_PPERM_NC);
InstallMethod(LambdaPerm, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> BIPART_PERM_LEFT_QUO);
InstallMethod(LambdaPerm, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S ->
function(x, y)
if x![1] = 0 or y![1] = 0 then
return ();
fi;
return x![2] ^ -1 * y![2];
end);
InstallMethod(LambdaPerm, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
S -> {x, y} -> x[2] ^ -1 * y[2]);
InstallMethod(LambdaPerm, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S ->
{x, y} -> MatrixOverFiniteFieldSchutzGrpElement(S, x, y));
# Returns a permutation mapping LambdaFunc(S)(x) to LambdaFunc(S)(y) so that
# yx ^ -1(i) = p(i) when RhoFunc(S)(x) = RhoFunc(S)(y)!!
InstallMethod(LambdaConjugator, "for a transformation semigroup",
[IsTransformationSemigroup], S -> TRANS_IMG_CONJ);
InstallMethod(LambdaConjugator, "for a partial perm semigroup",
[IsPartialPermSemigroup], S ->
{x, y} -> MappingPermListList(IMAGE_PPERM(x), IMAGE_PPERM(y)));
InstallMethod(LambdaConjugator, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> BIPART_LAMBDA_CONJ);
InstallMethod(LambdaConjugator, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S ->
# FIXME(later) is this right???? This is not right!!
{x, y} -> ());
InstallMethod(LambdaConjugator, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
function(S)
local T, G, act;
T := MTSEParent(Representative(S));
G := McAlisterTripleSemigroupGroup(T);
act := MTSUnderlyingAction(T); # MTSAction is not an action, causes problems
return {x, y} -> RepresentativeAction(G,
LambdaFunc(S)(x),
LambdaFunc(S)(y),
act);
end);
InstallMethod(LambdaConjugator, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S ->
{x, y} -> MatrixOverFiniteFieldLambdaConjugator(S, x, y));
# the function used to test if there is an idempotent with the specified
# lambda and rho values.
InstallMethod(IdempotentTester, "for a transformation semigroup",
[IsTransformationSemigroup], S ->
function(img, ker)
if IsEmpty(img) then
return IsEmpty(ker);
fi;
return IsInjectiveListTrans(img, ker) and Length(img) = MaximumList(ker);
end);
InstallMethod(IdempotentTester, "for a partial perm semigroup",
[IsPartialPermSemigroup], S -> \=);
InstallMethod(IdempotentTester, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> BLOCKS_E_TESTER);
InstallMethod(IdempotentTester, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], R ->
function(j, i)
local parent;
if i = 0 and j = 0 then
return true;
fi;
parent := ReesMatrixSemigroupOfFamily(ElementsFamily(FamilyObj(R)));
return Matrix(parent)[j][i] <> 0;
end);
InstallMethod(IdempotentTester, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S -> {x, y} -> x = y);
InstallMethod(IdempotentTester, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup],
S -> {x, y} -> MatrixOverFiniteFieldIdempotentTester(S, x, y));
# the function used to create an idempotent with the specified lambda and rho
# values.
InstallMethod(IdempotentCreator, "for a transformation semigroup",
[IsTransformationSemigroup], S -> IDEM_IMG_KER_NC);
InstallMethod(IdempotentCreator, "for a partial perm semigp",
[IsPartialPermSemigroup], S -> PartialPermNC);
InstallMethod(IdempotentCreator, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> BLOCKS_E_CREATOR);
InstallMethod(IdempotentCreator, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], R ->
function(j, i)
local mat;
if i = 0 and j = 0 then
return Objectify(TypeReesMatrixSemigroupElements(R), [0]);
fi;
mat := Matrix(ReesMatrixSemigroupOfFamily(ElementsFamily(FamilyObj(R))));
return Objectify(TypeReesMatrixSemigroupElements(R),
[i, mat[j][i] ^ -1, j, mat]);
end);
InstallMethod(IdempotentCreator, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S ->
function(x, _)
local T;
T := MTSEParent(Representative(S));
return MTSE(T, x, One(McAlisterTripleSemigroupGroup(T)));
end);
InstallMethod(IdempotentCreator, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup],
S -> {x, y} -> MatrixOverFiniteFieldIdempotentCreator(S, x, y));
# the action of elements of the stabiliser of a lambda-value on any element of
# the semigroup with that lambda-value
# StabilizerAction will be \* for transformation and partial perm semigroups
# and something else for semigroups of bipartitions.
InstallMethod(StabilizerAction, "for a transformation semigroup",
[IsTransformationSemigroup], S -> OnRight);
InstallMethod(StabilizerAction, "for a partial perm semigroup",
[IsPartialPermSemigroup], S -> OnRight);
InstallMethod(StabilizerAction, "for a bipartition semigroup",
[IsBipartitionSemigroup], S -> BIPART_STAB_ACTION);
InstallMethod(StabilizerAction, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup], S ->
function(x, p)
if x![1] = 0 then
return x;
fi;
return Objectify(TypeObj(x), [x![1], x![2] * p, x![3], x![4]]);
end);
InstallMethod(StabilizerAction, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup], S ->
function(x, p)
local T;
T := MTSEParent(x);
return MTSE(T, x[1], x[2] * p);
end);
InstallMethod(StabilizerAction, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup], S ->
{x, y} -> MatrixOverFiniteFieldStabilizerAction(S, x, y));
# IsActingSemigroupWithFixedDegreeMultiplication should be <true> if and only
# if it is only possible to multiply elements of the type in the semigroup with
# equal degrees.
InstallMethod(IsActingSemigroupWithFixedDegreeMultiplication,
"for a transformation semigroup",
[IsTransformationSemigroup and IsActingSemigroup], ReturnFalse);
InstallTrueMethod(IsActingSemigroupWithFixedDegreeMultiplication,
IsBipartitionSemigroup and IsActingSemigroup);
InstallMethod(IsActingSemigroupWithFixedDegreeMultiplication,
"for an acting partial perm semigroup",
[IsPartialPermSemigroup and IsActingSemigroup], ReturnFalse);
# this is not really relevant here.
InstallMethod(IsActingSemigroupWithFixedDegreeMultiplication,
"for an acting Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup and IsActingSemigroup], ReturnFalse);
InstallMethod(IsActingSemigroupWithFixedDegreeMultiplication,
"for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup and IsActingSemigroup], ReturnFalse);
InstallTrueMethod(IsActingSemigroupWithFixedDegreeMultiplication,
IsMatrixOverFiniteFieldSemigroup);
InstallMethod(SchutzGpMembership, "for a transformation semigroup",
[IsTransformationSemigroup],
S -> {stab, x} -> SiftedPermutation(stab, x) = ());
InstallMethod(SchutzGpMembership, "for a partial perm semigroup",
[IsPartialPermSemigroup],
S -> {stab, x} -> SiftedPermutation(stab, x) = ());
InstallMethod(SchutzGpMembership, "for a Rees 0-matrix subsemigroup",
[IsReesZeroMatrixSubsemigroup],
S -> {stab, x} -> SiftedPermutation(stab, x) = ());
InstallMethod(SchutzGpMembership, "for a McAlister triple subsemigroup",
[IsMcAlisterTripleSubsemigroup],
S -> {stab, x} -> SiftedPermutation(stab, x) = ());
InstallMethod(SchutzGpMembership, "for a bipartition semigroup",
[IsBipartitionSemigroup],
S -> {stab, x} -> SiftedPermutation(stab, x) = ());
InstallMethod(SchutzGpMembership, "for a matrix semigroup",
[IsMatrixOverFiniteFieldSemigroup],
S -> {stab, x} -> x in stab);
# One or a fake one for those types of object without one.
InstallMethod(FakeOne, "for a transformation collection",
[IsTransformationCollection], One);
InstallMethod(FakeOne, "for a partial perm collection",
[IsPartialPermCollection], One);
InstallMethod(FakeOne, "for a bipartition collection",
[IsBipartitionCollection], One);
InstallMethod(FakeOne, "for a Rees 0-matrix semigroup element collection",
[IsReesZeroMatrixSemigroupElementCollection], R -> SEMIGROUPS.UniversalFakeOne);
InstallMethod(FakeOne, "for a McAlister triple semigroup element collection",
[IsMcAlisterTripleSemigroupElementCollection],
S -> SEMIGROUPS.UniversalFakeOne);
# Matrix semigroup elements
InstallMethod(FakeOne, "for an FFE coll coll coll",
[IsFFECollCollColl],
function(coll)
Assert(1, ForAll(coll, IsMatrixObjOverFiniteField));
Assert(1, ForAll(coll, x -> NrRows(x) = NrRows(Representative(coll))));
return One(Representative(coll));
end);
# missing hash functions
SEMIGROUPS.HashFunctionRZMSE := function(x, data, func)
if x![1] = 0 then
return 1;
fi;
# Use some big primes that are near the default hash table size
if IsNBitsPcWordRep(x![2]) then
return (104723 * x![1] + 104729 * x![3] + func(x![2], data))
mod data[2] + 1;
else
return (104723 * x![1] + 104729 * x![3] + func(x![2], data)) mod data + 1;
fi;
end;
InstallMethod(ChooseHashFunction,
"for a Rees 0-matrix semigroup element and integer",
[IsReesZeroMatrixSemigroupElement, IsInt],
function(x, hashlen)
local R, data, under, func;
R := ReesMatrixSemigroupOfFamily(FamilyObj(x));
if IsMultiplicativeZero(R, x) then
x := EmptyPlist(3);
x[2] := Representative(UnderlyingSemigroup(R));
fi;
if IsNBitsPcWordRep(x![2]) then
under := ChooseHashFunction(x![2], hashlen).func;
data := ChooseHashFunction(x![2], hashlen).data;
else
under := ChooseHashFunction(x![2], hashlen).func;
data := ChooseHashFunction(x![2], hashlen).data;
fi;
if data = fail then
data := hashlen;
fi;
func := {x, hashlen} -> SEMIGROUPS.HashFunctionRZMSE(x, data, under);
return rec(func := func, data := data);
end);
# fallback method for hashing
InstallMethod(ChooseHashFunction, "for an object and an int",
[IsObject, IsInt],
{p, hashlen} -> rec(func := {v, data} -> 1, data := fail));
# The next two methods are more general than might seem necessary but
# apparently ReesZeroMatrixSemigroup'S satisfying IsWholeFamily are not in
# IsActingSemigroup but their ideals are, and we still require a method for
# ConvertToInternalElement as a result.
InstallMethod(ConvertToInternalElement,
"for a semigroup and mult. elt.",
[IsSemigroup, IsMultiplicativeElement],
{S, x} -> x);
InstallMethod(ConvertToExternalElement,
"for a semigroup and mult. elt.",
[IsSemigroup, IsMultiplicativeElement],
{S, x} -> x);
InstallMethod(ConvertToInternalElement,
"for an acting matrix over ff semigroup and matrix obj",
[IsActingSemigroup and IsMatrixOverFiniteFieldSemigroup, IsMatrixObj],
function(S, mat)
local bd, n;
Assert(1, IsMatrixObjOverFiniteField(mat));
if NrRows(mat) = NrRows(Representative(S)) + 1 then
return mat;
fi;
Assert(1, NrRows(mat) = NrRows(Representative(S)));
bd := BaseDomain(mat);
n := NrRows(mat);
mat := List([1 .. n],
i -> Concatenation(mat[i], [Zero(bd)]));
Add(mat, ZeroMatrix(bd, 1, n + 1)[1]);
mat[n + 1, n + 1] := One(bd);
return Matrix(bd, mat);
end);
InstallMethod(ConvertToExternalElement,
"for an acting matrix over ff semigroup and matrix obj",
[IsActingSemigroup and IsMatrixOverFiniteFieldSemigroup, IsMatrixObj],
function(S, mat)
local n;
Assert(1, IsMatrixObjOverFiniteField(mat));
if NrRows(mat) = NrRows(Representative(S)) then
return mat;
fi;
Assert(1, NrRows(mat) = NrRows(Representative(S)) + 1);
n := NrRows(mat) - 1;
return Matrix(Unpack(mat){[1 .. n]}{[1 .. n]}, mat);
end);
InstallMethod(WeakInverse, "for a transformation",
[IsTransformation], InverseOfTransformation);
InstallMethod(WeakInverse, "for a partial perm",
[IsPartialPerm], InverseMutable);
InstallMethod(WeakInverse, "for a bipartition",
[IsBipartition], Star);
[ Dauer der Verarbeitung: 0.42 Sekunden
(vorverarbeitet)
]
|