ulrail.gif

Homework 5

  ur-2c.gif urrail.gif
blrail-nonavbar.gif

Home | Resources | Assignments | Exams
Lectures | Course Staff | Submit

br-2a.gif   br-2c.gif brrail.gif
spacer.gif

spacer.gif

Due: 11:59 PM, Tuesday, November 6

Purpose

The goal of this assignment is to gain experience creating your own data types, and learn about a very important problem in computer science: the Traveling Salesperson Problem.

Before Lab

Read this document carefully, and make sure you have read up to and including chapter 3.3 in your textbook.

For the post-lab assignment, you should begin reading chapter 4; there is lots of useful information in chapter 4.3.

In Lab

  1. Create three Java projects:

    • ComplexConcreteRepresentation
    • ComplexAbstractDataType
    • ComplexObjectOriented

  2. Copy the Java files from the corresponding source directories into these projects.

  3. The first (Concrete) project illustrates how to implement new data types using no more Java than you already know.

  4. The second (Abstract) project introduces one important new programming concept and mechanism -- the ability to *instantiate abstract types* (your own classes) having non-static data members. This is the key trick that lets you "hide" concrete representations behind *abstract* data type interfaces. Note that the interface as seen by the client no longer gives any indication that the underlying, concrete representation is an array of doubles. The *concrete data representation* is abstracted away, so that clients need reason only in terms of the desired abstraction. To see how the abstraction really works, compare and contrast the ADT and Concrete versions of exactly the same abstraction.

  5. The third (Object oriented) introduces a second -- and for many the most difficult to grasp -- programming construct and mechanism: the idea that we can operate on "objects" (which are just instances of classes as seen in the Abstract project), by "sending them messages". You can think of the caller as sending a message to a complex number to tell the number to compute and return its absolute value, for example, or to add itself to a second complex number and to return a new complex number as the result. The way this actually works is that the "receiver" of the message is simply passed as a *hidden* first parameter to any given function call. Within the code that implements that function, this implicit parameter is referred to as "this." To see how this really works, carefully compare and contrast the OO and ADT versions of the same abstraction. You should be able to see precisely how the *explicit* first parameter in the ADT version becomes an *implicit* (but nevertheless present) parameter in the OO version.

  6. In the lab session, you should implement a few methods where indicated, first in the Concrete code, then in the ADT code, then in the OO code, to get a clear sense of how the same method gets implemented in different ways depending on your design strategy. In practice the concrete version would generally be unacceptable, unless you happened to be working in a language with little or no support for data abstraction. Abstraction is really the key to complexity management, and the "concrete" version doesn't "have enough of it," in the sense that the concrete representation decision is exposed to clients who shouldn't have to "see" that decision. The ADT and OO versions would both be acceptable in many cases, although most developers today would prefer (and would typically require) the OO version.

  7. By the time you leave the lab, you should understand how to complete all three versions. You are welcome to work with one or two partners (no more) to complete this assignment, however, if you choose to work with someone, you must *not* split up the work. Rather you must work together. The essence of this assignment is to make sure that each person considers carefully the relationships between the three designs. If you split up the work, that won't happen. So feel free to work together as long as you're all physically in the same place when the code is being written. Discuss the code as you write it. The concepts here are deep and tricky to grasp at first. It's going to take thinking and discussion to really "get it."

  8. You should submit complete versions of the code by midnight *next Tuesday*. In other words, we're giving more time to complete this lab assignment than usual.

Post Lab

Given a set of N points in the plane, the goal of a traveling salesperson is to visit all of them (and arrive back home) while keeping the total distance traveled as short as possible. Write a program to compute an approximate solution to the traveling salesperson problem (TSP), and use it to find the shortest tour that you can, connecting a given set of points in the plane.

Perspective. The importance of the TSP does not arise from an overwhelming demand of salespeople to minimize their travel distance, but rather from a wealth of other applications, many of which seem to have nothing to do with the TSP at first glance. Real world application areas include: vehicle routing, circuit board drilling, VLSI design, robot control, X-ray crystallography, machine scheduling, and computational biology.

Nervous? Help is here!

Greedy heuristics. The traveling salesperson problem is a notoriously difficult combinatorial optimization problem, In principle, one can enumerate all possible tours, but, in practice, the number of tours is so staggeringly large (roughly N factorial) that this approach is useless. For large N, no one knows an efficient method that can find the shortest possible tour for any given set of points. However, many methods have been studied that seem to work well in practice, even though they are not guaranteed to produce the best possible tour. Such methods are called heuristics. Your main task is to implement the nearest neighbor and smallest increase insertion heuristics for building a tour incrementally. Start with a one-point tour (from the first point back to itself), and iterate the following process until there are no points left.

  • Nearest neighbor heuristic:  Read in the next point, and add it to the current tour after the point to which it is closest. (If there is more than one point to which it is closest, insert it after the first such point you discover.)

  • Smallest increase heuristic:  Read in the next point, and add it to the current tour after the point where it results in the least possible increase in the tour length. (If there is more than one point, insert it after the first such point you discover.)

Point data type. First, create a Point data type that represents a point in the plane. Each Point object should be able to print itself to standard output, plot itself using standard draw, plot a line segment from itself to another point, and calculate the Euclidean distance between itself and another point. It should have the following API:

public Point(double x, double y)    // constructor
public String toString()            // return string representation
public void draw()                  // draw point
public void drawTo(Point b)         // draw line segment between the two points
public double distanceTo(Point b)   // return Euclidean distance between the two points

Tour data type. Next, create a Tour data type that represents the sequence of points visited in a TSP tour. Represent the tour as a circular linked list of nodes, one for each point. Each Node will contain a Point and a reference to the next Node in the tour. Within Tour.java, define a nested class Node in the standard way.

private class Node {
    private Point p;
    private Node next;
}
Each Tour object should be able to print its constituent points to standard output, plot its points using standad draw, compute its total distance, and insert a new point using either of the two heuristics. Your Tour data type should support the following API:
public Tour()                         // create an empty tour
public void show()                    // print the tour to standard output
public void draw()                    // draw the tour
public double distance()              // return the total distance of the tour
public void insertSmallest(Point p)   // insert p using the smallest insertion heuristic
public void insertNearest(Point p)    // insert p using the nearest neighbor heuristic

Confused? Help is here!

Input format. The input format will begin with two integers w and h, followed by pairs of real-valued x and y coordinates. All x coordinates will be real numbers between 0 and w; all y coordinates will be real numbers between 0 and h. As an example, the file tsp4.txt contains the following data

600 600
532.6531 247.7551
 93.0612 393.6735
565.5102 590.0000
 10.0000  10.0000

Testing. Many test data files are also available (click here for the whole directory as one .zip file). Once you implement Point and Tour, use the client program NearestInsertion.java to run the nearest insertion heuristic and print the resulting tour and its distance to standard output. Program SmallestInsertion.java is analogous but runs the smallest insertion heuristic. Programs NearestInsertionDraw.java and SmallestInsertionDraw.java are similar but they plot the results using StdDraw.

Contest and extra credit. Implement a better heuristic. For example, observe that any tour with paths that cross can be transformed into a shorter one with no crossing paths: add that improvement to your program. Here are some other ideas. We will award a special prize to whomever finds the shortest tour around the 1000-point set.

Want some help? Help is here!

Submission

Go to the CS101 submission page and follow the instructions provided. Submit the files readme.txt, Tour.java, and Point.java. Extra credit can be subbitted in a file called extracredit.zip.

spacer.gif
spacer.gif footer-middle.gif spacer.gif