CS 188, Spring 2004, Introduction to Artificial Intelligence
Assignment 0, due 1/28, total value 1% of grade

To be done individually

People entering CS188 vary widely in their Lisp experience: this assignment should serve as a refresher and an opportunity to become more familiar with Common Lisp in particular.

Grading on this assignment is binary: if you make an honest effort at most of the questions you will get 100%, otherwise 0%. As with any programming assignment, include with each answer a transcript showing that the code works on a few different inputs. Submit your solution using the submit program from an instructional (named or class) account, as described here. The name for the assignment is a0 and your solution file should be called a0.lisp. Your file should be loadable into lisp and should include explanations and output traces (as needed) in portions commented with semicolons.

You may find the Notes on Lisp useful as well as the Tutorial on how to use Lisp, emacs, and the AIMA code.

Please try to comment your code and use, meaningful variable names.

  1. Exponentiation
    Write a recursive function (two-to-the x) which takes a single non-negative integer parameter x and returns 2x. (This can be done in logarithmic time.)

  2. Write a LISP function (count-trees n) which returns the number of distinct strictly binary trees with n leaves. A strictly binary tree is one in which every node other than a leaf has exactly two children. A leaf has no children. There is 1 strictly binary tree with 1 leaf (just a single node tree), 1 strictly binary tree with 2 leaves, 2 distinct strictly binary trees with 3 leaves, and 5 distinct strictly binary trees with exactly 4 leaves. (count-trees n) can be implemented fairly easily using recursion. Test your program for n = 1 through 10. [Hint: Suppose a tree with n leaves has a leaves in its left subtree and b leaves in its right subtree, where a+b=n; how many such trees are there?]
    Optional: measure the runtime as a function of n and find a way to speed it up by caching partial results.

  3. Symbolic differentiation
    One important AI application area is symbolic mathematics, particularly calculus. For this problem, you will construct a function deriv which differentiates simple, single-variable mathematical expressions. The function takes two arguments. The first is a mathematical expression in standard LISP syntax, containing numbers, atoms (representing constants and variables) and the binary functions +,-,*,/,expt. The second is the name of the variable with respect to which to differentiate. Other symbols in the expression are treated as constants. The rules of differentiation are as follows (where u and v are arbitrary expressions):

    u = constant implies du/dx = 0
    d(u+v)/dx = du/dx + dv/dx; d(u-v)/dx = du/dx - dv/dx
    d(uv)/dx = udv/dx + vdu/dx
    d(u/v)/dx = (vdu/dx - udv/dx)/v
    v = constant implies d(uv)/dx = (du/dx)vu(v-1)
    d(eu)/dx = (du/dx)eu

    Test your function on some interesting inputs. Add more rules (e.g., for trig functions) if you wish. For extra brownie points, you can write a simplifier to reduce the resulting expressions to their simplest form. For example, 0 * u simplifies to 0 and so on.

  4. List recursion
    Write the following functions:
    (last-element l) returns the last element of l;
    (all-but-last l) returns all but the last element;
    (middle l) returns the middle element, assuming an odd number of elements.
    Don't use any numbers to implement middle.

    (Optional) A definition of middle using cdr and all-but-last uses quadratic time and space; you can try to write a version that uses linear time and constant space.

  5. Powerset
    A standard mathematical set function is powerset, which computes the set of all subsets of a set. For example,
       >    (powerset '(a b))
       (nil (a) (b) (a b))
    Implement this as a recursive function. It may require other subsidiary functions.

  6. Data types
    (a) Write defstructures for points and line segments in two dimensions.
    (b) Write a function (distance p1 p2) that returns the distance between two points.
    (c) Write a function (midpoint l) that returns the midpoint of a line segment.
    (d) Write a function (intersectp l1 l2) that decides if two line segments intersect. [Hint: the location of an arbitrary point on AB can be written as vA + (1-v)B; a point on CD is wC +(1-w)D; the lines cross where these are equal. This gives two equations (equating both x and y parts) for v and w. Solve these to find the intersection point, if any. Then you need to check that the intersection is actually on both segments - this can be determined by looking at the values of v and w.]
    (e) (Optional) A scene is a list of polygons, and a polygon is a list of points. Write a method (visiblep scene p1 p2) that checks if one point is visible from another in a scene (that is, there is a straight line from one to the other not intersecting any polygon). Note that one vertex on a polygon should be visible from its immediate neighbors on the same polygon.
    (f) (Optional) Create a scene full of polygons by instantiating your data types, using the coordinate data in here. Check to make sure that your visiblep predicate works.

  7. Load the AIMA (textbook) code in ~cs188/code-188 on the instructional machines (web-accessible here. Right now, just the code for Chapter 2 is installed. Make sure it works by running (test 'utilities) and (test 'agents). If you want, you can try to write a better vacuum world agent. More information on the AIMA code is available: see the overview and the instructions on how to use the code.