def _octile(self, id1, id2):
     """ 
     Returns the octile distance in KM between the two ID'd vertices.
     
     (x1, y1)
     [1]
      |
      |
      |
     [3]
      | .
      |   .      
      |     .
      |       .
      |         .
      |       45( .   
     [ ]----------[2]
  
     returns dist(1, 3) + dist(2, 3)
     """
     x1, y1 = self.coords[id1]
     x2, y2 = self.coords[id2]
     dx, dy = abs(x2 - x1), abs(y2 - y1)
     if dx > dy:
         x3 = max(x1, x2) - dy
         y3 = y1
     elif dx > dy:
         x3 = x1
         y3 = max(y1, y2) - dx
     else:
         return haversine(x1, y1, x2, y2)
     return haversine(x3, y3, x2, y2) + haversine(x3, y3, x1, y1)
 def _octile(self, id1, id2):
     """ 
     Returns the octile distance in KM between the two ID'd vertices.
     
     (x1, y1)
     [1]
      |
      |
      |
     [3]
      | .
      |   .      
      |     .
      |       .
      |         .
      |       45( .   
     [ ]----------[2]
  
     returns dist(1, 3) + dist(2, 3)
     """
     x1, y1 = self.coords[id1]
     x2, y2 = self.coords[id2]
     dx, dy = abs(x2 - x1), abs(y2 - y1)
     if dx > dy:
         x3 = max(x1, x2) - dy
         y3 = y1
     elif dx > dy:
         x3 = x1 
         y3 = max(y1, y2) - dx
     else:
         return haversine(x1, y1, x2, y2)
     return haversine(x3, y3, x2, y2) + haversine(x3, y3, x1, y1)
 def worker(landmarks, graph, graph_coords, pids, out_q, counter):
     """ The worker function, invoked in a process. 'nums' is a
         list of numbers to factor. The results are placed in
         a dictionary that's pushed to a queue.
     """
     lm_est = {}
     for lm_id, lm_coord in landmarks:
         lm_est[lm_id] = {}
         x, y = lm_coord
         for pid, coord in graph_coords.items():
             lm_est[lm_id][pid] = haversine(x, y, coord[0], coord[1])
     qtree = point_dict_to_quadtree(graph_coords, multiquadtree=True)
     lm_dists = defaultdict(list)
     l = len(graph_coords)
     for pid in pids:
         counter.value += 1
         print counter.value, '/', l, ':', pid
         for landmark, _ in landmarks:
             try:
                 d = lm_exact_dist(pid, landmark, graph, graph_coords,
                                   lm_est)
             except KeyError:
                 d = None
             lm_dists[pid].append(d)
     out_q.put(lm_dists)
    def _manhattan(self, id1, id2):
        """ 
        Returns the Manhattan distance in KM between the two ID'd vertices.

        (x1, y1)
        [1]
         |
         |
         |
         |            (x2, y2) 
        [3]-----------[2]
        (x1, y2)

        returns dist(1, 3) + dist(2, 3)
        """
        x1, y1 = self.coords[id1]
        x2, y2 = self.coords[id2]
        x3, y3 = x1, y2
        return haversine(x3, y3, x2, y2) + haversine(x3, y3, x1, y1)
    def _euclidean(self, id1, id2):
        """ 
        Returns the distance in KM between the two ID'd vertices.

        Arguments:
        id1, id2 -- IDs matching vertices in self.coords
        """
        x1, y1 = self.coords[id1]
        x2, y2 = self.coords[id2]
        return haversine(x1, y1, x2, y2)
    def _manhattan(self, id1, id2):
        """ 
        Returns the Manhattan distance in KM between the two ID'd vertices.

        (x1, y1)
        [1]
         |
         |
         |
         |            (x2, y2) 
        [3]-----------[2]
        (x1, y2)

        returns dist(1, 3) + dist(2, 3)
        """
        x1, y1 = self.coords[id1]
        x2, y2 = self.coords[id2]
        x3, y3 = x1, y2
        return haversine(x3, y3, x2, y2) + haversine(x3, y3, x1, y1)
    def _euclidean(self, id1, id2):
        """ 
        Returns the distance in KM between the two ID'd vertices.

        Arguments:
        id1, id2 -- IDs matching vertices in self.coords
        """
        x1, y1 = self.coords[id1]
        x2, y2 = self.coords[id2]
        return haversine(x1, y1, x2, y2)
