Exemple #1
0
    def init_backward(self,
                      g: nx.MultiDiGraph,
                      orig: NodeId,
                      dest: NodeId,
                      init_secs: float = 0,
                      init_cost: float = 0):
        for end_node in g.adj[dest]:
            edge = g.adj[dest][end_node][0]

            secs = edge['length'] / self._speed + init_secs
            cost = edge['length'] + init_cost
            sort_cost = cost + self._get_heuristic_cost(g, end_node, orig)

            idx = len(self._edge_labels_backward)
            self._edge_labels_backward.append(
                EdgeLabel(Cost(cost, secs, init_cost, init_secs),
                          sort_cost,
                          EdgeId(dest, end_node),
                          -1,
                          end_node,
                          is_origin=False,
                          is_destination=True))
            self._adjacency_list_backward.insert(sort_cost, idx)
            self._edges_status_backward[EdgeId(
                dest, end_node)] = EdgeStatus(idx).set_temporary()
    def append_bike_backward(self, g: nx.MultiDiGraph, bss_node: NodeId, orig: NodeId, init_secs: float = 0, init_cost: float = 0):
        for end_node in g.adj[bss_node]:
            edge = g.adj[bss_node][end_node][0]

            secs = edge['length'] / self._bike_speed + init_secs
            cost = edge['length'] * (self._walking_speed / self._bike_speed) + init_cost
            sort_cost = cost + self._get_bike_heuristic_cost(g, end_node, orig)
            edge_status = self._edges_status_bike_backward[EdgeId(bss_node, end_node)]

            if edge_status.is_permanent():
                # if it's permanent is this edge has less cost?
                edge_label_idx = edge_status.edge_label_index
                lab = weakref.proxy(self._edge_labels_bike_backward[edge_status.edge_label_index])
                if lab.end_node == end_node:
                    if cost > lab.cost.cost:
                        continue
                    self._adjacency_list_bike_backward.insert(new_key=sort_cost,
                                                              item=edge_label_idx)
                    lab.pred_idx = -1
                    lab.end_node = end_node
                    lab.cost = Cost(cost, secs, init_cost, init_secs)
                    lab.is_origin = False
                    lab.is_destination = True
            else:
                idx = len(self._edge_labels_bike_backward)
                self._edge_labels_bike_backward.append(EdgeLabel(Cost(cost, secs, init_cost, init_secs),
                                                                 sort_cost,
                                                                 EdgeId(bss_node, end_node),
                                                                 -1,
                                                                 end_node,
                                                                 is_origin=False,
                                                                 is_destination=True))
                self._adjacency_list_bike_backward.insert(sort_cost, idx)
                self._edges_status_bike_backward[EdgeId(bss_node, end_node)] = EdgeStatus(idx).set_temporary()
Exemple #3
0
    def append_bike(self, g: nx.MultiDiGraph, bss_node: NodeId, init_secs: float=0, init_cost: float=0):
        for end_node in g.adj[bss_node]:
            edge = g.adj[bss_node][end_node][0]

            secs = edge['length'] / self._bike_speed + init_secs
            cost = edge['length'] * (self._walking_speed / self._bike_speed) + init_cost

            # let's see if the edge has already been visited?
            edge_status = self._edges_status_bike[EdgeId(bss_node, end_node)]
            if not edge_status.is_unreached():
                # if it's visted, is this edge had less cost?
                edge_label_idx = edge_status.edge_label_index
                lab = weakref.proxy(self._edge_labels_bike[edge_status.edge_label_index])
                if lab.end_node == end_node:
                    if cost > lab.cost.cost:
                        continue
                    self._adjacency_list_bike.insert(new_key=cost,
                                                     item=edge_label_idx)
                    lab.pred_idx = -1
                    lab.end_node = end_node
                    lab.cost = Cost(cost, secs, init_cost, init_secs)
                    lab.is_origin = True
                    lab.is_destination = False

            else:
                idx = len(self._edge_labels_bike)
                self._edge_labels_bike.append(EdgeLabel(Cost(cost, secs, init_cost, init_secs),
                                                        cost,
                                                        EdgeId(bss_node, end_node),
                                                        -1,
                                                        end_node,
                                                        is_origin=True))
                self._adjacency_list_bike.insert(cost, idx)
                self._edges_status_bike[EdgeId(bss_node, end_node)] = EdgeStatus(idx).set_temporary()
