class GraphSearchAnimator(object): """ Draw a graph search. """ def __init__(self, graph, vertex_coords): """ """ self.graph = graph self.util = GraphUtil(vertex_coords) def _astar(self, source, dest, h): """ Implemented by objects that inherit from this. """ pass def _animation(self, source, dest, heuristic): seq, pred_list = self._astar(source, dest, heuristic) return self._process_search_result(seq, pred_list, dest) def _process_search_result(self, sequence, pred_list, dest): sequence_coords = self._sequence_coords(sequence) path = self._construct_shortest_path(pred_list, dest) return sequence, sequence_coords, path def _find_source_dest(self, source, dest): s_vertex = self.util._find_closest_vertex(source) d_vertex = self.util._find_closest_vertex(dest) return s_vertex, d_vertex def _construct_shortest_path(self, pred_list, dest): """ Given a predecessor list, such as created by A*, and the dest vertex ID, return the shortest path found by the algorithm. Will likely have to been overriden in the case of bidirectional algorithms. """ path = [] vertex = dest while pred_list[vertex]['pred'] is not None: path.append(vertex) vertex = pred_list[vertex]['pred'] path.reverse() path = [self.util.coords[v] for v in path] return path def _sequence_coords(self, seq): """ """ needed = {} coords = self.util.coords for vertex, actions in seq: needed[vertex] = coords[vertex] for arc in actions: needed[arc] = coords[arc] return needed def _heuristic_selector(self, heuristic): h_fun = self.util._euclidean if heuristic == "manhattan": h_fun = self.util._manhattan elif heuristic == "octile": h_fun = self.util._octile return h_fun def _alt_heuristic(self, id1, id2): max_dist = 0 lm_dists = self.landmark_dict for dist1, dist2 in zip(lm_dists[id1], lm_dists[id2]): try: d = abs(dist1 - dist2) if d > max_dist: max_dist = d except TypeError: # Some nodes couldnt reach a landmark pass return max_dist