Skip to content

Commit

Permalink
fropin: add Left/RightCayleyDigraph
Browse files Browse the repository at this point in the history
These essentially just wrap the value previously returned by
Left/RightCayleyGraphSemigroup in a Digraph object. Methods for
Left/RightCayleyGraphSemigroup continue to exist (just calling
OutNeighbours(Left/RightCayleyDigraph) since they are defined in the
library. All other occurrences of Left/RightCayleyGraphSemigroup are
replaced with Left/RightCayleyDigraph.
  • Loading branch information
James Mitchell committed Jul 22, 2017
1 parent 96181da commit 272aa00
Show file tree
Hide file tree
Showing 16 changed files with 127 additions and 72 deletions.
2 changes: 1 addition & 1 deletion PackageInfo.g
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ Dependencies := rec(
GAP := ">=4.9.0",
NeededOtherPackages := [["orb", ">=4.7.5"],
["io", ">=4.4.4"],
["digraphs", ">=0.10.0"],
["digraphs", ">=0.9.0"],
["genss", ">=1.5"]],
SuggestedOtherPackages := [["gapdoc", ">=1.5.1"]],

Expand Down
37 changes: 22 additions & 15 deletions doc/fropin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ false
returns a list of the elements of <A>S</A> in the order they are
enumerated by the Froidure-Pin Algorithm. This is the same as the order
used to index the elements of <A>S</A> in <Ref
Attr="RightCayleyGraphSemigroup"/> and <Ref
Attr="LeftCayleyGraphSemigroup"/>. <P/>
Attr="RightCayleyDigraph"/> and <Ref
Attr="LeftCayleyDigraph"/>. <P/>

<C>EnumeratorCanonical</C> and <C>IteratorCanonical</C> return an
enumerator and an iterator where the elements are
Expand All @@ -67,8 +67,8 @@ false
<C>AsList</C> may not equal the value returned by <C>AsListCanonical</C>.
<C>AsListCanonical</C> exists so that there is a method for obtaining the
elements of <A>S</A> in the particular order used by
<Ref Attr="RightCayleyGraphSemigroup"/> and
<Ref Attr="LeftCayleyGraphSemigroup"/>.<P/>
<Ref Attr="RightCayleyDigraph"/> and
<Ref Attr="LeftCayleyDigraph"/>.<P/>

See also <Ref Oper="PositionCanonical"/>.

Expand Down Expand Up @@ -183,27 +183,34 @@ true]]></Example>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="RightCayleyGraphSemigroup">
<#GAPDoc Label="RightCayleyDigraph">
<ManSection>
<Attr Name="RightCayleyGraphSemigroup" Arg="S"/>
<Attr Name="LeftCayleyGraphSemigroup" Arg="S"/>
<Attr Name="RightCayleyDigraph" Arg="S"/>
<Attr Name="LeftCayleyDigraph" Arg="S"/>
<Returns>A list of lists of positive integers.</Returns>
<Description>
When the argument <A>S</A> is a semigroup in the representation
<Ref Filt="IsEnumerableSemigroupRep"/>,
<C>RightCayleyGraphSemigroup</C> returns the right
Cayley graphs of <A>S</A>, as a list <C>graph</C> where
<C>graph[i][j]</C> is equal to
<C>RightCayleyDigraph</C> returns the right
Cayley graphs of <A>S</A>, as a <Ref Oper="Digraph" BookName="digraphs"/>
<C>digraph</C> where vertex <C>OutNeighbours(digraph)[i][j]</C> is
<C>PositionCanonical(<A>S</A>, AsListCanonical(<A>S</A>)[i] *
GeneratorsOfSemigroup(<A>S</A>)[j])</C>.
The list returned by <C>LeftCayleyGraphSemigroup</C> is defined analogously.
The list returned by <C>LeftCayleyDigraph</C> is defined analogously.<P/>