Exemple #4
0
    def init(self):
        self._edge_labels_forward = []
        self._edge_labels_backward = []

        self._adjacency_list_forward = PriorityQueue()
        self._adjacency_list_backward = PriorityQueue()

        self._edges_status_forward.clear()
        self._edges_status_backward.clear()

        self._best_path = BestConnection(EdgeId(-1, -1), EdgeId(-1, -1),
                                         float('inf'))
        self._threshold: float = float('inf')
Exemple #5
0
    def expand_backward(self, g, node, pred_idx, origin):

        for end_node in g.adj[node]:
            edge = g.adj[node][end_node][0]
            edge_status = self._get_edge_status_backward(EdgeId(
                node, end_node))

            if edge_status.is_permanent():
                continue

            pred = self._edge_labels_backward[pred_idx]

            new_cost = pred.cost + Cost(edge['length'],
                                        edge['length'] / self._speed)
            edge_id = EdgeId(node, end_node)

            sort_cost = new_cost.cost + self._get_heuristic_cost(
                g, end_node, origin)

            # the edge has been visited
            if edge_status.is_temporary():
                lab = weakref.proxy(
                    self._edge_labels_backward[edge_status.edge_label_index])
                if lab.end_node == end_node:
                    if new_cost < lab.cost:
                        self._adjacency_list_backward.insert(
                            new_key=sort_cost,
                            item=edge_status.edge_label_index)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost

                # Hmmm, we are visiting the edge in the opposing direction of last visit
                elif lab.end_node == node:
                    if new_cost.cost < (lab.cost.cost - edge['length']):
                        self._adjacency_list_backward.insert(
                            new_key=sort_cost,
                            item=edge_status.edge_label_index)
                        lab.edge_id = EdgeId(node, end_node)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost
                continue

            idx = len(self._edge_labels_backward)
            self._edge_labels_backward.append(
                EdgeLabel(new_cost, sort_cost, edge_id, pred_idx, end_node))

            self._edges_status_backward[edge_id] = EdgeStatus(
                idx).set_temporary()
            self._adjacency_list_backward.insert(sort_cost, idx)
Exemple #6
0
    def expand_walking(self, g: nx.MultiDiGraph, node: NodeId, pred_idx: EdgeLabelIdx):
        for end_node in g.adj[node]:
            edge = g.adj[node][end_node][0]

            pred = self._edge_labels_walking[pred_idx]

            edge_id = EdgeId(node, end_node, pred.can_change_mode)

            edge_status = self._edges_status_walking[edge_id]

            new_cost = pred.cost + Cost(edge['length'], edge['length'] / self._walking_speed)

            # the edge has been visited
            if not edge_status.is_unreached():
                lab = weakref.proxy(self._edge_labels_walking[edge_status.edge_label_index])
                if lab.end_node == end_node:
                    if new_cost < lab.cost:
                        self._adjacency_list_walking.insert(new_key=new_cost.cost,
                                                            item=edge_status.edge_label_index)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost
                        lab.can_change_mode = pred.can_change_mode

                # Hmmm, we are visiting the edge in the opposing direction of last visit
                elif lab.end_node == node:
                    if new_cost.cost < (lab.cost.cost - edge['length']):
                        self._adjacency_list_walking.insert(new_key=new_cost.cost,
                                                            item=edge_status.edge_label_index)
                        lab.edge_id = EdgeId(node, end_node)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost
                        lab.can_change_mode = pred.can_change_mode

                continue

            idx = len(self._edge_labels_walking)
            self._edge_labels_walking.append(EdgeLabel(new_cost,
                                                       new_cost.cost,
                                                       edge_id,
                                                       pred_idx,
                                                       end_node,
                                                       can_change_mode=pred.can_change_mode))

            self._edges_status_walking[edge_id] = EdgeStatus(idx).set_temporary()
            self._adjacency_list_walking.insert(new_cost.cost, idx)
