Dijkstra documented.

.PLT modified.

svn: r159
This commit is contained in:
Jono Spiro 2004-08-08 00:04:09 +00:00
parent cb87da8e26
commit 7c856d35a6
5 changed files with 82 additions and 19 deletions

View File

@ -1,3 +1,37 @@
#| This script tests a priority queue (heap) that is correctly implemented, but incorrectly used.
It is not commented because it uses a some advanced FrTime concepts that can easily be looked
up in the help desk, and both the description and motivation of the example can be found in
"A Dataflow Language for Scriptable Debugging" (Marceau, Cooper, Krishnamurthi, Reiss),
available at:
http://www.cs.brown.edu/~sk/Publications/Papers/Published/mckr-dataflow-lang-script-debug/
This script uses the concept of maintaining a local model of the heap being debugged, as a simple,
and very slow, list. The difference is that a fancy heap used can be naively implemented as a list,
simply removing only the smallest element each time. Models are external to your program, you don't
have to add any test code to your program to use them. By adding and removing the items to our local
"model" (the values come from the heap code we used), we can compare the results and assert whether
it is working correctly or not. Our model shows the values we should be getting from the program,
but clearly are not.
To provide some context for this demo, and what debugging problem MzTake helps us explore, I offer
the following, out of context, taken directly from the paper:
We find that the queue's elements are not in sorted order while those in the model
are. More revealingly, the queue's elements are not the same as those in the model.
A little further study shows that the bug is in our usage of the priority queue:
we have failed to account for the fact that the assignment to dest.weight
in relax (figure 1) updates the weights of nodes already in the queue. Because
the queue is not sensitive to these updates, what it returns is no longer the
smallest element in the queue.
On further reading, we trace the error to a subtle detail in the description of
Dijkstra's algorithm in Cormen, et al.'s book [9, page 530]. The book permits
the use of a binary heap (which is how we implemented the priority queue) for
sparse graphs, but subsequently amends the pseudocode to say that the assignment
to dest.weight must explicitly invoke a key-decrement operation. Our error,
therefore, was not in the implementation of the heap, but in using the (faster)
binary heap implementation without satisfying its (stronger) contract. |#
(require "dijkstra-solver.ss"
(lib "match.ss"))
@ -6,6 +40,12 @@
("heap.ss" [inserts 49 6 bind 'item]
[removes 67 10 bind 'result]))
#| The following code merely observes the insertions and removals
from the heap. We notice whether any of the removals are out
of order based on the last item removed, as long as there are
no insertions between the two events. We can keep track of the
last 2 using history-e. |#
(define (not-in-order e)
(filter-e
(match-lambda
@ -24,16 +64,21 @@
(printf-b "all inserts and removes: ~a" (history-b inserts-and-removes-e))
(printf-b "all violations: ~a" (history-b violations))
(printf-b "latest-violation: ~a" (hold violations))
#| This output indicates that the queue has yielded nodes whose weights are out of order.
This confirms our suspicion that the problem somehow involves the priority queue. |#
(define ((insert-in-model item) model) (cons item model))
(define ((remove-from-model item) model) (filter (lambda (i) (eq? i item)) model))
(define inserters (accum-e (inserts . ==> . insert-in-model) empty))
(define removers (accum-e (removes . ==> . remove-from-model) empty))
#| Implementation of the local model follows... |#
(define ((insert-in-model item) model)
(printf "~nInserting ~a into model containing:~n~a~n" item (value-now model))
(cons item model))
(define model (merge-e inserters removers))
(define ((remove-from-model item) model)
(printf "~nRemoving ~a from model containing:~n~a~n" item (value-now model))
(filter (lambda (i) (not (equal? i item))) model))
(printf-b "model: ~a" model)
(define inserters (accum-b (inserts . ==> . insert-in-model) empty))
(define removers (accum-b (removes . ==> . remove-from-model) inserters))
(start/resume p)

View File

@ -17,7 +17,7 @@
(for-each (lambda (n) (graph-node-add! g n)) nodes)
(define (n-ref label)
(first (filter (lambda (n) (eq? label (node-label n))) nodes)))
(define edges
(list (list (n-ref 's) (n-ref '1))
(list (n-ref 's) (n-ref '2))
@ -27,10 +27,6 @@
(list (n-ref 'J) (n-ref '6))))
(for-each (lambda (e) (graph-edge-add! g (first e) (second e)))
edges)
(require (lib "pretty.ss"))
;(printf "input:~n")
;(pretty-print (graph-to-list g))
(printf "output:~n")
(print-struct #t)
(pretty-print (solve g (reverse nodes) (n-ref 's))))
(printf "~n~n---output from dijkstra.ss:~n~a~n---~n"
(solve g (reverse nodes) (n-ref 's))))

View File

@ -588,6 +588,13 @@ Known Problems
Tips and Tricks
* If output seems difficult to read in the script, e.g. you ever
see "struct:signal" and a lot of garbage, try (print-struct #f)
before you do any printing, or use (value-now behavior-name) to
get a more usable/printable version of a FrTime behavior (the
caveat is that it is no longer 'reactive' and it may be out of
date after the moment it is processed).
* You may want to bind more than one variable at a certain point
so that you only get one change event -- otherwise, you will
get multiple change events even if at the same trace point

View File

@ -10,8 +10,18 @@
(regexp-match #rx".1$" path)
(regexp-match #rx"make" path)))))
;For use with PLaneT
(parameterize ((current-directory "."))
(pack "mztake-planet.plt"
"MzTake Debugger"
'(".")
'()
my-filter
#t
'file
#f
#f
'(("frtime") ("stepper"))))
(pack-collections "mztake.plt" "MzTake Debugger" '(("mztake")) #t '(("frtime") ("stepper")) my-filter #t))
; Now, check-out
;(make-planet-archive "mztake.plt"))
; for use not on PLaneT
(pack-collections "mztake-distro.plt" "MzTake Debugger" '(("mztake")) #t '(("frtime") ("stepper")) my-filter))

View File

@ -1,6 +1,6 @@
(module mztake mzscheme
(define mztake-version "(rev. 8/6/2004)")
(define mztake-version "rev. 8/6/2004")
#|:::::::::LOAD/ANNOTATOR BUGS:::::::::::
* catch oops exception
@ -13,6 +13,11 @@
::::::::::::::::::::::::::::::::::::::::::
Re-direct, or at least prefix, program output from the client so that it can be distinguished from the script
Paramterize print-struct to #f for printing in the script
DEMOS---------------------------------------------------------------------------------------
* Data structure examples
Binary search over a tree, show which node is being examined, or the most commonly taken path