# Programming Assignment 4: Search

- Due Date: 5/10/2017

Dijkstra's algorithm allows us to find the shortest path from one vertex in a graph to all other vertices in the graph. It is a great algorithm for finding the shortest path in an explict graph (that is, a graph that is defined using an adjacency list or an adjacency matrix). However, if the graph is implicit (we don't have the actual graph, just rules for how it can be created), then Dijkstra's algorithm can be problematic. Especailly if the entire explict graph is too big to store in memory.

## Implicit Grpah vs Explicit Graph

An Explcit grpah is one where you have, in memory, a list of all vertices and all edges in the graph. All of the graphs we have seen so far in this class have been explict. An implict graph is one where we have rules for creating vertices and edges, but do not have the entire graph in memory. Let's take a look a t a simple implicit graph: the search graph for the sliding tile puzzle.

### Sliding Tile Puzzle

The sliding tile puzzle is a simple toy that consists of a number of tiles, and an empty space that can be used to move tiles around. (wkikpedia link), Interactive version. The sliding tile puzze defines a graph, where each state of the puzzle is a vertex, and there are edges between states if they can be reacted by a single move:

We can define the search problem by giving:

- An initial state. This is like the start vertex of the Dijsktra problem
- A goal state. Unlike Dijkstra, we are finding the path to a specific state, not to all states (though we will find the path form the initial state to a number of other states along the way)
- A set of operators that define how to create states from other states. This is equivalent to the edges in the graph for Dijkstra's algorithm.

## Dijkstra in an implicit graoh

Recall how Dijkstra's algoritm worked, in broad strokes:

- While there are still unknown verties
- Pick the cheapest unknown vertex v
- Mark v as known
- For each of v's chiildren w
- Update the costs / paths to w

In class we discussed how to use a priority queue to pick the cheapest unknown vertex, and we further discuesses two ways of implementeing that priority queue when distances were updated: Actually going into the queue to rearrange elements, and adding duplicate entries to the queue. We will use the second of these (adding duplicate entires to the priority queue) and, generalize Dijstra's algorithm for implicit graphs as follows:

## General Search Algorithm for Implicit Graphs

We will maintain 2 lists, an "open list" and a "closed list" The "closed list" will be a list of all states (vertices in our implicit graph) that are Known. The Open lists is a list of all states that we can get to from the iniitial state, but whose shortest path is not necessarily known yet.

- Create two lists of states, an open list and a closed list
- Initially, the open list contains just the initial state we are searching from, and the closed list is empty
- While the Open List is not empty
- Remove the "best" vertex v from the open list
- If v is not on the closed list:
- If v is the goal state
- we have found the sortest path to the goal! End the algorithm and return the path
- Otherwise (if v is not the goal state)
- Add v to the closed list
- For each child c of v
- If c is not on the closed list
- Add c to the open list
- If we empty the entire open list, then the goal cannot be found from the initial state

## Uniform Cost Search

If the "best vertex" is the vertex that is the closest vertex to
the initial state, then what we have is "Uniform Cost Search", which
is essentially Dijkstra's algorithm on an implicit graph. We are
guaranteed to find the shortest path to the goal, but we are
expanding (that is removing from the open list and adding to the
closed list) a potentially large number of vertices. If the
branching factor (that is, number of children per state) is b, and
the length of the path to the goal is d, then we are expanding
b^{d} states, which can be a large number of states. We can
do a little better by adding some more information

## Heuristics

Instead of just expanding the state that is closest to the intial
state, it would be better to also take advantange of how close a
state is to the goal Of course, we do not know how close any state is to the goal
state (that is what we are trying to find out by searching!) but we can
make a guess as to how far a state is from the goal
state. A *heuristic* is just a guess of how close a particular
state is to the goal state. Which heuristic to use depends on the
specific problem you are trying to solve. Let's look at the
heuristic for the Sliding Tile puzzle:

### Sliding Tile Heuristic -- Manhattan Distance

