Removing broken demo
svn: r404
This commit is contained in:
parent
e6d8266b44
commit
f88319ffa6
|
@ -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)
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue
Block a user