def find_closest_node(target, quadtree, rng=.01):
    x, y = target
    close_nodes = quadtree.query_range(x - rng, x + rng, y - rng, y + rng)
    best_node = None
    best_dist = float("inf")
    for point, nodes in close_nodes.items():
        dist = haversine(point[0], point[1], target[0], target[1])
        if dist < best_dist:
            best_dist = dist
            best_node = nodes
    if best_node:
        return best_node[0]
    else:
        return None
def find_closest_node(target, quadtree, rng=.01):
    x, y = target
    close_nodes = quadtree.query_range(x - rng, x + rng, y - rng, y + rng)
    best_node = None
    best_dist = float("inf")
    for point, nodes in close_nodes.iteritems():
        dist = haversine(point[0], point[1], target[0], target[1])
        if dist < best_dist:
            best_dist = dist
            best_node = nodes
    if best_node:
        return best_node[0]
    else: 
        return None
def planar_landmark_selection(k, origin, coords, graph, qtree):
    origin_id = find_closest_node(origin, qtree)
    origin = coords[origin_id]
    sectors = section_plane(k, origin, coords)
    landmarks = []
    for sector in sectors:
        max_dist = float("-inf")
        best_candidate = None
        for pid, coord in sector:
            cur_dist = haversine(origin[0], origin[1], coord[0], coord[1])
            if cur_dist > max_dist and exact_dist(pid, origin_id, graph, coords):
                max_dist = cur_dist
                best_candidate = coord
        landmarks.append(best_candidate)
    return landmarks
def farthest_landmark_selection(k, origin, coords):
    landmarks = [origin]
    for _ in xrange(k):
        max_dist = float("-inf")
        best_candidate = None
        for pid, coord in coords.items():
            cur_dist = 0
            for lm in landmarks:
                cur_dist += haversine(lm[0], lm[1], coord[0], coord[1])
            if cur_dist > max_dist and not coord in landmarks:
                max_dist = cur_dist
                best_candidate = coord
        landmarks.append(best_candidate)
        if len(landmarks) > k:
            landmarks.pop(0)
    return landmarks
def planar_landmark_selection(k, origin, coords, graph, qtree):
    origin_id = find_closest_node(origin, qtree)
    origin = coords[origin_id]
    sectors = section_plane(k, origin, coords)
    landmarks = []
    for sector in sectors:
        max_dist = float("-inf")
        best_candidate = None
        for pid, coord in sector:
            cur_dist = haversine(origin[0], origin[1], coord[0], coord[1])
            if cur_dist > max_dist and exact_dist(pid, origin_id, graph,
                                                  coords):
                max_dist = cur_dist
                best_candidate = coord
        landmarks.append(best_candidate)
    return landmarks
def farthest_landmark_selection(k, origin, coords):
    landmarks = [origin]
    for _ in xrange(k):
        max_dist = float("-inf") 
        best_candidate = None
        for pid, coord in coords.iteritems():
            cur_dist = 0
            for lm in landmarks:
                cur_dist += haversine(lm[0], lm[1], coord[0], coord[1])
            if cur_dist > max_dist and not coord in landmarks:
                max_dist = cur_dist
                best_candidate = coord
        landmarks.append(best_candidate)
        if len(landmarks) > k:
            landmarks.pop(0)
    return landmarks
def landmark_distances(landmarks, graph, graph_coords):
    lm_est = {}
    for lm_id, lm_coord in landmarks:
        lm_est[lm_id] = {}
        x,y = lm_coord
        for pid, coord in graph_coords.iteritems():
            lm_est[lm_id][pid] = haversine(x, y, coord[0], coord[1])
    qtree = point_dict_to_quadtree(graph_coords, multiquadtree=True)
    lm_dists = defaultdict(list)
    l = len(graph_coords)
    for i, pid in enumerate(graph_coords):
        print i, '/', l, ':', pid
        for landmark, _ in landmarks:
            try:
                d = lm_exact_dist(pid, landmark, graph, graph_coords, lm_est)
            except KeyError:
                d = None
            lm_dists[pid].append(d)
    return lm_dists
