Professional Documents
Culture Documents
1 9/9/02 2
1
Application: Pathfinding Application
Consider a sample application
Find a minimal cost path from a start
node to a goal node GOAL
Can move one square horizontally or
vertically, each with a cost of one
Can be generalized to include diagonals
Can be generalized to include variable
costs
START
9/9/02 5 9/9/02 6
Solution 1 Solution 1
Trivial solution
7 6 7 7
Explore outward from the start node
GOAL
until reaching the goal node 6 5 7 6 7
2
Solution 1 Solution 2
Note that more than one path can lead Trivial observation that searching to
to a node depth 1 is a waste of time since we are
Some of these paths are non-optimal obviously more than 1 away from the
Note that cycles are possible goal
Observation: we need to eliminate Add to the search an evaluation
duplicate states! function that estimates the distance to
the goal
What is a simple estimator of distance?
9/9/02 9 9/9/02 10
9/9/02 11 9/9/02 12
3
Pathfinding IDA*
Iterative deepening A*
The cost of a node is (using A* terms)
GOAL f=g+h
5+2=7 7+0=7 6+1=7
g = cost incurred to get to this node
4+3=7 5+2=7 h = heuristic estimate of getting to goal
Iterative deepening iterates on a threshold
3+4=7 2+3=5 3+2=5 4+3=7 Search a node as long as f <= threshold
Either find a solution (done), or fail, in which case
1+4=5 2+3=5
the threshold is increased and a new search started
START
1+6=7 0+5=5 1+4=5 2+5=7
9/9/02 13 9/9/02 14
9/9/02 15 9/9/02 16
4
IDA* Comments IDA* Tree
Automatically builds a variable-depth search
Provably bad lines are cutoff as soon as possible Depth-first search
When the cutoff occurs depends on the quality of
the evaluation function Root’s value = T
v <= T
Storage requirements are trivial; just the Search nodes <= T
recursion stack Search nodes <= T+1
Iteration i+1 repeats all the work of iteration i! v <= T+1
Repeat until solution
For some domains you can do better than
iterate by 1 v <= T+2
Use the mimimum f-value seen at a leaf node
during an iteration as the next threshold
9/9/02 17 9/9/02 18
9/9/02 19 9/9/02 20
5
Monotonicity Examining h
Most admissible heuristics also have Simplified cost of a search
the monotonicity property Uniform branching factor b
The f values never decrease along a Search depth d
path if monotonicity holds Ignore all other enhancements
If you have a non-monotonic heuristic, No heuristic: bd
one can always modify the search to Average heuristic value is h: bd-h
make the heuristic monotonic…
The quality of the heuristic has an enormous
How?
impact on the search efficiency
9/9/02 21 9/9/02 22
9/9/02 23 9/9/02 24
6
Transposition Table Sliding Tile Puzzle
Store the t and g values in the table, and only
search a transpositon node with the smallest
g, and only once for the current t
Use table only to indicate which nodes not to Sam Lloyd’s
search creation was the
No need to store values, since the search Rubik’s Cube of
stops when a solution is found
the 1800s.
All other TT issues (table size, hashing, table
entry replacement) remain the same as for
two-player games
9/9/02 25 9/9/02 26
Experiments A*
Korf problem set of 100 positions Single-agent search began in the 1960s
with the A* algorithm [2]
Search 36700 This algorithm dominated AI search for
Search - move reversals 100 two decades, but has competition now
from IDA*
Search + TT (256K) 37
Why teach IDA* first? Easy to explain
once you’ve seen Alpha-Beta
9/9/02 27 9/9/02 28
7
A* Search Frontier
Each iteration of IDA* re-searches the
7 6 7 7
tree over again beginning at the root
GOAL
All that overhead can be eliminated… 6 5 7 6 7
9/9/02 31 9/9/02 32
8
A* Algorithm (2) A* (1)
Expanding a child A*( state s ) {
s.g = 0; s.h = Eval( s ); s.f = s.g + s.h; s.parent = null;
Check if seen before Open/ClosedList done = false;
If the node has been seen before with the same or better push s on OpenList
g value, then reject while( OpenList != empty && done == false ) {
Add to OpenList for consideration pop s from head of OpenList
if( s is a goal node ) { done = true; break; }
In effect the lists act as a cache of previously foreach( i = i; i <= Children( s ); i++ ) {
seen results Consider( s, s.child[i ] );
NOTE: the algorithm requires all nodes to be }
add s to ClosedList
in these lists, unlike a TT }
return( done );
9/9/02 33 9/9/02 } 34
A* (2) Example
Consider( state from, state to ) {
newg = from.g + Cost( from, to ); 6
if( ( to is in OpenList or ClosedList ) and
5 GOAL
( to.g <= newg ) ) return;
to.g = newg; to.h = Eval( to ); 4
to.f = to.g + to.h; to.parent = from;
if( to is in ClosedList ) remove to from ClosedList 3
if( to is not in OpenList ) insert to in OpenList sorted 2
by f-value
} 1 START
9/9/02 35 9/9/02 A B C D E F 36
9
Example Example
Step 1: Initialize Step 3: Expand C2
( C1, 0 + 5 = 5, null ) ( C3, 2 + 3 = 5, C2 ) ( D1, 1 + 4 = 5, C1 )
() ( D2, 2 + 3 = 5, C2 ) ( B1, 1 + 6 = 7, C1 )
Step 2: Expand C1 ( C1, 0 + 5 = 5, null ) (C2, 1 + 4 = 5, C1 )
( C2, 1 + 4 = 5, C1 ) (D1, 1 + 4 = 5, C1 ) Why isn’t C1 added to the OpenList?
( B1, 1 + 6 = 7, C1 )
C1 is found in the ClosedList with a lower
( C1, 0 + 5 = 5, null ) g value
9/9/02 37 9/9/02 38
9/9/02 39 9/9/02 40
10
A* IDA* versus A*
Does not have the iterative overhead of For many types of problems, IDA* flounders
IDA* in the cost of the re-searches, causing many
to prefer A* over IDA*
Only expands nodes that are shown to Why?
be relevant But… IDA* is handicapped with no storage!
Needs to maintain a history of all nodes A* uses a closed list -- in effect a perfect cache of
previously searched previously seen states
IDA* uses almost no storage
In practice, faster than IDA*, but A* runs
9/9/02 41 9/9/02 42
9/9/02 43 9/9/02 44
11