Exemple #7
0
    def init_origin(self, g, orig, init_secs=0, init_cost=0):

        # init origin
        for end_node in g.adj[orig]:
            edge = g.adj[orig][end_node][0]

            secs = edge['length'] / self._speed + init_secs
            cost = edge['length'] + init_cost
            sort_cost = cost + self._get_heuristic_cost(
                g, end_node, self._dest)

            idx = len(self._edge_labels)
            self._edge_labels.append(
                EdgeLabel(Cost(cost, secs, init_cost, init_secs), sort_cost,
                          EdgeId(orig, end_node), -1, end_node, True))
            self._adjacency_list.insert(sort_cost, idx)
            self._edges_status[EdgeId(
                orig, end_node)] = EdgeStatus(idx).set_temporary()
Exemple #8
0
    def get_best_path(
        self,
        g: nx.MultiDiGraph,
        orig: NodeId,
        dest: NodeId,
        callback: Callable = lambda *args, **kwargs: None
    ) -> Tuple[List[NodeId], float]:

        self._orig = orig
        self._dest = dest

        self.init()

        self.init_origin(g, orig)

        # init destination
        for end_node in g.adj[dest]:
            edge = g.adj[dest][end_node][0]
            self._destinations[EdgeId(dest, end_node)] = edge['length']

        i = 0
        a = 0
        # begin search
        while True:
            if i % 200 == 0:
                callback(g, orig, dest, self._edges_status, self._edge_labels,
                         str(a).zfill(4))
                a += 1
            i += 1

            current_labels = len(self._edge_labels)

            if current_labels > PriorityQueue.QUEUE_MAX_SIZE:
                return []

            _, pred_index = self._adjacency_list.pop()
            pred_edge_label = self._edge_labels[pred_index]

            # Do we touch the destination?
            d = self._destinations.get(pred_edge_label.edge_id)
            if d:
                if self._best_path.edge_label_index is -1:
                    self._best_path.edge_label_index = pred_index
                    self._best_path.cost = pred_edge_label.cost

                return self.make_osm_path()

            if not pred_edge_label.is_origin:
                self._edges_status[pred_edge_label.edge_id].set_permanent()

            self.expand_forward(g, pred_edge_label.end_node, pred_index, dest)
Exemple #9
0
    def append_walking(self, g, orig, can_change_mode: bool, init_secs: float=0, init_cost: float=0):
        # init origin
        for end_node in g.adj[orig]:
            edge = g.adj[orig][end_node][0]

            secs = edge['length'] / self._walking_speed + init_secs
            cost = edge['length'] + init_cost
            sort_cost = cost

            # let's see if the edge has already been visited?
            edge_status = self._edges_status_walking[EdgeId(orig, end_node, can_change_mode)]
            if not edge_status.is_unreached():
                # if it's visted, is this edge had less cost?
                edge_label_idx = edge_status.edge_label_index
                lab = weakref.proxy(self._edge_labels_walking[edge_label_idx])
                if lab.end_node == end_node:
                    if cost > lab.cost.cost:
                        continue
                    self._adjacency_list_walking.insert(new_key=cost,
                                                        item=edge_label_idx)
                    lab.pred_idx = -1
                    lab.end_node = end_node
                    lab.cost = Cost(cost, secs, init_cost, init_secs)
                    lab.is_origin = True
                    lab.is_destination = False

            else:
                idx = len(self._edge_labels_walking)
                self._edge_labels_walking.append(EdgeLabel(Cost(cost, secs, init_cost, init_secs),
                                                           sort_cost,
                                                           EdgeId(orig, end_node),
                                                           -1,
                                                           end_node,
                                                           is_origin=True,
                                                           can_change_mode=can_change_mode))
                self._adjacency_list_walking.insert(sort_cost, idx)
                self._edges_status_walking[EdgeId(orig, end_node, can_change_mode)] = EdgeStatus(idx).set_temporary()
