Big Assignment A – Testing Properties

Big Assignment A – Testing Properties

Due Fri 4/21 11:59pm

Unlike the assignments with numbers in their names, this assignment is worth more points. See the course website for more information about how your grade is calculated.

1.

The function below is a buggy implementation of Prim’s algorithm for finding a minimum spanning tree. It uses graph.rkt which, as far as I know, is not buggy. The top of the file documents its exports in comments.

Formulate a property that should hold for minimum spanning trees and then find an input that fails to satisfy that property. Use random testing. Once you have that input, turn it into a small test case. Fix the bug.

  #lang racket
  (require "graph.rkt" rackunit)
  (provide
   (contract-out
    [prim (-> graph? graph?)]
    [find-smallest-outgoing-edge
     (-> graph?
         (set/c string?)
         (or/c (cons/c string? string?) #f))]))
   
  (define (prim g)
    (define remaining (apply set (nodes g)))
    (define mst (copy-graph g))
    (remove-edges! mst)
    (cond
      [(set-empty? remaining)
       mst]
      [else
       (set! remaining (set-remove remaining (set-first remaining)))
       (let loop ()
         (unless (set-empty? remaining)
           (match-define (cons src dest) (find-smallest-outgoing-edge g remaining))
           (set! remaining (set-remove remaining src))
           (loop)))])
    mst)
   
  ;; returns the edge with the minimum weight that
  ;; starts from an element of `remaining` and does not
  ;; go into `remaining` or #f if there aren't any such
  (define (find-smallest-outgoing-edge g remaining)
    (define best-e #f)
    (for* ([v (in-set remaining)]
           [n (in-list (neighbors g v))])
      (cond
        [(set-member? remaining n) (void)]
        [(not best-e) (set! best-e (cons v n))]
        [else
         (define best-e-w (edge-weight g (car best-e) (cdr best-e)))
         (define new-e-w (edge-weight g v n))
         (when (and new-e-w (< new-e-w best-e-w))
           (set! best-e (cons v n)))]))
    best-e)
   
   

2.

Implement the Kruskal’s algorithm for finding the minimum spanning tree. Racket comes with an implementation of the union-find data structure in the library data/union-find which you may use if you wish (but you are not required to). Use random testing to try to find bugs in your implementation, using the property that you developed for the previous problem. The graph library comes with a function to make random undirected graphs. Strive to make a correct implementation, using the random testing as well as unit testing of your own to help you.

In general, it is not the case that the two algorithms will return the same minimum spanning tree, as there may be multiple different minimum spanning trees. Still, when there is a unique minimum spanning tree, then both algorithms must return that tree. Furthermore, when all of the edges in a graph have distinct weights, the minimum spanning tree is unique. Use this fact to build another property that compares the two algorithms directly and test it using random testing.

Submit a single racket file with your solution via Canvas.