CISC 320 Homework #4 Answers to last three questions.

  1. C-12.18 Algorithm 12.25 can go wrong in several ways.

    1. If there is only one point, the line next <- S.after(curr) has an error because there is nothing on the list beyond curr (the second copy of a ).

    2. If there are only two points {a, b}, then we get prev = a , curr = b, next = a Thus there is no left turn (colinear points), and the line prev <- S.before(prev) is an error, since calling prev() is an error on the first element in the list.

    3. If the first three points {a, b, c} are colinear, we get an error for the same reason as in 2 above. Attempt to take prev of the first element in the list. For example, S = {(0,0),(1,1),(2,2),...}

      I believe all examples where the simplified algorithm fails fall in these three categories. If 3 points further down the list are colinear each other (but not with a), the algorithm handles them correctly, removing (at least) the middle one. If two or more points {b, c} further down the list are colinear with a, the algorithm also handles them correctly regardless whether the farther one from a appears first or second. This can be checked by a careful case by case analysis. Thus the algorithm can be fixed by just returning S if it has fewer than three entries, and by handling an initial segment of colinear points correctly.

  2. The boxing out algorithm.

    1. The alg is correct because no point eliminated in step 3 is a vertex of the convex hull and because then GiftWrap correctly computes the convex hull.

    2. Step 0 is O(1), Step 1 is O(n*lg(n)), Step 2 is O(n*lg(n)), Step 3 is O(n), since it takes one pass through the points. For each point "strictly inside the quadrilateral" can be determined in O(1) by asking the left turn question regarding each side of the quadrilateral. Step 4 is O(n2), since that is the cost of GiftWrap and it is possible no points were eliminated. Thus the overall cost is O(n2). Using an output sensitive formula, we could say it is O(n (lg(n) + h)) where h is the size of the convex hull.

    3. Suppose the n points are chosen on a grid rather than random:
               ..
         ..............
       ..................
      ....................
      ....................
      ....................
       ..................
         ..............
               ..
      
      The area of the disk is pi, so the area of each square in the grid is about pi/n. The side of each square is about sqrt(pi/n). At most the two ends of each line may be vertices of the convex hull. The height of the picture is 2, so the number of points on the convex hull is no more than about 4/sqrt(pi/n), which is some constant times sqrt(n). I would expect random points to also have a number of convex hull points roughly proportional to sqrt(n). Therefore O(n1.5) expected cost for GiftWrap. [More generally boundary goes as sqrt of area, which can here be thought of as n. We hold the radius at 1 and let the points get closer together as n gets large. But equivalently, you could hold the spacing between points at approximately 1 getting a radius proportional to sqrt(n).]

    4. I'd expect the boxing out to eliminate points according to the ratio of quadrilateral area to circle area. For large n the quadrilateral will likely be close to a square inscribed in the circle with vertices at North, East, South, and West. Thus about 2/pi points are eliminated, leaving about n/3 points for the Gift Wrap. This will lead to a welcome speedup to in practice. We can expect it to take about 1/5th the time of pure GiftWrap, since step 4 dominates the cost when n is large, and (n/3)1.5 is about n1.5/5. But the big O will not be affected.

    5. It would definitely be better to use Graham Scan in step 4 since n1.5 dominates n*lg(n).

  3. R-13.15. SubsetSum is in NP because this algorithm runs in polynomial time:
    bool VerifySubsetSum( set S, int k, set Y )
    /* S is a set of numbers, k is a target sum.  These two items constitute SubsetSum input.
       Treat the hint Y as a proposed subset of S summing to k.
       */
    {    set::iterator p;
         // Check sum while making sure Y is a subset of S.
         for(p = Y.begin(); p != Y.end() && S.isMember(*p) ; ++p) k -= *p;
         if ( p == Y.end() || k == 0) // then the hint is verified 
    	 return true;
         else // we must resort to brute force
             return SlowSubsetSum(S, k);
    }
    
    If S has n elements and Y is a valid hint, then Y has no more than n elements, so there will be at most n iterations of the for loop. each call to S.isMember() takes at most n comparisons (lg(n) if a good data structure is used). So the total cost when the nondeterministic hint Y is valid is no more than O(n2) and the verifier is in P as is required to prove SubsetSum is in NP.