depth-first graph traversal of the dag.
This will visit each node in the graph once, and call the userfunc
.
If some nodes are not connected to ivertex
, then they will not be visited.
Todo
Should also add a bfs option.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(dag), | intent(inout) | :: | me | |||
integer(kind=ip), | intent(in) | :: | ivertex |
the vertex number to start on |
||
procedure(traverse_func) | :: | userfunc |
a user-provided function that will be called for each vertex/edge combination |
subroutine dag_traverse(me,ivertex,userfunc) class(dag),intent(inout) :: me integer(ip),intent(in) :: ivertex !! the vertex number to start on procedure(traverse_func) :: userfunc !! a user-provided function that will !! be called for each vertex/edge combination if (me%n==0) return ! nothing to do if (ivertex<0 .or. ivertex>me%n) error stop 'invalid vertex number in dag_traverse' ! initialize internal variables, in case ! we have called this routine before. call me%init_internal_vars() call dfs(ivertex) contains recursive subroutine dfs(ivertex,iedge) !! depth-first graph traversal integer(ip),intent(in) :: ivertex !! the vertex integer(ip),intent(in),optional :: iedge !! the edge index for this vertex if (present(iedge)) then ! visiting an edge associate ( v => me%vertices(me%vertices(ivertex)%edges(iedge)%ivertex) ) if (done(v,ivertex,iedge)) return end associate else ! the starting node, no edge associate ( v => me%vertices(ivertex) ) if (done(v,ivertex,iedge)) return end associate end if end subroutine dfs recursive function done(v,iv,ie) result(user_stop) !! process this vertex in the [[dfs]] and return true if done. type(vertex),intent(inout) :: v !! vertex to process logical :: user_stop !! if the user has signaled to stop integer(ip),intent(in) :: iv !! the vertex number integer(ip),intent(in),optional :: ie !! the edge index for this vertex (if this is an edge) integer(ip) :: jedge !! edge counter if (v%marked) return ! this one has already been visited v%marked = .true. ! ! call the user's function for this node/edge combo: call userfunc(iv,user_stop,ie) if (.not. user_stop) then ! continue traversing if (allocated(v%edges)) then do jedge = 1,size(v%edges) call dfs(v%ivertex,jedge) if (user_stop) return end do end if end if end function done end subroutine dag_traverse