strong.scm 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. ; Copyright (c) 1993-2007 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Code to find the strongly connected components of a graph.
  3. ; (TO <vertex>) are the vertices that have an edge to <vertex>.
  4. ; (SLOT <vertex>) and (SET-SLOT! <vertex> <value>) is a settable slot
  5. ; used by the algorithm.
  6. ;
  7. ; The components are returned in a backwards topologically sorted list.
  8. (define (strongly-connected-components vertices to slot set-slot!)
  9. (make-vertices vertices to slot set-slot!)
  10. (let loop ((to-do vertices) (index 0) (stack #t) (comps '()))
  11. (let ((to-do (find-next-vertex to-do slot)))
  12. (cond ((null? to-do)
  13. (for-each (lambda (n) (set-slot! n #f)) vertices)
  14. comps)
  15. (else
  16. (call-with-values
  17. (lambda ()
  18. (do-vertex (slot (car to-do)) index stack comps))
  19. (lambda (index stack comps)
  20. (loop to-do index stack comps))))))))
  21. (define (find-next-vertex vertices slot)
  22. (do ((vertices vertices (cdr vertices)))
  23. ((or (null? vertices)
  24. (= 0 (vertex-index (slot (car vertices)))))
  25. vertices)))
  26. (define-record-type vertex :vertex
  27. (really-make-vertex data edges stack index parent lowpoint)
  28. vertex?
  29. (data vertex-data) ; user's data
  30. (edges vertex-edges set-vertex-edges!) ; list of vertices
  31. (stack vertex-stack set-vertex-stack!) ; next vertex on the stack
  32. (index vertex-index set-vertex-index!) ; time at which this vertex was
  33. ; reached in the traversal
  34. (parent vertex-parent set-vertex-parent!) ; a vertex pointing to this one
  35. (lowpoint vertex-lowpoint set-vertex-lowpoint!)) ; lowest index in this
  36. ; vertices strongly connected component
  37. (define (make-vertex data)
  38. (really-make-vertex data '() #f 0 #f #f))
  39. (define (make-vertices vertices to slot set-slot!)
  40. (let ((maybe-slot (lambda (n)
  41. (let ((s (slot n)))
  42. (if (vertex? s)
  43. s
  44. (error "graph edge points to non-vertex" n))))))
  45. (for-each (lambda (n)
  46. (set-slot! n (make-vertex n)))
  47. vertices)
  48. (for-each (lambda (n)
  49. (set-vertex-edges! (slot n) (map maybe-slot (to n))))
  50. vertices)
  51. (values)))
  52. ; The numbers are the algorithm step numbers from page 65 of Graph Algorithms,
  53. ; Shimon Even, Computer Science Press, 1979.
  54. ; 2
  55. (define (do-vertex vertex index stack comps)
  56. (let ((index (+ index '1)))
  57. (set-vertex-index! vertex index)
  58. (set-vertex-lowpoint! vertex index)
  59. (set-vertex-stack! vertex stack)
  60. (get-strong vertex index vertex comps)))
  61. ; 3
  62. (define (get-strong vertex index stack comps)
  63. (if (null? (vertex-edges vertex))
  64. (end-vertex vertex index stack comps)
  65. (follow-edge vertex index stack comps)))
  66. ; 7
  67. (define (end-vertex vertex index stack comps)
  68. (call-with-values
  69. (lambda ()
  70. (if (= (vertex-index vertex) (vertex-lowpoint vertex))
  71. (unwind-stack vertex stack comps)
  72. (values stack comps)))
  73. (lambda (stack comps)
  74. (cond ((vertex-parent vertex)
  75. => (lambda (parent)
  76. (if (> (vertex-lowpoint parent) (vertex-lowpoint vertex))
  77. (set-vertex-lowpoint! parent (vertex-lowpoint vertex)))
  78. (get-strong parent index stack comps)))
  79. (else
  80. (values index stack comps))))))
  81. (define (unwind-stack vertex stack comps)
  82. (let loop ((n stack) (c '()))
  83. (let ((next (vertex-stack n))
  84. (c (cons (vertex-data n) c)))
  85. (set-vertex-stack! n #f)
  86. (if (eq? n vertex)
  87. (values next (cons c comps))
  88. (loop next c)))))
  89. ; 4
  90. (define (follow-edge vertex index stack comps)
  91. (let* ((next (pop-vertex-edge! vertex))
  92. (next-index (vertex-index next)))
  93. (cond ((= next-index 0)
  94. (set-vertex-parent! next vertex)
  95. (do-vertex next index stack comps))
  96. (else
  97. (if (and (< next-index (vertex-index vertex))
  98. (vertex-stack next)
  99. (< next-index (vertex-lowpoint vertex)))
  100. (set-vertex-lowpoint! vertex next-index))
  101. (get-strong vertex index stack comps)))))
  102. (define (pop-vertex-edge! vertex)
  103. (let ((edges (vertex-edges vertex)))
  104. (set-vertex-edges! vertex (cdr edges))
  105. (car edges)))
  106. ; GRAPH is ((<symbol> . <symbol>*)*)
  107. ;(define (test-strong graph)
  108. ; (let ((vertices (map (lambda (n)
  109. ; (vector (car n) #f #f))
  110. ; graph)))
  111. ; (for-each (lambda (data vertex)
  112. ; (vector-set! vertex 1 (map (lambda (s)
  113. ; (first (lambda (v)
  114. ; (eq? s (vector-ref v 0)))
  115. ; vertices))
  116. ; (cdr data))))
  117. ; graph
  118. ; vertices)
  119. ; (map (lambda (l)
  120. ; (map (lambda (n) (vector-ref n 0)) l))
  121. ; (strongly-connected-components vertices
  122. ; (lambda (v) (vector-ref v 1))
  123. ; (lambda (v) (vector-ref v 2))
  124. ; (lambda (v val)
  125. ; (vector-set! v 2 val))))))