diff --git a/.appveyor.yml b/.appveyor.yml
index f810e60fe..0dd768cb7 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,10 +1,6 @@
# set clone depth
clone_depth: 1 # clone entire repository history if not defined
-branches:
- except:
- - /rc-v\d+\.\d+\.\d+/
-
environment:
TEST_SUITE: test
PACKAGES: "latest"
diff --git a/PackageInfo.g b/PackageInfo.g
index f891bee13..e7ffa2b19 100644
--- a/PackageInfo.g
+++ b/PackageInfo.g
@@ -42,6 +42,16 @@ SourceRepository := rec(
Persons := [
rec(
+ LastName := "Anagnostopoulou-Merkouri",
+ FirstNames := "Marina",
+ IsAuthor := false,
+ IsMaintainer := false,
+ Email := "mam49@st-andrews.ac.uk",
+ PostalAddress := _STANDREWSMATHS,
+ Place := "St Andrews",
+ Institution := "University of St Andrews"),
+
+ rec(
LastName := "De Beule",
FirstNames := "Jan",
IsAuthor := true,
@@ -89,6 +99,16 @@ Persons := [
Place := "St Andrews",
Institution := "University of St Andrews"),
+rec(
+ LastName := "Harper",
+ FirstNames := "Samantha",
+ IsAuthor := false,
+ IsMaintainer := false,
+ Email := "seh25@st-andrews.ac.uk",
+ PostalAddress := _STANDREWSMATHS,
+ Place := "St Andrews",
+ Institution := "University of St Andrews"),
+
rec(
LastName := "Horn",
FirstNames := "Max",
diff --git a/doc/digraphs.bib b/doc/digraphs.bib
index 43be8f3fd..ae41987e4 100644
--- a/doc/digraphs.bib
+++ b/doc/digraphs.bib
@@ -66,6 +66,19 @@ @inproceedings{JK07
Year = {2007},
}
+@article{LT79,
+ Author = {Thomas Lengauer and Robert E. Tarjan},
+ Doi = {https://doi.org/10.1145/357062.357071},
+ Journal = {ACM Transactions on Programming Languages and Systems},
+ Number = {1},
+ Pages = {121--141},
+ Title = {A Fast Algorithm for Finding Dominators in a Flowgraph},
+ Url = {https://doi.org/10.1145/357062.357071},
+ Volume = {1},
+ Year = {1979},
+ Bdsk-Url-1 = {https://www.cs.princeton.edu/courses/archive/spr03/cs423/download/dominators.pdf}
+}
+
@article{MP14,
Author = {Brendan D. McKay and Adolfo Piperno},
Doi = {http://dx.doi.org/10.1016/j.jsc.2013.09.003},
diff --git a/doc/oper.xml b/doc/oper.xml
index aa0db2330..3806ffcd6 100644
--- a/doc/oper.xml
+++ b/doc/oper.xml
@@ -1572,6 +1572,70 @@ gap> DigraphShortestDistance(D, [1, 3], [3, 5]);
<#/GAPDoc>
+<#GAPDoc Label="Dominators">
+
+
+ A list of lists
+
+ Dominators is a function that takes a digraph and a specific root
+ vertex and returns the dominators of each vertex with respect to
+ the root. The root must be a verex of the digraph. The algorithm is an
+ implementation of the fast algorith written by Thomas Lengauer and Robert
+ Endre Tarjan . If there is no path from the root to a specific vertex,
+ the output will contain a hole in the corresponding position. The complexity
+ of this algorithm is O(mlog n).
+ d := Digraph([[2], [3, 6], [2, 4], [1], [], [3]]);
+
+gap> Dominators(d, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 2, 1 ], [ 4, 3, 2, 1 ],, [ 6, 2, 1 ] ]
+gap> Dominators(d, 2);
+[ [ 1, 4, 3, 2 ], [ 2 ], [ 3, 2 ], [ 4, 3, 2 ],, [ 6, 2 ] ]
+gap> Dominators(d, 3);
+[ [ 1, 4, 3 ], [ 2, 3 ], [ 3 ], [ 4, 3 ],, [ 6, 2, 3 ] ]
+gap> Dominators(d, 4);
+[ [ 1, 4 ], [ 2, 1, 4 ], [ 3, 2, 1, 4 ], [ 4 ],, [ 6, 2, 1, 4 ] ]
+gap> Dominators(d, 5);
+[ ,,,, [ 5 ] ]
+gap> Dominators(d, 6);
+[ [ 1, 4, 3, 6 ], [ 2, 3, 6 ], [ 3, 6 ], [ 4, 3, 6 ],, [ 6 ] ]
+]]>
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="DominatorTree">
+
+
+ A record.
+
+DominatorTree is a function that takes a digraph and a specific root
+vertex and returns a record with the following components:
+idom- the immediate dominators of the vertices with
+respect to the root
preorder- the preorder values of the vertices defined by the
+depth first search executed on the digraph
sdom- the semidominators
+of the vertices with respect to the root.
The algorithm is an implementation
+of the fast algorithm written by Thomas Lengauer and Robert Endre Tarjan.
+ D := Digraph([[2, 3], [4, 6], [4, 5], [3, 5], [1, 6], [2, 3]]);
+
+gap> DominatorTree(D, 1);
+rec( idom := [ fail, 1, 1, 1, 1, 1 ], preorder := [ 1, 2, 4, 3, 5, 6 ], sdom := [ 1, 1, 1, 1, 4, 2 ] )
+gap> DominatorTree(D, 5);
+rec( idom := [ 5, 5, 5, 5, fail, 5 ], preorder := [ 5, 1, 2, 4, 3, 6 ], sdom := [ 5, 5, 5, 5, 5, 5 ] )
+gap> D := CompleteDigraph(5);
+
+gap> DominatorTree(D, 1);
+rec( idom := [ fail, 1, 1, 1, 1 ], preorder := [ 1, 2, 3, 4, 5 ], sdom := [ 1, 1, 1, 1, 1 ] )
+gap> DominatorTree(D, 2);
+rec( idom := [ 2, fail, 2, 2, 2 ], preorder := [ 2, 1, 3, 4, 5 ], sdom := [ 2, 2, 2, 2, 2 ] )
+]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="PartialOrderDigraphMeetOfVertices">
<#Include Label="DigraphPath">
<#Include Label="DigraphShortestPath">
+ <#Include Label="Dominators">
+ <#Include Label="DominatorTree">
<#Include Label="IteratorOfPaths">
<#Include Label="DigraphAllSimpleCircuits">
<#Include Label="DigraphLongestSimpleCircuit">
diff --git a/gap/oper.gd b/gap/oper.gd
index 0fe68990d..e5504a02b 100644
--- a/gap/oper.gd
+++ b/gap/oper.gd
@@ -118,6 +118,8 @@ DeclareOperation("DigraphShortestDistance", [IsDigraph, IsPosInt, IsPosInt]);
DeclareOperation("DigraphShortestDistance", [IsDigraph, IsList, IsList]);
DeclareOperation("DigraphShortestDistance", [IsDigraph, IsList]);
DeclareOperation("DigraphShortestPath", [IsDigraph, IsPosInt, IsPosInt]);
+DeclareOperation("Dominators", [IsDigraph, IsPosInt]);
+DeclareOperation("DominatorTree", [IsDigraph, IsPosInt]);
# 10. Operations for vertices . . .
DeclareOperation("PartialOrderDigraphJoinOfVertices",
diff --git a/gap/oper.gi b/gap/oper.gi
index a4a6f0614..593561888 100644
--- a/gap/oper.gi
+++ b/gap/oper.gi
@@ -1725,6 +1725,225 @@ function(D, list)
return DigraphShortestDistance(D, list[1], list[2]);
end);
+# This function is left here only for testing purposes, for the
+# faster version of dominators.
+# InstallMethod(DominatorsQuadratic, "for a digraph and vertex",
+# [IsDigraph, IsPosInt],
+# function(D, root)
+# local N, seen, parent, index, next, current, succ, prev, n, comp,
+# predecessors, dominators, changes, intersection, i, v, pred;
+
+ # Figure out what nodes are reachable from the root
+ # TODO this should be a separate function VerticesReachableFrom?
+# N := DigraphNrVertices(D);
+
+# if root > N then
+# ErrorNoReturn("Error, the 2nd argument is not a ",
+# "vertex of the 1st argument ,");
+# fi;
+
+# seen := BlistList([1 .. N], [root]);
+
+# parent := [];
+# parent[root] := fail;
+# index := ListWithIdenticalEntries(N, 1);
+
+# next := 2;
+# current := root;
+# succ := OutNeighbours(D);
+
+ # Step 1: DFS to establish preorder
+# repeat
+# prev := current;
+# for i in [index[current] .. Length(succ[current])] do
+# n := succ[current][i];
+# if not seen[n] then
+# seen[n] := true;
+# parent[n] := current;
+# index[current] := i + 1;
+# next := next + 1;
+# current := n;
+# break;
+# fi;
+# od;
+ # continues from here
+# if prev = current then
+ # we backtrack
+# current := parent[current];
+# fi;
+# until current = fail;
+
+# comp := ListBlist([1 .. N], seen);
+# predecessors := InNeighbours(D);
+
+# dominators := List(DigraphVertices(D), x -> []);
+# dominators{comp} := List(comp, x -> ShallowCopy(comp));
+# dominators[root] := [root];
+
+# repeat
+# changes := false;
+# for v in comp do
+# if v <> root then
+# if not IsEmpty(predecessors[v]) then
+# intersection := ShallowCopy(comp);
+# for pred in predecessors[v] do
+# if seen[pred] then
+# IntersectSet(intersection, dominators[pred]);
+# fi;
+# od;
+# else
+# intersection := [];
+# fi;
+
+# AddSet(intersection, v);
+# if intersection <> dominators[v] then
+# changes := true;
+# dominators[v] := intersection;
+# fi;
+# fi;
+# od;
+# until changes = false;
+# return dominators;
+# end);
+
+InstallMethod(DominatorTree, "for a digraph and a vertex",
+[IsDigraph, IsPosInt],
+function(D, root)
+ local N, node_to_preorder_num, preorder_num_to_node, parent, index, next,
+ current, succ, prev, n, semi, label, ancestor, bucket, idom,
+ compress, eval, pred, w, y, x, i, v;
+
+ N := DigraphNrVertices(D);
+
+ node_to_preorder_num := [];
+ node_to_preorder_num[root] := 1;
+ preorder_num_to_node := [root];
+
+ parent := [];
+ parent[root] := fail;
+
+ index := ListWithIdenticalEntries(N, 1);
+
+ next := 2;
+ current := root;
+ succ := OutNeighbours(D);
+
+ # Step 1: DFS to establish preorder
+ repeat
+ prev := current;
+ for i in [index[current] .. Length(succ[current])] do
+ n := succ[current][i];
+ if not IsBound(node_to_preorder_num[n]) then
+ Add(preorder_num_to_node, n);
+ parent[n] := current;
+ index[current] := i + 1;
+ node_to_preorder_num[n] := next;
+ next := next + 1;
+ current := n;
+ break;
+ fi;
+ od;
+ # continues from here
+ if prev = current then
+ # we backtrack
+ current := parent[current];
+ fi;
+ until current = fail;
+
+ # Step 2: find semidominators, and first pass of immediate dominators
+ semi := [1 .. N];
+ label := [];
+ ancestor := ListWithIdenticalEntries(N, 0);
+ bucket := List([1 .. N], x -> []);
+ idom := [];
+ idom[root] := root;
+
+ compress := function(v)
+ local u;
+ u := ancestor[v];
+ if ancestor[u] <> 0 then
+ compress(u);
+ if node_to_preorder_num[semi[label[u]]]
+ < node_to_preorder_num[semi[label[v]]] then
+ label[v] := label[u];
+ fi;
+ ancestor[v] := ancestor[u];
+ fi;
+ end;
+
+ eval := function(v)
+ if ancestor[v] <> 0 then
+ compress(v);
+ return label[v];
+ else
+ return v;
+ fi;
+ end;
+
+ pred := InNeighbours(D);
+ N := Length(preorder_num_to_node);
+ for i in [N, N - 1 .. 2] do
+ w := preorder_num_to_node[i];
+ for v in bucket[w] do
+ y := eval(v);
+ if node_to_preorder_num[semi[y]] < node_to_preorder_num[w] then
+ idom[v] := y;
+ else
+ idom[v] := w;
+ fi;
+ od;
+ bucket[w] := [];
+ for v in pred[w] do
+ if IsBound(node_to_preorder_num[v]) then
+ # Node is reachable from root
+ x := eval(v);
+ if node_to_preorder_num[semi[x]] < node_to_preorder_num[semi[w]] then
+ semi[w] := semi[x];
+ fi;
+ fi;
+ od;
+ # if parent[w] = semi[w] then
+ # idom[w] := parent[w];
+ # else
+ Add(bucket[semi[w]], w);
+ # fi;
+ ancestor[w] := parent[w];
+ label[w] := semi[w];
+ od;
+ for v in bucket[root] do
+ idom[v] := root;
+ od;
+
+ # Step 3: finalize immediate dominators
+ for i in [2 .. N] do
+ w := preorder_num_to_node[i];
+ if idom[w] <> semi[w] then
+ idom[w] := idom[semi[w]];
+ fi;
+ od;
+ idom[root] := fail;
+ return rec(idom := idom, preorder := preorder_num_to_node, sdom := semi);
+end);
+
+InstallMethod(Dominators, "for a digraph and a vertex",
+[IsDigraph, IsPosInt],
+function(D, root)
+ local tree, preorder, result, u, v;
+ tree := DominatorTree(D, root);
+ preorder := tree.preorder;
+ tree := tree.idom;
+ result := [];
+ for v in preorder do
+ result[v] := [v];
+ u := tree[v];
+ if u <> fail then
+ Append(result[v], result[u]);
+ fi;
+ od;
+ # Perform(result, Sort);
+ return result;
+end);
+
#############################################################################
# 10. Operations for vertices
#############################################################################
diff --git a/tst/standard/oper.tst b/tst/standard/oper.tst
index e5d50270a..8b21b7894 100644
--- a/tst/standard/oper.tst
+++ b/tst/standard/oper.tst
@@ -2110,6 +2110,213 @@ gap> OutNeighbours(last);
[ 22, 24, 32, 34, 37, 39, 1, 5, 6, 10, 11, 15, 16, 20, 26, 30, 41, 45, 48 ],
[ 23, 25, 33, 35, 38, 40, 1, 2, 6, 7, 11, 12, 16, 17, 26, 27, 41, 42, 49 ],
[ 21, 24, 31, 34, 36, 39, 2, 3, 7, 8, 12, 13, 17, 18, 27, 28, 42, 43, 50 ] ]
+#
+gap> D := Digraph([[2], [3, 4, 6], [5], [5], [2], []]);
+
+gap> D := CompleteDigraph(5);
+
+gap> D := DigraphDisjointUnion(D, D);
+
+gap> D := NullDigraph(10);
+
+gap> D := ChainDigraph(10000);
+
+gap> D := Digraph([[1, 2, 3], [4], [1, 5], [], [2]]);;
+gap> D := CompleteDigraph(5);
+
+gap> Dominators(D, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 1 ], [ 4, 1 ], [ 5, 1 ] ]
+gap> Dominators(D, 2);
+[ [ 1, 2 ], [ 2 ], [ 3, 2 ], [ 4, 2 ], [ 5, 2 ] ]
+gap> Dominators(D, 5);
+[ [ 1, 5 ], [ 2, 5 ], [ 3, 5 ], [ 4, 5 ], [ 5 ] ]
+gap> D := CycleDigraph(10);
+
+gap> Dominators(D, 5);
+[ [ 1, 10, 9, 8, 7, 6, 5 ], [ 2, 1, 10, 9, 8, 7, 6, 5 ],
+ [ 3, 2, 1, 10, 9, 8, 7, 6, 5 ], [ 4, 3, 2, 1, 10, 9, 8, 7, 6, 5 ], [ 5 ],
+ [ 6, 5 ], [ 7, 6, 5 ], [ 8, 7, 6, 5 ], [ 9, 8, 7, 6, 5 ],
+ [ 10, 9, 8, 7, 6, 5 ] ]
+gap> D := Digraph([[3, 4], [1, 4], [2, 5], [3, 5], []]);
+
+gap> Dominators(D, 1);
+[ [ 1 ], [ 2, 3, 1 ], [ 3, 1 ], [ 4, 1 ], [ 5, 1 ] ]
+gap> Dominators(D, 2);
+[ [ 1, 2 ], [ 2 ], [ 3, 2 ], [ 4, 2 ], [ 5, 2 ] ]
+gap> Dominators(D, 3);
+[ [ 1, 2, 3 ], [ 2, 3 ], [ 3 ], [ 4, 2, 3 ], [ 5, 3 ] ]
+gap> Dominators(D, 4);
+[ [ 1, 2, 3, 4 ], [ 2, 3, 4 ], [ 3, 4 ], [ 4 ], [ 5, 4 ] ]
+gap> Dominators(D, 5);
+[ ,,,, [ 5 ] ]
+gap> d := Digraph([[2, 3], [4, 6], [4, 5], [3, 5], [1, 6], [2, 3]]);
+
+gap> Dominators(d, 5);
+[ [ 1, 5 ], [ 2, 5 ], [ 3, 5 ], [ 4, 5 ], [ 5 ], [ 6, 5 ] ]
+gap> Dominators(d, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 1 ], [ 4, 1 ], [ 5, 1 ], [ 6, 1 ] ]
+gap> Dominators(d, 3);
+[ [ 1, 5, 3 ], [ 2, 5, 3 ], [ 3 ], [ 4, 3 ], [ 5, 3 ], [ 6, 5, 3 ] ]
+gap> Dominators(d, 4);
+[ [ 1, 5, 4 ], [ 2, 5, 4 ], [ 3, 4 ], [ 4 ], [ 5, 4 ], [ 6, 5, 4 ] ]
+gap> Dominators(d, 6);
+[ [ 1, 5, 6 ], [ 2, 6 ], [ 3, 6 ], [ 4, 6 ], [ 5, 6 ], [ 6 ] ]
+gap> d := Digraph([[], [3], [4, 5], [2], [4]]);
+
+gap> Dominators(d, 1);
+[ [ 1 ] ]
+gap> Dominators(d, 2);
+[ , [ 2 ], [ 3, 2 ], [ 4, 3, 2 ], [ 5, 3, 2 ] ]
+gap> Dominators(d, 3);
+[ , [ 2, 4, 3 ], [ 3 ], [ 4, 3 ], [ 5, 3 ] ]
+gap> Dominators(d, 4);
+[ , [ 2, 4 ], [ 3, 2, 4 ], [ 4 ], [ 5, 3, 2, 4 ] ]
+gap> Dominators(d, 5);
+[ , [ 2, 4, 5 ], [ 3, 2, 4, 5 ], [ 4, 5 ], [ 5 ] ]
+gap> D := Digraph([[2, 3, 5], [1, 6], [4, 6, 7], [7, 8], [4], [], [8], []]);
+
+gap> Dominators(D, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 1 ], [ 4, 1 ], [ 5, 1 ], [ 6, 1 ], [ 7, 1 ], [ 8, 1 ]
+ ]
+gap> Dominators(D, 2);
+[ [ 1, 2 ], [ 2 ], [ 3, 1, 2 ], [ 4, 1, 2 ], [ 5, 1, 2 ], [ 6, 2 ],
+ [ 7, 1, 2 ], [ 8, 1, 2 ] ]
+gap> Dominators(D, 3);
+[ ,, [ 3 ], [ 4, 3 ],, [ 6, 3 ], [ 7, 3 ], [ 8, 3 ] ]
+gap> Dominators(D, 4);
+[ ,,, [ 4 ],,, [ 7, 4 ], [ 8, 4 ] ]
+gap> Dominators(D, 5);
+[ ,,, [ 4, 5 ], [ 5 ],, [ 7, 4, 5 ], [ 8, 4, 5 ] ]
+gap> Dominators(D, 6);
+[ ,,,,, [ 6 ] ]
+gap> Dominators(D, 7);
+[ ,,,,,, [ 7 ], [ 8, 7 ] ]
+gap> Dominators(D, 8);
+[ ,,,,,,, [ 8 ] ]
+gap> d := Digraph([[2], [3, 6], [2, 4], [1], [], [3]]);
+
+gap> Dominators(d, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 2, 1 ], [ 4, 3, 2, 1 ],, [ 6, 2, 1 ] ]
+gap> Dominators(d, 2);
+[ [ 1, 4, 3, 2 ], [ 2 ], [ 3, 2 ], [ 4, 3, 2 ],, [ 6, 2 ] ]
+gap> Dominators(d, 3);
+[ [ 1, 4, 3 ], [ 2, 3 ], [ 3 ], [ 4, 3 ],, [ 6, 2, 3 ] ]
+gap> Dominators(d, 4);
+[ [ 1, 4 ], [ 2, 1, 4 ], [ 3, 2, 1, 4 ], [ 4 ],, [ 6, 2, 1, 4 ] ]
+gap> Dominators(d, 5);
+[ ,,,, [ 5 ] ]
+gap> Dominators(d, 6);
+[ [ 1, 4, 3, 6 ], [ 2, 3, 6 ], [ 3, 6 ], [ 4, 3, 6 ],, [ 6 ] ]
+gap> d := Digraph([[1, 2, 3], [4, 5], [1, 3], [3, 5], [4]]);
+
+gap> Dominators(d, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 1 ], [ 4, 2, 1 ], [ 5, 2, 1 ] ]
+gap> Dominators(d, 2);
+[ [ 1, 3, 4, 2 ], [ 2 ], [ 3, 4, 2 ], [ 4, 2 ], [ 5, 2 ] ]
+gap> Dominators(d, 3);
+[ [ 1, 3 ], [ 2, 1, 3 ], [ 3 ], [ 4, 2, 1, 3 ], [ 5, 2, 1, 3 ] ]
+gap> Dominators(d, 4);
+[ [ 1, 3, 4 ], [ 2, 1, 3, 4 ], [ 3, 4 ], [ 4 ], [ 5, 4 ] ]
+gap> Dominators(d, 5);
+[ [ 1, 3, 4, 5 ], [ 2, 1, 3, 4, 5 ], [ 3, 4, 5 ], [ 4, 5 ], [ 5 ] ]
+gap> D := Digraph([[1, 2, 3], [4], [1, 5], [], [2]]);
+
+gap> Dominators(D, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 1 ], [ 4, 2, 1 ], [ 5, 3, 1 ] ]
+gap> Dominators(D, 2);
+[ , [ 2 ],, [ 4, 2 ] ]
+gap> Dominators(D, 3);
+[ [ 1, 3 ], [ 2, 3 ], [ 3 ], [ 4, 2, 3 ], [ 5, 3 ] ]
+gap> Dominators(D, 4);
+[ ,,, [ 4 ] ]
+gap> Dominators(D, 5);
+[ , [ 2, 5 ],, [ 4, 2, 5 ], [ 5 ] ]
+gap> D := EmptyDigraph(15);
+
+gap> Dominators(D, 3);
+[ ,, [ 3 ] ]
+gap> D := Digraph(IsMutableDigraph, [[1, 2, 3], [4], [1, 5], [], [2]]);
+
+gap> Dominators(D, 5);
+[ , [ 2, 5 ],, [ 4, 2, 5 ], [ 5 ] ]
+gap> Dominators(D, 4);
+[ ,,, [ 4 ] ]
+gap> Dominators(D, 3);
+[ [ 1, 3 ], [ 2, 3 ], [ 3 ], [ 4, 2, 3 ], [ 5, 3 ] ]
+gap> Dominators(D, 2);
+[ , [ 2 ],, [ 4, 2 ] ]
+gap> Dominators(D, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 1 ], [ 4, 2, 1 ], [ 5, 3, 1 ] ]
+gap> D := Digraph(IsMutableDigraph, [[2, 3, 5], [1, 6], [4, 6, 7], [7, 8], [4], [], [8], []]);
+
+gap> Dominators(D, 1);
+[ [ 1 ], [ 2, 1 ], [ 3, 1 ], [ 4, 1 ], [ 5, 1 ], [ 6, 1 ], [ 7, 1 ], [ 8, 1 ]
+ ]
+gap> Dominators(D, 2);
+[ [ 1, 2 ], [ 2 ], [ 3, 1, 2 ], [ 4, 1, 2 ], [ 5, 1, 2 ], [ 6, 2 ],
+ [ 7, 1, 2 ], [ 8, 1, 2 ] ]
+gap> Dominators(D, 3);
+[ ,, [ 3 ], [ 4, 3 ],, [ 6, 3 ], [ 7, 3 ], [ 8, 3 ] ]
+gap> Dominators(D, 4);
+[ ,,, [ 4 ],,, [ 7, 4 ], [ 8, 4 ] ]
+gap> Dominators(D, 5);
+[ ,,, [ 4, 5 ], [ 5 ],, [ 7, 4, 5 ], [ 8, 4, 5 ] ]
+gap> Dominators(D, 6);
+[ ,,,,, [ 6 ] ]
+gap> Dominators(D, 7);
+[ ,,,,,, [ 7 ], [ 8, 7 ] ]
+gap> Dominators(D, 8);
+[ ,,,,,,, [ 8 ] ]
+
+# DominatorTree
+gap> D := CompleteDigraph(5);
+
+gap> DominatorTree(D, 1);
+rec( idom := [ fail, 1, 1, 1, 1 ], preorder := [ 1, 2, 3, 4, 5 ],
+ sdom := [ 1, 1, 1, 1, 1 ] )
+gap> DominatorTree(D, 2);
+rec( idom := [ 2, fail, 2, 2, 2 ], preorder := [ 2, 1, 3, 4, 5 ],
+ sdom := [ 2, 2, 2, 2, 2 ] )
+gap> DominatorTree(D, 3);
+rec( idom := [ 3, 3, fail, 3, 3 ], preorder := [ 3, 1, 2, 4, 5 ],
+ sdom := [ 3, 3, 3, 3, 3 ] )
+gap> DominatorTree(D, 4);
+rec( idom := [ 4, 4, 4, fail, 4 ], preorder := [ 4, 1, 2, 3, 5 ],
+ sdom := [ 4, 4, 4, 4, 4 ] )
+gap> DominatorTree(D, 5);
+rec( idom := [ 5, 5, 5, 5, fail ], preorder := [ 5, 1, 2, 3, 4 ],
+ sdom := [ 5, 5, 5, 5, 5 ] )
+gap> D := CycleDigraph(10);
+
+gap> DominatorTree(D, 1);
+rec( idom := [ fail, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
+ preorder := [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
+ sdom := [ 1, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] )
+gap> DominatorTree(D, 2);
+rec( idom := [ 10, fail, 2, 3, 4, 5, 6, 7, 8, 9 ],
+ preorder := [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 1 ],
+ sdom := [ 10, 2, 2, 3, 4, 5, 6, 7, 8, 9 ] )
+gap> DominatorTree(D, 5);
+rec( idom := [ 10, 1, 2, 3, fail, 5, 6, 7, 8, 9 ],
+ preorder := [ 5, 6, 7, 8, 9, 10, 1, 2, 3, 4 ],
+ sdom := [ 10, 1, 2, 3, 5, 5, 6, 7, 8, 9 ] )
+gap> D := Digraph([[2, 3], [4, 6], [4, 5], [3, 5], [1, 6], [2, 3]]);
+
+gap> DominatorTree(D, 1);
+rec( idom := [ fail, 1, 1, 1, 1, 1 ], preorder := [ 1, 2, 4, 3, 5, 6 ],
+ sdom := [ 1, 1, 1, 1, 4, 2 ] )
+gap> DominatorTree(D, 5);
+rec( idom := [ 5, 5, 5, 5, fail, 5 ], preorder := [ 5, 1, 2, 4, 3, 6 ],
+ sdom := [ 5, 5, 5, 5, 5, 5 ] )
+gap> DominatorTree(D, 6);
+rec( idom := [ 5, 6, 6, 6, 6, fail ], preorder := [ 6, 2, 4, 3, 5, 1 ],
+ sdom := [ 5, 6, 6, 6, 4, 6 ] )
+gap> D := EmptyDigraph(15);
+
+gap> DominatorTree(D, 1);
+rec( idom := [ fail ], preorder := [ 1 ], sdom := [ 1 .. 15 ] )
+gap> DominatorTree(D, 6);
+rec( idom := [ ,,,,, fail ], preorder := [ 6 ], sdom := [ 1 .. 15 ] )
#DIGRAPHS_UnbindVariables
gap> Unbind(a);