CS 60 Fall 1997, Assignment 6

Due Monday, December 8

Predicate Logic and Complexity

[3 problems, 100 points total]

This assignment consists of one textual answer embedded as a comment in a Java program, one Prolog program, and another Java program. To simplify handling, please submit them as if they were three separate assignments, numbered 6, 7, and 8.

6. [25 points]

Devise an appropriate loop invariant (for the point marked by /* */) and use it to show that the following function returns the cube of its argument, provided that the argument is non-negative.

static long cube(long N)
  {
  long i, x, y, z;
  x = 0;
  y = 1;
  z = 6;

  for( i = 0; /* */ i < N; i++ )
    {
    x = x + y;
    y = y + z;
    z = z + 6;
    }
  return x;
}

Devise an appropriate energy function and use it to show that the program terminates for arguments N >= 0. What invariant do you need to show that your function really is an energy function?

(This is how Babbage's difference engine might have computed cube. To see how the method is derived, execute the following in rex:

cubes = map((i) => i*i*i, from(0));  // sequence of all cubes
first_diffs = diff(-, cubes);        // first differences of cubes
second_diffs = diff(-, first_diffs); // second differences of cubes
third_diffs = diff(-, second_diffs); // third differences of cube

Then look at each of the sequences defined.)

The proof of invariance should be inserted as a comment in the .java file.

Once you have your invariant, include it as the argument to an assert predicate in the code which is included in the loop test as shown below and test its validity by running the code on various input values, say 0 to 25, checking that the invariant never fails:

assert(.... your invariant ....) && i < N

Here the definition of assert is:

static boolean assert(boolean PredicateValue)
  {
  if( PredicateValue )
    return true;
  System.err.println("*** assertion failed ***");
  System.exit(1);
  return false;
  }

Thus a true assertion will have no effect on the test which follows, while a false assertion will terminate the program immediately, printing a message.

(This is how Babbage's difference engine might have computed cube. To see how the method can be derived, execute the following in rex:

     cubes = map((X) => X*X*X, range(0, 10)); // sequence of all cubes
     first_diffs = diff(-, cubes);            // first differences of cubes
     second_diffs = diff(-, first_diffs);     // second differences of cubes
     third_diffs = diff(-, second_diffs);     // third differences of cubes

Then look at each of the sequences defined.)

7. [25 points]

This problem entails coding information and queries into predicate logic using Prolog. Your file should be a program which will load and run in Prolog. (The executable on turing is called 'bp'. As always, you may need to ask some questions about the formulation of certain types of information. The names are in lower-case for convenience in working with Prolog; to capitalize them would require that we include them in single quotes.)

a. Code the following predicates about local restaurants in Prolog:

serves predicate: 
american restaurants serve 
	salad, steak, sandwiches, burgers, and fried chicken.
burger_place restaurants serve 
	burgers, fries, and salad.
cajun restaurants serve
	rice, beans, gumbo, and sausage.
chinese restaurants serve 
	eggrolls, rice, shrimp, soup, and noodles. 
indian restaurants serve 
	papadam, bagan_bharta, rice, tandoori, and naan.
italian restaurants serve 
	salad, pasta, cioppino, snapper, and bread.
japanese restaurants serve 
	sashimi, rice, tempura, and noodles. 
mediterranean restaurants serve
	gyros, humus, pita, and falafel. 
mexican restaurants serve 
	tacos, beans, rice, enchiladas, and snapper. 
pizza restaurants serve 
	pizza, salad, garlic_bread
seafood_place restaurants serve
	salad, shrimp, snapper, bouillabaisse, and clams. 
thai restaurants serve 
	eggrolls, rice, noodles, and pad_thai. 
dish predicate:
vegetarian dishes:
	beans, bagan_bharta, enchiladas, falafel, humus, 
	pizza, salad, soup, tempura, and all starch dishes 
meat dishes:
	burgers, enchiladas, gyros, pad_thai, pizza, steak, sandwiches, 
	fried_chicken, tacos, tandoori
seafood dishes:
	eggrolls, snapper, cioppino, sashimi, shrimp, bouillabaisse, 
	tempura 
starch dishes:
	naan, papadam, bread, rice, noodles, pita, garlic_bread, pasta, fries
