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.
- 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.)
- 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.
- 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
dx/dx=1
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)/v2
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.
- 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.
- 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.
- 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.
- 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.