AI Assignment 2 CSE2309/3309,CSC2091/3091 – Artificial Intelligence Assignment 2 1999 Due date: midnight, Friday 10th September. This assignment is worth 10% of your final mark for CSE2309/3309/CSC2091/3091. Approximately 80% of the marks of this assignment will be allocated to code correctness. The rest of the marks will be allocated to coding style and to program documentation. You may complete this assignment in pairs. I expect each student to spend approximately 10 hours completing this assignment. Supplied or example code will be in "/cs/cc/usr/examples/cse23309/Ass2". Problem Description An instance of the sliding tile puzzle has the following initial state. B W B W B W B W A tile may move into an adjacent empty location, with a cost of 1. A tile can hop over one or two tiles into the empty position. This has cost equal to the number of tiles jumped plus two. However, a tile cannot hop over tiles and go around the corner at the same time. Note that while the number of horizontal slots may vary, there are always exactly 2 slots below the horizontal at each end. The goal of the puzzle is to get all white tiles to the left of all the black tiles. One (of many) goal states for this example is: B B W W B W B W Programming Task Write a LISP program which implements a graphsearch algorithm to solve the general sliding tile puzzle. Using this program: 1. Apply DFS and BFS to plan a path to the puzzle solution. Which algorithm is more efficient? Which one finds the path with the least coast? 2. Devise a heuristic function, h1(n), based on the number of tiles out of place, which is an underestimate of the cost of the path from node n to the goal, and use this in algorithm A*. This means you must write a LISP function called h1. 3. Devise a second heuristic function, h2(n), based on the Manhattan distance, which is another underestimate of the cost of the path, and also use this in algorithm A*. This means you must write a LISP function called h2. 4. Are these heuristic functions admissable? AI Assignment 2 Programming Requirements 1. Your program must work on a representation of the sliding tile puzzle, which allows any number of tiles, as along as (a) there are only two slots at each end below the horizontal row of tiles (b) there are equal number of black and white tiles, i.e. m of each, and 2m+1 tile positions. It should be able to work on any initial configuration of the tiles (you may which to make *m* a global variable). The sliding tile puzzle should be represented as a list, where each element is either 'B (for black tile), 'W (for white tile) or '- (for the blank). The example puzzle (puzzle1) shown above would be represented by the list ('b 'w 'b '- 'w 'b 'w 'b). 2. Note that there is not a single goal state: the blank can be in any position. You should write a predicate goal-p to perform the goal test, which will take a puzzle position as its input. This predicate will be tested separately from the overall testing of your puzzle function. 3. You should write a predicate legal-moves which takes a puzzle configuration (i.e. a list as described in 1 above) as its argument, and which returns a list of all the possible successor configurations, together with the cost of the move. So for the example puzzle1, this function would return ((('b 'w 'b 'w '- 'b 'w 'b) 1)(('b 'w '- 'b 'w 'b 'w 'b) 1) (('b 'w 'b 'b 'w '- 'w 'b) 3)(('b 'w 'b 'w 'w 'b '- 'b) 4)) 4. The graphsearch procedure builds a search graph that represents the state of the search for a path to the puzzle solution. It is suggested that each node in the search graph have the following components: 1. the puzzle configuration 2. the cost g of reaching that node 3. a heuristic value h , (optional for BFS and DFS) 4 a value f, where f=g+h. (optional for BFS and DFS). One possibility is to use a LISP defstruct to make the appropriate data structure (see file node.lisp in the examples directory). Another is to store them as a list containing 4 elements. 5. When calculating the heuristic value with the particular heuristic function, the actual name of the function should be passed as a parameter, h. In this case, you can evaluate the heuristic on a given board instance board, using code such as (funcall h board) 6. You should implement the graphsearch algorithm GraphSearch provided at the end of this assignment (and described in the lecture) where an OPEN and a CLOSED list are maintained. In this case you will need to keep pointers to the parent and to the children of the node. See file ptr.lisp in the examples directory for how to set up these sorts of pointers. (This graphsearch algorithms are basically that given in Nilsson's texts Principles of Artificial Intelligence, 1980, and Artificial Intelligence, A New Synthesis, 1998.) 7. Input: Your main procedure is to be called puzzle and it will receive the following input: • A list with an odd number of elements, say 2m+1, m of which will be 'B, m of which will be 'W, and a single '-. • The type of algorithm to be activated. The possible values of this parameter are 'DFS, 'BFS, 'A. • A parameter which is nil if the algorithm is DFS or BFS, otherwise it is the name of the heuristic function i.e. h1 or h2. AI Assignment 2 • A flag which takes the value t if OPEN is to be printed, and nil otherwise. Note: the input for the puzzle given above will be provided in a file puzzle1.lisp in the examples directory. 8. The main puzzle function should call the graphsearch algorithm which will take the algorithm type as an argument. That algorithm type argument will be used in the graphsearch algorithm when deciding where to add new nodes to the open list, ready to be expanded (see Lecture Notes). DO NOT write separate function for BFS, DFS, A*. 9. Each time a node is expanded, your program should output the value of g, h, and f, for that node, and, if the flag is set, the lists OPEN and CLOSED. In addition, upon completion, your program should produce a sequence of nodes which constitute the path to the puzzle solution. Other Example Code Example search routine code is given in a sub-directory examples. You may find it useful to look at these but they do not directly implement the graphsearch algorithm. Some code for sorting, which you may be able to use in a modified form, is given in sort.lisp. Individual Function Testing I will perform individual testing of the following functions (which will allow me to determine what you've managed to do even if your program as a whole doesn't produce correct answers!) with a set of different board configurations. (goal-p board) (legal-moves board) (h2 board) (h2 board) (puzzle board 'BFS nil t) (puzzle board 'DFS nil t) (puzzle board 'A 'h1 t) (puzzle board 'A 'h2 t) Submission Requirements 2. Run your program(s) ie. BFS, DFS, A* with heuristic H1,, and with heuristic H2 with the above puzzle (puzzle1). In addition run your program on at least one additional puzzle with a different size and starting configuration, i.e. your own puzzle2. 3. Submit using the submit program, with course code cse2309-3309, assessment code ass2, from a ccds account. Only one submit is required from each pair. After you have given your student id, it will ask you for the name of the directory where the assignment files are kept. Put your work in a directory called ass2. This directory should contain your source code (in a file called ass2.lisp), and your output files (obtained using the dribble function), in files called output.puzzle1 and output.puzzle2. Please remove other files, especially core dumps, from the directory before you submit, otherwise the submit file system will fill up. 4. Your program should be accompanied by adequate in-line documentation plus a separate section including explanations regarding the selected data structure, the rationale supporting your heuristic functions and explanations about implementation issues which are not straightforward. You should also include a separate file README.with additional documentation and the names and student Ids of both the students who have worked on the assignment. 5. The assignment is due midnight on Friday, 10th September. Late submissions can be submitted as ass2-late from Saturday 11th September, however marks will be taken off for lateness. AI Assignment 2 Algorithm GraphSearch Procedure GraphSearch (start) 1. Put the start node in a list called OPEN. 2. Create a list called CLOSED that is initially empty. 3. LOOP: If OPEN is empty then exit with failure. 4. Select the first node on OPEN and remove it from OPEN. and put it on CLOSED. Call this node n.. 5. If n is a goal node, exit successfully with the solution obtained by tracing a path along the pointers from n to s. (pointers are established in step 7.) 6. Expand node n, generating a set M of its successors that are not ancestors of n. Install these members of M as successors of n. 7 Establish a pointer from n from those members of M that were not already in the search graph (ie not already on either OPEN or CLOSED). Add these members of M to OPEN. (a) For each member of M already on OPEN or CLOSED, decide whether or not to redirect its pointer to n. (b) For each member of M already on CLOSED, decide for each of its descendants whether or not to redirect its pointer. Pointers should be redirected if the cost of the new path is less than the path of the already existing path. 8. Re-order the list OPEN, either according to some arbitrary scheme or according to heuristic merit. 9. Go LOOP. NOTE: For BFS and DFS., you don't need to worry about the cost of the path. You do have to check first whether a newly generated successor is already on the OPEN list. For DFS: insert successors at the beginning of the OPEN list, and delete the previously occurring instance of the node. For BFS: insert nodes at the end of the list, except for those nodes which are already on the OPEN list.