Skip to content

Commit

Permalink
examples: add pancakes
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-mitchell committed Jul 28, 2021
1 parent 952410b commit 2079807
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 17 deletions.
79 changes: 79 additions & 0 deletions doc/examples.xml
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,85 @@ gap> TriangularGridGraph(IsMutable, 3, 3);
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="PancakeGraph">
<ManSection>
<Oper Name="PancakeGraph" Arg="[filt, ]n"/>
<Returns>A digraph.</Returns>
<Description>
If <A>n</A> is a positive integer, then this operation returns
the <E>pancake graph</E> with <M>n!</M> vertices and <M>n!(n - 1)</M>
directed edges. The <M>n</M>th pancake graph is the Cayley graph of the
symmetric group acting on <C>[1 .. <A>n</A>]</C> with respect to the
generating set consisting of the <Q>prefix reversals</Q>. This generating
set consists of the permutations <C>p2</C>, <C>p3</C>, ...,
<C>p<A>n</A></C> where <C>ListPerm(pi, <A>n</A>)</C> is the concatenation
of <C>[i, i - 1 .. 1]</C> and <C>[i + 1 .. <A>n</A>]</C>.
<P/>

If the optional first argument <A>filt</A> is not present, then <Ref
Filt="IsImmutableDigraph"/> is used by default.<P/>

See <URL>https://en.wikipedia.org/wiki/Pancake_graph</URL> for further
details.

<Example><![CDATA[
gap> D := PancakeGraph(5);
<immutable Hamiltonian connected symmetric digraph with 120 vertices, \
480 edges>
gap> DigraphUndirectedGirth(D);
6
gap> ChromaticNumber(D);
3
gap> IsHamiltonianDigraph(D);
true
gap> IsCayleyDigraph(D);
true
gap> IsVertexTransitive(D);
true]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="BurntPancakeGraph">
<ManSection>
<Oper Name="BurntPancakeGraph" Arg="[filt, ]n"/>
<Returns>A digraph.</Returns>
<Description>
If <A>n</A> is a positive integer, then this operation returns
the <E>burnt pancake graph</E> with <M>n!</M> vertices and <M>n2^(n)n!</M>
directed edges. The <M>n</M>th burnt pancake graph is the Cayley graph of the
hyperoctahedral group acting on <C>[<A>-n</A> .. -1, 1 .. <A>n</A>]</C> with respect to the
generating set consisting of the <Q>prefix reversals</Q>, which are defined in exactly
the same way as in <Ref Oper="PancakeGraph"/>. The hyperoctahedral group consists of
permutations <M>p</M> acting on <C>[<A>-n</A> .. -1, 1 .. <A>n</A>]</C>, where the image
of every point <M>i</M> in <C>[<A>-n</A> .. -1, 1 .. <A>n</A>]</C> is equal to the
negative of the image of <M>-i</M> under <M>p</M>.
GAP only works with permutations of positive integers and so <C>BurntPancakeGraph</C> returns
the Cayley graph of the hyperoctahedral group acting on <C>[1 .. <A>2n</A>]</C> instead of
<C>[<A>-n</A> .. -1, 1 .. <A>n</A>]</C>.
If the optional first argument <A>filt</A> is not present, then <Ref
Filt="IsImmutableDigraph"/> is used by default.<P/>

See <URL>https://en.wikipedia.org/wiki/Pancake_graph</URL> for further
details.

<Example><![CDATA[
gap> BurntPancakeGraph(3);
<immutable Hamiltonian connected symmetric digraph with 48 vertices, 144 edges\
>
gap> BurntPancakeGraph(4);
<immutable Hamiltonian connected symmetric digraph with 384 vertices, 1536 edg\
es>
gap> BurntPancakeGraph(5);
<immutable Hamiltonian connected symmetric digraph with 3840 vertices, 19200 e\
dges>
gap> BurntPancakeGraph(IsMutableDigraph, 1);
<mutable digraph with 1 vertex, 1 edge>
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="StarGraph">
<ManSection>
<Oper Name="StarGraph" Arg="[filt, ]k"/>
Expand Down
1 change: 1 addition & 0 deletions doc/z-chap2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
<#Include Label="BookGraph">
<#Include Label="StackedBookGraph">
<#Include Label="BinaryTree">
<#Include Label="PancakeGraph">
</Section>

</Chapter>
8 changes: 8 additions & 0 deletions gap/examples.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
64 changes: 64 additions & 0 deletions gap/examples.gi
Original file line number Diff line number Diff line change
Expand Up @@ -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));

5 changes: 5 additions & 0 deletions gap/grape.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
65 changes: 50 additions & 15 deletions gap/grape.gi
Original file line number Diff line number Diff line change
Expand Up @@ -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 <G> 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 <gens> 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)
Expand Down
27 changes: 27 additions & 0 deletions tst/standard/examples.tst
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,33 @@ true
gap> BinaryTree(4);
<immutable digraph with 15 vertices, 14 edges>
# PancakeGraph
gap> D := PancakeGraph(3);
<immutable Hamiltonian connected symmetric digraph with 6 vertices, 12 edges>
gap> ChromaticNumber(D);
2
gap> IsVertexTransitive(D);
true
gap> DigraphUndirectedGirth(D);
6
gap> IsHamiltonianDigraph(D);
true
gap> D := PancakeGraph(IsMutableDigraph, 1);
<mutable empty digraph with 1 vertex>
# BurntPancakeGraph
gap> BurntPancakeGraph(3);
<immutable Hamiltonian connected symmetric digraph with 48 vertices, 144 edges\
>
gap> BurntPancakeGraph(4);
<immutable Hamiltonian connected symmetric digraph with 384 vertices, 1536 edg\
es>
gap> BurntPancakeGraph(5);
<immutable Hamiltonian connected symmetric digraph with 3840 vertices, 19200 e\
dges>
gap> BurntPancakeGraph(IsMutableDigraph, 1);
<mutable digraph with 1 vertex, 1 edge>
#
gap> DIGRAPHS_StopTest();
gap> STOP_TEST("Digraphs package: standard/examples.tst", 0);
29 changes: 27 additions & 2 deletions tst/standard/grape.tst
Original file line number Diff line number Diff line change
Expand Up @@ -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);
<mutable digraph with 8 vertices, 24 edges>
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);
Expand All @@ -41,10 +48,11 @@ true
gap> GeneratorsOfCayleyDigraph(digraph);
[ () ]
gap> digraph := CayleyDigraph(group, [(1, 2, 3, 4), (2, 5)]);
Error, the 2nd argument <gens> 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 <G> must be a finite group,
Error, the 2nd argument (a group) must be finite

# CayleyDigraph: check edge labels
#
Expand Down Expand Up @@ -260,6 +268,23 @@ gap> if DIGRAPHS_IsGrapeLoaded then
gap> Digraph(SymmetricGroup(3), [1, 2, 3], OnPoints, {x, y} -> x <> y);
<immutable digraph with 3 vertices, 6 edges>

#
gap> Digraph(IsSemigroup, SymmetricGroup(3), [1, 2, 3], OnPoints,
> {x, y} -> x <> y);
Error, <imm> must be IsMutableDigraph or IsImmutableDigraph

# Code coverage
gap> D := Digraph([[1, 1]]);
<immutable multidigraph with 1 vertex, 2 edges>
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);

0 comments on commit 2079807

Please sign in to comment.