dag_traverse Subroutine

private subroutine dag_traverse(me, ivertex, userfunc)

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 Bound

dag

Arguments

Type IntentOptional 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


Calls

proc~~dag_traverse~~CallsGraph proc~dag_traverse dag_module::dag%dag_traverse proc~init_internal_vars dag_module::dag%init_internal_vars proc~dag_traverse->proc~init_internal_vars

Source Code

    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