|
#############################################################################
##
## examples.gi
## Copyright (C) 2019 Murray T. Whyte
## James D. Mitchell
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##
# This file contains constructions of certain types of digraphs from parameters
InstallMethod(EmptyDigraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsInt],
function(_, n)
if n < 0 then
ErrorNoReturn("the argument <n> must be a non-negative integer,");
fi;
return ConvertToMutableDigraphNC(List([1 .. n], x -> []));
end);
InstallMethod(EmptyDigraphCons, "for IsImmutableDigraph and an integer",
[IsImmutableDigraph, IsInt],
function(_, n)
local D;
if n < 0 then
ErrorNoReturn("the argument <n> must be a non-negative integer,");
fi;
D := MakeImmutable(EmptyDigraph(IsMutableDigraph, n));
SetIsEmptyDigraph(D, true);
SetIsMultiDigraph(D, false);
SetAutomorphismGroup(D, SymmetricGroup(n));
return D;
end);
InstallMethod(EmptyDigraph, "for an integer", [IsInt],
n -> EmptyDigraphCons(IsImmutableDigraph, n));
InstallMethod(EmptyDigraph, "for a function and an integer",
[IsFunction, IsInt], EmptyDigraphCons);
InstallMethod(CompleteBipartiteDigraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local src, ran, count, k, i, j;
src := EmptyPlist(2 * m * n);
ran := EmptyPlist(2 * m * n);
count := 0;
for i in [1 .. m] do
for j in [1 .. n] do
count := count + 1;
src[count] := i;
ran[count] := m + j;
k := (m * n) + ((j - 1) * m) + i; # Ensures that src is sorted
src[k] := m + j;
ran[k] := i;
od;
od;
return DigraphNC(IsMutableDigraph, rec(DigraphNrVertices := m + n,
DigraphSource := src,
DigraphRange := ran));
end);
InstallMethod(CompleteBipartiteDigraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D, aut;
if Maximum(m, n) = 1 then
return CompleteDigraph(IsImmutableDigraph, 2);
fi;
D := MakeImmutable(CompleteBipartiteDigraph(IsMutableDigraph, m, n));
SetIsSymmetricDigraph(D, true);
SetDigraphNrEdges(D, 2 * m * n);
SetIsCompleteBipartiteDigraph(D, true);
if m = n then
aut := WreathProduct(SymmetricGroup([1 .. m]), Group((1, m + 1)));
elif m = 1 then
aut := SymmetricGroup([2 .. n + 1]);
else
aut := DirectProduct(SymmetricGroup([1 .. m]),
SymmetricGroup([m + 1 .. m + n]));
fi;
SetAutomorphismGroup(D, aut);
SetIsPlanarDigraph(D, m <= 2 or n <= 2);
return D;
end);
InstallMethod(CompleteBipartiteDigraph, "for two positive integers",
[IsPosInt, IsPosInt],
{m, n} -> CompleteBipartiteDigraph(IsImmutableDigraph, m, n));
InstallMethod(CompleteBipartiteDigraph,
"for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
CompleteBipartiteDigraphCons);
# For input list <sizes> of length nr_parts, CompleteMultipartiteDigraph
# returns the complete multipartite digraph containing parts 1, 2, ..., n
# of orders sizes[1], sizes[2], ..., sizes[n], where each vertex is adjacent
# to every other not contained in the same part.
InstallMethod(CompleteMultipartiteDigraphCons,
"for IsMutableDigraph and a list",
[IsMutableDigraph, IsList],
function(_, list)
local M, N, out, start, next, i, v;
if not ForAll(list, IsPosInt) then
ErrorNoReturn("the argument <list> must be a list of positive ",
"integers,");
fi;
M := Length(list);
N := Sum(list);
if M <= 1 then
return EmptyDigraph(IsMutableDigraph, N);
fi;
out := EmptyPlist(N);
start := 1;
for i in [1 .. M] do
next := Concatenation([1 .. start - 1], [start + list[i] .. N]);
for v in [start .. start + list[i] - 1] do
out[v] := next;
od;
start := start + list[i];
od;
return ConvertToMutableDigraphNC(out);
end);
InstallMethod(CompleteMultipartiteDigraphCons,
"for IsImmutableDigraph and a list",
[IsImmutableDigraph, IsList],
function(_, list)
local D;
D := MakeImmutable(CompleteMultipartiteDigraph(IsMutableDigraph, list));
SetIsEmptyDigraph(D, Length(list) <= 1);
SetIsSymmetricDigraph(D, true);
SetIsCompleteBipartiteDigraph(D, Length(list) = 2);
SetIsCompleteMultipartiteDigraph(D, Length(list) > 1);
if Length(list) = 2 then
SetDigraphBicomponents(D, [[1 .. list[1]], [list[1] + 1 .. Sum(list)]]);
fi;
return D;
end);
InstallMethod(CompleteMultipartiteDigraph, "for a list", [IsList],
list -> CompleteMultipartiteDigraphCons(IsImmutableDigraph, list));
InstallMethod(CompleteMultipartiteDigraph, "for a function and a list",
[IsFunction, IsList], CompleteMultipartiteDigraphCons);
InstallMethod(ChainDigraphCons, "for IsMutableDigraph and a positive integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local list, i;
list := EmptyPlist(n);
for i in [1 .. n - 1] do
list[i] := [i + 1];
od;
list[n] := [];
return ConvertToMutableDigraphNC(list);
end);
InstallMethod(ChainDigraphCons,
"for IsImmutableDigraph and a positive integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(ChainDigraphCons(IsMutableDigraph, n));
SetIsChainDigraph(D, true);
SetIsTransitiveDigraph(D, n = 2);
SetDigraphHasLoops(D, false);
SetIsAcyclicDigraph(D, true);
SetIsMultiDigraph(D, false);
SetDigraphNrEdges(D, n - 1);
SetIsConnectedDigraph(D, true);
SetIsStronglyConnectedDigraph(D, false);
SetIsFunctionalDigraph(D, false);
SetAutomorphismGroup(D, Group(()));
return D;
end);
InstallMethod(ChainDigraph, "for a function and a positive integer",
[IsFunction, IsPosInt],
ChainDigraphCons);
InstallMethod(ChainDigraph, "for a positive integer", [IsPosInt],
n -> ChainDigraphCons(IsImmutableDigraph, n));
InstallMethod(CompleteDigraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsInt],
function(_, n)
local verts, out, i;
if n < 0 then
ErrorNoReturn("the argument <n> must be a non-negative integer,");
elif n = 0 then
return EmptyDigraph(IsMutableDigraph, 0);
fi;
verts := [1 .. n];
out := EmptyPlist(n);
for i in verts do
out[i] := Concatenation([1 .. (i - 1)], [(i + 1) .. n]);
od;
return ConvertToMutableDigraphNC(out);
end);
InstallMethod(CompleteDigraphCons, "for IsImmutableDigraph and an integer",
[IsImmutableDigraph, IsInt],
function(_, n)
local D;
D := MakeImmutable(CompleteDigraphCons(IsMutableDigraph, n));
SetIsEmptyDigraph(D, n <= 1);
SetIsAcyclicDigraph(D, n <= 1);
if n > 1 then
SetIsAntisymmetricDigraph(D, false);
fi;
SetIsMultiDigraph(D, false);
SetIsCompleteDigraph(D, true);
SetIsCompleteBipartiteDigraph(D, n = 2);
SetIsCompleteMultipartiteDigraph(D, n > 1);
SetAutomorphismGroup(D, SymmetricGroup(n));
SetIsPlanarDigraph(D, n <= 4);
return D;
end);
InstallMethod(CompleteDigraph, "for a function and an integer",
[IsFunction, IsInt], CompleteDigraphCons);
InstallMethod(CompleteDigraph, "for an integer", [IsInt],
n -> CompleteDigraphCons(IsImmutableDigraph, n));
InstallMethod(CycleDigraphCons, "for IsMutableDigraph and a positive integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local list, i;
list := EmptyPlist(n);
for i in [1 .. n - 1] do
list[i] := [i + 1];
od;
list[n] := [1];
return ConvertToMutableDigraphNC(list);
end);
InstallMethod(CycleDigraphCons,
"for IsImmutableDigraph and a positive integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(CycleDigraphCons(IsMutableDigraph, n));
SetIsAcyclicDigraph(D, false);
SetIsCycleDigraph(D, true);
SetIsEmptyDigraph(D, false);
SetIsMultiDigraph(D, false);
SetDigraphNrEdges(D, n);
SetIsTournament(D, n = 3);
SetIsTransitiveDigraph(D, n = 1);
SetAutomorphismGroup(D, CyclicGroup(IsPermGroup, n));
SetDigraphHasLoops(D, n = 1);
SetIsBipartiteDigraph(D, n mod 2 = 0);
if n > 1 then
SetChromaticNumber(D, 2 + (n mod 2));
fi;
return D;
end);
InstallMethod(CycleDigraph, "for a function and a positive integer",
[IsFunction, IsPosInt], CycleDigraphCons);
InstallMethod(CycleDigraph, "for a positive integer", [IsPosInt],
n -> CycleDigraphCons(IsImmutableDigraph, n));
InstallMethod(JohnsonDigraphCons,
"for IsMutableDigraph and two integers",
[IsMutableDigraph, IsInt, IsInt],
function(_, n, k)
if n < 0 or k < 0 then
ErrorNoReturn("the arguments <n> and <k> must be ",
"non-negative integers,");
fi;
return Digraph(IsMutableDigraph,
Combinations([1 .. n], k),
{u, v} -> Length(Intersection(u, v)) = k - 1);
end);
InstallMethod(JohnsonDigraphCons,
"for IsImmutableDigraph, integer, integer",
[IsImmutableDigraph, IsInt, IsInt],
function(_, n, k)
local D;
D := MakeImmutable(JohnsonDigraphCons(IsMutableDigraph, n, k));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(JohnsonDigraph, "for a function, integer, integer",
[IsFunction, IsInt, IsInt],
JohnsonDigraphCons);
InstallMethod(JohnsonDigraph, "for integer, integer", [IsInt, IsInt],
{n, k} -> JohnsonDigraphCons(IsImmutableDigraph, n, k));
InstallMethod(PetersenGraphCons, "for IsMutableDigraph", [IsMutableDigraph],
function(_)
local mat;
mat := [[0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 1, 0, 0, 0, 1, 0],
[1, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 1, 1],
[0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
[0, 0, 0, 1, 0, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 1, 1, 0, 0]];
# the above is an adjacency matrix of the Petersen graph
return DigraphByAdjacencyMatrix(IsMutableDigraph, mat);
end);
InstallMethod(PetersenGraphCons, "for IsImmutableDigraph",
[IsImmutableDigraph],
_ -> MakeImmutable(PetersenGraphCons(IsMutableDigraph)));
InstallMethod(PetersenGraph, "for a function", [IsFunction],
PetersenGraphCons);
InstallMethod(PetersenGraph, [], {} -> PetersenGraphCons(IsImmutableDigraph));
InstallMethod(GeneralisedPetersenGraphCons,
"for IsMutableDigraph, positive integer, integer",
[IsMutableDigraph, IsPosInt, IsInt],
function(filt, n, k)
local D, i;
if k < 0 then
ErrorNoReturn("the argument <k> must be a non-negative integer,");
elif k > n / 2 then
ErrorNoReturn("the argument <k> must be less than or equal to <n> / 2,");
fi;
D := EmptyDigraph(filt, 2 * n);
for i in [1 .. n] do
if i <> n then
DigraphAddEdge(D, [i, i + 1]);
else
DigraphAddEdge(D, [n, 1]);
fi;
DigraphAddEdge(D, [i, n + i]);
if n + i + k <= 2 * n then
DigraphAddEdge(D, [n + i, n + i + k]);
else
DigraphAddEdge(D, [n + i, ((n + i + k) mod n) + n]);
fi;
od;
return DigraphSymmetricClosure(D);
end);
InstallMethod(GeneralisedPetersenGraphCons,
"for IsImmutableDigraph, positive integer, int",
[IsImmutableDigraph, IsPosInt, IsInt],
function(_, n, k)
local D;
D := MakeImmutable(GeneralisedPetersenGraphCons(IsMutableDigraph, n, k));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(GeneralisedPetersenGraph,
"for a function, positive integer, integer", [IsFunction, IsPosInt, IsInt],
GeneralisedPetersenGraphCons);
InstallMethod(GeneralisedPetersenGraph, "for a positive integer and integer",
[IsPosInt, IsInt],
{n, k} -> GeneralisedPetersenGraphCons(IsImmutableDigraph, n, k));
InstallMethod(LollipopGraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := DigraphDisjointUnion(CompleteDigraph(IsMutableDigraph, m),
DigraphSymmetricClosure(ChainDigraph(IsMutableDigraph, n)));
DigraphAddEdges(D, [[m, m + 1], [m + 1, m]]);
return D;
end);
InstallMethod(LollipopGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := MakeImmutable(LollipopGraphCons(IsMutableDigraph, m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsConnectedDigraph(D, true);
SetDigraphHasLoops(D, false);
SetChromaticNumber(D, Maximum(2, m));
SetCliqueNumber(D, Maximum(2, m));
if m <= 2 then
SetDigraphUndirectedGirth(D, infinity);
else
SetDigraphUndirectedGirth(D, 3);
fi;
return D;
end);
InstallMethod(LollipopGraph, "for two pos int",
[IsPosInt, IsPosInt],
{m, n} -> LollipopGraphCons(IsImmutableDigraph, m, n));
InstallMethod(LollipopGraph, "for a function and two pos int",
[IsFunction, IsPosInt, IsPosInt],
{filt, m, n} -> LollipopGraphCons(filt, m, n));
# This function constructs an n by k square grid graph.
InstallMethod(SquareGridGraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D1, D2;
D1 := DigraphSymmetricClosure(ChainDigraph(IsMutableDigraph, n));
D2 := DigraphSymmetricClosure(ChainDigraph(IsMutableDigraph, k));
return DigraphCartesianProduct(D1, D2);
end);
InstallMethod(SquareGridGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D;
D := MakeImmutable(SquareGridGraphCons(IsMutableDigraph, n, k));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsBipartiteDigraph(D, n > 1 or k > 1);
SetIsPlanarDigraph(D, true);
SetIsConnectedDigraph(D, true);
SetDigraphHasLoops(D, false);
return D;
end);
InstallMethod(SquareGridGraph, "for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
SquareGridGraphCons);
InstallMethod(SquareGridGraph, "for two integers", [IsPosInt, IsPosInt],
{n, k} -> SquareGridGraphCons(IsImmutableDigraph, n, k));
# This function constructs an n by k triangular grid graph. It is the same as
# the square grid graph except that it adds diagonal edges.
InstallMethod(TriangularGridGraphCons,
"for IsMutableDigraph and two integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D, a, b, i, j;
D := SquareGridGraph(IsMutableDigraph, n, k);
for i in [1 .. (k - 1)] do
for j in [1 .. (n - 1)] do
a := ((i - 1) * n) + j + 1;
b := ((i - 1) * n) + j + n;
DigraphAddEdge(D, a, b);
DigraphAddEdge(D, b, a);
od;
od;
return D;
end);
InstallMethod(TriangularGridGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D;
D := MakeImmutable(TriangularGridGraphCons(IsMutableDigraph, n, k));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsBipartiteDigraph(D, n * k in Difference([n, k], [1]));
SetIsPlanarDigraph(D, true);
SetIsConnectedDigraph(D, true);
SetDigraphHasLoops(D, false);
return D;
end);
InstallMethod(TriangularGridGraph, "for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
TriangularGridGraphCons);
InstallMethod(TriangularGridGraph, "for two positive integers",
[IsPosInt, IsPosInt],
{n, k} -> TriangularGridGraphCons(IsImmutableDigraph, n, k));
InstallMethod(StarGraphCons, "for IsMutableDigraph and a positive integer",
[IsMutableDigraph, IsPosInt],
function(_, k)
if k = 1 then
return EmptyDigraph(IsMutable, 1);
fi;
return CompleteBipartiteDigraph(IsMutableDigraph, 1, k - 1);
end);
InstallMethod(StarGraph, "for a function and a positive integer",
[IsFunction, IsPosInt],
StarGraphCons);
InstallMethod(StarGraph, "for integer", [IsPosInt],
{k} -> StarGraphCons(IsImmutableDigraph, k));
InstallMethod(StarGraphCons,
"for IsImmutableDigraph and a positive integer",
[IsImmutableDigraph, IsPosInt],
function(_, k)
local D;
D := MakeImmutable(StarGraph(IsMutableDigraph, k));
SetIsMultiDigraph(D, false);
SetIsEmptyDigraph(D, k = 1);
SetIsCompleteBipartiteDigraph(D, k > 1);
return D;
end);
InstallMethod(KingsGraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D, a, b, i, j;
D := TriangularGridGraph(IsMutableDigraph, n, k);
for i in [1 .. (k - 1)] do
for j in [1 .. (n - 1)] do
a := ((i - 1) * n) + j;
b := ((i - 1) * n) + j + n + 1;
DigraphAddEdge(D, a, b);
DigraphAddEdge(D, b, a);
od;
od;
return D;
end);
InstallMethod(KingsGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D;
D := MakeImmutable(KingsGraphCons(IsMutableDigraph, n, k));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsConnectedDigraph(D, true);
SetIsBipartiteDigraph(D, n * k in Difference([n, k], [1]));
SetIsPlanarDigraph(D, n <= 2 or k <= 2 or n = 3 and k = 3);
SetDigraphHasLoops(D, false);
return D;
end);
InstallMethod(KingsGraph, "for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
KingsGraphCons);
InstallMethod(KingsGraph, "two positive integers",
[IsPosInt, IsPosInt],
{n, k} -> KingsGraphCons(IsImmutableDigraph, n, k));
InstallMethod(QueensGraphCons,
"for IsMutableDigraph and two integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D1, D2, labels;
D1 := RooksGraphCons(IsMutableDigraph, m, n);
D2 := BishopsGraphCons(IsMutableDigraph, m, n);
labels := DigraphVertexLabels(D1);
DigraphEdgeUnion(D1, D2);
SetDigraphVertexLabels(D1, labels);
return D1;
end);
InstallMethod(QueensGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := MakeImmutable(QueensGraphCons(IsMutableDigraph, m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsConnectedDigraph(D, true);
return D;
end);
InstallMethod(QueensGraph,
"for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
QueensGraphCons);
InstallMethod(QueensGraph, "for two positive integers",
[IsPosInt, IsPosInt],
{m, n} -> QueensGraphCons(IsImmutableDigraph, m, n));
InstallMethod(RooksGraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D1, D2;
D1 := CompleteDigraph(IsMutableDigraph, m);
D2 := CompleteDigraph(n);
return DigraphCartesianProduct(D1, D2);
end);
InstallMethod(RooksGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := MakeImmutable(RooksGraphCons(IsMutableDigraph, m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsConnectedDigraph(D, true);
SetIsRegularDigraph(D, true);
SetIsPlanarDigraph(D, m + n < 6);
return D;
end);
InstallMethod(RooksGraph,
"for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
RooksGraphCons);
InstallMethod(RooksGraph, "for two positive integers",
[IsPosInt, IsPosInt],
{m, n} -> RooksGraphCons(IsImmutableDigraph, m, n));
InstallMethod(BishopsGraphCons,
"for IsMutableDigraph, a string and two positive integers",
[IsMutableDigraph, IsString, IsPosInt, IsPosInt],
function(_, color, m, n)
local both, dark, nr, D1, D2, upL, inc, step, labels, v, not_final_row, i, j,
is_dark_square, range;
if not color in ["dark", "light", "both"] then
DError(["the argument <color> must be {}, {}, or {}"],
"\"dark\"", "\"light\"", "\"both\"");
fi;
# Set up booleans for whether to include dark and/or light squares
both := color = "both";
dark := both or color = "dark";
# Set up two empty digraphs to hold the differently oriented diagonal edges
# "both" => return a digraph with all m * n vertices, else return only half
if both then
nr := m * n;
else
nr := EuclideanQuotient(m * n, 2);
if dark and IsOddInt(m) and IsOddInt(n) then
nr := nr + 1;
fi;
fi;
D1 := EmptyDigraph(IsMutableDigraph, nr); # bottom left/top right diagonal
D2 := EmptyDigraph(IsMutableDigraph, nr); # bottom right/top left diagonal
# Set up a function for computing the increments from a vertex to its top-left
# and top-right neighbours, based on the current position in the grid.
if both then
upL := {v, j, is_dark_square} -> v + m - 1;
inc := 2;
else
if IsOddInt(m) then
step := EuclideanQuotient(m - 1, 2);
upL := {v, j, is_dark_square} -> v + step;
else
step := m / 2;
upL := function(v, j, is_dark_square)
if IsOddInt(j) = is_dark_square then
return v + step - 1;
else
return v + step;
fi;
end;
fi;
inc := 1;
fi;
labels := [];
v := 0;
for j in [1 .. n] do
not_final_row := j < n;
is_dark_square := IsOddInt(j);
for i in [1 .. m] do
# Decide whether the square [i, j] appears in the digraph
if both or (dark = is_dark_square) then
Add(labels, [i, j]);
v := v + 1;
if not_final_row then # Add edges from v to its neighbours in next row
range := upL(v, j, is_dark_square);
if i > 1 then
DigraphAddEdge(D2, v, range); # Diagonally up+left
fi;
if i < m then
DigraphAddEdge(D1, v, range + inc); # Diagonally up+right
fi;
fi;
fi;
is_dark_square := not is_dark_square;
od;
od;
Assert(0, v = nr);
DigraphTransitiveClosure(D1);
DigraphTransitiveClosure(D2);
DigraphEdgeUnion(D1, D2);
SetDigraphVertexLabels(D1, labels);
return DigraphSymmetricClosure(D1);
end);
InstallMethod(BishopsGraphCons,
"for IsImmutableDigraph, a string and two positive integers",
[IsImmutableDigraph, IsString, IsPosInt, IsPosInt],
function(_, color, m, n)
local D;
D := MakeImmutable(BishopsGraphCons(IsMutableDigraph, color, m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsConnectedDigraph(D, color <> "both" and (m > 1 or n > 1));
return D;
end);
InstallMethod(BishopsGraph,
"for a function, a string and two positive integers",
[IsFunction, IsString, IsPosInt, IsPosInt],
BishopsGraphCons);
InstallMethod(BishopsGraph, "for a string and two positive integers",
[IsString, IsPosInt, IsPosInt],
{color, m, n} -> BishopsGraphCons(IsImmutableDigraph, color, m, n));
InstallMethod(BishopsGraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
{_, m, n} -> BishopsGraphCons(IsMutableDigraph, "both", m, n));
InstallMethod(BishopsGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := MakeImmutable(BishopsGraphCons(IsMutableDigraph, "both", m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsConnectedDigraph(D, m * n = 1);
return D;
end);
InstallMethod(BishopsGraph,
"for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
BishopsGraphCons);
InstallMethod(BishopsGraph, "for two positive integers",
[IsPosInt, IsPosInt],
{m, n} -> BishopsGraphCons(IsImmutableDigraph, m, n));
InstallMethod(KnightsGraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D, moves, labels, v, r, s, range, j, i, move;
D := EmptyDigraph(IsMutableDigraph, m * n);
moves := [[2, 1], [-2, 1], [1, 2], [-1, 2]];
labels := [];
v := 0;
for j in [1 .. n] do
for i in [1 .. m] do
Add(labels, [i, j]); # Considering moves up from [i,j] or down to [i,j]
v := v + 1; # Square [i,j] <-> vertex v
for move in moves do
r := i + move[1];
s := j + move[2];
if r in [1 .. m] and s <= n then # Does the move leave us on the board?
range := (s - 1) * m + r;
DigraphAddEdge(D, v, range);
DigraphAddEdge(D, range, v);
fi;
od;
od;
od;
SetDigraphVertexLabels(D, labels);
return D;
end);
InstallMethod(KnightsGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := MakeImmutable(KnightsGraphCons(IsMutableDigraph, m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsConnectedDigraph(D, m > 2 and n > 2 and not (m = 3 and n = 3));
return D;
end);
InstallMethod(KnightsGraph, "for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
KnightsGraphCons);
InstallMethod(KnightsGraph, "for two positive integers", [IsPosInt, IsPosInt],
{m, n} -> KnightsGraphCons(IsImmutableDigraph, m, n));
InstallMethod(HaarGraphCons,
"for IsMutableDigraph and a positive integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local m, binaryList, D, i, j;
m := Log(n, 2) + 1;
binaryList := DIGRAPHS_BlistNumber(n + 1, m);
D := EmptyDigraph(IsMutableDigraph, 2 * m);
for i in [1 .. m] do
for j in [1 .. m] do
if binaryList[((j - i) mod m) + 1] then
DigraphAddEdge(D, [i, m + j]);
fi;
od;
od;
return DigraphSymmetricClosure(D);
end);
InstallMethod(HaarGraphCons,
"for IsImmutableDigraph and a positive integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(HaarGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsVertexTransitive(D, true);
SetIsBipartiteDigraph(D, true);
SetIsCompleteDigraph(D, n = 1);
return D;
end);
InstallMethod(HaarGraph, "for a function and a positive integer",
[IsFunction, IsPosInt],
HaarGraphCons);
InstallMethod(HaarGraph, "for a positive integer", [IsPosInt],
{n} -> HaarGraphCons(IsImmutableDigraph, n));
InstallMethod(BananaTreeCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D, j, list;
if n = 1 then
ErrorNoReturn("The second argument must be an integer",
" greater than one");
fi;
D := EmptyDigraph(IsMutable, 1);
list := Concatenation([D], ListWithIdenticalEntries(m, StarGraph(n)));
DigraphDisjointUnion(list); # changes <D> in place
for j in [0 .. (m - 1)] do
DigraphAddEdges(D, [[1, (j * n + 3)], [(j * n + 3), 1]]);
od;
return D;
end);
InstallMethod(BananaTreeCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := MakeImmutable(BananaTreeCons(IsMutableDigraph, m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsUndirectedTree(D, true);
return D;
end);
InstallMethod(BananaTree, "for a function and two positive integers",
[IsPosInt, IsPosInt],
{m, n} -> BananaTreeCons(IsImmutableDigraph, m, n));
InstallMethod(BananaTree, "for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
{filt, m, n} -> BananaTreeCons(filt, m, n));
InstallMethod(TadpoleGraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local tail, graph;
if m < 3 then
ErrorNoReturn("the first argument <m> must be an integer greater than 2");
fi;
graph := DigraphSymmetricClosure(CycleDigraph(IsMutableDigraph, m));
tail := DigraphSymmetricClosure(ChainDigraph(IsMutable, n));
DigraphDisjointUnion(graph, tail);
DigraphAddEdges(graph, [[m, n + m], [n + m, m]]);
return graph;
end);
InstallMethod(TadpoleGraph, "for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
TadpoleGraphCons);
InstallMethod(TadpoleGraph, "for two positive integers", [IsPosInt, IsPosInt],
{m, n} -> TadpoleGraphCons(IsImmutableDigraph, m, n));
InstallMethod(TadpoleGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := MakeImmutable(TadpoleGraph(IsMutableDigraph, m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(BookGraphCons,
"for IsMutableDigraph and one positive integer",
[IsMutableDigraph, IsPosInt],
{filt, m} -> StackedBookGraph(filt, m, 2));
InstallMethod(BookGraph, "for a function and a positive integer",
[IsFunction, IsPosInt], BookGraphCons);
InstallMethod(BookGraph, "for a positive integer", [IsPosInt],
m -> BookGraphCons(IsImmutableDigraph, m));
InstallMethod(BookGraphCons,
"for IsImmutableDigraph and a positive integer",
[IsImmutableDigraph, IsPosInt],
function(_, m)
local D;
D := MakeImmutable(BookGraph(IsMutableDigraph, m));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsBipartiteDigraph(D, true);
return D;
end);
InstallMethod(StackedBookGraphCons,
"for IsMutableDigraph and two positive integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local book;
book := DigraphSymmetricClosure(ChainDigraph(IsMutable, n));
return DigraphCartesianProduct(book, StarGraph(IsMutable, m + 1));
end);
InstallMethod(StackedBookGraph, "for a function and two positive integers",
[IsFunction, IsPosInt, IsPosInt],
StackedBookGraphCons);
InstallMethod(StackedBookGraph, "for two positive integers",
[IsPosInt, IsPosInt],
{m, n} -> StackedBookGraphCons(IsImmutableDigraph, m, n));
InstallMethod(StackedBookGraphCons,
"for IsImmutableDigraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, m, n)
local D;
D := MakeImmutable(StackedBookGraph(IsMutableDigraph, m, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsBipartiteDigraph(D, true);
return D;
end);
InstallMethod(BinaryTreeCons,
"for IsMutableDigraph and positive integer",
[IsMutableDigraph, IsPosInt],
function(_, depth)
local D, x, i, j;
D := [[]];
for i in [1 .. depth - 1] do
for j in [1 .. 2 ^ i] do
x := DIGRAPHS_BlistNumber(j, i){[2 .. i]};
Add(D, [DIGRAPHS_NumberBlist(x) + (2 ^ (i - 1)) - 1]);
od;
od;
return Digraph(IsMutableDigraph, D);
end);
InstallMethod(BinaryTreeCons,
"for IsImmutableDigraph and positive integer",
[IsImmutableDigraph, IsPosInt],
function(_, depth)
local D;
D := BinaryTreeCons(IsMutableDigraph, depth);
MakeImmutable(D);
return D;
end);
InstallMethod(BinaryTree, "for a positive integer", [IsPosInt],
depth -> BinaryTreeCons(IsImmutableDigraph, depth));
InstallMethod(BinaryTree, "for a function and a positive integer",
[IsFunction, IsPosInt], BinaryTreeCons);
InstallMethod(AndrasfaiGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local js;
js := List([0 .. (n - 1)], x -> (3 * x) + 1);
return CirculantGraph(IsMutableDigraph, (3 * n) - 1, js);
end);
InstallMethod(AndrasfaiGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(AndrasfaiGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsUndirectedTree(D, false);
SetIsRegularDigraph(D, true);
SetIsVertexTransitive(D, true);
SetIsHamiltonianDigraph(D, true);
SetIsBiconnectedDigraph(D, true);
return D;
end);
InstallMethod(AndrasfaiGraph, "for an integer", [IsPosInt],
n -> AndrasfaiGraphCons(IsImmutableDigraph, n));
InstallMethod(AndrasfaiGraph, "for a function and an integer",
[IsFunction, IsPosInt], AndrasfaiGraphCons);
InstallMethod(BinomialTreeGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local bits, is2n, verts, D, rep, pos, parent, parVert, i;
bits := Log(n, 2);
is2n := IsEvenInt(n) and IsPrimePowerInt(n);
if not is2n then
bits := bits + 1;
fi;
verts := List(Tuples([0, 1], bits){[1 .. n]},
x -> x{List([1 .. bits], y -> bits - y + 1)});
D := Digraph(IsMutableDigraph, []);
DigraphAddVertices(D, n);
for i in [2 .. n] do # 1 is the root vertex
rep := StructuralCopy(verts[i]);
pos := Position(rep, 1);
parent := rep;
parent[pos] := 0;
parVert := Position(verts, parent);
DigraphAddEdge(D, i, parVert);
od;
return DigraphSymmetricClosure(DigraphRemoveAllMultipleEdges(D));
end);
InstallMethod(BinomialTreeGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(BinomialTreeGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsEmptyDigraph(D, n = 1);
SetIsUndirectedTree(D, true);
return D;
end);
InstallMethod(BinomialTreeGraph, "for an integer", [IsPosInt],
n -> BinomialTreeGraphCons(IsImmutableDigraph, n));
InstallMethod(BinomialTreeGraph, "for a function and an integer",
[IsFunction, IsPosInt], BinomialTreeGraphCons);
InstallMethod(BondyGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsInt],
function(_, n)
if n < 0 then
ErrorNoReturn("the argument <n> must be a non-negative integer,");
fi;
return GeneralisedPetersenGraph(IsMutableDigraph, 3 * (2 * n + 1) + 2, 2);
end);
InstallMethod(BondyGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsInt],
function(_, n)
local D;
D := MakeImmutable(BondyGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsHamiltonianDigraph(D, false);
return D;
end);
InstallMethod(BondyGraph, "for an integer", [IsInt],
n -> BondyGraphCons(IsImmutableDigraph, n));
InstallMethod(BondyGraph, "for a function and an integer",
[IsFunction, IsInt], BondyGraphCons);
InstallMethod(CirculantGraphCons, "for IsMutableDigraph, an integer and a list",
[IsMutableDigraph, IsPosInt, IsList],
function(_, n, par)
local D, i, j;
if (n < 2) or (not ForAll(par, x -> IsInt(x) and x in [1 .. n])) then
ErrorNoReturn("arguments must be an integer <n> greater ",
"than 1 and a list of integers between 1 and n,");
fi;
D := EmptyDigraph(IsMutableDigraph, n);
for i in [1 .. n] do
for j in par do
if (i - j) mod n = 0 then
DigraphAddEdge(D, i, n);
else
DigraphAddEdge(D, i, (i - j) mod n);
fi;
if (i + j) mod n = 0 then
DigraphAddEdge(D, i, n);
else
DigraphAddEdge(D, i, (i + j) mod n);
fi;
od;
od;
return DigraphRemoveAllMultipleEdges(DigraphSymmetricClosure(D));
end);
InstallMethod(CirculantGraphCons,
"for IsImmutableDigraph, integer, list of integers",
[IsImmutableDigraph, IsPosInt, IsList],
function(_, n, par)
local D;
D := MakeImmutable(CirculantGraphCons(IsMutableDigraph, n, par));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsVertexTransitive(D, true);
SetIsUndirectedTree(D, false);
SetIsUndirectedForest(D, IsEmpty(par) or
(IsEvenInt(n) and Unique(par) = [n / 2]));
if Gcd(Concatenation([n], par)) = 1 then
SetIsHamiltonianDigraph(D, true);
SetIsBiconnectedDigraph(D, true);
fi;
return D;
end);
InstallMethod(CirculantGraph, "for an integer and a list", [IsPosInt, IsList],
{n, par} -> CirculantGraphCons(IsImmutableDigraph, n, par));
InstallMethod(CirculantGraph, "for a function and an integer",
[IsFunction, IsPosInt, IsList], CirculantGraphCons);
InstallMethod(CycleGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(filt, n)
if n < 3 then
ErrorNoReturn("the argument <n> must be an integer greater than 2,");
fi;
return DigraphSymmetricClosure(CycleDigraph(filt, n));
end);
InstallMethod(CycleGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(CycleGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(CycleGraph, "for an integer", [IsPosInt],
n -> CycleGraphCons(IsImmutableDigraph, n));
InstallMethod(CycleGraph, "for a function and an integer",
[IsFunction, IsPosInt], CycleGraphCons);
InstallMethod(GearGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D, i, central;
if n < 3 then
ErrorNoReturn("the argument <n> must be an integer greater than 2,");
fi;
central := 2 * n + 1;
D := CycleGraph(IsMutableDigraph, central - 1);
DigraphAddVertex(D);
for i in [1 .. n] do
DigraphAddEdge(D, 2 * i, central);
DigraphAddEdge(D, central, 2 * i);
od;
return D;
end);
InstallMethod(GearGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(GearGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(GearGraph, "for an integer", [IsPosInt],
n -> GearGraphCons(IsImmutableDigraph, n));
InstallMethod(GearGraph, "for a function and an integer",
[IsFunction, IsPosInt], GearGraphCons);
InstallMethod(HalvedCubeGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D, tuples, vertices, i, j;
tuples := Tuples([0, 1], n);
vertices := List([1 .. (2 ^ (n - 1))], x -> []);
j := 1;
for i in [1 .. Length(tuples)] do
if Sum(tuples[i]) mod 2 = 0 then
vertices[j] := tuples[i];
j := j + 1;
fi;
od;
D := EmptyDigraph(IsMutableDigraph, Length(vertices));
for i in [1 .. Length(vertices) - 1] do
for j in [i + 1 .. Length(vertices)] do
if SizeBlist(List([1 .. Length(vertices[i])],
x -> vertices[i][x] <> vertices[j][x])) = 2 then
DigraphAddEdge(D, i, j);
DigraphAddEdge(D, j, i);
fi;
od;
od;
return D;
end);
InstallMethod(HalvedCubeGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(HalvedCubeGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsEmptyDigraph(D, n = 1);
SetIsDistanceRegularDigraph(D, true);
SetIsHamiltonianDigraph(D, true);
return D;
end);
InstallMethod(HalvedCubeGraph, "for an integer", [IsPosInt],
n -> HalvedCubeGraphCons(IsImmutableDigraph, n));
InstallMethod(HalvedCubeGraph, "for a function and an integer",
[IsFunction, IsPosInt], HalvedCubeGraphCons);
InstallMethod(HanoiGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local e, D, nrVert, prevNrVert, anchor1, anchor2, anchor3, i;
D := Digraph(IsMutableDigraph, []);
nrVert := 3 ^ n;
DigraphAddVertices(D, nrVert);
e := [[1, 2], [2, 3], [3, 1]];
# Anchors correspond to the top, bottom left and bottom right node of the
# current graph.
anchor1 := 1;
anchor2 := 2;
anchor3 := 3;
prevNrVert := 1;
# Starting from the triangle graph G := C_3, iteratively triplicate G, and
# connect each copy using their anchors.
for i in [2 .. n] do
prevNrVert := prevNrVert * 3;
Append(e, Concatenation(e + prevNrVert, e + (2 * prevNrVert)));
Add(e, [anchor2, anchor1 + prevNrVert]);
Add(e, [anchor3, anchor1 + (2 * prevNrVert)]);
Add(e, [anchor3 + prevNrVert, anchor2 + (2 * prevNrVert)]);
anchor2 := anchor2 + prevNrVert;
anchor3 := anchor3 + (2 * prevNrVert);
od;
DigraphAddEdges(D, e);
return DigraphSymmetricClosure(D);
end);
InstallMethod(HanoiGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(HanoiGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsPlanarDigraph(D, true);
SetIsHamiltonianDigraph(D, true);
return D;
end);
InstallMethod(HanoiGraph, "for an integer", [IsPosInt],
n -> HanoiGraphCons(IsImmutableDigraph, n));
InstallMethod(HanoiGraph, "for a function and an integer",
[IsFunction, IsPosInt], HanoiGraphCons);
InstallMethod(HelmGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D;
if n < 3 then
ErrorNoReturn("the argument <n> must be an integer greater than 2,");
fi;
D := WheelGraph(IsMutableDigraph, n + 1);
DigraphAddVertices(D, n);
DigraphAddEdges(D, List([1 .. n], x -> [x, x + n + 1]));
DigraphSymmetricClosure(D);
return D;
end);
InstallMethod(HelmGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(HelmGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(HelmGraph, "for an integer", [IsPosInt],
n -> HelmGraphCons(IsImmutableDigraph, n));
InstallMethod(HelmGraph, "for a function and an integer",
[IsFunction, IsPosInt], HelmGraphCons);
InstallMethod(HypercubeGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsInt],
function(_, n)
local D;
D := MakeImmutable(HypercubeGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsEmptyDigraph(D, n = 0);
SetIsHamiltonianDigraph(D, true);
SetIsDistanceRegularDigraph(D, true);
SetIsBipartiteDigraph(D, true);
return D;
end);
InstallMethod(HypercubeGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsInt],
function(_, n)
local D, vertices, i, j;
if n < 0 then
ErrorNoReturn("the argument <n> must be a non-negative integer,");
fi;
vertices := Tuples([0, 1], n);
D := EmptyDigraph(IsMutableDigraph, Length(vertices));
for i in [1 .. Length(vertices) - 1] do
for j in [i + 1 .. Length(vertices)] do
if SizeBlist(List([1 .. Length(vertices[i])],
x -> vertices[i][x] <> vertices[j][x])) = 1 then
DigraphAddEdge(D, i, j);
DigraphAddEdge(D, j, i);
fi;
od;
od;
return D;
end);
InstallMethod(HypercubeGraph, "for an integer", [IsInt],
n -> HypercubeGraphCons(IsImmutableDigraph, n));
InstallMethod(HypercubeGraph, "for a function and an integer",
[IsFunction, IsInt], HypercubeGraphCons);
InstallMethod(KellerGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsInt],
function(_, n)
local D, vertices, i, j;
if n < 0 then
ErrorNoReturn("the argument <n> must be a non-negative integer,");
fi;
vertices := Tuples([0, 1, 2, 3], n);
D := Digraph(IsMutableDigraph, []);
DigraphAddVertices(D, Length(vertices));
for i in [1 .. Length(vertices) - 1] do
for j in [i + 1 .. Length(vertices)] do
if SizeBlist(List([1 .. Length(vertices[i])],
x -> vertices[i][x] <> vertices[j][x])) > 1 and
SizeBlist(List([1 .. Length(vertices[i])],
x -> AbsInt(vertices[i][x] - vertices[j][x]) mod 4 = 2)) > 0 then
DigraphAddEdge(D, i, j);
DigraphAddEdge(D, j, i);
fi;
od;
od;
return D;
end);
InstallMethod(KellerGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsInt],
function(_, n)
local D;
D := MakeImmutable(KellerGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
if n > 1 then
SetChromaticNumber(D, 2 ^ n);
SetIsHamiltonianDigraph(D, true);
else
SetIsEmptyDigraph(D, true);
fi;
return D;
end);
InstallMethod(KellerGraph, "for an integer", [IsInt],
n -> KellerGraphCons(IsImmutableDigraph, n));
InstallMethod(KellerGraph, "for a function and an integer",
[IsFunction, IsInt], KellerGraphCons);
InstallMethod(KneserGraphCons, "for IsMutableDigraph and two integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D, vertices, i, j;
if n < k then
ErrorNoReturn("argument <n> must be greater than or equal to argument <k>");
fi;
vertices := Combinations([1 .. n], k);
D := EmptyDigraph(IsMutableDigraph, Length(vertices));
for i in [1 .. Length(vertices) - 1] do
for j in [i + 1 .. Length(vertices)] do
if Length(Intersection(vertices[i], vertices[j])) = 0 then
DigraphAddEdge(D, i, j);
DigraphAddEdge(D, j, i);
fi;
od;
od;
return D;
end);
InstallMethod(KneserGraphCons,
"for IsImmutableDigraph, integer, integer",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D;
D := MakeImmutable(KneserGraphCons(IsMutableDigraph, n, k));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsRegularDigraph(D, true);
SetIsVertexTransitive(D, true);
SetIsEdgeTransitive(D, true);
if n >= 2 * k then
SetChromaticNumber(D, n - 2 * k + 2);
else
SetChromaticNumber(D, 1);
SetIsEmptyDigraph(D, true);
fi;
if Float(n) >= ((3 + 5 ^ 0.5) / 2) * Float(k) + 1 then
SetIsHamiltonianDigraph(D, true);
fi;
SetCliqueNumber(D, Int(n / k));
return D;
end);
InstallMethod(KneserGraph, "for two integers", [IsPosInt, IsPosInt],
{n, k} -> KneserGraphCons(IsImmutableDigraph, n, k));
InstallMethod(KneserGraph, "for a function and two integers",
[IsFunction, IsPosInt, IsPosInt], KneserGraphCons);
InstallMethod(LindgrenSousselierGraphCons,
"for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D, central, i, threei;
central := 6 * n + 4;
D := CycleGraph(IsMutableDigraph, central - 1);
DigraphAddVertex(D);
for i in [0 .. (2 * n)] do
threei := 3 * i;
DigraphAddEdge(D, central, threei + 1);
DigraphAddEdge(D, threei + 1, central);
if i <> 2 * n then
DigraphAddEdge(D, 2 + threei, 6 + threei);
DigraphAddEdge(D, 6 + threei, 2 + threei);
fi;
od;
DigraphAddEdge(D, central - 2, 3);
DigraphAddEdge(D, 3, central - 2);
return D;
end);
InstallMethod(LindgrenSousselierGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(LindgrenSousselierGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsHamiltonianDigraph(D, false);
return D;
end);
InstallMethod(LindgrenSousselierGraph, "for an integer", [IsPosInt],
n -> LindgrenSousselierGraphCons(IsImmutableDigraph, n));
InstallMethod(LindgrenSousselierGraph, "for a function and an integer",
[IsFunction, IsPosInt], LindgrenSousselierGraphCons);
InstallMethod(MobiusLadderGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D, i;
if n < 4 then
ErrorNoReturn("the argument <n> must be an integer equal to 4 or more,");
fi;
D := CycleGraph(IsMutableDigraph, 2 * n);
for i in [1 .. n] do
DigraphAddEdge(D, i, i + n);
DigraphAddEdge(D, i + n, i);
od;
return DigraphSymmetricClosure(D);
end);
InstallMethod(MobiusLadderGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(MobiusLadderGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(MobiusLadderGraph, "for an integer", [IsPosInt],
n -> MobiusLadderGraphCons(IsImmutableDigraph, n));
InstallMethod(MobiusLadderGraph, "for a function and an integer",
[IsFunction, IsPosInt], MobiusLadderGraphCons);
InstallMethod(MycielskiGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D, i;
if n < 2 then
ErrorNoReturn("the argument <n> must be an integer greater than 1,");
fi;
D := Digraph(IsMutableDigraph, []);
DigraphAddVertices(D, 2);
DigraphAddEdges(D, [[1, 2], [2, 1]]);
for i in [3 .. n] do
D := DigraphMycielskian(D);
od;
return D;
end);
InstallMethod(MycielskiGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(MycielskiGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetChromaticNumber(D, n);
SetCliqueNumber(D, 2);
SetIsHamiltonianDigraph(D, true);
return D;
end);
InstallMethod(MycielskiGraph, "for an integer", [IsPosInt],
n -> MycielskiGraphCons(IsImmutableDigraph, n));
InstallMethod(MycielskiGraph, "for a function and an integer",
[IsFunction, IsPosInt], MycielskiGraphCons);
InstallMethod(OddGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsInt],
function(_, n)
if n < 1 then
ErrorNoReturn("the argument <n> must be an integer greater than 0,");
fi;
return KneserGraph(IsMutableDigraph, 2 * n - 1, n - 1);
end);
InstallMethod(OddGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsInt],
function(_, n)
local D;
D := MakeImmutable(OddGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsVertexTransitive(D, true);
SetIsEdgeTransitive(D, true);
SetIsRegularDigraph(D, true);
SetIsDistanceRegularDigraph(D, true);
SetChromaticNumber(D, 3);
return D;
end);
InstallMethod(OddGraph, "for an integer", [IsInt],
n -> OddGraphCons(IsImmutableDigraph, n));
InstallMethod(OddGraph, "for a function and an integer",
[IsFunction, IsInt], OddGraphCons);
InstallMethod(PathGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
{_, n} -> DigraphSymmetricClosure(ChainDigraph(IsMutableDigraph, n)));
InstallMethod(PathGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(PathGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsUndirectedTree(D, true);
SetIsEmptyDigraph(D, n = 1);
return D;
end);
InstallMethod(PathGraph, "for an integer", [IsPosInt],
n -> PathGraphCons(IsImmutableDigraph, n));
InstallMethod(PathGraph, "for a function and an integer",
[IsFunction, IsPosInt], PathGraphCons);
InstallMethod(PermutationStarGraphCons, "for IsMutableDigraph and two integers",
[IsMutableDigraph, IsPosInt, IsInt],
function(_, n, k)
local D, permList, vertices, bList, pos, i, j;
if k < 0 then
ErrorNoReturn("the arguments <n> and <k> must be integers, ",
"with n greater than 0 and k non-negative,");
fi;
if k > n then
Error("the argument <n> must be greater than or equal to <k>,");
fi;
permList := PermutationsList([1 .. n]);
vertices := Unique(List(permList, x -> List([1 .. k], y -> x[y])));
D := Digraph(IsMutableDigraph, []);
DigraphAddVertices(D, Length(vertices));
for i in [1 .. Length(vertices) - 1] do
for j in [i + 1 .. Length(vertices)] do
bList := List([1 .. Length(vertices[i])],
x -> vertices[i][x] <> vertices[j][x]);
pos := Positions(bList, true);
if bList[1] then
if (SizeBlist(bList) = 2 and
vertices[j][pos[2]] = vertices[i][pos[1]] and
vertices[j][pos[1]] = vertices[i][pos[2]]) or
(SizeBlist(bList) = 1 and (not vertices[j][1] in vertices[i])) then
DigraphAddEdge(D, i, j);
DigraphAddEdge(D, j, i);
fi;
fi;
od;
od;
return D;
end);
InstallMethod(PermutationStarGraphCons,
"for IsImmutableDigraph, integer, integer",
[IsImmutableDigraph, IsPosInt, IsInt],
function(_, n, k)
local D;
D := MakeImmutable(PermutationStarGraphCons(IsMutableDigraph, n, k));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsRegularDigraph(D, true);
SetIsVertexTransitive(D, true);
if k <= Int(n / 2) then
SetDigraphDiameter(D, 2 * k - 1);
else
SetDigraphDiameter(D, Int((n - 1) / 2) + k);
fi;
return D;
end);
InstallMethod(PermutationStarGraph, "for two integers", [IsPosInt, IsInt],
{n, k} -> PermutationStarGraphCons(IsImmutableDigraph, n, k));
InstallMethod(PermutationStarGraph, "for a function and two integers",
[IsFunction, IsPosInt, IsInt], PermutationStarGraphCons);
InstallMethod(PrismGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
if n < 3 then
ErrorNoReturn("the argument <n> must be an integer equal to 3 or more,");
else
return GeneralisedPetersenGraph(IsMutableDigraph, n, 1);
fi;
end);
InstallMethod(PrismGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(PrismGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(PrismGraph, "for an integer", [IsPosInt],
n -> PrismGraphCons(IsImmutableDigraph, n));
InstallMethod(PrismGraph, "for a function and an integer",
[IsFunction, IsPosInt], PrismGraphCons);
InstallMethod(StackedPrismGraphCons, "for IsMutableDigraph and two integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
if n < 3 then
ErrorNoReturn("the arguments <n> and <k> must be integers, ",
"with <n> greater than 2 and <k> greater than 0,");
fi;
return DigraphCartesianProduct(CycleGraph(IsMutableDigraph, n),
PathGraph(IsMutableDigraph, k));
end);
InstallMethod(StackedPrismGraphCons,
"for IsImmutableDigraph, integer, integer",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, n, k)
local D;
D := MakeImmutable(StackedPrismGraphCons(IsMutableDigraph, n, k));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(StackedPrismGraph, "for two integers", [IsPosInt, IsPosInt],
{n, k} -> StackedPrismGraphCons(IsImmutableDigraph, n, k));
InstallMethod(StackedPrismGraph, "for a function and two integers",
[IsFunction, IsPosInt, IsPosInt], StackedPrismGraphCons);
InstallMethod(WalshHadamardGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local H_2, H_n, i, D, j, sideHn;
H_2 := [[1, 1],
[1, -1]];
H_n := [[1]];
if n > 1 then
for i in [2 .. n] do
H_n := KroneckerProduct(H_2, H_n);
od;
fi;
sideHn := Length(H_n);
D := EmptyDigraph(IsMutableDigraph, 4 * sideHn);
for i in [1 .. sideHn] do
for j in [1 .. sideHn] do
if H_n[i][j] = 1 then
DigraphAddEdge(D, i, 2 * sideHn + j);
DigraphAddEdge(D, sideHn + i, 3 * sideHn + j);
else
DigraphAddEdge(D, i, 3 * sideHn + j);
DigraphAddEdge(D, sideHn + i, 2 * sideHn + j);
fi;
od;
od;
return DigraphSymmetricClosure(D);
end);
InstallMethod(WalshHadamardGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(WalshHadamardGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsDistanceRegularDigraph(D, true);
return D;
end);
InstallMethod(WalshHadamardGraph, "for an integer", [IsPosInt],
n -> WalshHadamardGraphCons(IsImmutableDigraph, n));
InstallMethod(WalshHadamardGraph, "for a function and an integer",
[IsFunction, IsPosInt], WalshHadamardGraphCons);
InstallMethod(WebGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D, i;
if n < 3 then
ErrorNoReturn("the argument <n> must be an integer greater than 2,");
fi;
D := StackedPrismGraph(IsMutableDigraph, n, 3);
for i in [1 .. (n - 1)] do
D := DigraphRemoveEdge(D, i, i + 1);
D := DigraphRemoveEdge(D, i + 1, i);
od;
D := DigraphRemoveEdge(D, n, 1);
return DigraphRemoveEdge(D, 1, n);
end);
InstallMethod(WebGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(WebGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
return D;
end);
InstallMethod(WebGraph, "for an integer", [IsPosInt],
n -> WebGraphCons(IsImmutableDigraph, n));
InstallMethod(WebGraph, "for a function and an integer",
[IsFunction, IsPosInt], WebGraphCons);
InstallMethod(WheelGraphCons, "for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D;
if n < 4 then
ErrorNoReturn("the argument <n> must be an integer greater than 3,");
fi;
D := CycleGraph(IsMutableDigraph, n - 1);
DigraphAddVertex(D, 1);
DigraphAddEdges(D, List([1 .. n - 1], x -> [x, n]));
DigraphAddEdges(D, List([1 .. n - 1], x -> [n, x]));
return D;
end);
InstallMethod(WheelGraphCons,
"for IsImmutableDigraph, integer",
[IsImmutableDigraph, IsPosInt],
function(_, n)
local D;
D := MakeImmutable(WheelGraphCons(IsMutableDigraph, n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetIsHamiltonianDigraph(D, true);
SetIsPlanarDigraph(D, true);
if (n mod 2) = 1 then
SetChromaticNumber(D, 3);
else
SetChromaticNumber(D, 4);
fi;
return D;
end);
InstallMethod(WheelGraph, "for an integer", [IsPosInt],
n -> WheelGraphCons(IsImmutableDigraph, n));
InstallMethod(WheelGraph, "for a function and an integer",
[IsFunction, IsPosInt], WheelGraphCons);
InstallMethod(WindmillGraphCons, "for IsMutableDigraph and two integers",
[IsMutableDigraph, IsPosInt, IsPosInt],
function(_, n, m)
local D, i, K, nrVert;
if m < 2 or n < 2 then
ErrorNoReturn("the arguments <n> and <m> must be integers greater than 1,");
fi;
D := Digraph(IsMutableDigraph, []);
K := CompleteDigraph(n - 1);
nrVert := 1 + DigraphNrVertices(K) * m;
DigraphAddVertices(D, nrVert);
for i in [0 .. (m - 1)] do
DigraphAddEdges(D, DigraphEdges(K) + (i * DigraphNrVertices(K)));
od;
for i in [1 .. (DigraphNrVertices(D) - 1)] do
DigraphAddEdge(D, i, nrVert);
DigraphAddEdge(D, nrVert, i);
od;
return D;
end);
InstallMethod(WindmillGraphCons,
"for IsImmutableDigraph, integer, integer",
[IsImmutableDigraph, IsPosInt, IsPosInt],
function(_, n, m)
local D;
D := MakeImmutable(WindmillGraphCons(IsMutableDigraph, n, m));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(D, true);
SetChromaticNumber(D, n);
SetDigraphDiameter(D, 2);
return D;
end);
InstallMethod(WindmillGraph, "for two integers", [IsPosInt, IsPosInt],
{n, m} -> WindmillGraphCons(IsImmutableDigraph, n, m));
InstallMethod(WindmillGraph, "for a function and two integers",
[IsFunction, IsPosInt, IsPosInt], WindmillGraphCons);
BindGlobal("DIGRAPHS_PrefixReversalGroup",
n -> Group(List([2 .. n], i -> PermList([i, i - 1 .. 1])), ()));
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(_, 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(_, n)
local D;
D := CayleyDigraph(IsImmutableDigraph, DIGRAPHS_HyperoctahedralGroup(n));
SetIsMultiDigraph(D, false);
SetIsSymmetricDigraph(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));
[ zur Elbe Produktseite wechseln0.68Quellennavigators
Analyse erneut starten
]
|