reference: “artificial intelligence for games”, ian millington. a* (a-star)
TRANSCRIPT
R E F E R E N C E : “A R T I F I C I A L I N T E L L I G E N C E F O R G A M E S ” , I A N M I L L I N G T O N .
A* (A-STAR)
GOALS
• Find a “pretty-short” path from point A to point B.• The best path is often
prohibitively expensive to find.
S
G
GRAPH-BASED ALGORITHM
• Graph• Vertices (Nodes)• Edges• Single edge• Double edge• Cost
• (For map traversal), distance is the norm• Cost multiplier (>1) for rough terrain.
• Representation• Adjacency Matrix• Adjacency List
GRAPH NODES VS. SEARCH NODES
0
3
4
1
2
56
Graph
6.0
3.0
1.0
9.04.0
4.03.0
Start == 0, Goal == 6
Search Tree
0
3
4
1
5 6
There are usually many search trees for the same graph.
2.0
GRAPH NODES VS. SEARCH NODES, CONT.
• One approach:• GraphNode(id, …)• Id• …• Neighbor_pointers = […] # Or this could be stored in map
• SearchNode(graphNodePointer, parent)• Parent is None for the starting node
• Create a search node as you traverse the graph.
DEPTH-FIRST SEARCH
S
0
8
6
3
547
1
2
G
• Need a (bool) visited value for each graph node (to prevent re-visiting).• Visit a (“random”) new node from the current node.• Total Cost is the edge cost of all edges traversed.• We have to try all possible search graphs to find the least costly path – EXPENSIVE!
10.0
3.5
4.5
2.0
2.03.0
4.5
6.0
5.0
4.0
5.0
5.0
7.5
1.5
6.0
3.5
3.0
Total=17
Total=19
BREADTH-FIRST SEARCHS
0
8
6
3
547
1
2
G
10.0
3.5
4.5
2.0
2.03.0
4.5
6.0
5.0
4.0
5.0
5.0
7.5
1.5
6.0
3.5
3.0
• Need a list of “frontier” nodes and a (bool) visited flag.• Expand the frontier by one hop each iteration.• We end up with several search trees.• Problem:
• A lot of search trees – MEMORY + TIME INTENSIVE (especially for large graphs).• The search trees are dependent on the graph structure (2=>6 vs 0=>6)
HEURISTICS
• "A trial-and-error guess".• Used a lot in AI• Often leads to an OK solution (but much more quickly) when
compared to an exhaustive search
• In A*: an estimate of how far a given node is from the goal state.• Accuracy is critical to good performance of A*• For path-finding, often use the straight-line distance.• Or c * dist (where c >= 1.0)
• We'll store 3 things for each search node:• The parent search node (if any)• The cost-so-far value (g)• The cost-heuristic (h)
• A* is basically a "best-first" search (based on g and h)
OPEN, CLOSED “LISTS”
• We'll maintain two "lists" of search nodes:• OPEN: Those on the search "frontier"• CLOSED: Those we've already visited• anything not on these lists is unexplored• The graph node doesn't have a search node.
• Often more efficient to maintain:• A Priority Queue for OPEN• A state variable for each search node (OPEN or CLOSED)
A* ALGORITHM1. Create search node for Start Node
a) Parent = None, Cost-so-far = 0, H = (distance to goal)
2. Add this new node to OPEN3. Repeat these steps as long as OPEN isn’t empty.
a) Take the best node, C, off OPENi. If C is the goal, construct a Graph-node sequence and return.ii. If not, add C to CLOSED.
b) Repeat for each of C's neighbors, N:i. If N is unexplored, create a Search Node for it and add it to
OPEN.ii. If N is on OPEN and path from Cc.s.f. + cost(C,N) < Nc.s.f.:
• Update the parent and cost-so-far of N• Reheapify that node on OPEN
iii. If N is on CLOSED and path from Cc.s.f.+ cost(C,N) < Nc.s.f.:• remove it from CLOSED and put it on OPEN• Update the parent and cost-so-far of N• #NOTE: This case shouldn't happen if your heuristic is well-
formed
4. Return False (no path found)
MINHEAP + A*
• A* uses this as its "metric"CostSoFar (actual cost from start to this node) +Heuristic (estimated cost from this node to the goal)
• Note: The heuristic is almost always an under-estimate.• So…we give priority to those nodes that appear
to take us closer to the goal.
UNDER-/OVER-ESTIMATING HEURISTIC
• Very important to get as close as possible!• 0 => breadth-first search.• The closer they get to the real cost, the more the "countours"
will bend towards the goal.
• >= actual cost => explore all nodes.• Too high => find a "bad" path before a "good"• Too low => look at too many nodes.
NAV-MESHES
• A common way to represent:• Walkable areas of a map.• Cover-spots• Jumping-points (to cross a chasm)• Ladders• Save points, ammo drops, etc.
• Key Ideas:• Not usually visible• Usually much lower poly-count than the actual ground
NAV-MESHES, CONT.Display Mesh (16541 faces)
Nav Mesh (301 faces)
NAV-MESHES, CONT.
• We can use these for pathfinding…• Nodes are faces (their center?)• Edges are connections between neighboring faces• Cost is just the euclidean distance between centers.
• Probably best done off-line• Finding neighbors can be costly.
ANOTHER APPLICATION OF A*
A* VARIANTS / IMPROVEMENTS
• IDA*• Iterative Deepening Algorithm• Slightly slower, but less memory than A*
• Pruning• A* often produces "jerky" paths• Some post-processing makes the paths nicer• Curves• Simplification / pruning.
• Saving the results• Often (esp. in games), the new search is similar to the last
(except perhaps the first and last nodes) – temporal coherency.• You can eliminate long searches by re-using parts of the last
search.
HEAP-BASED PRIORITY QUEUES
• …