2005-02-14 01:48:08 -05:00
|
|
|
;;;
|
|
|
|
;;; merge(?) sort for general purpose:
|
|
|
|
;;; ==================================
|
|
|
|
;;;
|
|
|
|
;;; (sort predicate list-to-be-sorted to-sort-in-list) ---> sorted-list
|
|
|
|
;;;
|
|
|
|
;;; where
|
|
|
|
;;;
|
|
|
|
;;; predicate : (lambda (a b) ...) with a x b ---> {#t, #f}
|
|
|
|
;;; e.g. (lambda (a b) (> a b))
|
|
|
|
;;; list-to-be-sorted : e.g. '(4 2 5 1 3)
|
|
|
|
;;; to-sort-in-list : e.g. '(6)
|
|
|
|
;;;
|
|
|
|
;;; will produce the result '(6 5 4 3 2 1).
|
|
|
|
;;;
|
|
|
|
(define (sort pred todo done)
|
|
|
|
(if (null? todo)
|
|
|
|
done
|
|
|
|
(sort pred (cdr todo) (insert pred (car todo) done))))
|
|
|
|
|
|
|
|
(define (insert pred item ls)
|
|
|
|
(if (or (null? ls) (pred item (car ls)))
|
|
|
|
(cons item ls)
|
|
|
|
(cons (car ls) (insert pred item (cdr ls)))))
|
|
|
|
|
2005-02-04 03:05:55 -05:00
|
|
|
(define time 0)
|
|
|
|
|
2005-01-21 10:40:59 -05:00
|
|
|
(define-enumerated-type color :color
|
|
|
|
is-color?
|
2005-02-04 03:05:55 -05:00
|
|
|
the-colors
|
2005-01-21 10:40:59 -05:00
|
|
|
color-name
|
|
|
|
color-index
|
|
|
|
(white grey black))
|
|
|
|
|
2005-02-04 03:05:55 -05:00
|
|
|
;;;
|
|
|
|
;;; DFS:
|
|
|
|
;;; ====
|
|
|
|
;;;
|
|
|
|
;;; (make-dfs node-name adjacencies ignored-data) ---> #{:dfs}
|
|
|
|
;;;
|
|
|
|
;;; node-name : "this is a node name"
|
|
|
|
;;; adjacencies : (list "another node name" "no node name")
|
|
|
|
;;; ignored-data : "anything you need in each node, eg. a long list..."
|
|
|
|
;;;
|
|
|
|
;;; (dfs->list node) ---> '(node-name adjacencies ignored-data)
|
|
|
|
;;;
|
|
|
|
;;; node : #{:dfs}
|
|
|
|
;;;
|
|
|
|
;;; (dfs-name node) ---> node-name
|
|
|
|
;;; (dfs-adjacencies node) ---> adjacencies
|
|
|
|
;;; (dfs-color node) ---> #{:color}
|
|
|
|
;;; (dfs-ftime node) ---> finishing-time
|
|
|
|
;;; (dfs-ignored node) ---> ignored-data
|
|
|
|
;;;
|
2005-01-21 10:40:59 -05:00
|
|
|
(define-record-type :dfs
|
2005-02-04 03:05:55 -05:00
|
|
|
(really-make-dfs name adjacencies color ftime ignored)
|
2005-01-21 10:40:59 -05:00
|
|
|
is-dfs?
|
2005-02-04 03:05:55 -05:00
|
|
|
(name dfs-name)
|
2005-01-21 10:40:59 -05:00
|
|
|
(adjacencies dfs-adjacencies)
|
|
|
|
;; color (white by default)
|
|
|
|
(color dfs-color)
|
|
|
|
;; finishing-time
|
|
|
|
(ftime dfs-ftime)
|
|
|
|
;; put in there what you like
|
2005-02-04 03:05:55 -05:00
|
|
|
(ignored dfs-ignored))
|
2005-01-21 10:40:59 -05:00
|
|
|
|
2005-02-04 03:05:55 -05:00
|
|
|
(define (make-dfs node-name adjacencies ignored-data)
|
|
|
|
(really-make-dfs node-name adjacencies (color white) 0 ignored-data))
|
2005-01-21 10:40:59 -05:00
|
|
|
|
2005-02-04 03:05:55 -05:00
|
|
|
(define (dfs->list dfs-node)
|
|
|
|
(list (dfs-name dfs-node) (dfs-adjacencies dfs-node) (dfs-ignored dfs-node)))
|
2005-01-21 10:40:59 -05:00
|
|
|
|
2005-02-16 06:05:39 -05:00
|
|
|
(define (dfs-lookup-node pred node-name dag)
|
2005-02-04 03:05:55 -05:00
|
|
|
(find (lambda (candidate)
|
2005-02-16 06:05:39 -05:00
|
|
|
(pred (dfs-name candidate) node-name))
|
2005-02-04 03:05:55 -05:00
|
|
|
dag))
|
2005-01-21 10:40:59 -05:00
|
|
|
|
2005-02-04 03:05:55 -05:00
|
|
|
;;;
|
|
|
|
;;; DEPTH FIRST SEARCH:
|
|
|
|
;;; ===================
|
|
|
|
;;;
|
|
|
|
;;; (dfs dag) ---> sorted-dag
|
2005-02-16 09:07:41 -05:00
|
|
|
;;; (dfs dag pred auto-leafs? create-leaf) ---> sorted-dag
|
2005-02-04 03:05:55 -05:00
|
|
|
;;;
|
2005-02-16 09:07:41 -05:00
|
|
|
;;; where
|
2005-02-04 03:05:55 -05:00
|
|
|
;;;
|
2005-02-14 01:48:08 -05:00
|
|
|
;;; dag : '(#{:dfs} ...) ; representation of a given
|
|
|
|
;;; directed acyclic graph)
|
2005-02-16 09:07:41 -05:00
|
|
|
;;; pred : (pred adj-id node-id) ---> #t (if adj-identifier
|
|
|
|
;;; and node-identifier are equal) or #f
|
2005-02-04 03:05:55 -05:00
|
|
|
;;;
|
2005-02-16 09:07:41 -05:00
|
|
|
;;; auto-leafs? : #t (by default) or #f
|
|
|
|
;;; if auto-leafs? is set to #f then it is an error
|
|
|
|
;;; that an adjacency is unresolveable in the list of
|
|
|
|
;;; all node-names. if auto-leafs? is enabled then
|
|
|
|
;;; every adjacency which is unresolveable in the list
|
|
|
|
;;; of all node-names is assumed to point to a leaf.
|
|
|
|
;;; this leaf is then created automatically by
|
|
|
|
;;; executing the function create-leaf.
|
|
|
|
;;;
|
|
|
|
;;; create-leaf : (create-leaf unresolved-adjacency-identifier) ---> #{:dfs}
|
|
|
|
;;; create-leaf is a function which is called with the
|
|
|
|
;;; unresolved adjacency identifier. By default, this
|
|
|
|
;;; argument is function returning a leaf named with
|
|
|
|
;;; the unresolved adjacency identifier, with no
|
|
|
|
;;; adjacencies, and ignored-data set to #f. This
|
|
|
|
;;; leaf, created by create-leaf, doesn't really have
|
|
|
|
;;; to be a leaf; it can be a node as well. Maybe this
|
|
|
|
;;; introduces new cyclic dependency problems; not sure.
|
2005-02-04 03:05:55 -05:00
|
|
|
;;;
|
2005-02-16 09:07:41 -05:00
|
|
|
;;; sorted-dag : the sorted dag
|
2005-02-04 03:05:55 -05:00
|
|
|
;;;
|
2005-02-16 09:07:41 -05:00
|
|
|
(define (dfs dag . maybe-args)
|
|
|
|
(let-optionals maybe-args ((pred string=?)
|
|
|
|
(auto-leafs? #t)
|
|
|
|
(create-leaf (lambda (unresolved-adj-id)
|
|
|
|
;; (display "unresolved adjecency: ")
|
|
|
|
;; (display unresolved-adj-id)
|
|
|
|
;; (newline)
|
|
|
|
(make-dfs unresolved-adj-id '() #f))))
|
2005-02-04 03:05:55 -05:00
|
|
|
(set! time 0)
|
|
|
|
(let ((node-names (map dfs-name dag)))
|
|
|
|
(if (not (null? node-names))
|
|
|
|
;; (sort pred todo-list done-list)
|
|
|
|
(sort (lambda (current position)
|
|
|
|
(< (dfs-ftime current) (dfs-ftime position)))
|
2005-02-14 01:48:08 -05:00
|
|
|
;;
|
|
|
|
;; the result of this should be the dag with the ftimes
|
|
|
|
;;
|
2005-02-04 03:05:55 -05:00
|
|
|
(let for-all-nodes ((node-name (car node-names))
|
|
|
|
(nodes-to-do (cdr node-names))
|
|
|
|
(current-dag dag))
|
2005-02-16 06:05:39 -05:00
|
|
|
(let ((current-node (dfs-lookup-node pred node-name current-dag)))
|
2005-02-04 03:05:55 -05:00
|
|
|
(cond
|
|
|
|
((eq? (dfs-color current-node) (color white))
|
2005-02-16 06:05:39 -05:00
|
|
|
(let ((new-dag (dfs-visit current-dag current-node
|
2005-02-16 09:07:41 -05:00
|
|
|
pred auto-leafs? create-leaf)))
|
2005-02-04 03:05:55 -05:00
|
|
|
(if (not (null? nodes-to-do))
|
|
|
|
(for-all-nodes (car nodes-to-do)
|
|
|
|
(cdr nodes-to-do)
|
|
|
|
new-dag)
|
|
|
|
new-dag)))
|
|
|
|
(else (if (not (null? nodes-to-do))
|
|
|
|
(for-all-nodes (car nodes-to-do)
|
|
|
|
(cdr nodes-to-do)
|
|
|
|
current-dag)
|
|
|
|
current-dag)))))
|
|
|
|
'())
|
|
|
|
node-names))))
|
2005-01-21 10:40:59 -05:00
|
|
|
|
2005-02-16 09:07:41 -05:00
|
|
|
(define (dfs-visit dag node pred auto-leafs? create-leaf)
|
2005-02-04 03:05:55 -05:00
|
|
|
;; (dfs-dag-show dag node)
|
|
|
|
(let ((name (dfs-name node))
|
|
|
|
(adjs (dfs-adjacencies node))
|
|
|
|
(ignored (dfs-ignored node)))
|
|
|
|
(let* ((current-node (really-make-dfs name adjs (color grey)
|
|
|
|
(dfs-ftime node) ignored))
|
|
|
|
(current-dag (cons current-node (delete node dag))))
|
|
|
|
(if (not (null? adjs))
|
|
|
|
(let for-all-adjs ((current-adj (car adjs))
|
|
|
|
(todo-adjs (cdr adjs)))
|
2005-02-16 06:05:39 -05:00
|
|
|
(let ((maybe-node (dfs-lookup-node pred current-adj current-dag)))
|
2005-02-04 03:05:55 -05:00
|
|
|
(if maybe-node
|
|
|
|
(begin
|
|
|
|
(if (eq? (dfs-color maybe-node) (color white))
|
2005-02-16 06:05:39 -05:00
|
|
|
(let ((next-dag (dfs-visit current-dag maybe-node
|
2005-02-16 09:07:41 -05:00
|
|
|
pred auto-leafs? create-leaf)))
|
2005-02-04 03:05:55 -05:00
|
|
|
(set! current-dag next-dag))
|
|
|
|
(if (eq? (dfs-color maybe-node) (color grey))
|
|
|
|
(error "dfs-visit: cycle detected; node-name: "
|
|
|
|
(dfs-name node)))))
|
|
|
|
(if auto-leafs?
|
2005-02-16 09:07:41 -05:00
|
|
|
(let ((leaf (create-leaf current-adj)))
|
2005-02-16 06:05:39 -05:00
|
|
|
(set! current-dag (dfs-visit (cons leaf current-dag) leaf
|
2005-02-16 09:07:41 -05:00
|
|
|
pred auto-leafs? create-leaf)))
|
2005-02-14 01:48:08 -05:00
|
|
|
(error "dfs-visit: unresolveable adjacency: "
|
|
|
|
current-adj))))
|
2005-02-04 03:05:55 -05:00
|
|
|
(if (not (null? todo-adjs))
|
|
|
|
(for-all-adjs (car todo-adjs) (cdr todo-adjs)))))
|
|
|
|
(set! time (+ time 1))
|
|
|
|
(cons (really-make-dfs name adjs (color black) time ignored)
|
|
|
|
(delete current-node current-dag)))))
|
2005-01-21 10:40:59 -05:00
|
|
|
|
2005-03-08 08:14:36 -05:00
|
|
|
(define (dfs-dag-show dag . maybe-arg)
|
|
|
|
(let-optionals maybe-arg ((node (make-dfs "show dag" '() #f)))
|
|
|
|
(newline) (newline) (newline) (newline)
|
|
|
|
(display "************************************************************\n")
|
|
|
|
(display (dfs-name node)) (newline)
|
|
|
|
(display "************************************************************\n")
|
|
|
|
(let ((dfs-node-show (lambda (node)
|
|
|
|
(newline)
|
|
|
|
(display "~dfs-name: ")
|
|
|
|
(display (dfs-name node))
|
|
|
|
(newline)
|
|
|
|
(display "~dfs-adjacencies: ")
|
|
|
|
(display (dfs-adjacencies node))
|
|
|
|
(newline)
|
|
|
|
(display "~dfs-color: ")
|
|
|
|
(display (dfs-color node))
|
|
|
|
(newline)
|
|
|
|
(display "~dfs-ftime: ")
|
|
|
|
(display (dfs-ftime node))
|
|
|
|
(newline)
|
|
|
|
(display "~dfs-ignored: ")
|
|
|
|
(display (dfs-ignored node))
|
|
|
|
(newline))))
|
|
|
|
(if (not (null? dag))
|
|
|
|
(let visit-each-node ((current-node (car dag))
|
|
|
|
(nodes-to-do (cdr dag)))
|
|
|
|
(dfs-node-show current-node)
|
|
|
|
(if (not (null? nodes-to-do))
|
|
|
|
(visit-each-node (car nodes-to-do) (cdr nodes-to-do))
|
|
|
|
(newline)))))))
|