#!/usr/bin/guile !# ;; (TreeOptimizer->reset n_nodes) -> unspecified ;; Restart generation with n_nodes (define TreeOptimizer->reset #f) ;; (TreeOptimizer->iterate) -> (topo_factor . specification) ;; Calculate the topological factor of the next specified iteration (define TreeOptimizer->iterate #f) (let ([iterator (list)] [n_nodes #f]) (set! TreeOptimizer->reset (lambda (n_nodes_new) (set! iterator (list)) (set! n_nodes n_nodes_new))) (set! TreeOptimizer->iterate (lambda () (let vertical_rec ([last_node #t] [remaining_nodes n_nodes] [index 0] [tf 0]) (let ([trailing (= (+ (length iterator) 1) index)]) (let ([stage (if (<= (length iterator) index) '(1 . 1) (list-ref iterator index))]) (if (and trailing (= (car stage) remaining_nodes)) ; Break recursion. Must only happen on last_node (list (list) 0 remaining_nodes index) (let ([stage (if trailing (let ([max_substream (remainder (- remaining_nodes (car stage)) 2)]) (if (= (cdr stage) max_substream) (let ([new_nodecount (+ (car stage) 1)]) (cons new_nodecount (if (and last_node (not (= new_nodecount remaining_nodes))) 1 0)) (cons (car stage) (+ (cdr stage) 1)))) stage))]) (let ([horizontal_result (let horizontal_rec ([substream 0] [remaining_nodes remaining_nodes] [subindex (+ index 1)]) (if (< substream (cdr stage)) (let ([vertical_result (vertical_rec (and last_node (= substream (- (cdr stage) 1))) remaining_nodes subindex (+ tf (cdr stage) (car stage)))]) (let ([vertical_result (horizontal_rec (+ substream 1) (list-ref vertical_result 2) (list-ref vertical_result 3))]) (list (append (list-ref vertical_result 0) (list-ref horizontal_result 0)) (+ (list-ref vertical_result 1) (list-ref horizontal_result 1)) (list-ref horizontal_result 2) (list-ref horizontal_result 3)))) (list (list) 0 remaining_nodes subindex)))]) (list (append (list stage) (list-ref horizontal_result 0)) (* tf (car stage)) (list-ref horizontal_result 2) (list-ref horizontal_result 3))))))))))) (TreeOptimizer->reset 4) (TreeOptimizer->iterate) ; The iterator is a list of pairs each indicating the number of nodes ; and number of substreams, respectively, for each substream in a ; depth-first order. The iteration per pair proceeds according to ; - number of nodes: 1 .. remaining_nodes ; - number of substreams: 0 (1) .. (remaining_nodes - number_of nodes)/2 ; where 1 is taken if ; - number of nodes is 1 or ; - number of nodes is not remaining_nodes and there are no further. ; The last iteration has thus the number of nodes being the remaining ; nodes ; (horizontal_rec ; ; ; ) ; => ; ; (vertical_rec ; ; ; ; ) ; => ; (list ; ; ) ; ;