From f88319ffa661acc3e0ea70d120c5d58c7f280280 Mon Sep 17 00:00:00 2001 From: Jay McCarthy Date: Wed, 20 Jul 2005 18:44:26 +0000 Subject: [PATCH] Removing broken demo svn: r404 --- .../dijkstra/dijkstra-mztake-uncommented.ss | 43 +++++++++- .../mztake/demos/dijkstra/dijkstra-mztake.ss | 84 ------------------- 2 files changed, 42 insertions(+), 85 deletions(-) delete mode 100644 collects/mztake/demos/dijkstra/dijkstra-mztake.ss diff --git a/collects/mztake/demos/dijkstra/dijkstra-mztake-uncommented.ss b/collects/mztake/demos/dijkstra/dijkstra-mztake-uncommented.ss index ad576e22f6..28772659d2 100644 --- a/collects/mztake/demos/dijkstra/dijkstra-mztake-uncommented.ss +++ b/collects/mztake/demos/dijkstra/dijkstra-mztake-uncommented.ss @@ -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 (lib "mztake.ss" "mztake") "dijkstra-solver.ss" (lib "match.ss")) @@ -5,6 +39,12 @@ (define/bind (loc "heap.ss" 49 6) item) (define/bind (loc "heap.ss" 67 10) 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 @@ -23,7 +63,8 @@ (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. |# #| Implementation of the local model follows... |# (define ((insert-in-model item) model) diff --git a/collects/mztake/demos/dijkstra/dijkstra-mztake.ss b/collects/mztake/demos/dijkstra/dijkstra-mztake.ss deleted file mode 100644 index e44da55202..0000000000 --- a/collects/mztake/demos/dijkstra/dijkstra-mztake.ss +++ /dev/null @@ -1,84 +0,0 @@ -#| 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")) - -(define-mztake-process p - ("dijkstra.ss") - ("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 - [('reset _) false] - [(_ 'reset) false] - [(previous current) (> previous current)] - [else false]) - (history-e 2 e))) - - -(define inserts-and-removes-e (merge-e (removes . ==> . node-weight) - (inserts . -=> . 'reset))) -(define violations (not-in-order inserts-and-removes-e)) - - -(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. |# - - - -#| 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 ((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)) - -(define inserters (accum-b (inserts . ==> . insert-in-model) empty)) -(define removers (accum-b (removes . ==> . remove-from-model) inserters)) - -(start/resume p)