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