-
Notifications
You must be signed in to change notification settings - Fork 65
ExecuteDFS (generic depth first search) #459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 58 commits
55b4760
972aa22
cb26213
c7376d9
c3a1b25
976f5db
a4a4be7
5b44346
e478973
67ce8d2
a92aa88
80864f0
f76b728
6755e84
054050f
4ced3e8
51b6aa0
197e24a
4df9bfe
d4b5a6b
27cd4c9
a95f5d2
4fdec16
1df8f45
163ec48
176e61f
29dc997
718aab3
fc14567
a0b5b18
d4cdc50
68f58d6
3ea0590
2626b0a
9383335
00afd60
804da96
5bcbf23
7656429
e78bcdc
96006cd
4b6b7b9
2baf42c
201a2e2
48c169e
2f76d58
bd027ce
7ae7123
5bcdae4
3fef2a8
a519cc0
2a2c866
2310751
2408daf
fcc53af
c084a8e
da0a9aa
c64d54f
653376d
2103189
7704cd4
a784b93
3e6dacd
31393b8
383c8db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -1321,7 +1321,7 @@ gap> D := CompleteDigraph(5); | |||||
| gap> VerticesReachableFrom(D, 1); | ||||||
| [ 2, 1, 3, 4, 5 ] | ||||||
| gap> VerticesReachableFrom(D, 3); | ||||||
| [ 1, 2, 3, 4, 5 ] | ||||||
| [ 1, 3, 2, 4, 5 ] | ||||||
| gap> D := EmptyDigraph(5); | ||||||
| <immutable empty digraph with 5 vertices> | ||||||
| gap> VerticesReachableFrom(D, 1); | ||||||
|
|
@@ -1964,3 +1964,157 @@ gap> ModularProduct(NullDigraph(0), CompleteDigraph(10)); | |||||
| </Description> | ||||||
| </ManSection> | ||||||
| <#/GAPDoc> | ||||||
|
|
||||||
| <#GAPDoc Label="NewDFSRecord"> | ||||||
| <ManSection> | ||||||
| <Oper Name="NewDFSRecord" Arg="digraph"/> | ||||||
| <Returns>A record.</Returns> | ||||||
| <Description> | ||||||
| This record contains three lists (parent, preorder and postorder) with their length | ||||||
| equal to the number of verticies in the <A>digraph</A>. Each index of the lists maps to the | ||||||
| vertex within the <A>digraph</A> equating to the vertex number. These lists store | ||||||
| the following: | ||||||
| <List> | ||||||
| <Item><E>parent</E>: at each index, the parent of the vertex is stored</Item> | ||||||
| <Item><E>preorder</E>: at each index, the preorder number (order in which the vertex is visited) | ||||||
| is stored</Item> | ||||||
| <Item><E>postorder</E>: at each index, the postorder number (order in which the vertex is backtracked on) | ||||||
| is stored</Item> | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| </List> | ||||||
|
|
||||||
| The record also stores a further 4 attributes. | ||||||
| <List> | ||||||
| <Item><E>current</E>: the current vertex that is being visited</Item> | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe use mark here too? |
||||||
| <Item><E>child</E>: the child of the current vertex</Item> | ||||||
| <Item><E>graph</E>: the <A>digraph</A></Item> | ||||||
| <Item><E>stop</E>: whether to stop the depth first search</Item> | ||||||
| </List> | ||||||
|
|
||||||
| Initially, the current and child attributes will have -1 values and the lists (parent, | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| preorder and postorder) will have -1 values at all of their indicies as no vertex has | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| been visited. The stop attribute will initially be false. | ||||||
| <E>This record should be passed into the ExecuteDFS function.</E> | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| See <Ref Func="ExecuteDFS" Label="for a record, object, integer and 4 functions"/>. | ||||||
| <Example><![CDATA[ | ||||||
| gap> record := NewDFSRecord(CompleteDigraph(2)); | ||||||
| rec( child := -1, current := -1, | ||||||
| graph := <immutable complete digraph with 2 vertices>, | ||||||
| parent := [ -1, -1 ], postorder := [ -1, -1 ], | ||||||
| preorder := [ -1, -1 ], stop := false ) | ||||||
| gap> record.preorder; | ||||||
| [ -1, -1 ] | ||||||
| gap> record.postorder; | ||||||
| [ -1, -1 ] | ||||||
| gap> record.stop; | ||||||
| false | ||||||
| gap> record.parent; | ||||||
| [ -1, -1 ] | ||||||
| gap> record.child; | ||||||
| -1 | ||||||
| gap> record.current; | ||||||
| -1 | ||||||
| gap> record.graph; | ||||||
| <immutable complete digraph with 2 vertices> | ||||||
| ]]></Example> | ||||||
| </Description> | ||||||
| </ManSection> | ||||||
| <#/GAPDoc> | ||||||
|
|
||||||
| <#GAPDoc Label="DFSDefault"> | ||||||
| <ManSection> | ||||||
| <Oper Name="DFSDefault" Arg="record, data"/> | ||||||
| <Description> | ||||||
| This is a default function to be passed into the ExecuteDFS function. | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| This does nothing and can be used in place of the PreOrderFunc, PostOrderFunc, | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| AncestorFunc and/or CrossFunc of the ExecuteDFS function. | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| See <Ref Func="ExecuteDFS" Label="for a record, object, integer and 4 functions"/>. | ||||||
| <Example><![CDATA[ | ||||||
| gap> PreOrderFunc := function(record, data) | ||||||
| > data.num_vertices := data.num_vertices + 1; | ||||||
| > end;; | ||||||
| gap> record := NewDFSRecord(CompleteDigraph(2));; | ||||||
| gap> data := rec(num_vertices := 0);; | ||||||
| gap> ExecuteDFS(record, data, 1, PreOrderFunc, | ||||||
| > DFSDefault, DFSDefault, DFSDefault); | ||||||
| gap> data; | ||||||
| rec( num_vertices := 2 ) | ||||||
| gap> record := NewDFSRecord(CompleteDigraph(2));; | ||||||
| gap> ExecuteDFS(record, [], 1, DFSDefault, | ||||||
| > DFSDefault, DFSDefault, DFSDefault); | ||||||
| gap> record; | ||||||
| rec( child := 1, current := 1, | ||||||
| graph := <immutable complete digraph with 2 vertices>, | ||||||
| parent := [ 1, 1 ], postorder := [ 2, 1 ], preorder := [ 1, 2 ], | ||||||
| stop := false ) | ||||||
| ]]></Example> | ||||||
| </Description> | ||||||
| </ManSection> | ||||||
| <#/GAPDoc> | ||||||
|
|
||||||
| <#GAPDoc Label="ExecuteDFS"> | ||||||
| <ManSection> | ||||||
| <Oper Name="ExecuteDFS" Arg="record, data, start, PreOrderFunc, PostOrderFunc, AncestorFunc, | ||||||
| CrossFunc"/> | ||||||
| <Description> | ||||||
| This performs a full depth first search from the <A>start</A> vertex (where <A>start</A> is within the graph). | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| The depth first search can be terminated by changing the <A>record</A>.stop attribute to true in the | ||||||
| <A>PreOrderFunc</A>, <A>PostOrderFunc</A>, <A>AncestorFunc</A> or <A>CrossFunc</A> functions. | ||||||
| ExecuteDFS takes 7 arguments: | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| <List> | ||||||
| <Item><A>record</A>: the depth first search record (created using NewDFSRecord)</Item> | ||||||
| <Item><A>data</A>: an object that you want manipulate in the functions passed.</Item> | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| <Item><A>start</A>: the vertex where we begin the depth first search.</Item> | ||||||
| <Item><A>PreOrderFunc</A>: this function is called when a vertex is first visited. This vertex | ||||||
| is stored in <A>record</A>.current</Item> | ||||||
| <Item><A>PostOrderFunc</A>: this function is called when a vertex has no more unvisited children | ||||||
| causing us to backtrack. This vertex is stored in <A>record</A>.child and its parent is stored | ||||||
| in <A>record</A>.current</Item> | ||||||
| <Item><A>AncestorFunc</A>: this function is called when (<A>record</A>.current, | ||||||
| <A>record</A>.child) is an edge and <A>record</A>.child is an ancestor of <A>record</A>.current. An ancestor here means that | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| <A>record</A>.child is on the same branch as <A>record</A>.current but was visited prior to <A>record</A>.current</Item> | ||||||
| <Item><A>CrossFunc</A>: this function is called when (<A>record</A>.current, | ||||||
| <A>record</A>.child) is an edge and <A>record</A>.child has been visited before <A>record</A>.current | ||||||
| and it is not an ancestor of <A>record</A>.current</Item> | ||||||
| </List> | ||||||
| Note that this function only performs a depth first search on the connected graph that has <A>start</A>. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think however that this line should be completely changed to "the digraph induced by the vertices reachable from start.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this is much clearer! |
||||||
| To perform a depth first search on unconnected components, you need to call this function with a <A>start</A> that is | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| within those unconnected components. It is also important to note that all functions passed need to accept 2 arguments | ||||||
| (<A>record</A>, <A>data</A>). Finally, for the <A>start</A> vertex, its parent is itself and the <A>PreOrderFunc</A> | ||||||
|
LRacine marked this conversation as resolved.
Outdated
|
||||||
| will be called on it. | ||||||
| See <Ref Oper="NewDFSRecord"/>. | ||||||
| <Example><![CDATA[ | ||||||
| gap> record := NewDFSRecord(CycleDigraph(10));; | ||||||
| gap> ExecuteDFS(record, [], 1, DFSDefault, | ||||||
| > DFSDefault, DFSDefault, DFSDefault); | ||||||
| gap> record.preorder; | ||||||
| [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] | ||||||
| gap> record := NewDFSRecord(CompleteDigraph(10));; | ||||||
| gap> data := rec(cycle_vertex := 0);; | ||||||
| gap> AncestorFunc := function(record, data) | ||||||
| > record.stop := true; | ||||||
| > data.cycle_vertex := record.child; | ||||||
| > end;; | ||||||
| gap> ExecuteDFS(record, data, 1, DFSDefault, | ||||||
| > DFSDefault, AncestorFunc, DFSDefault); | ||||||
| gap> record.stop; | ||||||
| true | ||||||
| gap> data.cycle_vertex; | ||||||
| 1 | ||||||
| gap> record.preorder; | ||||||
| [ 1, 2, 3, -1, -1, -1, -1, -1, -1, -1 ] | ||||||
| gap> record := NewDFSRecord(Digraph([[2, 3], [4], [5], [], [4]]));; | ||||||
| gap> CrossFunc := function(record, data) | ||||||
| > record.stop := true; | ||||||
| > Add(data, record.child); | ||||||
| > end;; | ||||||
| gap> data := [];; | ||||||
| gap> ExecuteDFS(record, data, 1, DFSDefault, | ||||||
| > DFSDefault, DFSDefault, CrossFunc); | ||||||
| gap> record.stop; | ||||||
| true | ||||||
| gap> data; | ||||||
| [ 4 ] | ||||||
| ]]></Example> | ||||||
| </Description> | ||||||
| </ManSection> | ||||||
| <#/GAPDoc> | ||||||
Uh oh!
There was an error while loading. Please reload this page.