***************************** Lecture #6 -- Informed search ***************************** Lecture notes ============= Slides: :download:`Lecture 6 <../lectures/Lecture 6 - Informed search.pdf>` Related research articles: * :download:`Hart, Nilsson and Raphael <../articles/A_Formal_Basis_for_the_Heuristic_Determination_of_Minimum_Cost_Paths.pdf>` Code ==== Problem example --------------- We need to modify our definition of the route problem to use a heuristic function. We can also define a basic heurisitic function , the eucliean distance function. .. code-block:: python class RouteProblem(Problem): """A problem to find a route between locations on a `Map`. Create a problem with RouteProblem(start, goal, map=Map(...)}). States are the vertexes in the Map graph; actions are destination states.""" def actions(self, state): """The places neighboring `state`.""" return self.map.neighbors[state] def result(self, state, action): """Go to the `action` place, if the map says that is possible.""" return action if action in self.map.neighbors[state] else state def action_cost(self, s, action, s1): """The distance (cost) to go from s to s1.""" return self.map.distances[s, s1] def h(self, node): if self.map.heuristic: return self.map.heuristic[node.state, self.goal] locs = self.map.locations return euclidean_distance(locs[node.state], locs[self.goal]) def euclidean_distance(A, B): """Straight-line distance between two points.""" return sum(abs(a - b)**2 for (a, b) in zip(A, B)) ** 0.5 I also modified the class `Map` to accept a static heurisitic to match the example. .. code-block:: python class Map: """A map of places in a 2D world: a graph with vertexes and links between them. In `Map(links, locations)`, `links` can be either [(v1, v2)...] pairs, or a {(v1, v2): distance...} dict. Optional `locations` can be {v1: (x, y)} If `directed=False` then for every (v1, v2) link, we add a (v2, v1) link.""" def __init__(self, links, locations=None, directed=False, heuristic=None): if not hasattr(links, 'items'): # Distances are 1 by default links = {link: 1 for link in links} if not directed: for (v1, v2) in list(links): links[v2, v1] = links[v1, v2] self.distances = links self.neighbors = multimap(links) self.locations = locations or defaultdict(lambda: (0, 0)) self.heuristic = heuristic if not directed and self.heuristic: for (v1, v2) in list(self.heuristic): self.heuristic[v2, v1] = self.heuristic[v1, v2]