separators.scm 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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/separators.scm
  8. ;;;
  9. ;;; Code to determine the separation vertices of a graph
  10. ;;;
  11. ;;; NODES is a list of nodes
  12. ;;; (TO node) returns a list of the nodes which are connected to this one
  13. ;;; (SLOT-NODE node) and (SET-SLOT! node value) are used by the algorithm to
  14. ;;; associate data with nodes (in the absence of a tables).
  15. (define-module (ps-compiler util separators)
  16. #:use-module (srfi srfi-9)
  17. #:use-module (prescheme scheme48)
  18. #:export (separation-verticies))
  19. (define (separation-vertices nodes to slot set-slot!)
  20. (cond ((null? nodes)
  21. (values '() '()))
  22. ((null? (cdr nodes))
  23. (values nodes (list nodes)))
  24. (else
  25. (receive (separators components)
  26. (real-separation-vertices (make-vertices nodes to slot set-slot!))
  27. (for-each (lambda (n) (set-slot! n #f)) nodes)
  28. (values separators components)))))
  29. (define-record-type :vertex
  30. (really-make-vertex data edges dfs-index)
  31. vertex?
  32. (data vertex-data) ;; user's data
  33. (edges vertex-edges ;; list of edges from this vertex
  34. set-vertex-edges!)
  35. (dfs-index vertex-dfs-index ;; ordering from depth-first-search
  36. set-vertex-dfs-index!)
  37. (level vertex-level ;; value used in algorithm...
  38. set-vertex-level!)
  39. (parent vertex-parent ;; parent of this node in DFS tree
  40. set-vertex-parent!))
  41. (define (make-vertex data)
  42. (really-make-vertex data '() 0))
  43. (define-record-type :edge
  44. (really-make-edge from to unused?)
  45. edge?
  46. (from edge-from) ;; two (unordered) vertices
  47. (to edge-to)
  48. (unused? edge-unused? ;; used to mark edges that have been traversed
  49. set-edge-unused?!))
  50. (define (make-edge from to)
  51. (really-make-edge from to #t))
  52. (define (other-vertex edge v)
  53. (if (eq? v (edge-from edge))
  54. (edge-to edge)
  55. (edge-from edge)))
  56. (define (maybe-add-edge from to)
  57. (if (and (not (eq? from to))
  58. (not (any? (lambda (e)
  59. (or (eq? to (edge-from e))
  60. (eq? to (edge-to e))))
  61. (vertex-edges from))))
  62. (let ((e (make-edge from to)))
  63. (set-vertex-edges! from (cons e (vertex-edges from)))
  64. (set-vertex-edges! to (cons e (vertex-edges to))))))
  65. (define (make-vertices nodes to slot set-slot!)
  66. (let ((vertices (map (lambda (n)
  67. (let ((v (make-vertex n)))
  68. (set-slot! n v)
  69. v))
  70. nodes)))
  71. (for-each (lambda (n)
  72. (for-each (lambda (n0)
  73. (maybe-add-edge (slot n) (slot n0)))
  74. (to n)))
  75. nodes)
  76. vertices))
  77. ;; The numbers are the algorithm step numbers from page 62 of Graph Algorithms,
  78. ;; Shimon Even, Computer Science Press, 1979.
  79. ;; Them Us
  80. ;; L(v) (vertex-level v)
  81. ;; k(v) (vertex-dfs-index v)
  82. ;; f(v) (vertex-parent v)
  83. ;; S stack
  84. ;; s start
  85. (define (real-separation-vertices vertices)
  86. (do-vertex (car vertices) 0 '() (car vertices) '() '()))
  87. ;; 2
  88. (define (do-vertex v i stack start v-res c-res)
  89. (let ((i (+ i 1)))
  90. (set-vertex-level! v i)
  91. (set-vertex-dfs-index! v i)
  92. (find-unused-edge v i (cons v stack) start v-res c-res)))
  93. ;; 3
  94. (define (find-unused-edge v i stack start v-res c-res)
  95. (let ((e (first edge-unused? (vertex-edges v))))
  96. (if e
  97. (do-edge e v i stack start v-res c-res)
  98. (no-unused-edge v i stack start v-res c-res))))
  99. ;; 4
  100. (define (do-edge e v i stack start v-res c-res)
  101. (let ((u (other-vertex e v)))
  102. (set-edge-unused?! e #f)
  103. (cond ((= 0 (vertex-dfs-index u))
  104. (set-vertex-parent! u v)
  105. (do-vertex u i stack start v-res c-res))
  106. (else
  107. (if (> (vertex-level v)
  108. (vertex-dfs-index u))
  109. (set-vertex-level! v (vertex-dfs-index u)))
  110. (find-unused-edge v i stack start v-res c-res)))))
  111. ;; 5
  112. (define (no-unused-edge v i stack start v-res c-res)
  113. (let* ((parent (vertex-parent v))
  114. (p-dfs-index (vertex-dfs-index parent)))
  115. (cond ((= 1 p-dfs-index)
  116. (gather-nonseparable-with-start v i stack start v-res c-res))
  117. ((< (vertex-level v) p-dfs-index)
  118. (if (< (vertex-level v)
  119. (vertex-level parent))
  120. (set-vertex-level! parent (vertex-level v)))
  121. (find-unused-edge parent i stack start v-res c-res))
  122. (else
  123. (gather-nonseparable v i stack start v-res c-res)))))
  124. ;; 7
  125. (define (gather-nonseparable v i stack start v-res c-res)
  126. (let* ((parent (vertex-parent v))
  127. (data (vertex-data parent)))
  128. (receive (vertices stack)
  129. (pop-down-to stack v)
  130. (find-unused-edge parent
  131. i
  132. stack
  133. start
  134. (if (not (memq? data v-res))
  135. (cons data v-res)
  136. v-res)
  137. (cons (cons data (map vertex-data vertices)) c-res)))))
  138. ;; 9
  139. (define (gather-nonseparable-with-start v i stack start v-res c-res)
  140. (receive (vertices stack)
  141. (pop-down-to stack v)
  142. (let* ((data (vertex-data start))
  143. (c-res (cons (cons data (map vertex-data vertices)) c-res)))
  144. (if (not (any? edge-unused? (vertex-edges start)))
  145. (values v-res c-res)
  146. (find-unused-edge start
  147. i
  148. stack
  149. start
  150. (if (not (memq? data v-res))
  151. (cons data v-res)
  152. v-res)
  153. c-res)))))
  154. (define (pop-down-to stack v)
  155. (do ((stack stack (cdr stack))
  156. (res '() (cons (car stack) res)))
  157. ((eq? v (car stack))
  158. (values (cons v res) (cdr stack)))))
  159. (define (test-separation-vertices graph)
  160. (let ((nodes (map (lambda (n)
  161. (vector (car n) #f #f))
  162. graph)))
  163. (for-each (lambda (data node)
  164. (vector-set! node 1 (map (lambda (s)
  165. (first (lambda (v)
  166. (eq? s (vector-ref v 0)))
  167. nodes))
  168. (cdr data))))
  169. graph
  170. nodes)
  171. (receive (separation-vertices components)
  172. (separation-vertices nodes
  173. (lambda (v) (vector-ref v 1))
  174. (lambda (v) (vector-ref v 2))
  175. (lambda (v val) (vector-set! v 2 val)))
  176. (values (map (lambda (v) (vector-ref v 0)) separation-vertices)
  177. (map (lambda (l)
  178. (map (lambda (v) (vector-ref v 0))
  179. l))
  180. components)))))