def landmark_distances(landmarks, graph, graph_coords):
    lm_est = {}
    for lm_id, lm_coord in landmarks:
        lm_est[lm_id] = {}
        x, y = lm_coord
        for pid, coord in graph_coords.items():
            lm_est[lm_id][pid] = haversine(x, y, coord[0], coord[1])
    qtree = point_dict_to_quadtree(graph_coords, multiquadtree=True)
    lm_dists = defaultdict(list)
    l = len(graph_coords)
    for i, pid in enumerate(graph_coords):
        print i, '/', l, ':', pid
        for landmark, _ in landmarks:
            try:
                d = lm_exact_dist(pid, landmark, graph, graph_coords, lm_est)
            except KeyError:
                d = None
            lm_dists[pid].append(d)
    return lm_dists
def exact_dist(source, dest, graph, coords):
    dest_x, dest_y = coords[dest]
    pred_list = {source : 0}
    closed_set = set()
    unseen = [(0, source)]    # keeps a set and heap structure
    while unseen:
        _, vert = heappop(unseen)
        if vert in closed_set:
            # needed because we dont have a heap with decrease-key
            continue
        elif vert == dest:
            return pred_list[vert]
        closed_set.add(vert)
        for arc, arc_len in graph[vert]:
            if arc not in closed_set:
                new_dist = (pred_list[vert] + arc_len)
                if arc not in pred_list or new_dist < pred_list[arc]:
                    pred_list[arc] = new_dist
                    x, y = coords[arc]
                    heappush(unseen, (new_dist + haversine(x, y, dest_x, dest_y), arc))
    return None    # no valid path found
    def _find_closest_vertex(self, target, rng=.01):
        """ 
        Using the query_range function of the given quadtree, locate a vertex
        in the graph that is closest to the given point.

        Arguments:
        target -- (x, y) point to be matched to the graph.

        Returns:
        The ID of the vertex that is closest to the given point.
        """
        x, y = target
        close_vertices = self.qtree.query_range(x - rng, x + rng, y - rng, y + rng)
        best_vertex = None
        best_dist = float("inf")
        for point, vertices in close_vertices.iteritems():
            dist = haversine(point[0], point[1], target[0], target[1])
            if dist < best_dist:
                best_dist = dist
                best_vertex = vertices[0]
        return best_vertex    
def exact_dist(source, dest, graph, coords):
    dest_x, dest_y = coords[dest]
    pred_list = {source: 0}
    closed_set = set()
    unseen = [(0, source)]  # keeps a set and heap structure
    while unseen:
        _, vert = heappop(unseen)
        if vert in closed_set:
            # needed because we dont have a heap with decrease-key
            continue
        elif vert == dest:
            return pred_list[vert]
        closed_set.add(vert)
        for arc, arc_len in graph[vert]:
            if arc not in closed_set:
                new_dist = (pred_list[vert] + arc_len)
                if arc not in pred_list or new_dist < pred_list[arc]:
                    pred_list[arc] = new_dist
                    x, y = coords[arc]
                    heappush(unseen,
                             (new_dist + haversine(x, y, dest_x, dest_y), arc))
    return None  # no valid path found
    def _find_closest_vertex(self, target, rng=.01):
        """ 
        Using the query_range function of the given quadtree, locate a vertex
        in the graph that is closest to the given point.

        Arguments:
        target -- (x, y) point to be matched to the graph.

        Returns:
        The ID of the vertex that is closest to the given point.
        """
        x, y = target
        close_vertices = self.qtree.query_range(x - rng, x + rng, y - rng,
                                                y + rng)
        best_vertex = None
        best_dist = float("inf")
        for point, vertices in close_vertices.items():
            dist = haversine(point[0], point[1], target[0], target[1])
            if dist < best_dist:
                best_dist = dist
                best_vertex = vertices[0]
        return best_vertex
 def worker(landmarks, graph, graph_coords, pids, out_q, counter):
     """ The worker function, invoked in a process. 'nums' is a
         list of numbers to factor. The results are placed in
         a dictionary that's pushed to a queue.
     """
     lm_est = {}
     for lm_id, lm_coord in landmarks:
         lm_est[lm_id] = {}
         x,y = lm_coord
         for pid, coord in graph_coords.iteritems():
             lm_est[lm_id][pid] = haversine(x, y, coord[0], coord[1])
     qtree = point_dict_to_quadtree(graph_coords, multiquadtree=True)
     lm_dists = defaultdict(list)
     l = len(graph_coords)
     for pid in pids:
         counter.value += 1
         print counter.value, '/', l, ':', pid
         for landmark, _ in landmarks:
             try:
                 d = lm_exact_dist(pid, landmark, graph, graph_coords, lm_est)
             except KeyError:
                 d = None
             lm_dists[pid].append(d)
     out_q.put(lm_dists)