An easy to calculate heuristic for the sliding tile puzzle is Manhattan Distance - The distance each tile needs to move from its current position to its final position in the solution, assuming tiles can only move horizontally or vertically (like going between intersections in Manhattan, where you can only take east/west streets or north/south strees). For example for the following initial and goal positions:

The Current state has a manhattan distannce of 9 to the goal state in the above example

## A*

This leads us to a new variant of the generic searching algorithm. The only difference is what makes a state the "best" state to consider next. When is a state the "best" to expand? When that state is on the optimal path from the initial node to the goal. How can we determine that? Unfortuneatly, we can't know for sure, but we can make a pretty good guess. If we have a heuristic function that gives a guess of the cost to get from a state to the the goal, then for each state s, we know:

- The cost to get from the initial state to s
- A guess for the cost to get from s to the goal

So, the estimated cost to get from the inital state to the goal through s is just the cost to get from the initial state to s, plus the estimate of the cost to get from s to the goal

A* is a search algorithm that always expands the next state that has the best estimated cost to the goal.

So, if:

- g(s) = cost to get from the initial state to state s
- h(s) = estimated cost to get from s to goal (heuristic value

Then A* is just a general search algorithm where the "best" state s is the state with the minimum g(s) + h(s) value. That is, the state whose actual cost from the initial state, plus the estimated cost from s to the goal, is minimized

A* and Uniform Cost search both find optimal paths to the goal. However, A* will (in general) expand fewer states -- so will take less time (and less memory) than Uniform Cost Search. If, howeveer, you are willing to give up on optimallity, you can have an even more efficient algorithm

## Greedy Search

Greedy search picks as the "best" state the one that is closest to
the goal. The idea behind greedy search is not to find the cheapest
possible solution, but to find *a* solution as quickliy as
possible. Greedy seach always picks the node with the smallest
heuristic (h) value. For problems with a very large search space,
greedy can often find a solution when Uniform Cost Search or A*
would take way too long or require way too much memory. For
example, solving hard 15 puzzles (or 24-puzzles, or the like) can
take prohibitively long using A*, but can be solved relatively
quickly using Greedy (at the cost of geting a non-optimal solution)

## Search Overview

- Create an open list and a closed list
- While the open list is not empty
- Remove the element s from the open list with the smallest f(s) value
- If s is the goal, return the path from the initial state to s
- If s not on the closed list
- Add s to the closed list
- For each child c of s, if c is not on the closed list, add c to the open list
- If the open list becomes empty, return failure

Where f(s) is determined by the kind of search you are doing:

- Uniform Cost Search: f(s) = g(s) (cost of the path from initial state to s)
- A*: f(s) = g(s) + h(s) (estimated cost from intial state to goal through s)
- Greedy: f(s) = g(s) (estimated cost from s to the goal)

# Implemenation Details

To do a search over an implicit graph, you need to:

- Implement an Open List, that allows you to add a state / priority pair and remove the pair with the smallest priority
- Implement a Closed List, that allows you to add a state, and check if a state is in the closed list quickly
- Implement a search state, that allows you to compare two search states, find the estimated cost from one search state to another, and generate all of the children of a given search state (along with costs)

## Open List

We will use a min-heap based priority queue to implement the open
list. We will insert priority / value pairs, where the value is a state,
and the priority is a float. **You will need to write this priority
code yourself, and not rely on Java library code **

## Closed List

We will used a Hash Table to implement the closed list. The
states will have a method hashCode and equals that the hash table
will use to insert into the table and check for membership. You can
use either open or closed hashing. **You are not allowed to use a
build-in Java collection for this, but need to write the hash table
on your own. ** Your hash table should use the hashCode method of the
states that are inserted to create the appropriate hash value.

## States

States will need to implement the following interface: State.java

public interface State { /** * Return an array of all of the children of this state. The returned array * should be just large enough to hold all of the children of this state. * @return Array of children of this state */ public State[] getChildren(); /** * Return the parent of this state (that is, the state that generated this * state), or null if this is an initial state * @return */ public State getParent(); /** * Returns true if this state is equal to another state, ignoring parents * @param other The state to compare to * @return True if the states are equal */ public boolean equals(State other); /** * String representation of the state * @return */ public String toString(); /** * Return the distance of this state from the initial state. * @return */ public float gValue(); /** * Hash code for this state. States that are equal (via the above equals) need * to have the same HashCode * @return */ public int hashCode(); /** * Returns a string representation of the solution path. See concrete states for more information * @return String representation of the standard solution path */ public String solutionPath(); /** * Returns a more verbose representation of the solution path. See concrete states for more information. * @return String representation of the verbose solution path */ public String solutionPathExtended(); /** * Returns the (estimated) distance from this state to an arbitrary different state. * The heuristic (h) value is the estimated distance of that state from the goal. * @return Estimated distance to the state */ public float distanceToState(State otherState); }

A few things to note about this state interface

- Each state needs to store internally a pointer to the state that created it, it order to create the path properly
- The equals method should return true if two states are
equal
*ignoring parent pointers and g values* - The hashCode method should return the same hashCode for two states for whom equals returns true (thus the hashCode should be independent of parent pointers and g values!)
- It is a little odd to put equals and hashCode into an interface (since all objects have a default equals and hashCode method, so putting them in an interface does not require any class that extends the interface to override them), they are here just to remind you that you will need to overide those methods for your States

### Sliding Tile State

The sliding tile state should have 2 constructors, the "external" constructor used to create the initial (and goal) states, and an "internal" constructor, used by getChildren to create the child states. The external constructor needs to be of the from

public SlidingTileState(int width, int height, int tiles[])

Where tiles is a one-dimensional array of tiles, listing the tiles in row major order. '0' will be used for the empty tile. So, to create the tile:

we would use the constuctor call

new SlidingTileState(3,3, new int[] {0,1,2,3,4,5,6,7,8})

And to create the tile

we would use the constuctor call

new SlidingTileState(4,2, new int[] {1,6,2,3,4,0,7,5})

The internal constructor will need to have (at least!) an extra parameter for the parent, and may have other different parameters as well (you may, for instance, want to pass in the tiles as a 2D array, or something else convienient based on your internal representation.)

#### gValue

For the sliding tile puzzle, the gValue of a particular state s is the number of moves from the initial state to state s. I recommend that you cache this value in the state, but you can reconstruct it on every call to gValue if you prefer.

#### toString

toString should return a string representation of the board, in a nice visual format, like:

+-+-+-+ | |1|2| +-+-+-+ |3|4|5| +-+-+-+ |6|7|8| +-+-+-+

or, for a 4x2 puzzle

+-+-+-+-+ |2|3|7|6| +-+-+-+-+ | |1|4|5| +-+-+-+-+

or, for a 4x4 puzzle

+--+--+--+--+ | 1| 5| 2| 3| +--+--+--+--+ | 4| 6|10| 7| +--+--+--+--+ |12| 9| |11| +--+--+--+--+ |13| 8|14|15| +--+--+--+--+

#### solutionPath

solutionPath should return a string that consists of a list of the tiles to move to get from the initial state to the final state, separated by commas. For example, for the following initial and final states:

Initial: +-+-+-+ |1|4|2| +-+-+-+ |3|5|8| +-+-+-+ |6|7| | +-+-+-+ Final: +-+-+-+ | |1|2| +-+-+-+ |3|4|5| +-+-+-+ |6|7|8| +-+-+-+

The solutionPath should return:

8,5,4,1

Since you can get to the final state by first moving the 8 tile, then the 5 tile, then the 4 tile, then the 1 tile

#### solutionPathExtended

solutionPathExtended should return a string representing a concatenation of each state along the path from the initial to the final state. So, for the above problem, solutionPathExtended should return

+-+-+-+ |1|4|2| +-+-+-+ |3|5|8| +-+-+-+ |6|7| | +-+-+-+ ------- +-+-+-+ |1|4|2| +-+-+-+ |3|5| | +-+-+-+ |6|7|8| +-+-+-+ ------- +-+-+-+ |1|4|2| +-+-+-+ |3| |5| +-+-+-+ |6|7|8| +-+-+-+ ------- +-+-+-+ |1| |2| +-+-+-+ |3|4|5| +-+-+-+ |6|7|8| +-+-+-+ ------- +-+-+-+ | |1|2| +-+-+-+ |3|4|5| +-+-+-+ |6|7|8| +-+-+-+

#### distanceToState(State otherState)

distanceToState should return the Manhattan Distance between the
two states. That is, for each tile in the puzzle, count the number
of spaces it would need to move to get into the required position.
Remember that the 0 is an empty space (and not a tile!) and should
*not* be considered as part of the Manhattan Distance.

#### getChildren

getChildren should return an array of all of the children of the state. Note that there will be a different number of children, depending upon the position of the blank space: between 2 (if the blank space is in a corner) to 3 (for an edge) to 4 (for the middle). You should return an array that is just large enough to hold all of the children

### Maze Position State

The required constructor for the MazePositionState is as follows:

public MazePositionState(String maze, int x, int y)

Where maze is a string representing the maze, with a space characeter ' ' for traversable spaces, and a non-space character for non-traversable spaces. The string will use the end-of-line character '\n' to separate rows of the maze. x and y represent the (x,y) position, starting at (0,0) for the upper-left corner of the maze

As with the slidingTileState, you will also likely want a separate constructor that you use when you generate children. I strongly recommend that there be one 2D array that all states use (that is, each state will have a pointer to the same overall maze, in addition to a local x,y position)

#### getChildren

getChildren returns a state for each posistion that is reachable in a single step. A position is reachable if it is adjacent to the current position (diagonals allowed) and is not blocked. For the 4 positions that are immediatley above, below, left, and right of the current postion, they are not blocked if the space is traversable. For the diagonals, the spaces surronding the new position must also be traversrable.

From the postion (x,y), you can move to position (x,y+1), (x,y-1),
(x+1,y), and (x-1,y), assuming the desitnation position is
traversable. In addition, you can move along the diagonal to position (x+1, y+1) if
positions (x+1,y+1) **and** positions (x,y+1) **and**
positions (x+1,y) are traversable, and likewise for the other 3 diagonals

#### gValue

The gValue of a state **s** is the sum of the legths of the subpaths
from the initial state to **s**. Non-diagonal subpaths have a length of
1, while diagonal subpaths have a length of
√ 2
(you could just ise 1.4142f if you like, but this is likely a good
place for a constant!). As with the sliding tile puzzle, I would
recommend caching this value, but you can recalculate it every time
if you prefer.

#### toString

toString for a state should just return the (x,y) position of the state, such as (3,4)

#### solutionPath

solutionPath should return a string of x,y positions to get from the initial state to the final state, separated by commas. Something like:

(1,1),(1,2),(1,3),(1,4),(2,5),(3,6),(4,6),(5,6),(6,6),(7,6),(8,7),(9,7),(10,8),(10,9),(10,10),(10,11),(10,12),(10,13),(10,14),(9,14),(9,15),(9,16),(9,17),(10,17),(11,17),(12,17),(13,17),(14,17),(15,17),(16,17),(17,17),(18,17)

#### solutionPathExtended

solutionPathExtended should return a string representing the entire map, with a . character at each position along the path. Something like:

******************** *. ** * * *. ** * * * *.*** ** * * * *. *** ** * * * . ************ * * ..... * * .. ****** * *** . * * *****. * ******** . ** * * . **** * *****. ****** * ****. * * .. * * ** * .* * * ** .********** * ..........* ********************

# The Assignment

For this project, you will need to create the following classes

- SlidingTileState (implements the interface State)
- MazePositionState (implements the interface State)
- Search

This class should contain the static method:public static State doSearch(State initial, State goal, SearchType searchType, boolean printNumberOfExpandedStates)

where:- intitial is the intial state to search from
- goal is the goal state to find
- searchType is the Search Type
- printNumberOfExpandedStates is a flag that, if true, causes your seach function to print out the number of expanded states (that is, the number of states that are added to the closed list, and whose children are added to the open list).

- Some class of your design for use in the Open list
- Some class of your design for use in the Closed list

## Extra Credit

For up to 50 project points, you can add a 3rd problem domain: sliding tile puzzles with differing piece sizes. This new type of sliding tile puzzle has rectangular tiles that can have different sizes. Wikipedia has a nice explanation of these puzzles, and there are some nice interactive examples on the web

Your implementation will need to follow the same interface as the standard sliding tile puzzle. You will write a class SlidingTileState2 that implements the State interface. The constructor for SlidingTileState2 should take 3 parameters:

- integer representing the width of the puzzle
- integer representing the height of the puzzle
- A string representing a list of all of the tiles in the puzzle, separated by commas. Each tile will be 4 integers, the width and height of the tile, followed by the x,y position of the tile on the board

So, the board:

Would be created with the contstructor

new SlidingTileState2(4,5,"2 2 0 0,2 1 2 0,2 1 2 1,1 1 0 2,1 1 1 2,1 2 0 3,1 2 1 3,2 1 2 3,2 1 2 4");

Your toString should produce a pretty version of the puzzle, for the above puzzle, something like:

+------------+ |+----++----+| ||****||****|| ||****|+----+| ||****|+----+| ||****||****|| |+----++----+| |+-++-+ | ||*||*| | |+-++-+ | |+-++-++----+| ||*||*||****|| ||*||*|+----+| ||*||*|+----+| ||*||*||****|| |+-++-++----+| +------------+

would be nice, but you can use your own creativity here

solutionPath should return a list of substrings of the form ((x1,y1),(x2,y2)) separated by commas, where (x1,y1) is the upper-left corner of the piece to move, and (x2,y2) is the upper-left corner of the location to move the piece to (where (0,0) is the upper-left position of the entire board). So, for the inital and final states:

Initial: +------+ |+-++-+| ||*||*|| |+-++-+| |+-+ | ||*| | |+-+ | +------+ Final: +------+ | +-+| | |*|| | +-+| |+-++-+| ||*||*|| |+-++-+| +------+

A valid solution path would be:

((0,1),(1,1)),((0,0),(0,1))

For the extended solution path, concatenate a series of boards, just like the original sliding tile puzzle. For the above example, and extended solution path would be

+------+ |+-++-+| ||*||*|| |+-++-+| |+-+ | ||*| | |+-+ | +------+ -------- +------+ |+-++-+| ||*||*|| |+-++-+| | +-+| | |*|| | +-+| +------+ -------- +------+ | +-+| | |*|| | +-+| |+-++-+| ||*||*|| |+-++-+| +------+

### Extra Credit Hints

- The extra credit is fairly difficult. Do the regular project first!
- Note that you probably want to store, for your representation of a state, both:
- A list of all of the pieces on the board (with both sizes and positions of each piece), and
- A 2D array of booleans that show which spaces are free (so you know which pieces can be moved.

- If your distance estimate overestimates, you might get non-optimal solutions for astar. (A working, but non-optimal, astar for SlidingTile2 will get nearly full partial extra credit)
- As always, come by my office to discuss solutions if you plan to do the partial credit

### Extra Credit Provided Files

- TestAstar2.java A version of the test file that contains examples of SlidingTile2
- ecoutput Output file for TestAstar2 with extended output
- ecoutputnoextend Output file for TestAstar2 without extended output

## Provided Files

- State.java The interface that your states need to implement
- Search.java Skeleton code to fill in for the Search function
- SearchType.java Enumerated Type used by the Search function
- TestAstar.java Provided test code
- mazeSmall Used by provided test code
- maze1 Used by provided test code
- output Correct output for test code
- outputnoextend Correct output for test code, breif output only