class: center, middle # Creación de Videojuegos ### Pathfinding --- # Pathfinding * In many games you have moving, computer-controlled opponents * These opponents need to determine where they are going * Simplest approach: Walk back and forth between walls, fixed points, etc. * What if we want them to actually find a target? * Pathfinding! --- # Reminder: PacMan
--- # What can we do?
--- # What can we do?
--- # Graphs * A graph G = (V,E) consists of *vertices* (nodes) V and *edges* (connections) `\( E \subseteq V \times V \)` * Graphs can be connected, or have multiple components * Graphs can be directed (one-way streets) or undirected * Edges can have weights (costs) associated with them: `\( w: E \mapsto \mathbb{R} \)` * We can represent many things in graphs --- # The (undirected) Pathfinding problem Given a graph G = (V,E), with edge weights w, a start node `\( s \in V \)`, a destination node `\( d \in V \)`, find a sequence of vertices `\( v_1, v_2, \ldots, v_n \)`, such that `\(v_1 = s, v_n = d \)` and `\( \forall i: (v_i, v_{i+1}) \in E \)` We call the sequence `\( v_1, v_2, \ldots, v_n \)` a *path*, and the *cost* of the path is `\( \sum_i w((v_i,v_{i+1})) \)` -- This means what you would expect: To find a path from a start node to a destination node means to find vertices to walk through that lead from the start to the destination by being connected with edges. The cost is the sum of the costs of edges that need to be traversed. --- # Another example: Romania
--- # How could we find a path?
--- class: small # Every Search Algorithm All search algorithms (that we are looking at) operate the same way: * Store a list of nodes to visit, called the "frontier" * Take the next/"best" node from the frontier, and add all its neighbors to the frontier * If the goal is in the frontier, we are done Different algorithms simply use different data structures to store the frontier. Note: This outline works for trees, for arbitrary graphs we need to handle the case where a node would be added to the frontier a second time. --- class: small # Depth-First Search * Pick an order (say, north first, and then clockwise) * Store frontier as a stack, pushing the nodes in reverse order * Essentially, what this does: * Visit the first neighbor * Visit the first neighbor's first neighbor * Visit the first neighbor's first neighbor's first neighbor * etc, until we encounter a loop (continue with the second neighbor), or the goal (done) --- # Depth-First Search
--- # Depth-First Search
75 --- # Depth-First Search
75 + 71 = 146 --- # Depth-First Search
75 + 71 + 151 = 297 --- # Depth-First Search
75 + 71 + 151 + 99 = 396 --- # Depth-First Search
75 + 71 + 151 + 99 + 211 = 607 --- # Depth-First Search: What if?
--- # Depth-First Search: Revisiting nodes
--- # Depth-First Search: What if?
--- # Depth-First Search: Long way
--- class: small # Breadth-First Search * Save the "frontier" as a list, initialized with the starting node * If the goal is in the frontier, we are done * Else, for each node in the frontier, add all of its neighbors that to the frontier * Repeat * Basically: Add all neighbors, then add all neighbor's neighbors, then add all neighbor's neighbor's neighbors, etc. --- # Breadth-First Search
--- # Breadth-First Search
--- # Breadth-First Search
--- # Breadth-First Search
--- class: small # Limitations * Depth-First Search can lead to some very long paths * If we had an infinite graph, Depth-First Search will probably even fail completely * Breadth-First Search may need a lot of memory to remember the frontier and paths to get there * Both of them ignore costs --- class: small # Some improvements * We can limit the depth that Depth-First Search should explore - Now it will "work" on infinite graphs - We may also avoid some of the long paths * Idea: start with a depth limit of 1, run Depth-First Search, and if it can't find a path, increase the depth limit * This is called "Iterative Deepening" * To account for costs, we can use the cost as the order for Depth-First Search, and only make Breadth-First Search expand the node it can reach with the lowest cost in each iteration --- class: small # Heuristic Search * All of these techniques are called "uninformed" * What if we can give the path finding algorithm some more information? * For example, we may not know how to drive everywhere, but we can measure the straight line distance * This "extra" information is called a "heuristic" * Search algorithms can use it to "guide" the search process --- # Heuristic Search: General algorithm * Keep a "frontier" as a priority list, initialized with the start node * If the goal is in the frontier, we are done * Expand "the best" node from the frontier by adding all of its neighbors that have not been visited yet to the frontier What's "the best" node? What's the "priority" in the priority list? --- # Greedy Search * Let's use our heuristic! * We consider the node with the lowest heuristic to be "the best" * Heuristic: straight line distance to Bucharest --- class: tiny # Greedy Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Arad (366) --- class: tiny # Greedy Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Sibiu (253), Timisoara (329), Zerind (374) --- class: tiny # Greedy Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Fagaras (176), Rimnicu Vilcea (193), Timisoara (329), Zerind (374), Oradea (380) --- class: tiny # Greedy Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Bucharest (0), Rimnicu Vilcea (193), Timisoara (329), Zerind (374), Oradea (380) --- # A* Search * Greedy search sometimes does not give us the optimal result * It tries to get to the goal as fast as possible, but ignores the cost of actually getting to each node * Idea: Instead of using the node with the lowest heuristic value, use the node with the lowest sum of heuristic value and cost to get to * This is called A* search --- class: tiny # A* Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Arad (0 + 366) --- class: tiny # A* Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Sibiu (140 + 253), Timisoara (118 + 329), Zerind (75 + 374) --- class: tiny # A* Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Rimnicu Vilcea (220 + 193), Fagaras (239 + 176), Timisoara (118 + 329), Zerind (75 + 374), Orodea (291 + 380) --- class: tiny # A* Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Fagaras (239 + 176), Pitesti (317 + 100), Timisoara (118 + 329), Zerind (75 + 374), Craiova (366 + 160), Orodea (291 + 380) --- class: tiny # A* Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Pitesti (317 + 100), Timisoara (118 + 329), Zerind (75 + 374), Bucharest (450 + 0), Craiova (366 + 160), Orodea (291 + 380) --- class: tiny # A* Search
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
Frontier: Bucharest (418 + 0), Timisoara (118 + 329), Zerind (75 + 374), Craiova (366 + 160), Orodea (291 + 380) --- class: small # A* Search * To find *optimal* solution, keep expanding nodes until the goal node is the best node in the frontier * A* is actually guaranteed to find the optimal solution if the heuristic is: - Admissible: Never overestimate the cost - Consistent: For a node x and its neighbor y, the heuristic value for x has to be less than or equal to that of y plus the cost of getting from x to y - Every consistent heuristic is also admissible * You can also reduce the memory requirements of A* by using Iterative Deepening --- class: tiny # Another Example
Heuristic:
Arad
366
Bucharest
0
Craiova
160
Drobeta
242
Eforie
161
Fagaras
176
Giurgiu
77
Hirsova
151
Iasi
226
Lugoj
244
Mehadia
241
Neamt
234
Oradea
380
Pitesti
100
Rimnicu Vilcea
193
Sibiu
253
Timisoara
329
Urziceni
80
Vaslui
199
Zerind
374
--- class: small # Search * While we have looked at finding paths in physical spaces so far, there are many other applications * Take, for example, Super Mario * An AI could play the game using A*
--- # References * *Artificial Intelligence: A Modern Approach* by Russel and Norvig, chapter 3: Search * [An interactive demo of different search algorithms](https://qiao.github.io/PathFinding.js/visual/) * [The Super Mario 2009 AI competition](http://julian.togelius.com/Togelius2010The.pdf)