diff --git a/doc/examples.xml b/doc/examples.xml
index 60a28de39..bad6a4062 100644
--- a/doc/examples.xml
+++ b/doc/examples.xml
@@ -419,6 +419,85 @@ gap> TriangularGridGraph(IsMutable, 3, 3);
<#/GAPDoc>
+<#GAPDoc Label="PancakeGraph">
+
+
+ A digraph.
+
+ If n is a positive integer, then this operation returns
+ the pancake graph with n! vertices and n!(n - 1)
+ directed edges. The nth pancake graph is the Cayley graph of the
+ symmetric group acting on [1 .. n] with respect to the
+ generating set consisting of the prefix reversals
. This generating
+ set consists of the permutations p2, p3, ...,
+ pn where ListPerm(pi, n) is the concatenation
+ of [i, i - 1 .. 1] and [i + 1 .. n].
+
+
+ If the optional first argument filt is not present, then is used by default.
+
+ See https://en.wikipedia.org/wiki/Pancake_graph for further
+ details.
+
+ D := PancakeGraph(5);
+
+gap> DigraphUndirectedGirth(D);
+6
+gap> ChromaticNumber(D);
+3
+gap> IsHamiltonianDigraph(D);
+true
+gap> IsCayleyDigraph(D);
+true
+gap> IsVertexTransitive(D);
+true]]>
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="BurntPancakeGraph">
+
+
+ A digraph.
+
+ If n is a positive integer, then this operation returns
+ the burnt pancake graph with n! vertices and n2^(n)n!
+ directed edges. The nth burnt pancake graph is the Cayley graph of the
+ hyperoctahedral group acting on [-n .. -1, 1 .. n] with respect to the
+ generating set consisting of the prefix reversals
, which are defined in exactly
+ the same way as in . The hyperoctahedral group consists of
+ permutations p acting on [-n .. -1, 1 .. n], where the image
+ of every point i in [-n .. -1, 1 .. n] is equal to the
+ negative of the image of -i under p.
+ GAP only works with permutations of positive integers and so BurntPancakeGraph returns
+ the Cayley graph of the hyperoctahedral group acting on [1 .. 2n] instead of
+ [-n .. -1, 1 .. n].
+ If the optional first argument filt is not present, then is used by default.
+
+ See https://en.wikipedia.org/wiki/Pancake_graph for further
+ details.
+
+ BurntPancakeGraph(3);
+
+gap> BurntPancakeGraph(4);
+
+gap> BurntPancakeGraph(5);
+
+gap> BurntPancakeGraph(IsMutableDigraph, 1);
+
+]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="StarGraph">
diff --git a/doc/z-chap2.xml b/doc/z-chap2.xml
index 210b4da68..aafca146c 100644
--- a/doc/z-chap2.xml
+++ b/doc/z-chap2.xml
@@ -100,6 +100,7 @@
<#Include Label="BookGraph">
<#Include Label="StackedBookGraph">
<#Include Label="BinaryTree">
+ <#Include Label="PancakeGraph">
diff --git a/gap/examples.gd b/gap/examples.gd
index 16ba7f4c5..e52fa7a41 100644
--- a/gap/examples.gd
+++ b/gap/examples.gd
@@ -98,3 +98,11 @@ DeclareOperation("StackedBookGraph", [IsFunction, IsPosInt, IsPosInt]);
DeclareConstructor("BinaryTreeCons", [IsDigraph, IsPosInt]);
DeclareOperation("BinaryTree", [IsPosInt]);
DeclareOperation("BinaryTree", [IsFunction, IsPosInt]);
+
+DeclareConstructor("PancakeGraphCons", [IsDigraph, IsPosInt]);
+DeclareOperation("PancakeGraph", [IsPosInt]);
+DeclareOperation("PancakeGraph", [IsFunction, IsPosInt]);
+
+DeclareConstructor("BurntPancakeGraphCons", [IsDigraph, IsPosInt]);
+DeclareOperation("BurntPancakeGraph", [IsPosInt]);
+DeclareOperation("BurntPancakeGraph", [IsFunction, IsPosInt]);
diff --git a/gap/examples.gi b/gap/examples.gi
index 59943d5a7..913e22c9d 100644
--- a/gap/examples.gi
+++ b/gap/examples.gi
@@ -793,3 +793,67 @@ depth -> BinaryTreeCons(IsImmutableDigraph, depth));
InstallMethod(BinaryTree, "for a function and a positive integer",
[IsFunction, IsPosInt], BinaryTreeCons);
+
+BindGlobal("DIGRAPHS_PrefixReversalGroup",
+function(n)
+ return Group(List([2 .. n], i -> PermList([i, i - 1 .. 1])), ());
+end);
+
+InstallMethod(PancakeGraphCons, "for IsMutableDigraph and pos int",
+[IsMutableDigraph, IsPosInt],
+{filt, n} -> CayleyDigraph(IsMutableDigraph, DIGRAPHS_PrefixReversalGroup(n)));
+
+InstallMethod(PancakeGraphCons, "for IsImmutableDigraph and pos int",
+[IsImmutableDigraph, IsPosInt],
+function(filt, n)
+ local D;
+ D := CayleyDigraph(IsImmutableDigraph, DIGRAPHS_PrefixReversalGroup(n));
+ SetIsMultiDigraph(D, false);
+ SetIsSymmetricDigraph(D, true);
+ SetIsHamiltonianDigraph(D, true);
+ return D;
+end);
+
+InstallMethod(PancakeGraph, "for a function and pos int",
+[IsFunction, IsPosInt], PancakeGraphCons);
+
+InstallMethod(PancakeGraph, "for a pos int",
+[IsPosInt], n -> PancakeGraphCons(IsImmutableDigraph, n));
+
+BindGlobal("DIGRAPHS_HyperoctahedralGroup",
+function(n)
+ local id, A, i;
+ if n = 1 then
+ return Group(());
+ fi;
+ id := [1 .. 2 * n];
+ A := [];
+ for i in [1 .. n] do
+ id{[1 .. i]} := [i + n, i - 1 + n .. 1 + n];
+ id{[n + 1 .. n + i]} := [i, i - 1 .. 1];
+ Add(A, PermList(id));
+ od;
+ return Group(A);
+end);
+
+InstallMethod(BurntPancakeGraphCons, "for IsMutableDigraph and pos int",
+[IsMutableDigraph, IsPosInt],
+{filt, n} -> CayleyDigraph(IsMutableDigraph, DIGRAPHS_HyperoctahedralGroup(n)));
+
+InstallMethod(BurntPancakeGraphCons, "for IsImmutableDigraph and pos int",
+[IsImmutableDigraph, IsPosInt],
+function(filt, n)
+ local D;
+ D := CayleyDigraph(IsImmutableDigraph, DIGRAPHS_HyperoctahedralGroup(n));
+ SetIsMultiDigraph(D, false);
+ SetIsSymmetricDigraph(D, true);
+ SetIsHamiltonianDigraph(D, true);
+ return D;
+end);
+
+InstallMethod(BurntPancakeGraph, "for a function and pos int",
+[IsFunction, IsPosInt], BurntPancakeGraphCons);
+
+InstallMethod(BurntPancakeGraph, "for a pos int",
+[IsPosInt], n -> BurntPancakeGraphCons(IsImmutableDigraph, n));
+
diff --git a/gap/grape.gd b/gap/grape.gd
index 9eab49d94..205a931c0 100644
--- a/gap/grape.gd
+++ b/gap/grape.gd
@@ -11,8 +11,13 @@
DeclareOperation("Graph", [IsDigraph]);
# Cayley digraphs
+DeclareConstructor("CayleyDigraphCons", [IsDigraph, IsGroup, IsList]);
+
DeclareOperation("CayleyDigraph", [IsGroup]);
DeclareOperation("CayleyDigraph", [IsGroup, IsList]);
+DeclareOperation("CayleyDigraph", [IsFunction, IsGroup]);
+DeclareOperation("CayleyDigraph", [IsFunction, IsGroup, IsList]);
+
DeclareAttribute("GroupOfCayleyDigraph", IsCayleyDigraph);
DeclareAttribute("SemigroupOfCayleyDigraph", IsCayleyDigraph);
DeclareAttribute("GeneratorsOfCayleyDigraph", IsCayleyDigraph);
diff --git a/gap/grape.gi b/gap/grape.gi
index 2a10a286e..5b5106bd7 100644
--- a/gap/grape.gi
+++ b/gap/grape.gi
@@ -91,37 +91,72 @@ function(imm, G, obj, act, adj)
return D;
end);
-InstallMethod(CayleyDigraph, "for a group with generators",
-[IsGroup, IsHomogeneousList],
-function(G, gens)
- local elts, adj, D, edge_labels;
-
+InstallMethod(CayleyDigraphCons,
+"for IsMutableDigraph, group, and list of elements",
+[IsMutableDigraph, IsGroup, IsHomogeneousList],
+function(filt, G, gens)
if not IsFinite(G) then
- ErrorNoReturn("the 1st argument must be a finite group,");
+ ErrorNoReturn("the 2nd argument (a group) must be finite");
elif not ForAll(gens, x -> x in G) then
- ErrorNoReturn("the 2nd argument must consist of elements of the ",
- "1st argument,");
+ ErrorNoReturn("the 3rd argument (a homog. list) must consist of ",
+ "elements of the 2nd argument (a group)");
fi;
+ return Digraph(IsMutableDigraph,
+ G,
+ AsList(G),
+ OnLeftInverse,
+ {x, y} -> x ^ -1 * y in gens);
+end);
+InstallMethod(CayleyDigraphCons,
+"for IsImmutableDigraph, group, and list of elements",
+[IsImmutableDigraph, IsGroup, IsHomogeneousList],
+function(filt, G, gens)
+ local D, edge_labels;
+ # This method is a duplicate of the one above because the method for Digraph
+ # sets some additional attributes if IsImmutableDigraph is passed as 1st
+ # argument, and so we don't want to make a mutable version of the returned
+ # graph, and then make it immutable, because then those attributes won't be
+ # set.
+
+ if not IsFinite(G) then
+ ErrorNoReturn("the 2nd argument (a group) must be finite");
+ elif not ForAll(gens, x -> x in G) then
+ ErrorNoReturn("the 3rd argument (a homog. list) must consist ",
+ "of elements of the 2nd argument (a list)");
+ fi;
# vertex i in the Cayley digraph corresponds to elts[i].
- elts := AsList(G);
- adj := {x, y} -> LeftQuotient(x, y) in gens;
+ D := Digraph(IsImmutableDigraph,
+ G,
+ AsList(G),
+ OnLeftInverse,
+ {x, y} -> LeftQuotient(x, y) in gens);
- D := Digraph(IsImmutableDigraph, G, elts, OnLeftInverse, adj);
SetFilterObj(D, IsCayleyDigraph);
SetGroupOfCayleyDigraph(D, G);
SetGeneratorsOfCayleyDigraph(D, gens);
- SetDigraphVertexLabels(D, elts);
+ SetDigraphVertexLabels(D, AsList(G));
# Out-neighbours of identity give the correspondence between edges & gens
- edge_labels := elts{OutNeighboursOfVertex(D, Position(elts, One(G)))};
+ edge_labels := AsList(G){OutNeighboursOfVertex(D,
+ Position(AsList(G), One(G)))};
SetDigraphEdgeLabels(D, ListWithIdenticalEntries(Size(G), edge_labels));
-
return D;
end);
+InstallMethod(CayleyDigraph, "for a group and list of elements",
+[IsGroup, IsHomogeneousList],
+{G, gens} -> CayleyDigraphCons(IsImmutableDigraph, G, gens));
+
+InstallMethod(CayleyDigraph, "for a filter and group with generators",
+[IsFunction, IsGroup, IsHomogeneousList], CayleyDigraphCons);
+
InstallMethod(CayleyDigraph, "for a group with generators",
[IsGroup and HasGeneratorsOfGroup],
-G -> CayleyDigraph(G, GeneratorsOfGroup(G)));
+G -> CayleyDigraphCons(IsImmutableDigraph, G, GeneratorsOfGroup(G)));
+
+InstallMethod(CayleyDigraph, "for a filter and group with generators",
+[IsFunction, IsGroup and HasGeneratorsOfGroup],
+{filt, G} -> CayleyDigraphCons(filt, G, GeneratorsOfGroup(G)));
InstallMethod(Graph, "for a digraph", [IsDigraph],
function(D)
diff --git a/tst/standard/examples.tst b/tst/standard/examples.tst
index 9b1f019ed..ef43338df 100644
--- a/tst/standard/examples.tst
+++ b/tst/standard/examples.tst
@@ -401,6 +401,33 @@ true
gap> BinaryTree(4);
+# PancakeGraph
+gap> D := PancakeGraph(3);
+
+gap> ChromaticNumber(D);
+2
+gap> IsVertexTransitive(D);
+true
+gap> DigraphUndirectedGirth(D);
+6
+gap> IsHamiltonianDigraph(D);
+true
+gap> D := PancakeGraph(IsMutableDigraph, 1);
+
+
+# BurntPancakeGraph
+gap> BurntPancakeGraph(3);
+
+gap> BurntPancakeGraph(4);
+
+gap> BurntPancakeGraph(5);
+
+gap> BurntPancakeGraph(IsMutableDigraph, 1);
+
+
#
gap> DIGRAPHS_StopTest();
gap> STOP_TEST("Digraphs package: standard/examples.tst", 0);
diff --git a/tst/standard/grape.tst b/tst/standard/grape.tst
index a121d7f68..65101cd74 100644
--- a/tst/standard/grape.tst
+++ b/tst/standard/grape.tst
@@ -26,6 +26,13 @@ true
gap> ForAll(DigraphEdges(digraph), e -> AsList(group)[e[1]]
> * DigraphEdgeLabel(digraph, e[1], e[2]) = AsList(group)[e[2]]);
true
+gap> digraph := CayleyDigraph(IsMutableDigraph, group);
+
+gap> digraph := CayleyDigraph(IsMutableDigraph, FreeGroup(1));
+Error, the 2nd argument (a group) must be finite
+gap> digraph := CayleyDigraph(IsMutableDigraph, group, [(2, 3)]);
+Error, the 3rd argument (a homog. list) must consist of elements of the 2nd ar\
+gument (a group)
gap> group := DihedralGroup(IsPermGroup, 8);
Group([ (1,2,3,4), (2,4) ])
gap> digraph := CayleyDigraph(group);
@@ -41,10 +48,11 @@ true
gap> GeneratorsOfCayleyDigraph(digraph);
[ () ]
gap> digraph := CayleyDigraph(group, [(1, 2, 3, 4), (2, 5)]);
-Error, the 2nd argument must consist of elements of the 1st argument,
+Error, the 3rd argument (a homog. list) must consist of elements of the 2nd ar\
+gument (a list)
gap> group := FreeGroup(2);;
gap> digraph := CayleyDigraph(group);
-Error, the 1st argument must be a finite group,
+Error, the 2nd argument (a group) must be finite
# CayleyDigraph: check edge labels
#
@@ -260,6 +268,23 @@ gap> if DIGRAPHS_IsGrapeLoaded then
gap> Digraph(SymmetricGroup(3), [1, 2, 3], OnPoints, {x, y} -> x <> y);
+#
+gap> Digraph(IsSemigroup, SymmetricGroup(3), [1, 2, 3], OnPoints,
+> {x, y} -> x <> y);
+Error, must be IsMutableDigraph or IsImmutableDigraph
+
+# Code coverage
+gap> D := Digraph([[1, 1]]);
+
+gap> Graph(D);
+rec( adjacencies := [ [ 1 ] ], group := Group(()), isGraph := true,
+ names := [ 1 ], order := 1, representatives := [ 1 ],
+ schreierVector := [ -1 ] )
+gap> D := CompleteDigraph(IsMutableDigraph, 5);;
+gap> HasDigraphGroup(D);
+false
+gap> Graph(D);;
+
#
gap> DIGRAPHS_StopTest();
gap> STOP_TEST("Digraphs package: standard/grape.tst", 0);