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..15bb16e80 100644
--- a/doc/oper.xml
+++ b/doc/oper.xml
@@ -1572,6 +1572,93 @@ 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 root 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 almost linear time algorithm 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) where m and n are the
+ number of edges and number of nodes in the subdigraph induced by the nodes
+ in digraph reachable from root, respectively.
+ 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 .
+The complexity of this algorithm is
+O(mlog n) where m and n are the
+number of edges and number of nodes in the subdigraph induced by the nodes
+in digraph reachable from root, respectively.
+
+ 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..8d6e38c3f 100644
--- a/gap/oper.gi
+++ b/gap/oper.gi
@@ -1725,6 +1725,146 @@ function(D, list)
return DigraphShortestDistance(D, list[1], list[2]);
end);
+InstallMethod(DominatorTree, "for a digraph and a vertex",
+[IsDigraph, IsPosInt],
+function(D, root)
+ local M, node_to_preorder_num, preorder_num_to_node, parent, index, next,
+ current, succ, prev, n, semi, lastlinked, label, bucket, idom,
+ compress, eval, pred, N, w, y, x, i, v;
+
+ M := DigraphNrVertices(D);
+
+ node_to_preorder_num := [];
+ node_to_preorder_num[root] := 1;
+ preorder_num_to_node := [root];
+
+ parent := [];
+ parent[root] := fail;
+
+ index := ListWithIdenticalEntries(M, 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 .. M];
+ lastlinked := M + 1; # never linked
+ label := [];
+ bucket := List([1 .. M], x -> []);
+ idom := [];
+ idom[root] := root;
+
+ compress := function(v)
+ local u;
+ u := parent[v];
+ if u <> fail and lastlinked <= M and node_to_preorder_num[u] >=
+ node_to_preorder_num[lastlinked] then
+ compress(u);
+ if node_to_preorder_num[semi[label[u]]]
+ < node_to_preorder_num[semi[label[v]]] then
+ label[v] := label[u];
+ fi;
+ parent[v] := parent[u];
+ fi;
+ end;
+
+ eval := function(v)
+ if lastlinked <= M and node_to_preorder_num[v] >=
+ node_to_preorder_num[lastlinked] 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;
+ lastlinked := 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..31140917e 100644
--- a/tst/standard/oper.tst
+++ b/tst/standard/oper.tst
@@ -2002,8 +2002,7 @@ gap> OutNeighbours(C);
[ [ 5, 6, 7 ], [ 7 ], [ 7 ], [ 7 ], [ 1, 6, 7 ], [ 1, 5, 7 ],
[ 3, 2, 1, 6, 5, 4 ] ]
-#DigraphDijkstra
-# When there is one path to target
+# DigraphDijkstra - when there is one path to target
gap> mat := [[0, 1, 1], [0, 0, 1], [0, 0, 0]];
[ [ 0, 1, 1 ], [ 0, 0, 1 ], [ 0, 0, 0 ] ]
gap> gr := DigraphByAdjacencyMatrix(mat);
@@ -2043,7 +2042,7 @@ gap> DigraphDijkstra(gr, 1, 2);
gap> DigraphDijkstra(gr, 1, 3);
[ [ 0, 1, 1, 1 ], [ -1, 1, 1, 1 ] ]
-#ModularProduct
+# ModularProduct
gap> ModularProduct(NullDigraph(0), CompleteDigraph(10));
gap> ModularProduct(PetersenGraph(), CompleteDigraph(10));
@@ -2111,6 +2110,214 @@ gap> OutNeighbours(last);
[ 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 ] ]
+# Dominators
+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);
gap> Unbind(adj);