graphs.sch 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. ; Modified 2 March 1997 by Will Clinger to add graphs-benchmark
  2. ; and to expand the four macros below.
  3. ; Modified 11 June 1997 by Will Clinger to eliminate assertions
  4. ; and to replace a use of "recur" with a named let.
  5. ;
  6. ; Performance note: (graphs-benchmark 7) allocates
  7. ; 34509143 pairs
  8. ; 389625 vectors with 2551590 elements
  9. ; 56653504 closures (not counting top level and known procedures)
  10. (define (graphs-benchmark . rest)
  11. (let ((N (if (null? rest) 7 (car rest))))
  12. (run-benchmark (string-append "graphs" (number->string N))
  13. (lambda ()
  14. (fold-over-rdg N
  15. 2
  16. cons
  17. '())))))
  18. ; End of new code.
  19. ;;; ==== std.ss ====
  20. ; (define-syntax assert
  21. ; (syntax-rules ()
  22. ; ((assert test info-rest ...)
  23. ; #F)))
  24. ;
  25. ; (define-syntax deny
  26. ; (syntax-rules ()
  27. ; ((deny test info-rest ...)
  28. ; #F)))
  29. ;
  30. ; (define-syntax when
  31. ; (syntax-rules ()
  32. ; ((when test e-first e-rest ...)
  33. ; (if test
  34. ; (begin e-first
  35. ; e-rest ...)))))
  36. ;
  37. ; (define-syntax unless
  38. ; (syntax-rules ()
  39. ; ((unless test e-first e-rest ...)
  40. ; (if (not test)
  41. ; (begin e-first
  42. ; e-rest ...)))))
  43. (define assert
  44. (lambda (test . info)
  45. #f))
  46. ;;; ==== util.ss ====
  47. ; Fold over list elements, associating to the left.
  48. (define fold
  49. (lambda (lst folder state)
  50. '(assert (list? lst)
  51. lst)
  52. '(assert (procedure? folder)
  53. folder)
  54. (do ((lst lst
  55. (cdr lst))
  56. (state state
  57. (folder (car lst)
  58. state)))
  59. ((null? lst)
  60. state))))
  61. ; Given the size of a vector and a procedure which
  62. ; sends indicies to desired vector elements, create
  63. ; and return the vector.
  64. (define proc->vector
  65. (lambda (size f)
  66. '(assert (and (integer? size)
  67. (exact? size)
  68. (>= size 0))
  69. size)
  70. '(assert (procedure? f)
  71. f)
  72. (if (zero? size)
  73. (vector)
  74. (let ((x (make-vector size (f 0))))
  75. (let loop ((i 1))
  76. (if (< i size) (begin ; [wdc - was when]
  77. (vector-set! x i (f i))
  78. (loop (+ i 1)))))
  79. x))))
  80. (define vector-fold
  81. (lambda (vec folder state)
  82. '(assert (vector? vec)
  83. vec)
  84. '(assert (procedure? folder)
  85. folder)
  86. (let ((len
  87. (vector-length vec)))
  88. (do ((i 0
  89. (+ i 1))
  90. (state state
  91. (folder (vector-ref vec i)
  92. state)))
  93. ((= i len)
  94. state)))))
  95. (define vector-map
  96. (lambda (vec proc)
  97. (proc->vector (vector-length vec)
  98. (lambda (i)
  99. (proc (vector-ref vec i))))))
  100. ; Given limit, return the list 0, 1, ..., limit-1.
  101. (define giota
  102. (lambda (limit)
  103. '(assert (and (integer? limit)
  104. (exact? limit)
  105. (>= limit 0))
  106. limit)
  107. (let -*-
  108. ((limit
  109. limit)
  110. (res
  111. '()))
  112. (if (zero? limit)
  113. res
  114. (let ((limit
  115. (- limit 1)))
  116. (-*- limit
  117. (cons limit res)))))))
  118. ; Fold over the integers [0, limit).
  119. (define gnatural-fold
  120. (lambda (limit folder state)
  121. '(assert (and (integer? limit)
  122. (exact? limit)
  123. (>= limit 0))
  124. limit)
  125. '(assert (procedure? folder)
  126. folder)
  127. (do ((i 0
  128. (+ i 1))
  129. (state state
  130. (folder i state)))
  131. ((= i limit)
  132. state))))
  133. ; Iterate over the integers [0, limit).
  134. (define gnatural-for-each
  135. (lambda (limit proc!)
  136. '(assert (and (integer? limit)
  137. (exact? limit)
  138. (>= limit 0))
  139. limit)
  140. '(assert (procedure? proc!)
  141. proc!)
  142. (do ((i 0
  143. (+ i 1)))
  144. ((= i limit))
  145. (proc! i))))
  146. (define natural-for-all?
  147. (lambda (limit ok?)
  148. '(assert (and (integer? limit)
  149. (exact? limit)
  150. (>= limit 0))
  151. limit)
  152. '(assert (procedure? ok?)
  153. ok?)
  154. (let -*-
  155. ((i 0))
  156. (or (= i limit)
  157. (and (ok? i)
  158. (-*- (+ i 1)))))))
  159. (define natural-there-exists?
  160. (lambda (limit ok?)
  161. '(assert (and (integer? limit)
  162. (exact? limit)
  163. (>= limit 0))
  164. limit)
  165. '(assert (procedure? ok?)
  166. ok?)
  167. (let -*-
  168. ((i 0))
  169. (and (not (= i limit))
  170. (or (ok? i)
  171. (-*- (+ i 1)))))))
  172. (define there-exists?
  173. (lambda (lst ok?)
  174. '(assert (list? lst)
  175. lst)
  176. '(assert (procedure? ok?)
  177. ok?)
  178. (let -*-
  179. ((lst lst))
  180. (and (not (null? lst))
  181. (or (ok? (car lst))
  182. (-*- (cdr lst)))))))
  183. ;;; ==== ptfold.ss ====
  184. ; Fold over the tree of permutations of a universe.
  185. ; Each branch (from the root) is a permutation of universe.
  186. ; Each node at depth d corresponds to all permutations which pick the
  187. ; elements spelled out on the branch from the root to that node as
  188. ; the first d elements.
  189. ; Their are two components to the state:
  190. ; The b-state is only a function of the branch from the root.
  191. ; The t-state is a function of all nodes seen so far.
  192. ; At each node, b-folder is called via
  193. ; (b-folder elem b-state t-state deeper accross)
  194. ; where elem is the next element of the universe picked.
  195. ; If b-folder can determine the result of the total tree fold at this stage,
  196. ; it should simply return the result.
  197. ; If b-folder can determine the result of folding over the sub-tree
  198. ; rooted at the resulting node, it should call accross via
  199. ; (accross new-t-state)
  200. ; where new-t-state is that result.
  201. ; Otherwise, b-folder should call deeper via
  202. ; (deeper new-b-state new-t-state)
  203. ; where new-b-state is the b-state for the new node and new-t-state is
  204. ; the new folded t-state.
  205. ; At the leaves of the tree, t-folder is called via
  206. ; (t-folder b-state t-state accross)
  207. ; If t-folder can determine the result of the total tree fold at this stage,
  208. ; it should simply return that result.
  209. ; If not, it should call accross via
  210. ; (accross new-t-state)
  211. ; Note, fold-over-perm-tree always calls b-folder in depth-first order.
  212. ; I.e., when b-folder is called at depth d, the branch leading to that
  213. ; node is the most recent calls to b-folder at all the depths less than d.
  214. ; This is a gross efficiency hack so that b-folder can use mutation to
  215. ; keep the current branch.
  216. (define fold-over-perm-tree
  217. (lambda (universe b-folder b-state t-folder t-state)
  218. '(assert (list? universe)
  219. universe)
  220. '(assert (procedure? b-folder)
  221. b-folder)
  222. '(assert (procedure? t-folder)
  223. t-folder)
  224. (let -*-
  225. ((universe
  226. universe)
  227. (b-state
  228. b-state)
  229. (t-state
  230. t-state)
  231. (accross
  232. (lambda (final-t-state)
  233. final-t-state)))
  234. (if (null? universe)
  235. (t-folder b-state t-state accross)
  236. (let -**-
  237. ((in
  238. universe)
  239. (out
  240. '())
  241. (t-state
  242. t-state))
  243. (let* ((first
  244. (car in))
  245. (rest
  246. (cdr in))
  247. (accross
  248. (if (null? rest)
  249. accross
  250. (lambda (new-t-state)
  251. (-**- rest
  252. (cons first out)
  253. new-t-state)))))
  254. (b-folder first
  255. b-state
  256. t-state
  257. (lambda (new-b-state new-t-state)
  258. (-*- (fold out cons rest)
  259. new-b-state
  260. new-t-state
  261. accross))
  262. accross)))))))
  263. ;;; ==== minimal.ss ====
  264. ; A directed graph is stored as a connection matrix (vector-of-vectors)
  265. ; where the first index is the `from' vertex and the second is the `to'
  266. ; vertex. Each entry is a bool indicating if the edge exists.
  267. ; The diagonal of the matrix is never examined.
  268. ; Make-minimal? returns a procedure which tests if a labelling
  269. ; of the verticies is such that the matrix is minimal.
  270. ; If it is, then the procedure returns the result of folding over
  271. ; the elements of the automoriphism group. If not, it returns #F.
  272. ; The folding is done by calling folder via
  273. ; (folder perm state accross)
  274. ; If the folder wants to continue, it should call accross via
  275. ; (accross new-state)
  276. ; If it just wants the entire minimal? procedure to return something,
  277. ; it should return that.
  278. ; The ordering used is lexicographic (with #T > #F) and entries
  279. ; are examined in the following order:
  280. ; 1->0, 0->1
  281. ;
  282. ; 2->0, 0->2
  283. ; 2->1, 1->2
  284. ;
  285. ; 3->0, 0->3
  286. ; 3->1, 1->3
  287. ; 3->2, 2->3
  288. ; ...
  289. (define make-minimal?
  290. (lambda (max-size)
  291. '(assert (and (integer? max-size)
  292. (exact? max-size)
  293. (>= max-size 0))
  294. max-size)
  295. (let ((iotas
  296. (proc->vector (+ max-size 1)
  297. giota))
  298. (perm
  299. (make-vector max-size 0)))
  300. (lambda (size graph folder state)
  301. '(assert (and (integer? size)
  302. (exact? size)
  303. (<= 0 size max-size))
  304. size
  305. max-size)
  306. '(assert (vector? graph)
  307. graph)
  308. '(assert (procedure? folder)
  309. folder)
  310. (fold-over-perm-tree (vector-ref iotas size)
  311. (lambda (perm-x x state deeper accross)
  312. (case (cmp-next-vertex graph perm x perm-x)
  313. ((less)
  314. #F)
  315. ((equal)
  316. (vector-set! perm x perm-x)
  317. (deeper (+ x 1)
  318. state))
  319. ((more)
  320. (accross state))
  321. (else
  322. (assert #F))))
  323. 0
  324. (lambda (leaf-depth state accross)
  325. '(assert (eqv? leaf-depth size)
  326. leaf-depth
  327. size)
  328. (folder perm state accross))
  329. state)))))
  330. ; Given a graph, a partial permutation vector, the next input and the next
  331. ; output, return 'less, 'equal or 'more depending on the lexicographic
  332. ; comparison between the permuted and un-permuted graph.
  333. (define cmp-next-vertex
  334. (lambda (graph perm x perm-x)
  335. (let ((from-x
  336. (vector-ref graph x))
  337. (from-perm-x
  338. (vector-ref graph perm-x)))
  339. (let -*-
  340. ((y
  341. 0))
  342. (if (= x y)
  343. 'equal
  344. (let ((x->y?
  345. (vector-ref from-x y))
  346. (perm-y
  347. (vector-ref perm y)))
  348. (cond ((eq? x->y?
  349. (vector-ref from-perm-x perm-y))
  350. (let ((y->x?
  351. (vector-ref (vector-ref graph y)
  352. x)))
  353. (cond ((eq? y->x?
  354. (vector-ref (vector-ref graph perm-y)
  355. perm-x))
  356. (-*- (+ y 1)))
  357. (y->x?
  358. 'less)
  359. (else
  360. 'more))))
  361. (x->y?
  362. 'less)
  363. (else
  364. 'more))))))))
  365. ;;; ==== rdg.ss ====
  366. ; Fold over rooted directed graphs with bounded out-degree.
  367. ; Size is the number of verticies (including the root). Max-out is the
  368. ; maximum out-degree for any vertex. Folder is called via
  369. ; (folder edges state)
  370. ; where edges is a list of length size. The ith element of the list is
  371. ; a list of the verticies j for which there is an edge from i to j.
  372. ; The last vertex is the root.
  373. (define fold-over-rdg
  374. (lambda (size max-out folder state)
  375. '(assert (and (exact? size)
  376. (integer? size)
  377. (> size 0))
  378. size)
  379. '(assert (and (exact? max-out)
  380. (integer? max-out)
  381. (>= max-out 0))
  382. max-out)
  383. '(assert (procedure? folder)
  384. folder)
  385. (let* ((root
  386. (- size 1))
  387. (edge?
  388. (proc->vector size
  389. (lambda (from)
  390. (make-vector size #F))))
  391. (edges
  392. (make-vector size '()))
  393. (out-degrees
  394. (make-vector size 0))
  395. (minimal-folder
  396. (make-minimal? root))
  397. (non-root-minimal?
  398. (let ((cont
  399. (lambda (perm state accross)
  400. '(assert (eq? state #T)
  401. state)
  402. (accross #T))))
  403. (lambda (size)
  404. (minimal-folder size
  405. edge?
  406. cont
  407. #T))))
  408. (root-minimal?
  409. (let ((cont
  410. (lambda (perm state accross)
  411. '(assert (eq? state #T)
  412. state)
  413. (case (cmp-next-vertex edge? perm root root)
  414. ((less)
  415. #F)
  416. ((equal more)
  417. (accross #T))
  418. (else
  419. (assert #F))))))
  420. (lambda ()
  421. (minimal-folder root
  422. edge?
  423. cont
  424. #T)))))
  425. (let -*-
  426. ((vertex
  427. 0)
  428. (state
  429. state))
  430. (cond ((not (non-root-minimal? vertex))
  431. state)
  432. ((= vertex root)
  433. '(assert
  434. (begin
  435. (gnatural-for-each root
  436. (lambda (v)
  437. '(assert (= (vector-ref out-degrees v)
  438. (length (vector-ref edges v)))
  439. v
  440. (vector-ref out-degrees v)
  441. (vector-ref edges v))))
  442. #T))
  443. (let ((reach?
  444. (make-reach? root edges))
  445. (from-root
  446. (vector-ref edge? root)))
  447. (let -*-
  448. ((v
  449. 0)
  450. (outs
  451. 0)
  452. (efr
  453. '())
  454. (efrr
  455. '())
  456. (state
  457. state))
  458. (cond ((not (or (= v root)
  459. (= outs max-out)))
  460. (vector-set! from-root v #T)
  461. (let ((state
  462. (-*- (+ v 1)
  463. (+ outs 1)
  464. (cons v efr)
  465. (cons (vector-ref reach? v)
  466. efrr)
  467. state)))
  468. (vector-set! from-root v #F)
  469. (-*- (+ v 1)
  470. outs
  471. efr
  472. efrr
  473. state)))
  474. ((and (natural-for-all? root
  475. (lambda (v)
  476. (there-exists? efrr
  477. (lambda (r)
  478. (vector-ref r v)))))
  479. (root-minimal?))
  480. (vector-set! edges root efr)
  481. (folder
  482. (proc->vector size
  483. (lambda (i)
  484. (vector-ref edges i)))
  485. state))
  486. (else
  487. state)))))
  488. (else
  489. (let ((from-vertex
  490. (vector-ref edge? vertex)))
  491. (let -**-
  492. ((sv
  493. 0)
  494. (outs
  495. 0)
  496. (state
  497. state))
  498. (if (= sv vertex)
  499. (begin
  500. (vector-set! out-degrees vertex outs)
  501. (-*- (+ vertex 1)
  502. state))
  503. (let* ((state
  504. ; no sv->vertex, no vertex->sv
  505. (-**- (+ sv 1)
  506. outs
  507. state))
  508. (from-sv
  509. (vector-ref edge? sv))
  510. (sv-out
  511. (vector-ref out-degrees sv))
  512. (state
  513. (if (= sv-out max-out)
  514. state
  515. (begin
  516. (vector-set! edges
  517. sv
  518. (cons vertex
  519. (vector-ref edges sv)))
  520. (vector-set! from-sv vertex #T)
  521. (vector-set! out-degrees sv (+ sv-out 1))
  522. (let* ((state
  523. ; sv->vertex, no vertex->sv
  524. (-**- (+ sv 1)
  525. outs
  526. state))
  527. (state
  528. (if (= outs max-out)
  529. state
  530. (begin
  531. (vector-set! from-vertex sv #T)
  532. (vector-set! edges
  533. vertex
  534. (cons sv
  535. (vector-ref edges vertex)))
  536. (let ((state
  537. ; sv->vertex, vertex->sv
  538. (-**- (+ sv 1)
  539. (+ outs 1)
  540. state)))
  541. (vector-set! edges
  542. vertex
  543. (cdr (vector-ref edges vertex)))
  544. (vector-set! from-vertex sv #F)
  545. state)))))
  546. (vector-set! out-degrees sv sv-out)
  547. (vector-set! from-sv vertex #F)
  548. (vector-set! edges
  549. sv
  550. (cdr (vector-ref edges sv)))
  551. state)))))
  552. (if (= outs max-out)
  553. state
  554. (begin
  555. (vector-set! edges
  556. vertex
  557. (cons sv
  558. (vector-ref edges vertex)))
  559. (vector-set! from-vertex sv #T)
  560. (let ((state
  561. ; no sv->vertex, vertex->sv
  562. (-**- (+ sv 1)
  563. (+ outs 1)
  564. state)))
  565. (vector-set! from-vertex sv #F)
  566. (vector-set! edges
  567. vertex
  568. (cdr (vector-ref edges vertex)))
  569. state)))))))))))))
  570. ; Given a vector which maps vertex to out-going-edge list,
  571. ; return a vector which gives reachability.
  572. (define make-reach?
  573. (lambda (size vertex->out)
  574. (let ((res
  575. (proc->vector size
  576. (lambda (v)
  577. (let ((from-v
  578. (make-vector size #F)))
  579. (vector-set! from-v v #T)
  580. (for-each
  581. (lambda (x)
  582. (vector-set! from-v x #T))
  583. (vector-ref vertex->out v))
  584. from-v)))))
  585. (gnatural-for-each size
  586. (lambda (m)
  587. (let ((from-m
  588. (vector-ref res m)))
  589. (gnatural-for-each size
  590. (lambda (f)
  591. (let ((from-f
  592. (vector-ref res f)))
  593. (if (vector-ref from-f m); [wdc - was when]
  594. (begin
  595. (gnatural-for-each size
  596. (lambda (t)
  597. (if (vector-ref from-m t)
  598. (begin ; [wdc - was when]
  599. (vector-set! from-f t #T)))))))))))))
  600. res)))
  601. ;;; ==== test input ====
  602. ; Produces all directed graphs with N verticies, distinguished root,
  603. ; and out-degree bounded by 2, upto isomorphism (there are 44).
  604. ;(define go
  605. ; (let ((N 7))
  606. ; (fold-over-rdg N
  607. ; 2
  608. ; cons
  609. ; '())))