class BestConnection:
    forward: EdgeId = EdgeId(-1, -1)
    backward: EdgeId = EdgeId(-1, -1)
    cost: float = float('inf')
    mode: str = None
    def expand_forward(self, g: nx.MultiDiGraph, node: NodeId, pred_idx: EdgeLabelIdx, dest: NodeId, bss_nodes: Set[NodeId]):

        def _get_speed(travel_mode: TravelMode):
            return (self._walking_speed, self._bike_speed)[travel_mode.value]

        def _normalize_factor(travel_mode: TravelMode):
            return self._walking_speed / (self._walking_speed, self._bike_speed)[travel_mode.value]

        def _get_heurestic_cost(travel_mode: TravelMode, *args, **kwargs):
            fun = (self._get_walking_heuristic_cost, self._get_bike_heuristic_cost)[travel_mode.value]
            return fun(*args, **kwargs)

        for end_node in g.adj[node]:
            edge = g.adj[node][end_node][0]

            pred = self._edge_labels[pred_idx]

            edge_status = self._get_edge_status(EdgeId(node, end_node, mode=pred.edge_id.mode))

            if node not in bss_nodes and edge_status.is_permanent():
                continue

            if node not in bss_nodes and not edge_status.is_permanent():
                new_cost = pred.cost + Cost(edge['length'] * _normalize_factor(pred.edge_id.mode),
                                            edge['length'] / _get_speed(pred.edge_id.mode))
                edge_id = EdgeId(node, end_node, pred.edge_id.mode)
                sort_cost = new_cost.cost + _get_heurestic_cost(pred.edge_id.mode, g, end_node, dest)
                # the edge has been visited
                if edge_status.is_temporary():
                    lab = weakref.proxy(self._edge_labels[edge_status.edge_label_index])
                    if lab.end_node == end_node:
                        if new_cost < lab.cost:
                            self._adjacency_list.insert(new_key=sort_cost,
                                                        item=edge_status.edge_label_index)
                            lab.edge_id = EdgeId(node, end_node, pred.edge_id.mode)
                            lab.pred_idx = pred_idx
                            lab.end_node = end_node
                            lab.cost = new_cost

                    # Hmmm, we are visiting the edge in the opposing direction of last visit
                    elif lab.end_node == node:
                        if new_cost.cost < (lab.cost.cost - edge['length'] * _normalize_factor(pred.edge_id.mode)):
                            self._adjacency_list.insert(new_key=sort_cost,
                                                        item=edge_status.edge_label_index)
                            lab.edge_id = EdgeId(node, end_node, pred.edge_id.mode)
                            lab.pred_idx = pred_idx
                            lab.end_node = end_node
                            lab.cost = new_cost
                    continue

                idx = len(self._edge_labels)
                self._edge_labels.append(EdgeLabel(new_cost,
                                                   sort_cost,
                                                   edge_id,
                                                   pred_idx,
                                                   end_node))
                self._edges_status[edge_id] = EdgeStatus(idx).set_temporary()
                self._adjacency_list.insert(sort_cost, idx)

            if node in bss_nodes:
                for mode in TravelMode:
                    edge_status = self._get_edge_status(EdgeId(node, end_node, mode=mode))

                    if edge_status.is_permanent():
                        continue
                    new_cost = pred.cost + Cost(edge['length'] * _normalize_factor(mode),
                                                edge['length'] / _get_speed(mode))

                    edge_id = EdgeId(node, end_node, mode)
                    if mode == TravelMode.WALKING:
                        sort_cost = new_cost.cost + self._get_walking_heuristic_cost(g, end_node, dest)
                    else:
                        sort_cost = new_cost.cost + self._get_bike_heuristic_cost(g, end_node, dest)

                    # the edge has been visited
                    if edge_status.is_temporary():
                        lab = weakref.proxy(self._edge_labels[edge_status.edge_label_index])
                        if lab.end_node == end_node:
                            if new_cost < lab.cost:
                                self._adjacency_list.insert(new_key=sort_cost,
                                                            item=edge_status.edge_label_index)
                                # lab.edge_id = EdgeId(node, end_node, mode)
                                lab.pred_idx = pred_idx
                                lab.end_node = end_node
                                lab.cost = new_cost
                        # Hmmm, we are visiting the edge in the opposing direction of last visit
                        elif lab.end_node == node:
                            if new_cost.cost < (lab.cost.cost - edge['length'] * _normalize_factor(mode)):
                                self._adjacency_list.insert(new_key=sort_cost,
                                                            item=edge_status.edge_label_index)
                                # lab.edge_id = EdgeId(node, end_node, mode)
                                lab.pred_idx = pred_idx
                                lab.end_node = end_node
                                lab.cost = new_cost
                        continue

                    idx = len(self._edge_labels)
                    self._edge_labels.append(EdgeLabel(new_cost,
                                                       sort_cost,
                                                       edge_id,
                                                       pred_idx,
                                                       end_node))
                    self._edges_status[edge_id] = EdgeStatus(idx).set_temporary()
                    self._adjacency_list.insert(sort_cost, idx)
 def init_destination(self,  g: nx.MultiDiGraph, dest: NodeId):
     # init destination
     for end_node in g.adj[dest]:
         edge = g.adj[dest][end_node][0]
         self._destinations[EdgeId(dest, end_node, mode=TravelMode.WALKING)] = edge['length']
