class: center, middle # Artificial Intelligence ### Informed Search --- class: center, middle # Syllabus Changes --- # Changes in Class Structure To account for the weeks we missed: * I cut one lab * I reduced the content about logic a bit * I am using the week that was scheduled to be Semana U --- # Changes in Class Format * We will be using Google Meet for the classes * The lecture-part of each class will be limited to 50 minutes (recommendation from VD) * We will have these mini-lectures each Monday **and** Thursday * The remaining time of the class period will be to work on the labs (and project progress updates) --- # Changes in Grading * One fewer lab: Each lab is now worth 9% (instead of 7%) * This means the lab total 4 * 9 = 36% instead of 5 * 7 = 35% * You could get up to 101% (grades are still calculated out of 100%) * A new syllabus with all these changes is available from the class website --- class: center, middle # Search --- # Reminder: 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. --- # Reminder: Romania
--- # How could we find a path?
--- class: small # Heuristic Search * 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 * We use the same algorithm as above: - Keep track of which nodes are candidates for expansion (starting with the start node) - Take one of these nodes and expand it - If you reach the target, you have found a path * Instead of using a stack or list, we use a *priority queue*, where the nodes are ordered according to some value derived from the heuristic * So how do we determine this value? --- # Greedy Search * Let's just use our heuristic! * We order the nodes in the priority queue by heuristic value * 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) --- class: center, middle # A* Search --- # 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 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 * You can also reduce the memory requirements of A* by using Iterative Deepening: - Limit search to a particular depth - If no path is found, increase the limit --- # Dijkstra's algorithm * Maybe you have heard of Dijkstra's algorithm (and its variants) before? * Dijkstra's algorithm is basically A* without using the heuristic * In some popular formulations you also let the algorithm compute a path for *every* possible destination * This will give you a shortest path tree, which may be useful if you have to repeatedly find a path to different destinations --- # Goal Conditions * We often also don't want to look for one specific (of our infinitely many) nodes, but rather a node that satisfies some condition * For example, what if we want a node that is greater than 1000 and a power of 2? * Each of the nodes "1024", "2048", "4096", etc. would be a valid solution * Let's use A* starting from "127" to find such a goal node * We need a heuristic! --- # Integer graph heuristic Let's use the following heuristic: $$ h(n) = \lvert \lfloor \log_2(n) \rfloor - \lfloor \log_2(1024)\rfloor \rvert $$ What does it do? Look for the next lowest power of two of the current node and the lowest valued goal node and calculate the difference. Now we could do A* on this graph! --- class: center, middle # Lab 1 --- class: mmedium # For the Lab * In Lab 1 you will implement Breadth-First Search, Depth-First Search, Greedy Search and A* (we will cover the last two next time) for arbitrary graphs * You will get a python "framework" that contains some example graphs you can test your algorithms on * You should also come up with at least one graph of your own (a map of your home town, campus, your favorite video game, ...) * You will have the class hours from 13/4-30/4, where I will be able to directly assist you * You should be able to finish in these hours, but the submission deadline is on Friday, 1/5, AoE --- # For the Lab * The framework contains a definition of a graph that makes use of a lazy evaluation scheme ```python class Node: def get_neighbors(self): # returns a list of edges to neighbors return [] # Each edge contains the target node, the cost of taking # that path and a name class Edge: def __init__(self, target, cost, name): self.target = target self.cost = cost self.name = name ``` --- # For the Lab * Take a look at `graph.py` to see how these classes are used to set up a finite graph (of Austria), as well as an infinite graph (the integer graph we discussed earlier). * You do not have to change anything in `graph.py`, but you can use it to create more test examples --- class: medium # For the Lab The actual task is to complete `search.py` by implementing `bfs`, `dfs`, `greedy` and `astar`: ```python def bfs(start, goal): # returns: # path (list of edges) or None if no path found # length of the path # nodes visited (added to the frontier) # nodes expanded (removed from the frontier) return [],0,0,0 ``` Note that the goal is a function! ```python def atgoal(n): return n.get_id() == target ``` --- class: small # References * [A* implementations in multiple languages](https://rosettacode.org/wiki/A*_search_algorithm) * [Sliding puzzle using A*](https://blog.goodaudience.com/solving-8-puzzle-using-a-algorithm-7b509c331288) * [JavaScript visualization of several search algorithms on a grid](https://qiao.github.io/PathFinding.js/visual/)