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