The digraph returned by this attribute belongs to the category
<Ref Filt="IsCayleyDigraph" BookName="digraphs"/>, the semigroup <A>S</A>
and the generators used to create the digraph can be recovered from the
digraph using <Ref Attr="SemigroupOfCayleyDigraph" BookName="digraphs"/>
and <Ref Attr="GeneratorsOfCayleyDigraph" BookName="digraphs"/>.

<Example><![CDATA[
gap> S := FullTransformationMonoid(2);
<full transformation monoid of degree 2>
gap> RightCayleyGraphSemigroup(S);
[ [ 1, 2, 3 ], [ 2, 1, 3 ], [ 3, 4, 3 ], [ 4, 3, 3 ] ]
gap> LeftCayleyGraphSemigroup(S);
[ [ 1, 2, 3 ], [ 2, 1, 4 ], [ 3, 3, 3 ], [ 4, 4, 4 ] ]]]></Example>
gap> RightCayleyDigraph(S);
<multidigraph with 4 vertices, 12 edges>
gap> LeftCayleyDigraph(S);
<multidigraph with 4 vertices, 12 edges>]]></Example>
</Description>
</ManSection>
<#/GAPDoc>
2 changes: 1 addition & 1 deletion doc/z-chap13.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<Heading>
Cayley graphs
</Heading>
<#Include Label = "RightCayleyGraphSemigroup">
<#Include Label = "RightCayleyDigraph">
</Section>

<!--**********************************************************************-->
Expand Down
2 changes: 1 addition & 1 deletion gap/congruences/conginv.gi
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ SEMIGROUPS.KernelTraceClosure := function(S, kernel, traceBlocks, pairstoapply)
hashlen := SEMIGROUPS.OptionsRec(S).hashlen.L;
ht := HTCreate([1, 1], rec(forflatplainlists := true,
treehashsize := hashlen));
right := RightCayleyGraphSemigroup(idsmgp);
right := OutNeighbours(RightCayleyDigraph(idsmgp));
genstoapply := [1 .. Length(right[1])];

#
Expand Down
2 changes: 0 additions & 2 deletions gap/greens/gree.gi
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,6 @@ function(S)

l := LeftCayleyGraphSemigroup(S);
r := RightCayleyGraphSemigroup(S);
# WW: in the future, when l and r are digraphs, gr can be created
# by using DigraphEdgeUnion(l, r)
gr := Digraph(List([1 .. Length(l)], i -> Concatenation(l[i], r[i])));
gr := QuotientDigraph(gr, DigraphStronglyConnectedComponents(gr).comps);
return List(OutNeighbours(gr), Set);
Expand Down
27 changes: 14 additions & 13 deletions gap/greens/gren.gi
Original file line number Diff line number Diff line change
Expand Up @@ -225,19 +225,19 @@ end);
InstallMethod(GreensRRelation, "for an enumerable semigroup",
[IsEnumerableSemigroupRep],
function(S)
local fam, rel;
local fam, data, rel;
if IsActingSemigroup(S) then
TryNextMethod();
fi;
fam := GeneralMappingsFamily(ElementsFamily(FamilyObj(S)),
ElementsFamily(FamilyObj(S)));

data := DigraphStronglyConnectedComponents(RightCayleyDigraph(S));
rel := Objectify(NewType(fam,
IsEquivalenceRelation
and IsEquivalenceRelationDefaultRep
and IsGreensRRelation
and IsEnumerableSemigroupGreensRelationRep),
rec(data := GABOW_SCC(RightCayleyGraphSemigroup(S))));
rec(data := data));
SetSource(rel, S);
SetRange(rel, S);
SetIsLeftSemigroupCongruence(rel, true);
Expand All @@ -250,19 +250,19 @@ end);
InstallMethod(GreensLRelation, "for an enumerable semigroup",
[IsEnumerableSemigroupRep],
function(S)
local fam, rel;
local fam, data, rel;
if IsActingSemigroup(S) then
TryNextMethod();
fi;
fam := GeneralMappingsFamily(ElementsFamily(FamilyObj(S)),
ElementsFamily(FamilyObj(S)));

data := DigraphStronglyConnectedComponents(LeftCayleyDigraph(S));
rel := Objectify(NewType(fam,
IsEquivalenceRelation
and IsEquivalenceRelationDefaultRep
and IsGreensLRelation
and IsEnumerableSemigroupGreensRelationRep),
rec(data := GABOW_SCC(LeftCayleyGraphSemigroup(S))));
rec(data := data));
SetSource(rel, S);
SetRange(rel, S);
SetIsRightSemigroupCongruence(rel, true);
Expand Down Expand Up @@ -514,19 +514,20 @@ InstallMethod(HClassReps, "for a Green's class of an enumerable semigroup",
[IsGreensClass and IsEnumerableSemigroupGreensClassRep],
C -> SEMIGROUPS.XClassRepsOfClass(C, GreensHRelation));

