Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PancakeGraph #403

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/>
flsmith marked this conversation as resolved.
Show resolved Hide resolved

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there documentation for the burnt pancake graph?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LRacine I have created a pull request on James's branch and if you would like to have a look I'd love to hear your comments :)
james-d-mitchell#14

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marinaanagno Thank you, doing so now

<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]);

james-d-mitchell marked this conversation as resolved.
Show resolved Hide resolved
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);
wilfwilson marked this conversation as resolved.
Show resolved Hide resolved
<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
wilfwilson marked this conversation as resolved.
Show resolved Hide resolved

# 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);