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: +idomthe immediate dominators of the vertices with +respect to the rootpreorderthe preorder values of the vertices defined by the +depth first search executed on the digraphsdomthe 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);