Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson TDDC65 Artificial intelligence and Lisp 07-09-14 Generalized assignment Lecture 5 and 6 Lisp (setf “location” “expression”) Data structures (sec 11.1-11.3 in Haraldsson Swedish lisp-book) arrays structures - records Iterative expressions (sec 12.2) do, dotimes, dolist, loop In- and output (chap 13) Parameter lists (sec 14.4) Error handling / dynamic returns Pointers (chap 16) Lisp interpreter (eval, apply) The macro facility (chap 15) Memory management Compare assignment statements in other languages: “location” = “expression” a=a+b table[4] = table[2]+table[3] Location is given by the corresponding “selectorfunction. selector-function for arrays is: (aref array index) (setf (aref array index) value) Laboratory assignment 3 selector-function for the global variable is: Search - depth - breadth first search, Dijkstra, A* Code for the assignment my-pi (setf my-pi 3.1415) For the global variable is setf the same as setq Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 07-09-14 Structures - records Arrays A table with pointers. Index starts from 0 One or more dimensions With defstruct a new data type is introduced (defstruct student name points courses) 0 1 2 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson (a b c) Lisp will automatically construct primitive functions. 10 3 15 4 index (make-array 10) ; allocation / construction (make-array ’(3 4 5)) ; a 3x4x5 matrix (make-array 3 :initial-element 0) (make-array 2 :initial-contents ’(1 2)) (setq v (vector 1 2 3)) => #(1 2 3) (aref v 0) => 1 (setf (aref v 2) 30) ; selection ; assignment v => #(1 2 30) ; external notation (setq my-new-vecot ’#(a b c d)) (setq kalle (make-student :name “Kalle” :points 10 :courses ’(math ai/lisp)) => #S(student name “Kalle” points 10 courses (math ai/lisp)) (student-points kalle) => 10 (setf (student-points kalle) 20) (student-p kalle) => t Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson More for structures: 07-09-14 Iterative structures Default values - repetition (defstruct student name (points 0)) iteration over each element in a list: dolist (compare with mapc) (make-student :name “Nisse”) (defun my-length (l) (let ((counter 0)) (dolist (element l counter) (setq counter (+ 1 counter)) ))) User defined names on primitives (defstruct (student (:constructor create-student) (: predicate student?)) name points) iteration a number of steps: dotimes (defun fak (n) (let ((result 1)) (dotimes (i n result) (setq result (* (+ 1 i) result) ))) Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson General iteration Sequencing of expressions loop - terminates with return (corresponds to begin - end in Ada) { } in C and Java) (defun my-length (list) (let ((counter 0)) (loop (if (endp list) (return counter)) (setq counter (+ counter 1)) (setq list (rest list)) ))) do - general repetition (do ((var init-expr update-expr) (var init-expr update-expr) ... ) (terminal-cond result-expr) expression ... expression) 07-09-14 In positions where we are allowed to write one expression we can use progn (prog1 and prog2) to give several expressions. (progn e1 e2 e3 ... en) = ”the value of en” (prog1 e1 e2 e3 ... en) = ”the value of e1” (if (= n 0) (progn (format t ”n = 0”) (f n)) (progn (format t ”n /= 0”) (g n))) (prog1 n (setq n (+ n 10)) Gives as value the old n Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Implicit progn 07-09-14 A stream is a sequence of characters which reads/writes from the terminal, a file, ... Use cond with implicit progn. Input of a Lisp-object: read - read next number, symbol, list, .. Input of a character and a full line: read-char read-line peek-char - look at next character (cond ((= n 0) (format t ”n = 0”) (f n)) (t (format t ”n /= 0”) (g n))) Example: (list (read) (read) (read) (read)) kalle (a b c) ”hej hopp” 15.35 => (kalle (a b c) ”hej hopp” 15.35) Also for defun, let, labels .. (defun outputs () (format t ”what’s your name? ”) (format t ”your name is ~s” (read)) ) (list (read-char) (read-char) (read-char) (read-char) (read-char)) a b c =>(#\a #\Space #\b #\Newline #\c) what’s your name? anders your name is anders Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 File handling Output of a Lisp-object: princ, format (format t output-string arg1 ... argn) output-string contains characters and + format instructions Opening a file: open Closing a file: close Deleting a file: delete-file Read Lisp-expressions from a file: load General file handling: (progn (princ ”kalle”) (princ #\Space) (princ ’()) kalle nil (with-open-file (streamvar filename options) body) (format t ”~%The prize is ~a:-” prize) The prize is 5:- (with-openfile (in ”data.dat” :direction :input) (list (read in) (read in) (read in))) Output of a Lisp-object which can be read again with read: (prin1 ”kalle”) ”kalle” Read in three data from the file data.dat: Test of end of file: (setq indata (read in nil ’end-of-file)) (if (eq indata ’end-of-file) ... eof.. ... process data...) Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Formal parameter lists Formal parameter lists optional parameters Keyword parameters (defun f (x &optional y)) (list x y)) (defun f (x &key min max) (list x min max)) (f 1 2) => (1 2) (f 1) => (1 nil) (f ’a :max 100 :min 10) => (a 10 100) (f ’b :min 0 :max 10) => (b 0 10) (defun f (x &optional (y 100)) (list x y)) The actual parameters can be given in arbitrary order. (f 1) => (1 100) Several functions use keyword parameters in order to give extra argument: arbitrary number of parameters (defun f (x &rest args) (list x (reverse args))) The formal parameter args binds to the list of the value of the actual parameters. (f 1) => (1 ()) (f 1 2 3 4 5) => (1 (5 4 3 2)) Are there a given key in an association list? (defun key? (key al) (member key al :test #’(lambda (key pair) (eq key (car pair))))) (key? ’one ’((one . ett) (tw0 . två) (three . tre))) => t Remove all x’s from position 2 to 6 (remove ’x ’(x a x b x c x) :start 1 :end 5) => (x a b c x) Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Error messages Pointers: (error ”not correct argument, n=~a” n) generalized assignment: (setf (first p) 'q) Dynamic return, used to catch errors p (catch catch-label expression) (throw catch-label value-expression) (defun p (x) (let ((value (catch ’error (q)))) (if (eq value ’bad-value) ... process error... ... process value....))) (defun q () ... (throw ’error ’bad-value) ... )) x q y z (setf (rest p) (rest (rest p))) p x y z Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Pointers: Concatenation of two lists: With pointer new more specialized structures may be built. append - copies its first argument nconc - changing of pointer A queue with a head containing pointer to the first and the last element. (defun append (x y) (if (endp x) y (cons (first x) (append (rest x) y)))) car-queue (defun nconc (x y) (if (endp x) y (progn (setf (rest (last x)) y) x))) opel removes from this end saab adds to this end A circular structure can be constructed by What happens? (setq start ’(1 2 3 4)) (setq p ’(a b)) (nconc p ’(c d)) p? (setq p ’()) (nconc p ’(c d)) p? Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 (progn (setf (rest (last start)) start) ’ok) Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 The interpreter functions eval and apply. The macro facility Programs in Lisp are stored as list structures. Common Lisp and you can use this possibility to create program code through the macro facility. By constructing lists at execution time we can generate new programs and give them to the interpreter, the eval-function, to execute them. During execution and at compile time macro expression are translate to new Lisp code. (eval lisp-expression) (eval (list ’+ 1 2)) -> (eval ’(+ 1 2)) -> gives to eval as a Lisp expression -> (+ 1 2) => 3 (eval (list ’append (list ’quote ’(a b)) (list ’list 1 2))) -> (eval ’(append (quote (a b)) (list 1 2))) -> (append (quote (a b)) (list 1 2))) -> (append ’(a b) ’( 1 2)) => (a b 1 2) (apply function argumentlist) (funcall function arg1 arg2 ... argn) (apply #’(lambda (x y) (list x x y y)) ’(a b)) => (a a b b) (funcall #’(lambda (x y) (list x x y y)) ’a ’b) => (a a b b) Common Lisp interpreter does not know of about cond, only if. It can, however, translate all cond-expressions to corresponding if-expression. (cond ((endp l) ’()) ((endp (rest l)) (first l)) (t (rest l))) translates during execution to (if (endp l) ’() (if (endp (rest l)) (first l) (rest l))) Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 The macro facility The macro facility A macro function defines in the same way as an ordinary function with two exceptions: A convenient way to write macro-function is by using the backquote-syntax. It does not evaluate its argument, The formal parameter binds directly to the actual parameter. ‘(a (b ,(+ 2 3) c) ,(list (+ 3 4) 5) d) => (a (b 5 c) (7 5) d) It must return a Lisp-expression, which will be given to the Lisp interpreter (the eval function) ‘ is the backquote-character Example: A two way cond-expression is expanded to an if-expression An alternative (defmacro cond-2 (cl1 cl2) (list ’if (first cl1) (second cl1) (second cl2)))’ (defun f (l) (cond-2 ((endp l) nil) (t (first l))) ) ‘(a (b ,(+ 2 3) c) ,@(list (+ 3 4) 5) d) => (a (b 5 c) 7 5 d) The elements of the list will be “sliced” into the result, not the whole list. The cond2-expression will be expanded to (if (endp l) nil (first l)) (f ’(a b c)) => a Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson The macro facility 07-09-14 Memory management With the macro facility we can introduce several constructs we would like to use, i e new control structures. In a language as Lisp we have a dynamic memory management. Example. Introduce a while-structure. A list (a (b c) d) is represented as memory areas and memory pointers. This can be viewed as: (let ((i 10)) (while (> i 0) (print i) (setq i (- i 1)))) writes 10, 9, .. to 1 d a translates to (let ((I 10)) (loop (if (> i 0) (return nil)) (print i) (setq i (- i 1))))) (defmacro while (pred &rest exprs) ‘(loop (unless ,pred (return nil)) ,@exprs)) b c The function cons allocates a cons-cell. The cons-cells are referenced by pointers. Cons-cells that are not accessible are collected a new free memory by a garbage collection. This schema holds also for the other data types. Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Laboratory assignment 3 - Search Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 The problem IN A B K The algorithms will be recursivly defined and will structured as general search patterns with hogher order functions describing search strategies. There is a lab description in the course webpage and a Common Lisp file with code to work from. The file is not complete. You have to complete this file with your own code. IN D In the lab you will explore search in gaphs. C D A C B G E F I H J UT K G E F I UT H J Search in a graph - maze depth first-search breath first-search Dijkstras algorithm A*-algorithm Representation of the maze (setq a-maze '((in . (a)) (a . (in b c)) (b . (a)) (c . (a d e)) (d . (c)) (e . (c f k j)) (f . (g e h)) (h . (f i j)) (g . (f)) (i . (h)) (j . (e h out)) (out . (j)))) (path-maze ’in ’ut a-maze) => (in a c e f h j ut) Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 DEPTH-FIRST SEARCH Code see lab 3 This algorithm is a very naive algorithm and may not work for large graphs. The general strategy is that you expand the start-node, get its neighbors, the first neighbors and expand that to get its neighbor etc. If we come to a dead end or to en earlier processed node we “back-track” to fins the next neighbor. Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 07-09-14 Breath first-search 1. Expand a node and put its neigbor nodes in a queue. 2. Sort the queue after some criteria. 3. Take the first node and process it. We introduce two queues que-of-not-visited-nodes - a queue with node not yet processed visited-nodes - a queue with visited nodes BREADTH-FIRST SEARCH The idea here is to explore the nodes around the start node and expand its neighbors. And in the nest step explore those nodes and its neighbors etc. Here we will have a number of nodes, not yet processed, which will be stored on a queue. The main algorithms is to take the first node from the queue and expand it and store the new neighbors on that queue. The order how the nodes are stored on the queue is of absolute importance. If we have domain specific information which can help us with this ordering we may get much more efficient search strategies. We will explore three of them - a naive one, Dijkstra’s algorithm if we know the distance between nodes and the A’-algorithm if we also know some position (coordinates) where the node is situated. Dijkstras algorithm If the arcs in the graph have a distance associated with them we can order the nodes to take the one closed from the start node. A*-algoritmen If the nodes are in a coordinate system, when can estimate the distance from a node to the goal. estimated distance from the start to the goal passing a given node = distance from the start to the node + estimated distance from the node to the goal.