Exemple #13
0
class DoubleAstar(object):
    _edge_labels_forward: List[EdgeLabel] = field(default_factory=list)
    _edge_labels_backward: List[EdgeLabel] = field(default_factory=list)

    _adjacency_list_forward: PriorityQueue = PriorityQueue()
    _adjacency_list_backward: PriorityQueue = PriorityQueue()

    _edges_status_forward: Dict[EdgeId, EdgeStatus] = defaultdict(EdgeStatus)
    _edges_status_backward: Dict[EdgeId, EdgeStatus] = defaultdict(EdgeStatus)

    _cost_factor: float = .5
    _best_path: BestConnection = BestConnection(EdgeId(-1, -1), EdgeId(-1, -1),
                                                float('inf'))
    _speed: float = 1.4
    _threshold: float = float('inf')

    def __init__(self, speed=1.4, cost_factor=1):
        self._speed = speed
        self._cost_factor = cost_factor

    def _get_heuristic_cost(self, g: nx.MultiDiGraph, start_node: NodeId,
                            end_node: NodeId) -> float:
        if self._cost_factor == 0 or end_node is None:
            return 0
        start_ll = utils.osm_to_pointll(g, start_node)
        end_ll = utils.osm_to_pointll(g, end_node)

        return start_ll.distance_to(end_ll) * self._cost_factor

    @staticmethod
    def _get_edge_status_impl(container: Dict[EdgeId, EdgeStatus],
                              edge_id: EdgeId) -> EdgeStatus:
        s = container.get(edge_id)
        if not s:
            return container[edge_id].set_unreached()
        return s

    def _get_edge_status_forward(self, edge_id: EdgeId) -> EdgeStatus:
        return self._get_edge_status_impl(self._edges_status_forward, edge_id)

    def _get_edge_status_backward(self, edge_id: EdgeId) -> EdgeStatus:
        return self._get_edge_status_impl(self._edges_status_backward, edge_id)

    def init_forward(self,
                     g: nx.MultiDiGraph,
                     orig: NodeId,
                     dest: NodeId,
                     init_secs: float = 0,
                     init_cost: float = 0):
        for end_node in g.adj[orig]:
            edge = g.adj[orig][end_node][0]

            secs = edge['length'] / self._speed + init_secs
            cost = edge['length'] + init_cost
            sort_cost = cost + self._get_heuristic_cost(g, end_node, dest)

            idx = len(self._edge_labels_forward)
            self._edge_labels_forward.append(
                EdgeLabel(Cost(cost, secs, init_cost, init_secs),
                          sort_cost,
                          EdgeId(orig, end_node),
                          -1,
                          end_node,
                          is_origin=True,
                          is_destination=False))
            self._adjacency_list_forward.insert(sort_cost, idx)
            self._edges_status_forward[EdgeId(
                orig, end_node)] = EdgeStatus(idx).set_temporary()

    def init_backward(self,
                      g: nx.MultiDiGraph,
                      orig: NodeId,
                      dest: NodeId,
                      init_secs: float = 0,
                      init_cost: float = 0):
        for end_node in g.adj[dest]:
            edge = g.adj[dest][end_node][0]

            secs = edge['length'] / self._speed + init_secs
            cost = edge['length'] + init_cost
            sort_cost = cost + self._get_heuristic_cost(g, end_node, orig)

            idx = len(self._edge_labels_backward)
            self._edge_labels_backward.append(
                EdgeLabel(Cost(cost, secs, init_cost, init_secs),
                          sort_cost,
                          EdgeId(dest, end_node),
                          -1,
                          end_node,
                          is_origin=False,
                          is_destination=True))
            self._adjacency_list_backward.insert(sort_cost, idx)
            self._edges_status_backward[EdgeId(
                dest, end_node)] = EdgeStatus(idx).set_temporary()

    def init(self):
        self._edge_labels_forward = []
        self._edge_labels_backward = []

        self._adjacency_list_forward = PriorityQueue()
        self._adjacency_list_backward = PriorityQueue()

        self._edges_status_forward.clear()
        self._edges_status_backward.clear()

        self._best_path = BestConnection(EdgeId(-1, -1), EdgeId(-1, -1),
                                         float('inf'))
        self._threshold: float = float('inf')

    # forward searching reach on a edge reached by backward searching
    def set_forward_connection(self, pred: EdgeId):

        edge_status_backward = self._edges_status_backward.get(pred)
        edge_label_backward = edge_status_backward.edge_label_index

        edge_status_forward = self._edges_status_forward.get(pred)
        edge_label_forward = edge_status_forward.edge_label_index
        pred_idx_forward = self._edge_labels_forward[
            edge_label_forward].pred_idx

        c = self._edge_labels_backward[edge_label_backward].cost \
            + self._edge_labels_forward[pred_idx_forward].cost

        if c.cost < self._best_path.cost:
            self._best_path = BestConnection(
                self._edge_labels_forward[pred_idx_forward].edge_id,
                self._edge_labels_backward[edge_label_backward].edge_id,
                c.cost)

    # backward searching reach on a edge reached by forward searching
    def set_backward_connection(self, pred: EdgeId):

        edge_status_forward = self._edges_status_forward.get(pred)
        edge_label_forward = edge_status_forward.edge_label_index

        edge_status_backward = self._edges_status_backward.get(pred)
        edge_label_backward = edge_status_backward.edge_label_index
        pred_idx_backward = self._edge_labels_backward[
            edge_label_backward].pred_idx

        c = self._edge_labels_backward[pred_idx_backward].cost \
            + self._edge_labels_forward[edge_label_forward].cost

        if c.cost < self._best_path.cost:
            self._best_path = BestConnection(
                self._edge_labels_forward[edge_label_forward].edge_id,
                self._edge_labels_backward[pred_idx_backward].edge_id, c.cost)

    def expand_forward(self, g: nx.MultiDiGraph, node: NodeId,
                       pred_idx: EdgeLabelIdx, dest: NodeId):

        for end_node in g.adj[node]:
            edge = g.adj[node][end_node][0]
            edge_status = self._get_edge_status_forward(EdgeId(node, end_node))

            if edge_status.is_permanent():
                continue

            pred = self._edge_labels_forward[pred_idx]

            new_cost = pred.cost + Cost(edge['length'],
                                        edge['length'] / self._speed)
            edge_id = EdgeId(node, end_node)

            sort_cost = new_cost.cost + self._get_heuristic_cost(
                g, end_node, dest)

            # the edge has been visited
            if edge_status.is_temporary():
                lab = weakref.proxy(
                    self._edge_labels_forward[edge_status.edge_label_index])
                if lab.end_node == end_node:
                    if new_cost < lab.cost:
                        self._adjacency_list_forward.insert(
                            new_key=sort_cost,
                            item=edge_status.edge_label_index)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost

                # Hmmm, we are visiting the edge in the opposing direction of last visit
                elif lab.end_node == node:
                    if new_cost.cost < (lab.cost.cost - edge['length']):
                        self._adjacency_list_forward.insert(
                            new_key=sort_cost,
                            item=edge_status.edge_label_index)
                        lab.edge_id = EdgeId(node, end_node)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost
                continue

            idx = len(self._edge_labels_forward)
            self._edge_labels_forward.append(
                EdgeLabel(new_cost, sort_cost, edge_id, pred_idx, end_node))

            self._edges_status_forward[edge_id] = EdgeStatus(
                idx).set_temporary()
            self._adjacency_list_forward.insert(sort_cost, idx)

    def expand_backward(self, g, node, pred_idx, origin):

        for end_node in g.adj[node]:
            edge = g.adj[node][end_node][0]
            edge_status = self._get_edge_status_backward(EdgeId(
                node, end_node))

            if edge_status.is_permanent():
                continue

            pred = self._edge_labels_backward[pred_idx]

            new_cost = pred.cost + Cost(edge['length'],
                                        edge['length'] / self._speed)
            edge_id = EdgeId(node, end_node)

            sort_cost = new_cost.cost + self._get_heuristic_cost(
                g, end_node, origin)

            # the edge has been visited
            if edge_status.is_temporary():
                lab = weakref.proxy(
                    self._edge_labels_backward[edge_status.edge_label_index])
                if lab.end_node == end_node:
                    if new_cost < lab.cost:
                        self._adjacency_list_backward.insert(
                            new_key=sort_cost,
                            item=edge_status.edge_label_index)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost

                # Hmmm, we are visiting the edge in the opposing direction of last visit
                elif lab.end_node == node:
                    if new_cost.cost < (lab.cost.cost - edge['length']):
                        self._adjacency_list_backward.insert(
                            new_key=sort_cost,
                            item=edge_status.edge_label_index)
                        lab.edge_id = EdgeId(node, end_node)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost
                continue

            idx = len(self._edge_labels_backward)
            self._edge_labels_backward.append(
                EdgeLabel(new_cost, sort_cost, edge_id, pred_idx, end_node))

            self._edges_status_backward[edge_id] = EdgeStatus(
                idx).set_temporary()
            self._adjacency_list_backward.insert(sort_cost, idx)

    def make_osm_path(self):
        res_forward = []
        edge = self._best_path.forward
        edge_label_idx = self._edges_status_forward[edge].edge_label_index
        edge_label = self._edge_labels_forward[edge_label_idx]
        forward_secs = edge_label.cost.secs
        while not edge_label.is_origin:
            res_forward.append(edge_label.end_node)
            edge_label_idx = edge_label.pred_idx
            edge_label = self._edge_labels_forward[edge_label_idx]

        res_forward.append(edge_label.edge_id.end)
        res_forward.append(edge_label.edge_id.start)
        res_forward = res_forward[::-1]

        res_backward = []

        edge = self._best_path.backward
        edge_label_idx = self._edges_status_backward[edge].edge_label_index
        edge_label = self._edge_labels_backward[edge_label_idx]
        backward_secs = edge_label.cost.secs

        while not edge_label.is_destination:
            res_backward.append(edge_label.end_node)
            edge_label_idx = edge_label.pred_idx
            edge_label = self._edge_labels_backward[edge_label_idx]

        res_backward.append(edge_label.edge_id.end)
        res_backward.append(edge_label.edge_id.start)

        if res_forward[-1] == res_backward[0]:
            res_forward.pop(-1)

        return res_forward + res_backward, forward_secs + backward_secs

    def run(
        self,
        g: nx.MultiDiGraph,
        orig: NodeId,
        dest: NodeId,
        callback: Callable = lambda *args, **kwargs: None
    ) -> Tuple[List[NodeId], float]:
        expand_forward = True
        expand_backward = True

        forward_edge_label = None
        forward_edge_label_idx = None
        backward_edge_label = None
        backward_edge_label_idx = None

        a = 0
        i = 0

        # in order to balance the research in both directions
        diff = None

        while True:

            if a % 15 == 0:
                callback(g, orig, dest, self._edges_status_forward,
                         self._edge_labels_forward,
                         self._edges_status_backward,
                         self._edge_labels_backward,
                         str(i).zfill(4))
                i += 1
            a += 1

            if expand_forward:
                _, forward_edge_label_idx = self._adjacency_list_forward.pop()
                forward_edge_label = self._edge_labels_forward[
                    forward_edge_label_idx]

                # We don't want the expansion to go forever
                if forward_edge_label.sort_cost - (diff if diff is not None
                                                   else 0) > self._threshold:
                    return self.make_osm_path()

                if self._edges_status_backward[
                        forward_edge_label.edge_id].is_permanent():
                    if self._threshold == float('inf'):
                        self._threshold = forward_edge_label.sort_cost + kThresholdDelta

                    self.set_forward_connection(forward_edge_label.edge_id)

            if expand_backward:
                _, backward_edge_label_idx = self._adjacency_list_backward.pop(
                )
                backward_edge_label = self._edge_labels_backward[
                    backward_edge_label_idx]

                # We don't want the expansion to go forever
                if backward_edge_label.sort_cost > self._threshold:
                    return self.make_osm_path()

                if self._edges_status_forward[
                        backward_edge_label.edge_id].is_permanent():
                    if self._threshold == float('inf'):
                        self._threshold = forward_edge_label.sort_cost + kThresholdDelta

                    self.set_backward_connection(backward_edge_label.edge_id)

            if diff is None:
                diff = forward_edge_label.sort_cost - backward_edge_label.sort_cost

            if forward_edge_label.sort_cost <= backward_edge_label.sort_cost + diff:
                expand_forward = True
                expand_backward = False

                if not forward_edge_label.is_origin:
                    self._edges_status_forward[
                        forward_edge_label.edge_id].set_permanent()

                self.expand_forward(g, forward_edge_label.end_node,
                                    forward_edge_label_idx, dest)

            else:
                expand_forward = False
                expand_backward = True

                if not backward_edge_label.is_destination:
                    self._edges_status_backward[
                        backward_edge_label.edge_id].set_permanent()

                self.expand_backward(g, backward_edge_label.end_node,
                                     backward_edge_label_idx, orig)

    def get_best_path(
        self,
        g: nx.MultiDiGraph,
        orig: NodeId,
        dest: NodeId,
        callback: Callable = lambda *args, **kwargs: None
    ) -> Tuple[List[NodeId], float]:
        self.init()

        self.init_forward(g, orig, dest)
        self.init_backward(g, orig, dest)

        return self.run(g, orig, dest, callback)
