Different graph implementations statistics added by arthurmaciel on Wed Feb 6 22:01:58 2013

$ csc implementations.scm -o implementations && ./implementations 

 Adding edges (Nested hash-tables)
6.632s CPU time, 3.396s GC time (major), 5209795 mutations, 45/17615 GCs (major/minor)

 Serializing to file (Nested hash-tables)
19.613s CPU time, 2.592s GC time (major), 22653398 mutations, 5/56528 GCs (major/minor)

 Checking nodes (Nested hash-tables)
0s CPU time

 Checking edges (Nested hash-tables)
1.076s CPU time, 0/8441 GCs (major/minor)

 Removing edges (Nested hash-tables)
1.112s CPU time, 0/8746 GCs (major/minor)

-----------------------------------------------------------------

 Adding edges (List in hash-table)
1.564s CPU time, 2504795 mutations, 0/10471 GCs (major/minor)

 Serializing to file (List in hash-table)
20.25s CPU time, 3.216s GC time (major), 22673569 mutations, 10/54625 GCs (major/minor)

 Checking nodes (List in hash-table)
0s CPU time

 Checking edges (List in hash-table)
47.315s CPU time, 0/4889 GCs (major/minor)

 Removing edges (List in hash-table)
102.21s CPU time, 0.288s GC time (major), 1/732014 GCs (major/minor)


(use extras srfi-69 srfi-1)

;; Conventions:
;; nht = nested hash tables
;; lht = list in hash table
;; s-node = source node (of edge)
;; d-node = destination node (of edge)

(define (lht-graph)
  (define g (make-hash-table))

  (define (id) "List in hash-table")
  
  (define (add-edge! s-node d-node #!optional (property 'none))
    (hash-table-update!/default g
                                s-node
                                (lambda (v)
                                  (cons (cons d-node property) v))
                                (list (cons d-node property))))

  (define (remove-edge! s-node d-node)
    (let ((edges (hash-table-ref/default g s-node #f)))
      (if edges
          (delete! d-node edges))))

  (define (has-node? node)
    (hash-table-exists? g node))
  
  (define (has-edge? s-node d-node)
    (member d-node (hash-table-ref/default g s-node '())))

  (define (graph->alist)
    (hash-table-map g (lambda(k v)
                        (cons k v))))

  (define (serialize #!optional (file "graph.txt"))
    (with-output-to-file file (lambda ()
                                (pp (graph->alist)))))
  
  ;; Dispatcher
  (lambda (selector)
    (case selector
      ((id)                id)
      ;;((add-node!)         add-node!)
      ((add-edge!)         add-edge!)
      ((remove-edge!)      remove-edge!)
      ((has-edge?)         has-edge?)
      ((has-node?)         has-node?)
      ((graph->alist)      graph->alist)
      ((serialize)         serialize)
      (else (error "Uknown procedure")))))

(define (nht-graph)
  (define g (make-hash-table))
  
  (define (id) "Nested hash-tables")

  (define (add-edge! s-node d-node #!optional (property 'none))
    (let ((edges (hash-table-ref/default g s-node #f)))
      (if edges
          (hash-table-set! edges d-node property)
          (hash-table-set! g
                           s-node
                           (alist->hash-table `((,d-node . ,property)))))))

  (define (remove-edge! s-node d-node)
    (let ((edges (hash-table-ref/default g s-node #f)))
      (if edges
          (hash-table-delete! edges d-node)
          #f)))

  (define (has-node? node)
    (hash-table-exists? g node))

  (define (has-edge? s-node d-node)
    (let ((edges (hash-table-ref/default g s-node #f)))
      (if edges
          (hash-table-exists? edges d-node)
          #f)))

  (define (graph->alist)
    (hash-table-map g (lambda(k v)
                        (cons k (hash-table->alist v)))))

 (define (serialize #!optional (file "graph.txt"))
  (with-output-to-file file (lambda ()
                              (pp (graph->alist)))))

  ;; Dispatcher
  (lambda (selector)
    (case selector
      ((id)                id)
      ;;((add-node!)         add-node!)
      ((add-edge!)         add-edge!)
      ((remove-edge!)      remove-edge!)
      ((has-edge?)         has-edge?)
      ((has-node?)         has-node?)
      ((graph->alist)      graph->alist)
      ((serialize)         serialize)
      (else (error "Uknown procedure")))))

(define (make-graph #!optional (impl 'lht))
  (case impl
    ((lht)     (lht-graph))
    ((nht)     (nht-graph))))


;; Test case
(define VERTEXES 2500)
(define EDGES 1000)

(define (add-edges g)
  (printf "~N Adding edges (~A)~N" ((g 'id)))
  (do ((n 0 (+ n 1))) ((= n VERTEXES))
    (do ((e 0 (+ e 1))) ((= e EDGES))
      ((g 'add-edge!) n (+ e 1)))))

(define (del-edges g)
  (printf "~N Removing edges (~A)~N" ((g 'id)))  
  (do ((n 0 (+ n 1))) ((= n VERTEXES))
    (do ((e 0 (+ e 1))) ((= e EDGES))
      ((g 'remove-edge!) n (+ e 1)))))

(define (check-nodes g)
  (printf "~N Checking nodes (~A)~N" ((g 'id)))  
  (do ((n 0 (+ n 1))) ((= n VERTEXES))
    (g 'has-node?) n))

(define (check-edges g)
  (printf "~N Checking edges (~A)~N" ((g 'id)))  
  (do ((n 0 (+ n 1))) ((= n VERTEXES))
    (do ((e 0 (+ e 1))) ((= e EDGES))
      ((g 'has-edge?) n (+ e 1)))))

(define (serialize-to-file g)
  (printf "~N Serializing to file (~A)~N" ((g 'id)))  
  ((g 'serialize)))

(define (run-test graph)
  (time (add-edges graph))
;;  (pp ((graph 'graph->alist)))
  (time (serialize-to-file graph))
  (time (check-nodes graph))
  (time (check-edges graph))
  (time (del-edges graph)))

(define lht-graph (make-graph 'lht))
(define nht-graph (make-graph 'nht))

(run-test nht-graph)
(printf "~N-----------------------------------------------------------------~N")
(run-test lht-graph)