strong.scm 5.3 KB

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