## Partial order of D-classes
# There is duplicate code in here and in maximal D-classes
# There is duplicate code in here and in maximal D-classes.
#
# This cannot be replaced with the method for IsSemigroup and IsFinite since
# the value of GreensDRelation(S)!.data.comps is not the same as the output of
# DigraphStronglyConnectedComponents.

InstallMethod(PartialOrderOfDClasses, "for a finite enumerable semigroup",
[IsEnumerableSemigroupRep and IsFinite],
function(S)
local l, r, gr;

l := LeftCayleyGraphSemigroup(S);
r := RightCayleyGraphSemigroup(S);
gr := Digraph(List([1 .. Length(l)], i -> Concatenation(l[i], r[i])));
l := LeftCayleyDigraph(S);
r := RightCayleyDigraph(S);
gr := DigraphEdgeUnion(l, r);
gr := QuotientDigraph(gr, GreensDRelation(S)!.data.comps);

return List(OutNeighbours(gr), Set);
end);

Expand Down
4 changes: 2 additions & 2 deletions gap/ideals/idealenum.gi
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ SEMIGROUPS.EnumerateIdeal := function(enum, limit, lookfunc)
indices := enum!.indices;

S := SupersemigroupOfIdeal(UnderlyingCollection(enum));
left := LeftCayleyGraphSemigroup(S);
right := RightCayleyGraphSemigroup(S);
left := OutNeighbours(LeftCayleyDigraph(S));
right := OutNeighbours(RightCayleyDigraph(S));
# FIXME Once the left and right Cayley graphs have been calculated, the
# entire data structure of S is known and from this it is relatively easy to
# find the entire data structure for I, so there is no point to what follows,
Expand Down
3 changes: 3 additions & 0 deletions gap/main/fropin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@ DeclareOperation("Enumerate", [IsEnumerableSemigroupRep]);
DeclareOperation("IsFullyEnumerated", [IsEnumerableSemigroupRep]);

DeclareProperty("IsSemigroupEnumerator", IsEnumeratorByFunctions);

DeclareAttribute("LeftCayleyDigraph", IsEnumerableSemigroupRep);
DeclareAttribute("RightCayleyDigraph", IsEnumerableSemigroupRep);
32 changes: 28 additions & 4 deletions gap/main/fropin.gi
Original file line number Diff line number Diff line change
Expand Up @@ -565,11 +565,23 @@ end);
InstallMethod(RightCayleyGraphSemigroup, "for an enumerable semigroup rep",
[IsEnumerableSemigroupRep], 3,
function(S)
return OutNeighbours(RightCayleyDigraph(S));
end);

