CS440: Assignment #4
Assigned Sept. 5th
Due 12:30, Sept. 24th

Chapter 3: Search (Programming Assignment)

Do Exercises 3.4 and 3.16 from the end of Chapter 3 of Artificial Intelligence: A Modern Approach, by Russell and Norvig. These require you to use lisp code provided by Russell and Norvig and to write some of your own lisp code.

Please turn in printouts of your lisp code and examples of your code running correctly. Also, type or write neatly an explanation of your lisp code. You must write at least one sentence for each lisp function you write and more than one sentence for long functions that cannot be cleary explained in one sentence.

Also, e-mail to me a single file that loads the necessary functions from ~cs440/Russell-code, defines all of your functions and variables, and runs an example or two demonstrating that you have solved all of the required exercises. I will run most of these myself to check that they actually run. Be sure you check your file first before you e-mail it to me.

For example, to prove to me that you know how to square a number, you would put this into one file, say it is named hw1.lisp:

    (defun square (x)
        (* x x))
    
    (print '(square 3))
    (print (square 3))
    
    (print '(square 6))
    (print (square 6))
then test it by doing
    USER(4): (load "hw4.lisp")
    ; Loading hw4.lisp.
    
    (SQUARE 3) 
    9 
    (SQUARE 6) 
    36 
    T

Please put your name and student number at the top of the first page and staple multiple pages together.

Lisp Code Discussed in Class for 3.16

Much of this code was discussed in class. I've rewritten bits to be more readable. You still must write #'sequence-successors and #'generates-sequence?. Look up any functions you see here that you haven't used before in the on-line documentation or in a Lisp text.
(defun predict-sequence (sequence)
  "Return the number that comes next in this sequence.  Also return an 
   expression that, as a function of n, generates the sequence."
  (let* ((node (iterative-deepening-search
		(sequence-prediction-problem sequence)))
	 (exp (node-state node)))
    (values (funcall (make-fn exp) (length sequence)) exp)))

(defun sequence-prediction-problem (sequence)
  (make-problem
   :initial-state 1
   :goal-test #'(lambda (exp) (generates-sequence? exp sequence))
   :successor-fn #'sequence-successors
   :domain "Sequence prediction"))

(defun sequence-successors (exp)
  "Successors are all expressions formed by replacing a leaf with a more
   complex expression.  We have to specify some action, so we use IGNORE."
  (mapcar #'(lambda (x) (cons 'ignore x))
	  (collect-tree-replacements exp)))

(defun make-fn (exp)
  "Turn exp into a function of n."
  (coerce `(lambda (n) (ignore-errors ,exp)) 'function))

(defun try (form)
  "Function to try an example and print the results."
  (print form)
  (multiple-value-bind (answer exp) (eval form)
		       (print answer) (print exp)))

(try '(predict-sequence '(1 2 3 4 5)))
(try '(predict-sequence '(1 2 4 8 16)))
(try '(predict-sequence '(1 3 5 7)))
(try '(predict-sequence '(1 4 9)))
(try '(predict-sequence (loop for n from 0 to 4 collect (* n n))))

When I run a complete form of this, I see
(PREDICT-SEQUENCE '(1 2 3 4 5)) 
6 
(+ 1 N) 
(PREDICT-SEQUENCE '(1 2 4 8 16)) 
32 
(EXPT (+ 1 1) N) 
(PREDICT-SEQUENCE '(1 3 5 7)) 
9 
(+ (+ 1 N) N) 
(PREDICT-SEQUENCE '(1 4 9)) 
16 
(* (+ 1 N) (+ 1 N)) 
(PREDICT-SEQUENCE (LOOP FOR N FROM 0 TO 4 COLLECT (* N N))) 
; Autoloading for EXCL::COMPLEX-LOOP-EXPANDER:
;   Fast loading from bundle code/loop.fasl.

25 
(* (* 1 N) N) 
T

That last Autoloading comment comes from Lisp loading the definition for the powerful loop macro.