cuisine and location predicate:
arrufos is an italian restaurant in claremont.
bamboo_yuan is a chinese restaurant in claremont.
bombay is an indian restaurant in ontario.
chilis is an american restaurant in laverne. 
don_salsa is a mexican restaurant in claremont. 
el_gato is a mexican restaurant in upland. 
full_house is a chinese restaurant in upland. 
islands is a burger place in montclair. 
kishi is a japanese restaurant in upland. 
nirvana is an indian restaurant in montclair. 
nogi is a japanese restaurant in claremont. 
orchid_garden is a thai restaurant in laverne. 
pizza_n_such is a pizza_place restaurant in claremont. 
rosas is an italian restaurant in ontario. 
sacas is a mediterranean restaurant in claremont. 
sanamluang_cafe is a thai restaurant in pomona. 
shrimp_house is a seafood restaurant in claremont. 
tutti_mangia is an italian restaurant in claremont. 
warehouse is a pizza_place restaurant in laverne. 
yiannis is a mediterranean restaurant in claremont. 
county predicate: 
claremont is in los_angeles_county. 
laverne is in los_angeles_county. 
montclair is in san_bernardino_county. 
ontario is in san_bernardino_county. 
pomona is in los_angeles_county. 
upland is in san_bernardino_county. 

b. Code the following queries in Prolog and show their execution relative to the database above. In some cases, you may find it helpful to define auxiliary predicates to assist.

  1. Which restaurants are in claremont?
  2. Which restaurants have italian cuisine?
  3. Which restaurants serve bouillabaisse?
  4. Where can you get served rice in claremont?
  5. Where can you get served a vegetarian dish in montclair?
  6. Which restaurants serve both vegetarian and meat dishes?
  7. Which cities have both a chinese restaurant and a mexican restaurant?
  8. Which restaurants in claremont or upland serve meat dishes?
  9. Which restaurants in san_bernardino_county serve vegetarian dishes?
  10. Which restaurants in claremont don't serve snapper?
  11. Which cities have more than one restaurant of some type of cuisine?
  12. Which cities have more than one restaurant serving noodles?

 

8. [50 points]

This problem exercises several ideas:

  1. Constructing an efficient sorting program,
  2. Empirical complexity analysis; and
  3. Using modifiable list structure.

The problem is to program class mergesort in Java for sorting data of type float. This form of sort is described in greater detail below. The actual merge sort should be a static method called sort of class mergesort. The header for this method will thus be:

static List sort(List list)

Here are the requirements for your sort:

  1. It must run in time O(n log n) upper bound. This must be verified empirically by running your sort on data sets of increasing size, say up to about 100,000 elements.
  2. It should sort the list "in place", that is, without generating additional lists. Thus, once the input list is created, you should not generate additional list cells; instead you will just be changing references in existing cells.

Below we show the mergesort process. The original list is split into two lists of roughly equal length. This can be done most easily by modifying the references in the original list, scanning it from front to back and building the split lists back to front. After splitting, the two lists are sorted by recursive calls to mergesort. Then the two resulting lists are merged. Merging consists of traversing the two sorted lists from front to back and "building" a new list from front to back at the same time.

Here are some hints and suggestions:

  1. sort will be recursive. Its basis is lists of length 0 or 1.
  2. For the inductive case, sort should, in effect, divide its argument list into two parts. Assume that we are willing to allow the argument to be restructured in the process. It should recursively sort each half resulting from the split, then merge the two halves destructively, in a manner that zero or minimal new list cells are created in the process.
  3. There is a merge sort described in the notes on functional programming. While its analysis is similar to the one for your program, it uses lists of lists and no splitting. You should avoid this technique, since it uses more list cells than are necessary.
  4. It is probably simpler if you don't use any knowledge of the lengths of the two lists in merging.
  5. The program random will generate a specified number of random numbers in a specified range.
    
            random N low high | java -cs mergesort
    

    will generate N random integers in a range low to high and pipe them into your program.

  6. The timer used measures wall-clock time rather than processor time. For large data sets it will not necessarily give the most accurate picture of your run-time, since others are sharing the computer with you. This is ok, but be aware that the time may be a little inflated.