14 integer,
dimension(:),
allocatable :: edges
15 integer :: ivertex = 0
16 logical :: checking = .false.
17 logical :: marked = .false.
18 character(len=:),
allocatable :: label
19 character(len=:),
allocatable :: attributes
30 type(
vertex),
dimension(:),
allocatable :: vertices
53 class(
dag),
intent(inout) :: me
56 if (
allocated(me%vertices))
deallocate(me%vertices)
67 class(
vertex),
intent(inout) :: me
68 integer,
dimension(:),
intent(in) :: edges
72 if (
allocated(me%edges))
then
74 call me%add_edge(edges(i))
77 allocate(me%edges(
size(edges)))
90 class(
vertex),
intent(inout) :: me
91 integer,
intent(in) :: edge
93 if (
allocated(me%edges))
then
94 if (.not. any(edge==me%edges))
then
95 me%edges = [me%edges, edge]
114 class(
dag),
intent(in) :: me
115 integer,
intent(in) :: ivertex
116 integer,
dimension(:),
allocatable :: edges
118 if (ivertex>0 .and. ivertex <= me%n)
then
119 edges = me%vertices(ivertex)%edges
133 class(
dag),
intent(in) :: me
134 integer,
intent(in) :: ivertex
135 integer,
dimension(:),
allocatable :: dep
140 if (ivertex>0 .and. ivertex <= me%n)
then
144 if (
allocated(me%vertices(i)%edges))
then
145 if (any(me%vertices(i)%edges == ivertex))
then
146 if (
allocated(dep))
then
166 class(
dag),
intent(inout) :: me
167 integer,
intent(in) :: nvertices
172 allocate(me%vertices(nvertices))
173 me%vertices%ivertex = [(i,i=1,nvertices)]
184 class(
dag),
intent(inout) :: me
185 integer,
intent(in) :: ivertex
186 character(len=*),
intent(in),
optional :: label
189 character(len=*),
intent(in),
optional :: attributes
192 if (
present(label))
then
193 me%vertices(ivertex)%label = label
199 if (
present(attributes))
then
200 me%vertices(ivertex)%attributes = attributes
212 class(
dag),
intent(inout) :: me
213 integer,
intent(in) :: ivertex
214 integer,
dimension(:),
intent(in) :: edges
216 call me%vertices(ivertex)%set_edges(edges)
227 class(
dag),
intent(inout) :: me
228 integer,
dimension(:),
allocatable,
intent(out) :: order
229 integer,
intent(out) :: istat
239 allocate(order(me%n))
244 if (.not. me%vertices(i)%marked)
call dfs(me%vertices(i))
248 if (istat==-1)
deallocate(order)
252 recursive subroutine dfs(v)
256 type(
vertex),
intent(inout) :: v
259 if (istat==-1)
return
265 if (.not. v%marked)
then
267 if (
allocated(v%edges))
then
269 call dfs(me%vertices(v%edges(j)))
270 if (istat==-1)
return
276 order(iorder) = v%ivertex
297 class(
dag),
intent(in) :: me
298 character(len=:),
allocatable :: str
299 character(len=*),
intent(in),
optional :: rankdir
300 integer,
intent(in),
optional :: dpi
301 character(len=*),
intent(in),
optional :: edge
305 character(len=:),
allocatable :: attributes,label
306 logical :: has_label, has_attributes
308 character(len=*),
parameter :: tab =
' '
309 character(len=*),
parameter :: newline = new_line(
' ')
311 if (me%n == 0)
return
313 str =
'digraph G {'//newline//newline
314 if (
present(rankdir)) &
315 str = str//tab//
'rankdir='//rankdir//newline//newline
319 str = str//tab//
'edge [ dir = "'//trim(adjustl(edge))//
'" ]'//newline//newline
323 has_label =
allocated(me%vertices(i)%label)
324 has_attributes =
allocated(me%vertices(i)%attributes)
325 if (has_label) label =
'label="'//trim(adjustl(me%vertices(i)%label))//
'"'
326 if (has_label .and. has_attributes)
then
327 attributes =
'['//trim(adjustl(me%vertices(i)%attributes))//
','//label//
']'
328 elseif (has_label .and. .not. has_attributes)
then
329 attributes =
'['//label//
']'
330 elseif (.not. has_label .and. has_attributes)
then
331 attributes =
'['//trim(adjustl(me%vertices(i)%attributes))//
']'
336 if (i==me%n) str = str//newline
341 if (
allocated(me%vertices(i)%edges))
then
342 n_edges =
size(me%vertices(i)%edges)
347 if (n_edges>1 .and. j<n_edges) str = str//
','
349 str = str//
';'//newline
353 str = str//newline//
'}'
369 class(
dag),
intent(in) :: me
370 logical,
dimension(:,:),
intent(out),
allocatable :: mat
376 allocate(mat(me%n,me%n))
380 if (
allocated(me%vertices(i)%edges))
then
381 mat(i,me%vertices(i)%edges) = .true.
398 class(
dag),
intent(in) :: me
399 character(len=*),
intent(in),
optional :: filename
400 character(len=*),
intent(in),
optional :: rankdir
401 integer,
intent(in),
optional :: dpi
402 character(len=*),
intent(in),
optional :: edge
404 integer :: iunit, istat
405 character(len=:),
allocatable :: diagraph
407 diagraph = me%generate_digraph(rankdir,dpi,edge)
409 open(newunit=iunit,file=filename,status=
'REPLACE',iostat=istat)
412 write(iunit,fmt=
'(A)',iostat=istat) diagraph
414 write(*,*)
'error opening '//trim(filename)
417 close(iunit,iostat=istat)
430 integer,
intent(in) :: i
431 character(len=:),
allocatable :: s
435 allocate(
character(len=64) :: s )
436 write(s,fmt=
'(ss,I0)',iostat=istat) i
recursive subroutine dfs(v)
pure character(len=:) function, allocatable integer_to_string(i)
character(len=:) function, allocatable dag_generate_digraph(me, rankdir, dpi, edge)
subroutine add_edge(me, edge)
pure integer function, dimension(:), allocatable dag_get_dependencies(me, ivertex)
subroutine dag_generate_dependency_matrix(me, mat)
subroutine dag_set_vertex_info(me, ivertex, label, attributes)
subroutine dag_save_digraph(me, filename, rankdir, dpi, edge)
subroutine dag_destroy(me)
subroutine dag_toposort(me, order, istat)
pure integer function, dimension(:), allocatable dag_get_edges(me, ivertex)
subroutine set_edge_vector(me, edges)
subroutine dag_set_edges(me, ivertex, edges)
subroutine dag_set_vertices(me, nvertices)