diff --git a/.VERSION b/.VERSION
index bc80560fa..4cda8f19e 100644
--- a/.VERSION
+++ b/.VERSION
@@ -1 +1 @@
-1.5.0
+1.5.2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea6eba437..00b563dad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,22 @@
# CHANGELOG – Digraphs package for GAP
-Copyright © 2014-21 by Jan De Beule, Julius Jonušas, James D. Mitchell,
+Copyright © 2014-22 by Jan De Beule, Julius Jonušas, James D. Mitchell,
Wilf A. Wilson, Michael Young et al.
Licensing information can be found in the `LICENSE` file.
+## Version 1.5.2 (released 30/03/2022)
+
+This is a very minor release containing technical changes for maintaining compatibility with other GAP packages.
+
+## Version 1.5.1 (released 29/03/2022)
+
+This minor release contains several bugfixes and technical changes. This includes:
+
+* Bugfix: vertex labels are no longer wrongly retained when using `DigraphEdgeUnion`. This was reported by [Wilf A. Wilson][] in [Issue #496](https://github.com/digraphs/Digraphs/issues/496) and fixed by Joseph Edwards in [PR #507](https://github.com/digraphs/Digraphs/pull/507).
+* Bugfix: a segfault could be caused by calling `OutNeighbours` with an inappropriate argument. This was reported by [Wilf A. Wilson][] in [Issue #518](https://github.com/digraphs/Digraphs/issues/518) and fixed by [James D. Mitchell][] in [PR #519](https://github.com/digraphs/Digraphs/pull/519).
+* [Wilf A. Wilson][] improved the performance of `DigraphAddEdge` for digraphs without edge labels in [PR #509](https://github.com/digraphs/Digraphs/pull/509).
+* [Max Horn][] changed the declaration of the variable `Vertices` to improve compatibility with Grape in [PR #530](https://github.com/digraphs/Digraphs/pull/530).
+
## Version 1.5.0 (released 27/10/2021)
This is a fairly major release of the Digraphs package, containing some bugfixes and several new features.
diff --git a/PackageInfo.g b/PackageInfo.g
index aa97bc319..37e49dcc5 100644
--- a/PackageInfo.g
+++ b/PackageInfo.g
@@ -1,7 +1,7 @@
#############################################################################
##
## PackageInfo.g
-## Copyright (C) 2015-21 James D. Mitchell
+## Copyright (C) 2015-22 James D. Mitchell
##
## Licensing information can be found in the README.md file of this package.
##
@@ -9,15 +9,15 @@
##
## <#GAPDoc Label="PKGVERSIONDATA">
-##
+##
##
##
##
##
##
##
-##
-##
+##
+##
## <#/GAPDoc>
_STANDREWSMATHS := Concatenation(["Mathematical Institute, North Haugh, ",
@@ -28,8 +28,8 @@ _STANDREWSCS := Concatenation(["Jack Cole Building, North Haugh, ",
SetPackageInfo(rec(
PackageName := "Digraphs",
Subtitle := "Graphs, digraphs, and multidigraphs in GAP",
-Version := "1.5.0",
-Date := "27/10/2021", # dd/mm/yyyy format
+Version := "1.5.2",
+Date := "30/03/2022", # dd/mm/yyyy format
License := "GPL-3.0-or-later",
ArchiveFormats := ".tar.gz",
diff --git a/VERSIONS b/VERSIONS
index 22cee7c0f..d37734bc2 100644
--- a/VERSIONS
+++ b/VERSIONS
@@ -1,13 +1,15 @@
#############################################################################
##
#W VERSIONS
-#Y Copyright (C) 2015-21 James D. Mitchell
+#Y Copyright (C) 2015-22 James D. Mitchell
##
## Licensing information can be found in the README.md file of this package.
##
#############################################################################
##
+release 1.5.2 - 30/03/2022
+release 1.5.1 - 29/03/2022
release 1.5.0 - 27/10/2021
release 1.4.1 - 14/05/2021
release 1.4.0 - 27/01/2021
diff --git a/doc/oper.xml b/doc/oper.xml
index d8d03e86c..e50dceb50 100644
--- a/doc/oper.xml
+++ b/doc/oper.xml
@@ -1535,6 +1535,36 @@ gap> DigraphShortestPath(D, 1, 1);
<#/GAPDoc>
+<#GAPDoc Label="DigraphRandomWalk">
+
+
+ A pair of lists.
+
+ Returns a directed path corresponding to a random walk in the digraph
+ digraph, starting at vertex v and having length no more than
+ t.
+
+
+ A random walk is defined as follows. The path begins at v, and at
+ each step it follows a random edge leaving the current vertex. It continues
+ through the digraph in this way until it has traversed t edges, or
+ until it reaches a vertex with no out-edges (a sink) and therefore
+ cannot continue.
+
+
+ The output has the same form as that of .
+
+
+ D := Digraph([[1, 2], [3], [2, 4], [1], [2, 4]]);
+
+gap> DigraphRandomWalk(D, 1, 4);
+[ [ 1, 2, 3, 2, 3 ], [ 2, 1, 1, 1 ] ]
+]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="IteratorOfPaths">
diff --git a/doc/z-chap4.xml b/doc/z-chap4.xml
index 1524d671c..3689ed81d 100644
--- a/doc/z-chap4.xml
+++ b/doc/z-chap4.xml
@@ -68,6 +68,7 @@
<#Include Label="VerticesReachableFrom">
<#Include Label="DigraphPath">
<#Include Label="DigraphShortestPath">
+ <#Include Label="DigraphRandomWalk">
<#Include Label="Dominators">
<#Include Label="DominatorTree">
<#Include Label="IteratorOfPaths">
diff --git a/gap/grape.gi b/gap/grape.gi
index d4ec6f22d..3bdcd4421 100644
--- a/gap/grape.gi
+++ b/gap/grape.gi
@@ -132,7 +132,7 @@ function(D)
"the Grape graph will have fewer\n#I edges than the original,");
fi;
- if not DIGRAPHS_IsGrapeLoaded then
+ if not DIGRAPHS_IsGrapeLoaded() then
Info(InfoWarning, 1, "Grape is not loaded,");
fi;
diff --git a/gap/oper.gd b/gap/oper.gd
index f4abc08b0..68ecfafa2 100644
--- a/gap/oper.gd
+++ b/gap/oper.gd
@@ -49,10 +49,10 @@ DeclareOperation("LexicographicProduct", [IsDigraph, IsDigraph]);
DeclareOperation("AmalgamDigraphs",
[IsDigraph, IsDigraph, IsDigraph,
IsTransformation, IsTransformation]);
-DeclareOperation("AmalgamDigraphs",
+DeclareOperation("AmalgamDigraphs",
[IsDigraph, IsDigraph, IsDigraph, IsTransformation]);
-DeclareOperation("AmalgamDigraphs",
- [IsDigraph, IsDigraph, IsDigraph,]);
+DeclareOperation("AmalgamDigraphs",
+ [IsDigraph, IsDigraph, IsDigraph]);
DeclareSynonym("DigraphModularProduct", ModularProduct);
DeclareSynonym("DigraphStrongProduct", StrongProduct);
@@ -62,7 +62,7 @@ DeclareSynonym("DigraphLexicographicProduct", LexicographicProduct);
DeclareGlobalFunction("DIGRAPHS_CombinationOperProcessArgs");
DeclareOperation("DIGRAPHS_GraphProduct", [IsDigraph, IsDigraph, IsFunction]);
-DeclareOperation("NOCHECKS_AmalgamDigraphs",
+DeclareOperation("NOCHECKS_AmalgamDigraphs",
[IsDigraph, IsDigraph, IsDigraph,
IsTransformation, IsTransformation]);
@@ -135,6 +135,7 @@ DeclareOperation("IteratorOfPaths", [IsList, IsPosInt, IsPosInt]);
DeclareOperation("IteratorOfPathsNC", [IsList, IsPosInt, IsPosInt]);
DeclareOperation("IsReachable", [IsDigraph, IsPosInt, IsPosInt]);
DeclareOperation("DigraphLongestDistanceFromVertex", [IsDigraph, IsPosInt]);
+DeclareOperation("DigraphRandomWalk", [IsDigraph, IsPosInt, IsInt]);
DeclareOperation("DigraphLayers", [IsDigraph, IsPosInt]);
DeclareAttribute("DIGRAPHS_Layers", IsDigraph, "mutable");
diff --git a/gap/oper.gi b/gap/oper.gi
index 2ff8f6880..b8d671150 100644
--- a/gap/oper.gi
+++ b/gap/oper.gi
@@ -802,7 +802,7 @@ function(D1, D2, S, map1, map2)
n := DigraphNrVertices(D2) + DigraphNrVertices(D1) - DigraphNrVertices(S);
- # 'map' is an embedding of D2 into the final output graph.
+ # 'map' is an embedding of D2 into the final output graph.
# The embedding of D1 into the final output graph is the identity mapping.
map := [1 .. n];
@@ -856,7 +856,7 @@ function(D1, D2, S, map1)
if map2 = fail then
ErrorNoReturn(
"no embeddings could be found from the 3rd argument ",
- "(a digraph) to the 2nd argument (a digraph)");
+ "(a digraph) to the 2nd argument (a digraph)");
fi;
return NOCHECKS_AmalgamDigraphs(D1, D2, S, map1, map2);
@@ -890,7 +890,7 @@ function(D1, D2, S)
if map2 = fail then
ErrorNoReturn(
"no embeddings could be found from the 3rd argument ",
- "(a digraph) to the 2nd argument (a digraph)");
+ "(a digraph) to the 2nd argument (a digraph)");
fi;
return NOCHECKS_AmalgamDigraphs(D1, D2, S, map1, map2);
@@ -1891,6 +1891,41 @@ function(D, v)
return dist;
end);
+InstallMethod(DigraphRandomWalk,
+"for a digraph, a pos int and a non-negative int",
+[IsDigraph, IsPosInt, IsInt],
+function(D, v, t)
+ local vertices, edge_indices, i, neighbours, index;
+
+ # Check input
+ if v > DigraphNrVertices(D) then
+ ErrorNoReturn("the 2nd argument must be ",
+ "a vertex of the 1st argument ,");
+ elif t < 0 then
+ ErrorNoReturn("the 3rd argument must be a non-negative int,");
+ fi;
+
+ # Prepare output lists
+ vertices := [v];
+ edge_indices := [];
+
+ # Iterate to desired length
+ for i in [1 .. t] do
+ neighbours := OutNeighboursOfVertex(D, v);
+ if IsEmpty(neighbours) then
+ break; # Sink: path ends here
+ fi;
+ # Follow a random edge
+ index := Random(1, Length(neighbours));
+ v := neighbours[index];
+ vertices[i + 1] := v;
+ edge_indices[i] := index;
+ od;
+
+ # Format matches that of DigraphPath
+ return [vertices, edge_indices];
+end);
+
InstallMethod(DigraphLayers, "for a digraph, and a positive integer",
[IsDigraph, IsPosInt],
function(D, v)
diff --git a/init.g b/init.g
index 58acdd12a..8b02db573 100644
--- a/init.g
+++ b/init.g
@@ -25,14 +25,14 @@ if not IsBound(DIGRAPH_OUT_NBS) and
fi;
BindGlobal("DIGRAPHS_IsGrapeLoaded",
- IsPackageMarkedForLoading("grape", "4.8.1"));
+ {} -> IsPackageMarkedForLoading("grape", "4.8.1"));
# To avoid warnings when GRAPE is not loaded
if not IsBound(IsGraph) then
IsGraph := ReturnFalse;
fi;
if not IsBound(Vertices) then
- Vertices := IdFunc;
+ DeclareOperation("Vertices", [IsRecord]);
fi;
if not IsBound(Adjacency) then
Adjacency := IdFunc;
diff --git a/read.g b/read.g
index c9a71258f..ce3a63a6f 100644
--- a/read.g
+++ b/read.g
@@ -8,7 +8,7 @@
#############################################################################
##
-if not DIGRAPHS_IsGrapeLoaded then
+if not DIGRAPHS_IsGrapeLoaded() then
Add(DIGRAPHS_OmitFromTests, "Graph(");
fi;
diff --git a/tst/standard/digraph.tst b/tst/standard/digraph.tst
index d8cbffcb6..7acb51af2 100644
--- a/tst/standard/digraph.tst
+++ b/tst/standard/digraph.tst
@@ -211,7 +211,7 @@ gap> DigraphRange(gr);
[ 2, 3, 2 ]
gap> gr;
-gap> if DIGRAPHS_IsGrapeLoaded then
+gap> if DIGRAPHS_IsGrapeLoaded() then
> g := Graph(gr);
> if not Digraph(g) = gr then
> Print("fail");
@@ -1663,7 +1663,7 @@ gap> MakeImmutable(D);
#
gap> D := NullDigraph(10);
-gap> if DIGRAPHS_IsGrapeLoaded then
+gap> if DIGRAPHS_IsGrapeLoaded() then
> D := Graph(D);
> if D <> rec(
> adjacencies := [[]],
diff --git a/tst/standard/grape.tst b/tst/standard/grape.tst
index a121d7f68..ee7fca465 100644
--- a/tst/standard/grape.tst
+++ b/tst/standard/grape.tst
@@ -129,7 +129,7 @@ rec( adjacencies := [ [ 2, 4 ] ], group := Group([ (1,3), (1,2)(3,4) ]),
schreierVector := [ -1, 2, 1, 2 ] )
# Digraph: copying group from Grape
-gap> if DIGRAPHS_IsGrapeLoaded then
+gap> if DIGRAPHS_IsGrapeLoaded() then
> gr := Digraph(JohnsonGraph(5, 3));
> else
> gr := JohnsonDigraph(5, 3);
@@ -140,7 +140,7 @@ gap> HasDigraphGroup(gr);
true
gap> DigraphGroup(gr);
Group([ (1,7,10,6,3)(2,8,4,9,5), (4,7)(5,8)(6,9) ])
-gap> if DIGRAPHS_IsGrapeLoaded then
+gap> if DIGRAPHS_IsGrapeLoaded() then
> gr := Digraph(CompleteGraph(Group((1, 2, 3), (1, 2))));
> else
> gr := Digraph([[2, 3], [1, 3], [1, 2]]);
@@ -150,7 +150,7 @@ gap> HasDigraphGroup(gr);
true
gap> DigraphGroup(gr);
Group([ (1,2,3), (1,2) ])
-gap> if DIGRAPHS_IsGrapeLoaded then
+gap> if DIGRAPHS_IsGrapeLoaded() then
> gr := Digraph(Graph(Group([()]),
> [1, 2, 3],
> OnPoints,
@@ -252,7 +252,7 @@ true
# Graph
gap> gr := Digraph([[2, 2], []]);
-gap> if DIGRAPHS_IsGrapeLoaded then
+gap> if DIGRAPHS_IsGrapeLoaded() then
> Graph(gr);
> fi;
diff --git a/tst/standard/oper.tst b/tst/standard/oper.tst
index 06d14646a..f2f20aa8b 100644
--- a/tst/standard/oper.tst
+++ b/tst/standard/oper.tst
@@ -1443,6 +1443,36 @@ infinity
gap> DigraphLongestDistanceFromVertex(gr, 16);
Error, the 2nd argument must be a vertex of the 1st argument ,
+# DigraphRandomWalk
+gap> gr := CompleteDigraph(5);
+
+gap> path := DigraphRandomWalk(gr, 1, 100);;
+gap> Length(path[1]);
+101
+gap> ForAll(path[1], i -> i in [1 .. 5]);
+true
+gap> Length(path[2]);
+100
+gap> ForAll(path[2], i -> i in [1 .. 4]);
+true
+gap> gr := ChainDigraph(5);
+
+gap> DigraphRandomWalk(gr, 2, 100);
+[ [ 2, 3, 4, 5 ], [ 1, 1, 1 ] ]
+gap> DigraphRandomWalk(gr, 2, 2);
+[ [ 2, 3, 4 ], [ 1, 1 ] ]
+gap> DigraphRandomWalk(gr, 5, 100);
+[ [ 5 ], [ ] ]
+gap> gr := CompleteBipartiteDigraph(10, 8);;
+gap> DigraphRandomWalk(gr, 3, 0);
+[ [ 3 ], [ ] ]
+gap> DigraphRandomWalk(gr, 19, 5);
+Error, the 2nd argument must be a vertex of the 1st argument ,
+gap> DigraphRandomWalk(gr, 123, 5);
+Error, the 2nd argument must be a vertex of the 1st argument ,
+gap> DigraphRandomWalk(gr, 3, -1);
+Error, the 3rd argument must be a non-negative int,
+
# DigraphLayers
gap> gr := CompleteDigraph(4);
diff --git a/tst/testinstall.tst b/tst/testinstall.tst
index db8b3d116..abbaad0e7 100644
--- a/tst/testinstall.tst
+++ b/tst/testinstall.tst
@@ -23,11 +23,11 @@ gap> OutNeighbours(gr);
[ [ 8 ], [ 4, 5, 6, 8, 9 ], [ 2, 4, 5, 7, 10 ], [ 9 ], [ 1, 4, 6, 7, 9 ],
[ 2, 3, 6, 7, 10 ], [ 3, 4, 5, 8, 9 ], [ 3, 4, 9, 10 ],
[ 1, 2, 3, 5, 6, 9, 10 ], [ 2, 4, 5, 6, 9 ] ]
-gap> not DIGRAPHS_IsGrapeLoaded
-> or (DIGRAPHS_IsGrapeLoaded and Digraph(Graph(gr)) = gr);
+gap> not DIGRAPHS_IsGrapeLoaded()
+> or (DIGRAPHS_IsGrapeLoaded() and Digraph(Graph(gr)) = gr);
true
-gap> not DIGRAPHS_IsGrapeLoaded
-> or (DIGRAPHS_IsGrapeLoaded and Graph(Digraph(Graph(gr))).adjacencies =
+gap> not DIGRAPHS_IsGrapeLoaded()
+> or (DIGRAPHS_IsGrapeLoaded() and Graph(Digraph(Graph(gr))).adjacencies =
> Graph(gr).adjacencies);
true
gap> adj := [
@@ -38,8 +38,8 @@ gap> adj := [
> [1, 6, 8, 9, 11, 12, 13, 14], [2, 4, 7, 9, 10, 11, 13, 15, 16]];;
gap> func := function(x, y) return y in adj[x]; end;
function( x, y ) ... end
-gap> not DIGRAPHS_IsGrapeLoaded or
-> (DIGRAPHS_IsGrapeLoaded and
+gap> not DIGRAPHS_IsGrapeLoaded() or
+> (DIGRAPHS_IsGrapeLoaded() and
> Digraph(Graph(Group(()), [1 .. 20], OnPoints, func, true)) = Digraph(adj));
true