transitive.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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/transitive.scm
  8. ;;;
  9. ;;; General transitive closure
  10. ;;;
  11. ;;; (make-graph-from-predecessors nodes node-parents node-temp set-node-temp!)
  12. ;;; -> graph
  13. ;;; (make-graph-from-successors nodes node-kids node-temp set-node-temp!)
  14. ;;; -> graph
  15. ;;;
  16. ;;; (transitive-or! graph elements set-elements! element-temp set-element-temp!)
  17. ;;; (transitive-or-with-kill! graph elements set-elements! node-kills element-temp set-element-temp!)
  18. ;;; (transitive-or-with-pass! graph elements set-elements! node-passes element-temp set-element-temp!)
  19. ;;;
  20. ;;; (transitive-and! graph elements set-elements! element-temp set-element-temp!)
  21. ;;; (transitive-and-with-kill! graph elements set-elements! node-kills element-temp set-element-temp!)
  22. ;;; (transitive-and-with-pass! graph elements set-elements! node-passes element-temp set-element-temp!)
  23. ;;;
  24. ;;;----------------
  25. (define-module (ps-compiler util transitive)
  26. #:use-module (prescheme scheme48)
  27. #:use-module (prescheme s48-defrecord)
  28. #:use-module (ps-compiler util z-set)
  29. #:export (make-graph-from-predecessors
  30. make-graph-from-successors
  31. transitive-or! transitive-or-with-kill! transitive-or-with-pass!
  32. transitive-and! transitive-and-with-kill! transitive-and-with-pass!))
  33. (define (make-graph-from-predecessors user-nodes user-node-parents node-temp set-node-temp!)
  34. (let ((nodes (make-nodes user-nodes set-node-temp!)))
  35. (connect-nodes-using-parents! nodes user-node-parents node-temp)
  36. (for-each (lambda (node)
  37. (set-node-temp! (node-data node) #f))
  38. nodes)
  39. (make-graph nodes)))
  40. (define (make-graph-from-successors user-nodes user-node-kids node-temp set-node-temp!)
  41. (let ((nodes (make-nodes user-nodes set-node-temp!)))
  42. (connect-nodes-using-children! nodes user-node-kids node-temp)
  43. (for-each (lambda (node)
  44. (set-node-temp! (node-data node) #f))
  45. nodes)
  46. (make-graph nodes)))
  47. (define (make-nodes user-nodes set-node-temp!)
  48. (map (lambda (data)
  49. (let ((node (node-maker data '() '())))
  50. (set-node-temp! data node)
  51. node))
  52. user-nodes))
  53. (define-record-type graph
  54. (nodes ;; list of nodes
  55. )
  56. ())
  57. (define make-graph graph-maker)
  58. (define-record-type node
  59. (data ;; user's data
  60. (parents) ;; predecessors
  61. (kids)) ;; successors
  62. (elt-set ;; elements
  63. kill-set ;; elements that are not passed
  64. changed? ;; change flag for iteration
  65. ))
  66. ;;------------------------------
  67. ;; Six false fronts for the real procedure.
  68. (define (transitive-or! graph elts set-elts! elt-hash set-elt-hash!)
  69. (do-it graph elts set-elts! #f #f elt-hash set-elt-hash!
  70. (transitive-or-closure! or-update-node)))
  71. (define (transitive-or-with-kill! graph elts set-elts! kill-elts elt-hash set-elt-hash!)
  72. (do-it graph elts set-elts! kill-elts #f elt-hash set-elt-hash!
  73. (transitive-or-closure! or-update-node-with-kill)))
  74. (define (transitive-or-with-pass! graph elts set-elts! pass-elts elt-hash set-elt-hash!)
  75. (do-it graph elts set-elts! pass-elts #t elt-hash set-elt-hash!
  76. (transitive-or-closure! or-update-node-with-kill)))
  77. (define (transitive-and! graph elts set-elts! elt-hash set-elt-hash!)
  78. (do-it graph elts set-elts! #f #f elt-hash set-elt-hash!
  79. (transitive-and-closure! and-update-node)))
  80. (define (transitive-and-with-kill! graph elts set-elts! kill-elts elt-hash set-elt-hash!)
  81. (do-it graph elts set-elts! kill-elts #f elt-hash set-elt-hash!
  82. (transitive-and-closure! and-update-node-with-kill)))
  83. (define (transitive-and-with-pass! graph elts set-elts! pass-elts elt-hash set-elt-hash!)
  84. (do-it graph elts set-elts! pass-elts #t elt-hash set-elt-hash!
  85. (transitive-and-closure! and-update-node-with-kill)))
  86. (define (do-it graph elts set-elts! kill-elts pass? elt-hash set-elt-hash! op)
  87. (let* ((nodes (graph-nodes graph))
  88. (elt-unhash-vec (add-elements! nodes elts kill-elts pass?
  89. elt-hash set-elt-hash!)))
  90. (op nodes)
  91. (record-results! nodes elt-unhash-vec set-elts!)
  92. (do ((i 0 (+ i 1)))
  93. ((= i (vector-length elt-unhash-vec)))
  94. (set-elt-hash! (vector-ref elt-unhash-vec i) #f))
  95. (values)))
  96. ;;----------------
  97. ;; Setting the kids field of the nodes
  98. (define (connect-nodes-using-children! nodes children node-slot)
  99. (for-each
  100. (lambda (node)
  101. (set-node-kids! node
  102. (map (lambda (kid)
  103. (let ((t (node-slot kid)))
  104. (if (not (node? t))
  105. (missing-node-error kid "child" node))
  106. (set-node-parents! t
  107. (cons node
  108. (node-parents t)))
  109. t))
  110. (children (node-data node)))))
  111. nodes))
  112. (define (connect-nodes-using-parents! nodes parents node-slot)
  113. (for-each
  114. (lambda (node)
  115. (set-node-parents! node
  116. (map (lambda (parent)
  117. (let ((t (node-slot parent)))
  118. (if (not (node? t))
  119. (missing-node-error t "parent" node))
  120. (set-node-kids! t
  121. (cons node
  122. (node-kids t)))
  123. t))
  124. (parents (node-data node)))))
  125. nodes))
  126. (define (missing-node-error node relationship relation)
  127. (error (format #f "Transitive - ~S, ~A of ~S, not in list of nodes"
  128. node relationship (node-data relation))))
  129. ;;----------------
  130. (define (add-elements! nodes node-elements node-kills pass?
  131. element-temp set-element-temp!)
  132. (let ((unhash-vec (element-hasher nodes node-elements element-temp set-element-temp!))
  133. (element-hash (make-element-hash element-temp)))
  134. (for-each (lambda (node)
  135. (set-node-elt-set! node
  136. (make-element-set (node-elements (node-data node))
  137. element-hash)))
  138. nodes)
  139. (if node-kills
  140. (for-each (lambda (node)
  141. (let ((kill-set (make-element-set (node-kills (node-data node))
  142. element-hash)))
  143. (set-node-kill-set! node (if pass?
  144. (integer-set-not kill-set)
  145. kill-set))))
  146. nodes))
  147. unhash-vec))
  148. (define (make-element-set elts elt-hash)
  149. (let loop ((elts elts) (set (make-empty-integer-set)))
  150. (if (null? elts)
  151. set
  152. (loop (cdr elts)
  153. (cond ((elt-hash (car elts))
  154. => (lambda (hash)
  155. (add-to-integer-set set hash)))
  156. (else set))))))
  157. ;;----------------
  158. ;; Counting the elements and assigning numbers to them
  159. (define-record-type element-hash
  160. (number ;; the element-hash record is just a way of tagging this number
  161. ) ;; with a unique predicate
  162. ())
  163. (define (element-hasher nodes elts elt-hash set-elt-hash!)
  164. (let loop ((to-do '()) (ts nodes) (all-elts '()) (count 0))
  165. (cond ((null? to-do)
  166. (if (null? ts)
  167. (real-element-hasher all-elts count)
  168. (loop (elts (node-data (car ts))) (cdr ts) all-elts count)))
  169. ((element-hash? (elt-hash (car to-do)))
  170. (loop (cdr to-do) ts all-elts count))
  171. (else
  172. (set-elt-hash! (car to-do) (element-hash-maker count))
  173. (loop (cdr to-do) ts (cons (car to-do) all-elts) (+ count 1))))))
  174. (define (real-element-hasher elts count)
  175. (let ((unhash-vec (make-vector count)))
  176. (do ((i (- count 1) (- i 1))
  177. (elts elts (cdr elts)))
  178. ((null? elts))
  179. (vector-set! unhash-vec i (car elts)))
  180. unhash-vec))
  181. (define (make-element-hash elt-hash)
  182. (lambda (elt)
  183. (let ((hash (elt-hash elt)))
  184. (if (element-hash? hash)
  185. (element-hash-number hash)
  186. #f))))
  187. ;;----------------
  188. ;; Turn the element sets into lists of elements and clean up stray pointers
  189. ;; at the same time.
  190. (define (record-results! nodes elt-unhash-vec set-elts!)
  191. (for-each (lambda (node)
  192. (set-elts! (node-data node)
  193. (map-over-integer-set
  194. (lambda (i) (vector-ref elt-unhash-vec i))
  195. (node-elt-set node)))
  196. (set-node-elt-set! node #f)
  197. (set-node-kill-set! node #f))
  198. nodes))
  199. ;;----------------
  200. ;; The OR algorithm - keeps passing elements around until the changes stop.
  201. (define (transitive-or-closure! op)
  202. (lambda (nodes)
  203. (for-each (lambda (node)
  204. (set-node-changed?! node #t))
  205. nodes)
  206. (let loop ((to-do nodes))
  207. (if (not (null? to-do))
  208. (let* ((node (car to-do))
  209. (elt-set (node-elt-set node)))
  210. (set-node-changed?! node #f)
  211. (let kids-loop ((ts (node-kids node))
  212. (to-do (cdr to-do)))
  213. (cond ((null? ts)
  214. (loop to-do))
  215. ((and (op (car ts) elt-set)
  216. (not (node-changed? (car ts))))
  217. (set-node-changed?! (car ts) #t)
  218. (kids-loop (cdr ts) (cons (car ts) to-do)))
  219. (else
  220. (kids-loop (cdr ts) to-do)))))))))
  221. ;; The weird function INTEGER-SET-SUBTRACT&IOR-WITH-TEST! takes three integer
  222. ;; sets, subtracts the second from the first and inclusive OR's the result
  223. ;; with the third. It returns the resulting set and a flag which is #T if
  224. ;; the result is not the same as the original third set. The inclusive OR
  225. ;; may be destructive.
  226. (define (or-update-node-with-kill node elt-set)
  227. (receive (set change?)
  228. (integer-set-subtract&ior-with-test! elt-set
  229. (node-kill-set node)
  230. (node-elt-set node))
  231. (set-node-elt-set! node set)
  232. change?))
  233. (define (or-update-node node elt-set)
  234. (receive (set change?)
  235. (integer-set-ior-with-test! elt-set
  236. (node-elt-set node))
  237. (set-node-elt-set! node set)
  238. change?))
  239. ;; Implementations using simpler, nondestructive operations (these might be
  240. ;; done more efficiently if they had access to the underlying representation
  241. ;; of integer sets).
  242. (define (integer-set-subtract&ior-with-test! set1 set2 set3)
  243. (let ((result (integer-set-ior set3 (integer-set-subtract set1 set2))))
  244. (values result (not (integer-set-equal? set3 result)))))
  245. (define (integer-set-ior-with-test! set1 set3)
  246. (let ((result (integer-set-ior set3 set1)))
  247. (values result (not (integer-set-equal? set3 result)))))
  248. ;;----------------
  249. ;; The AND algorithm - keeps a to-do list of nodes whose parents' elements
  250. ;; have changed, instead of a list of nodes whose elements have changed.
  251. (define (transitive-and-closure! op)
  252. (lambda (nodes)
  253. (let loop ((to-do (filter (lambda (node)
  254. (if (not (null? (node-parents node)))
  255. (begin
  256. (set-node-changed?! node #t)
  257. #t)
  258. #f))
  259. nodes)))
  260. (if (not (null? to-do))
  261. (let ((node (car to-do)))
  262. (set-node-changed?! node #f)
  263. (if (op node)
  264. (let kids-loop ((ts (node-kids node))
  265. (to-do (cdr to-do)))
  266. (cond ((null? ts)
  267. (loop to-do))
  268. ((node-changed? (car ts))
  269. (kids-loop (cdr ts) to-do))
  270. (else
  271. (set-node-changed?! (car ts) #t)
  272. (kids-loop (cdr ts) (cons (car ts) to-do)))))
  273. (loop (cdr to-do))))))))
  274. ;; These are the same as for OR except that we AND together the parents'
  275. ;; elt-sets instead of using the one provided.
  276. (define (and-update-node-with-kill node)
  277. (receive (set change?)
  278. (integer-set-subtract&ior-with-test! (parents-elt-set node)
  279. (node-kill-set node)
  280. (node-elt-set node))
  281. (set-node-elt-set! node set)
  282. change?))
  283. (define (and-update-node node)
  284. (receive (set change?)
  285. (integer-set-ior-with-test! (parents-elt-set node)
  286. (node-elt-set node))
  287. (set-node-elt-set! node set)
  288. change?))
  289. (define (parents-elt-set node)
  290. (do ((parents (cdr (node-parents node))
  291. (cdr parents))
  292. (elts (node-elt-set (car (node-parents node)))
  293. (integer-set-and elts (node-elt-set (car parents)))))
  294. ((null? parents)
  295. elts)))
  296. ;;------------------------------------------------------------
  297. ;; Testing
  298. ;; GRAPH is ((<symbol> name
  299. ;; (element*) elements
  300. ;; (element*) kills
  301. ;; . <symbol*>)*) children
  302. ;;
  303. '((node1 (elt1 elt2) () node2)
  304. (node2 (elt3) (elt2) node1 node3)
  305. (node3 () () ))
  306. '((a (1) () b)
  307. (b () () ))
  308. '((a (1 2 3 4) (1) b)
  309. (b () (2) c)
  310. (c () (3) d)
  311. (d (5) (4) a))
  312. (define (test-transitive graph down? or? pass?)
  313. (let* ((elts '())
  314. (get-elt (lambda (sym)
  315. (cond ((first (lambda (v)
  316. (eq? sym (vector-ref v 0)))
  317. elts)
  318. => identity)
  319. (else
  320. (let ((new (vector sym #f)))
  321. (set! elts (cons new elts))
  322. new)))))
  323. (vertices (map (lambda (n)
  324. (vector (car n)
  325. (map get-elt (cadr n))
  326. (map get-elt (caddr n))
  327. #f #f))
  328. graph)))
  329. (for-each (lambda (data vertex)
  330. (vector-set! vertex 3 (map (lambda (s)
  331. (first (lambda (v)
  332. (eq? s (vector-ref v 0)))
  333. vertices))
  334. (cdddr data))))
  335. graph
  336. vertices)
  337. (let ((the-graph ((if down?
  338. make-graph-from-successors
  339. make-graph-from-predecessors)
  340. vertices
  341. (lambda (x) (vector-ref x 3))
  342. (lambda (x) (vector-ref x 4))
  343. (lambda (x v) (vector-set! x 4 v)))))
  344. (if (every? (lambda (n) (null? (caddr n))) graph)
  345. ((if or? transitive-or! transitive-and!)
  346. the-graph
  347. (lambda (v) (vector-ref v 1)) ;; elts
  348. (lambda (v x) (vector-set! v 1 x)) ;; set-elts!
  349. (lambda (e) (vector-ref e 1)) ;; elt-hash
  350. (lambda (e x) (vector-set! e 1 x))) ;; set-elt-hash!
  351. ((if or?
  352. (if pass?
  353. transitive-or-with-pass!
  354. transitive-or-with-kill!)
  355. (if pass?
  356. transitive-and-with-pass!
  357. transitive-and-with-kill!))
  358. the-graph
  359. (lambda (v) (vector-ref v 1)) ;; elts
  360. (lambda (v x) (vector-set! v 1 x)) ;; set-elts!
  361. (lambda (v) (vector-ref v 2)) ;; kills
  362. (lambda (e) (vector-ref e 1)) ;; elt-hash
  363. (lambda (e x) (vector-set! e 1 x))))) ;; set-elt-hash!
  364. (map (lambda (v)
  365. (list (vector-ref v 0)
  366. (map (lambda (e) (vector-ref e 0))
  367. (vector-ref v 1))))
  368. vertices)))