InstallMethod(RightCayleyDigraph,
"for an enumerable semigroup rep",
[IsEnumerableSemigroupRep],
function(S)
local digraph;
if not IsFinite(S) then
ErrorNoReturn("Semigroups: RightCayleyGraphSemigroup: usage,\n",
ErrorNoReturn("Semigroups: RightCayleyDigraph: usage,\n",
"the first argument (a semigroup) must be finite,");
fi;
return EN_SEMI_RIGHT_CAYLEY_GRAPH(S);
digraph := Digraph(EN_SEMI_RIGHT_CAYLEY_GRAPH(S));
SetFilterObj(digraph, IsCayleyDigraph);
SetSemigroupOfCayleyDigraph(digraph, S);
SetGeneratorsOfCayleyDigraph(digraph, GeneratorsOfSemigroup(S));
return digraph;
end);

# same method for ideals
Expand All @@ -578,11 +590,23 @@ InstallMethod(LeftCayleyGraphSemigroup,
"for an enumerable semigroup rep",
[IsEnumerableSemigroupRep], 3,
function(S)
return OutNeighbours(LeftCayleyDigraph(S));
end);

InstallMethod(LeftCayleyDigraph,
"for an enumerable semigroup rep",
[IsEnumerableSemigroupRep],
function(S)
local digraph;
if not IsFinite(S) then
ErrorNoReturn("Semigroups: LeftCayleyGraphSemigroup: usage,\n",
ErrorNoReturn("Semigroups: LeftCayleyDigraph: usage,\n",
"the first argument (a semigroup) must be finite,");
fi;
return EN_SEMI_LEFT_CAYLEY_GRAPH(S);
digraph := Digraph(EN_SEMI_LEFT_CAYLEY_GRAPH(S));
SetFilterObj(digraph, IsCayleyDigraph);
SetSemigroupOfCayleyDigraph(digraph, S);
SetGeneratorsOfCayleyDigraph(digraph, GeneratorsOfSemigroup(S));
return digraph;
end);

InstallMethod(MultiplicationTable, "for an enumerable semigroup",
Expand Down
2 changes: 1 addition & 1 deletion gap/semigroups/grpperm.gi
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function(S)
"IsGroupAsSemigroup,");
fi;

cay := RightCayleyGraphSemigroup(S);
cay := OutNeighbours(RightCayleyDigraph(S));
deg := Size(S);
gen := [];

Expand Down
2 changes: 1 addition & 1 deletion gap/semigroups/semifp.gi
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function(x1, x2)
return x1 ^ map < x2 ^ map;
end);

#TODO AsSSortedList, RightCayleyGraph, any more?
#TODO AsSSortedList, RightCayleyDigraph, any more?

InstallMethod(ViewString, "for an f.p. semigroup element",
[IsElementOfFpSemigroup], String);
Expand Down
6 changes: 3 additions & 3 deletions gap/semigroups/semitrans.gi
Original file line number Diff line number Diff line change
Expand Up @@ -782,12 +782,12 @@ function(S)
local cay, deg, gen, next, T, iso, inv, i;

if not IsFinite(S) then
# This is unreachable in tests, since there is not other method that
# This is unreachable in tests, since there is no other method that
# terminates
TryNextMethod();
fi;

cay := RightCayleyGraphSemigroup(S);
cay := OutNeighbours(RightCayleyDigraph(S));
deg := Size(S);
gen := [];

Expand Down Expand Up @@ -826,7 +826,7 @@ function(S)
TryNextMethod();
fi;

cay := RightCayleyGraphSemigroup(S);
cay := OutNeighbours(RightCayleyDigraph(S));
deg := Size(S);
gen := EmptyPlist(Length(cay[1]));

Expand Down
12 changes: 6 additions & 6 deletions src/fropin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,9 @@ Obj fropin(Obj obj, Obj limit, Obj lookfunc, Obj looking) {
return data;
}

// Using the output of GABOW_SCC on the right and left Cayley graphs of a
// semigroup, the following function calculates the strongly connected
// components of the union of these two graphs.
// Using the output of DigraphStronglyConnectedComponents on the right and left
// Cayley graphs of a semigroup, the following function calculates the strongly
// connected components of the union of these two graphs.

Obj SCC_UNION_LEFT_RIGHT_CAYLEY_GRAPHS(Obj self, Obj scc1, Obj scc2) {
UInt* ptr;
Expand Down Expand Up @@ -416,9 +416,9 @@ Obj SCC_UNION_LEFT_RIGHT_CAYLEY_GRAPHS(Obj self, Obj scc1, Obj scc2) {
}

// <right> and <left> should be scc data structures for the right and left
// Cayley graphs of a semigroup, as produced by GABOW_SCC. This function find
// the H-classes of the semigroup from <right> and <left>. The method used is
// that described in:
// Cayley graphs of a semigroup, as produced by
// DigraphStronglyConnectedComponents. This function find the H-classes of the
// semigroup from <right> and <left>. The method used is that described in:
// http://www.liafa.jussieu.fr/~jep/PDF/Exposes/StAndrews.pdf

Obj FIND_HCLASSES(Obj self, Obj right, Obj left) {
Expand Down
27 changes: 14 additions & 13 deletions tst/standard/attr.tst
Original file line number Diff line number Diff line change
Expand Up @@ -342,22 +342,23 @@ gap> Size(MinimalDClass(s));
gap> MultiplicativeZero(s);
Transformation( [ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ] )
#T# attr: RightCayleyGraphSemigroup
#T# attr: RightCayleyDigraph
gap> S := Semigroup(PartialPerm([1, 2, 3], [1, 3, 4]),
> PartialPerm([1, 2, 3], [2, 5, 3]),
> PartialPerm([1, 2, 3], [4, 1, 2]),
> PartialPerm([1, 2, 3, 4], [2, 4, 1, 5]),
> PartialPerm([1, 3, 5], [5, 1, 3]));;
gap> RightCayleyGraphSemigroup(S);;
gap> Length(STRONGLY_CONNECTED_COMPONENTS_DIGRAPH(last)) = NrRClasses(S);
gap> digraph := RightCayleyDigraph(S);;
gap> Length(DigraphStronglyConnectedComponents(digraph).comps)
> = NrRClasses(S);
true
#T# attr: RightCayleyGraphSemigroup, infinite
gap> RightCayleyGraphSemigroup(FreeSemigroup(2));
#T# attr: RightCayleyDigraph, infinite
gap> RightCayleyDigraph(FreeSemigroup(2));
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
Error, no 2nd choice method found for `CayleyGraphSemigroup' on 1 arguments
Error, no 1st choice method found for `RightCayleyDigraph' on 1 arguments

#T# attr: LeftCayleyGraphSemigroup
#T# attr: LeftCayleyDigraph
gap> S := Monoid(BooleanMat([[1, 1, 1, 1, 1], [1, 0, 1, 0, 0],
> [1, 1, 0, 1, 0], [1, 1, 1, 1, 1],
> [1, 1, 0, 0, 0]]),
Expand All @@ -373,15 +374,15 @@ gap> S := Monoid(BooleanMat([[1, 1, 1, 1, 1], [1, 0, 1, 0, 0],
> BooleanMat([[1, 0, 0, 0, 1], [1, 0, 0, 0, 1],
> [0, 0, 0, 0, 1], [0, 1, 1, 0, 1],
> [1, 1, 1, 0, 1]]));;
gap> LeftCayleyGraphSemigroup(S);;
gap> Length(STRONGLY_CONNECTED_COMPONENTS_DIGRAPH(last)) = NrLClasses(S);
gap> digraph := LeftCayleyDigraph(S);;
gap> Length(DigraphStronglyConnectedComponents(digraph).comps)
> = NrLClasses(S);
true

#T# attr: RightCayleyGraphSemigroup, infinite
gap> LeftCayleyGraphSemigroup(FreeInverseSemigroup(2));
#T# attr: RightCayleyDigraph, infinite
gap> LeftCayleyDigraph(FreeInverseSemigroup(2));
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
Error, no 2nd choice method found for `CayleyGraphDualSemigroup' on 1 argument\
s
Error, no 1st choice method found for `LeftCayleyDigraph' on 1 arguments
#T# attr: IsomorphismReesMatrixSemigroup
gap> D := GreensDClassOfElement(Semigroup(
Expand Down
Loading

0 comments on commit 272aa00

Please sign in to comment.