CS 662: AI Programming Homework #3: Search

Assigned: September 13
Due: September 20.
30 points

To turn in: Typed answers to the questions throughout the homework, along with a hard copy of your source code. Also, please place a copy of your code in your submit directory.

In this assignment, you'll be helping the members of the rock band U2 get to a concert on time.

Consider the following problem:
U2 has a concert that starts in 17 minutes and they must all cross a bridge to get there. All four men begin on the same side of the bridge. You must help them across to the other side. It is night. There is one flashlight. A maximum of two people can cross at one time. Any party who crosses, either 1 or 2 people, must have the flashlight with them. The flashlight must be walked back and forth, it cannot be thrown, etc. Each band member walks at a different speed. A pair must walk together at the rate of the slower man's pace:

Bono: 1 minute to cross
Edge: 2 minutes to cross
Larry: 10 minutes to cross

For example: if Bono and Larry walk across first, 10 minutes have elapsed when they get to the other side of the bridge. If Larry then returns with the flashlight, a total of 20 minutes have passed and you have failed the mission.

(note: this is a fairly well-known puzzle, and solutions to it undoubtedly can be found on the Web. I would suggest that you try to solve it yourself first. This will give you a much better understanding of the problem.)

Note: This homework is larger than the previous two homeworks. As a point of comparison, I wrote the code in an evening, using about 175 lines of fairly-compact Python (with several list comprehensions). Since I'm familiar with both Python and the subject matter, you should budget your time accordingly. I also strongly recommend unit testing each component of this program as you build it. It's much easier to debug the successor function independently of the search algorithm.

1. (2 points) (Warm-up) Solve the problem by hand. What sequence of moves will get the band members to the other side of the bridge in 17 minutes or less?
2. (8 points) For the rest of the homework, you'll solve this problem using a variety of search algorithms. To begin with, create a Python class called U2State that indicates where each band member is at a given point in time, where the flashlight is, and how much time has elapsed. You may also find it useful to keep a pointer to the 'parent' state, so that you can print out the sequence of moves once they are found. You may choose how you wish to represent the state variables.
• Add a constructor (__init__) to U2State. It should have default arguments that allow you to create an initial state if it is called without arguments, and set the corresponding instance variables otherwise.
• Now, add a method to U2State called isGoal(). It should return True if the state has all four members on the far side of the bridge in under 17 minutes, and false otherwise.
• Next, implement a method within U2State called successors(). It should return a list of all possible moves and the resulting states, including increments to the time.

For example, Let's say that you've decided to represent each side of the bridge as a list (this is not the only choice!), along with discrete variables for the flashlight and the time. So, one state might be: (['Edge', 'Bono'],['Larry','Adam'],'Left',10). The possible moves here are: Edge crosses alone, Bono crosses alone, or they go together. So the successor method for this state would return:

3. Now you're ready to implement search algorithms to solve this problem.
• (5 points) Begin by writing a function called search - it should take as input an initial state and an ordering function that will control how successors are placed in the priority queue.
```def search(initialState, orderingFn=None) :
```
Search should repeatedly dequeue the front node in the search queue, expand its children, check to see if they are in your closed list (i.e. they've already been visited) and then place them in the queue according to your ordering function. Nodes that cannot lad to a solution may be discarded without expanding. For example, if you reach a node in which all four members are on the left after 20 minutes, there is no way this can lead to the goal, and so you may throw it away without expanding it.
• The ordering function should control where a state is placed in the queue of nodes to be expended. Accordingly, it should take as input a state, a list, and a depth limit (only necessary for DLS) and should insert the new state into the list in the appropriate place. (for example, BFS should add a new state to the end of the list.)
```### should place newState at the appropriate place in the queue.
def BFS(newState, stateQueue, limit)
```
Hint: be sure you use list operations that actually change the list being passed in, and don't create a copy. Experiment on a test program first!
• (5 points) Now, implement ordering functions for BFS and DFS. Run each of these on this program and record the solution that is found and the total number of nodes that are created and expanded by each algorithm.
• (3 points) Now, implement a DLS ordering function (this is a trivial change to DFS) and use this to implement iterative deepening DFS. Record the solution that is found and the total number of nodes that are created and expanded.
• (5 points) Finally, implement an A* ordering function using the following heuristic: h(n) = the time needed for the slowest person remaining to cross the bridge. You should use python's heapq module within the ordering function to maintain the queue. (you may find it helpful to add a 'priority' variable to your state.) Using Python's heapq module will require you to override the comparison operators for your U2State class.See Dive Into Python or the Python documentation for more info on this. Again, measure the number of nodes created and expanded.
• (2 points) Is the above heuristic admissible? If so, prove it. If not, provide a counterexample.

Extra Credit: You may do either of the problems below (but not both). Each are worth 5 points extra credit.
• Design an admissible heuristic that dominates the one provided above, and prove a) that it is admissible and b) that it dominates the given heuristic.
• Implement SMA*, with a parameter that governs how many nodes can be retained in memory at a given time. Try it with values of 5, 10, 25, and 100 nodes and count the number of nodes created and expanded.