Exemple #14
0
    def expand_forward(self, g, node, pred_idx, dest):

        for end_node in g.adj[node]:
            edge = g.adj[node][end_node][0]
            edge_status = self._get_edge_status(EdgeId(node, end_node))

            if edge_status.is_permanent():
                continue

            pred = self._edge_labels[pred_idx]

            new_cost = pred.cost + Cost(edge['length'],
                                        edge['length'] / self._speed)

            edge_id = EdgeId(node, end_node)

            d = self._destinations.get(edge_id)
            if d is not None:
                if self._best_path.edge_label_index is -1 or new_cost < self._best_path.cost:
                    self._best_path.edge_label_index = edge_status.edge_label_index if edge_status.is_temporary() \
                                                                              else len(self._edge_labels)
                    self._best_path.cost = new_cost

            sort_cost = new_cost.cost + self._get_heuristic_cost(
                g, end_node, self._dest)

            # the edge has been visited
            if edge_status.is_temporary():
                lab = weakref.proxy(
                    self._edge_labels[edge_status.edge_label_index])
                #   Edge:
                #             4242   -------------  4141
                #              start       ->        end
                #                         or
                #               end        <-       start

                # the edge may have been visited either from its start or end,
                # let's find out in this case which one is "cheaper"

                # OK, we are visiting the edge at the same direction of last visit, nothing
                # to be done
                if lab.end_node == end_node:
                    if new_cost < lab.cost:
                        self._adjacency_list.insert(
                            new_key=sort_cost,
                            item=edge_status.edge_label_index)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost

                # Hmmm, we are visiting the edge in the opposing direction of last visit
                elif lab.end_node == node:
                    if new_cost.cost < (lab.cost.cost - edge['length']):
                        self._adjacency_list.insert(
                            new_key=sort_cost,
                            item=edge_status.edge_label_index)
                        lab.edge_id = EdgeId(node, end_node)
                        lab.pred_idx = pred_idx
                        lab.end_node = end_node
                        lab.cost = new_cost

                continue

            idx = len(self._edge_labels)
            self._edge_labels.append(
                EdgeLabel(new_cost, sort_cost, edge_id, pred_idx, end_node))

            self._edges_status[edge_id] = EdgeStatus(idx).set_temporary()

            self._adjacency_list.insert(sort_cost, idx)