spacepaste

  1.  
  2. #!/usr/bin/guile
  3. !#
  4. ;; (TreeOptimizer->reset n_nodes) -> unspecified
  5. ;; Restart generation with n_nodes
  6. (define TreeOptimizer->reset #f)
  7. ;; (TreeOptimizer->iterate) -> (topo_factor . specification)
  8. ;; Calculate the topological factor of the next specified iteration
  9. (define TreeOptimizer->iterate #f)
  10. (let ([iterator (list)] [n_nodes #f])
  11. (set! TreeOptimizer->reset
  12. (lambda (n_nodes_new)
  13. (set! iterator (list))
  14. (set! n_nodes n_nodes_new)))
  15. (set! TreeOptimizer->iterate
  16. (lambda ()
  17. (let vertical_rec ([last_node #t] [remaining_nodes n_nodes] [index 0] [tf 0])
  18. (let ([trailing (= (+ (length iterator) 1) index)])
  19. (let ([stage (if (<= (length iterator) index)
  20. '(1 . 1)
  21. (list-ref iterator index))])
  22. (if (and trailing (= (car stage) remaining_nodes))
  23. ; Break recursion. Must only happen on last_node
  24. (list (list) 0 remaining_nodes index)
  25. (let ([stage (if trailing
  26. (let ([max_substream (remainder (- remaining_nodes (car stage)) 2)])
  27. (if (= (cdr stage) max_substream)
  28. (let ([new_nodecount (+ (car stage) 1)])
  29. (cons new_nodecount (if (and last_node (not (= new_nodecount remaining_nodes))) 1 0))
  30. (cons (car stage) (+ (cdr stage) 1))))
  31. stage))])
  32. (let ([horizontal_result (let horizontal_rec
  33. ([substream 0]
  34. [remaining_nodes remaining_nodes]
  35. [subindex (+ index 1)])
  36. (if (< substream (cdr stage))
  37. (let ([vertical_result (vertical_rec
  38. (and last_node (= substream (- (cdr stage) 1)))
  39. remaining_nodes
  40. subindex
  41. (+ tf (cdr stage) (car stage)))])
  42. (let ([vertical_result (horizontal_rec (+ substream 1) (list-ref vertical_result 2) (list-ref vertical_result 3))])
  43. (list
  44. (append (list-ref vertical_result 0) (list-ref horizontal_result 0))
  45. (+ (list-ref vertical_result 1) (list-ref horizontal_result 1))
  46. (list-ref horizontal_result 2)
  47. (list-ref horizontal_result 3))))
  48. (list (list) 0 remaining_nodes subindex)))])
  49. (list
  50. (append (list stage) (list-ref horizontal_result 0))
  51. (* tf (car stage))
  52. (list-ref horizontal_result 2)
  53. (list-ref horizontal_result 3)))))))))))
  54. (TreeOptimizer->reset 4)
  55. (TreeOptimizer->iterate)
  56. ; The iterator is a list of pairs each indicating the number of nodes
  57. ; and number of substreams, respectively, for each substream in a
  58. ; depth-first order. The iteration per pair proceeds according to
  59. ; - number of nodes: 1 .. remaining_nodes
  60. ; - number of substreams: 0 (1) .. (remaining_nodes - number_of nodes)/2
  61. ; where 1 is taken if
  62. ; - number of nodes is 1 or
  63. ; - number of nodes is not remaining_nodes and there are no further.
  64. ; The last iteration has thus the number of nodes being the remaining
  65. ; nodes
  66. ; (horizontal_rec
  67. ; <substream>
  68. ; <nodes to distribute>
  69. ; <index of the substream>)
  70. ; =>
  71. ; <same as vertical_rec>
  72. ; (vertical_rec
  73. ; <no further nodes after this>
  74. ; <nodes to distribute>
  75. ; <index of the substream>
  76. ; <upstream component of topological factor>)
  77. ; =>
  78. ; (list
  79. ; <iterator section downstream>
  80. ; <sum of topological factor in substream>)
  81. ; <nodes to distribute left after>
  82. ; <first unused index after last node downstream>
  83.