Beispiel #1
0
    def step(self, record = None):
        """Starts the computation of the shortest path.
        *Note* : 
            This function works as a generator, a yield statement 
            is appended at the bottom of each loop to make this 
            function capable of being executed step by step.

            If you does not want the step feature, simply delete 
            the yield statements.

        :Parameters:
            record : deque or list
                if a queue is specified, a record of each operation 
                (OPEN, CLOSE, etc) will be pushed into the queue.
        """
        # add the source node into the open list
        sx, sy = self.source
        self.nodes[sy][sx].g = 0
        self.nodes[sy][sx].f = 0
        self.open_list.append(_QNode(self.source, self.nodes))
        self.nodes[sy][sx].status = OPENED

        # while the open list is not empty
        while self.open_list:

            # get the node with lowest F from the heap
            x, y = heappop(self.open_list).pos
            self.nodes[y][x].status = CLOSED
            if record != None:
                record.append(('CLOSE', (x, y)))

            # if the node is the target, reconstruct the path 
            # and break the loop
            if (x, y) == self.target:
                self._retrace()
                break

            # inspect the horizontal and vertical adjacent nodes
            for i in xrange(len(XOFFSET)):

                # next x and y
                nx = x + XOFFSET[i]
                ny = y + YOFFSET[i]

                # if the next coordinate is walkable, inspect it.
                if is_walkable(nx, ny, self.n_row, self.n_col, 
                               self.graph):
                    self._inspect_node((nx, ny), (x, y), False, record)

                    # further investigate the diagonal nodes
                    nx1 = x + DAXOFFSET[i]
                    ny1 = y + DAYOFFSET[i]
                    nx2 = x + DBXOFFSET[i]
                    ny2 = y + DBYOFFSET[i]
                    npos = ((nx1, ny1), (nx2, ny2))
                    for nx, ny in npos:
                        if is_walkable(nx, ny, self.n_row, self.n_col, 
                                       self.graph):
                            self._inspect_node((nx, ny), (x, y), 
                                                True, record)
    def _expand_target(self, rec):
        """Searches from the target. Until it meets a node which
        has been visited by the other tree.
        """
        # the procedure is identical with _expand_source.
        v, (x, y) = heappop(self.queue_target)
        node = self.nodes[y][x]
        diagonal_can = []
        if rec is not None:
            rec.append(('CLOSE', (x, y)))
        for i in range(len(XOFFSET)):
            nx = x + XOFFSET[i]
            ny = y + YOFFSET[i]
            if is_walkable(nx, ny, self.size, self.graph):
                diagonal_can.append(i)
                if self.nodes[ny][nx].visited_by == CTARGET:
                    continue
                nxt_node = self.nodes[ny][nx]
                if nxt_node.visited_by == CSOURCE:
                    if rec:
                        rec.append(('CLOSE', (nx, ny)))
                    self._retrace((nx, ny), (x, y))
                    self.success = True
                    return
                nxt_node.visited_by = CTARGET
                nxt_node.h = node.h + DIST
                nxt_node.parent = (x, y)
                heappush(self.queue_target, (nxt_node.h, (nx, ny)))
                if rec is not None:
                    rec.append(('OPEN', (nx, ny)))
                    rec.append(('VALUE', ('h', (nx, ny),
                                          nxt_node.h)))
                    rec.append(('PARENT', ((nx, ny), (x, y))))

        # further investigate the diagonal nodes
        for i in diagonal_can:
            nx1 = x + DAXOFFSET[i]
            ny1 = y + DAYOFFSET[i]
            nx2 = x + DBXOFFSET[i]
            ny2 = y + DBYOFFSET[i]
            npos = ((nx1, ny1), (nx2, ny2))
            for nx, ny in npos:
                if is_walkable(nx, ny, self.size, self.graph) and \
                        self.nodes[ny][nx].visited_by != CTARGET:
                    nxt_node = self.nodes[ny][nx]
                    if nxt_node.visited_by == CSOURCE:
                        if rec:
                            rec.append(('CLOSE', (nx, ny)))
                        self._retrace((nx, ny), (x, y))
                        self.success = True
                        return
                    nxt_node.visited_by = CTARGET
                    nxt_node.h = node.h + DDIST
                    nxt_node.parent = (x, y)
                    heappush(self.queue_target, (nxt_node.h, (nx, ny)))
                    if rec is not None:
                        rec.append(('OPEN', (nx, ny)))
                        rec.append(('VALUE', ('h', (nx, ny),
                                              nxt_node.h)))
                        rec.append(('PARENT', ((nx, ny), (x, y))))
Beispiel #3
0
    def step(self, record=None):
        """Starts the computation of the shortest path.
        *Note* : 
            This function works as a generator, a yield statement 
            is appended at the bottom of each loop to make this 
            function capable of being executed step by step.

            If you does not want the step feature, simply delete 
            the yield statements.

        :Parameters:
            record : deque or list
                if a queue is specified, a record of each operation 
                (OPEN, CLOSE, etc) will be pushed into the queue.
        """
        # add the source node into the open list
        sx, sy = self.source
        self.nodes[sy][sx].g = 0
        self.nodes[sy][sx].f = 0
        self.open_list.append(_QNode(self.source, self.nodes))
        self.nodes[sy][sx].status = OPENED

        # while the open list is not empty
        while self.open_list:

            # get the node with lowest F from the heap
            x, y = heappop(self.open_list).pos
            self.nodes[y][x].status = CLOSED
            if record != None:
                record.append(('CLOSE', (x, y)))

            # if the node is the target, reconstruct the path
            # and break the loop
            if (x, y) == self.target:
                self._retrace()
                break

            # inspect the horizontal and vertical adjacent nodes
            for i in xrange(len(XOFFSET)):

                # next x and y
                nx = x + XOFFSET[i]
                ny = y + YOFFSET[i]

                # if the next coordinate is walkable, inspect it.
                if is_walkable(nx, ny, self.n_row, self.n_col, self.graph):
                    self._inspect_node((nx, ny), (x, y), False, record)

                    # further investigate the diagonal nodes
                    nx1 = x + DAXOFFSET[i]
                    ny1 = y + DAYOFFSET[i]
                    nx2 = x + DBXOFFSET[i]
                    ny2 = y + DBYOFFSET[i]
                    npos = ((nx1, ny1), (nx2, ny2))
                    for nx, ny in npos:
                        if is_walkable(nx, ny, self.n_row, self.n_col,
                                       self.graph):
                            self._inspect_node((nx, ny), (x, y), True, record)
            yield
Beispiel #4
0
    def _expand_target(self, rec):
        """Searches from the target. Until it meets a node which 
        has been visited by the other tree.
        """
        # the procedure is identical with _expand_source.
        v, (x, y) = heappop(self.queue_target)
        node = self.nodes[y][x]
        diagonal_can = []
        if rec != None:
            rec.append(('CLOSE', (x, y)))
        for i in xrange(len(XOFFSET)):
            nx = x + XOFFSET[i]
            ny = y + YOFFSET[i]
            if is_walkable(nx, ny, self.n_row, self.n_col, self.graph):
                diagonal_can.append(i)
                if self.nodes[ny][nx].visited_by == CTARGET:
                    continue
                nxt_node = self.nodes[ny][nx]
                if nxt_node.visited_by == CSOURCE:
                    if rec:
                        rec.append(('CLOSE', (nx, ny)))
                    self._retrace((nx, ny), (x, y))
                    self.success = True
                    return
                nxt_node.visited_by = CTARGET
                nxt_node.h = node.h + DIST
                nxt_node.parent = (x, y)
                heappush(self.queue_target, (nxt_node.h, (nx, ny)))
                if rec != None:
                    rec.append(('OPEN', (nx, ny)))
                    rec.append(('VALUE', ('h', (nx, ny), nxt_node.h)))
                    rec.append(('PARENT', ((nx, ny), (x, y))))

        # further investigate the diagonal nodes
        for i in diagonal_can:
            nx1 = x + DAXOFFSET[i]
            ny1 = y + DAYOFFSET[i]
            nx2 = x + DBXOFFSET[i]
            ny2 = y + DBYOFFSET[i]
            npos = ((nx1, ny1), (nx2, ny2))
            for nx, ny in npos:
                if is_walkable(nx, ny, self.n_row, self.n_col,
                     self.graph) and \
                     self.nodes[ny][nx].visited_by != CTARGET:
                    nxt_node = self.nodes[ny][nx]
                    if nxt_node.visited_by == CSOURCE:
                        if rec:
                            rec.append(('CLOSE', (nx, ny)))
                        self._retrace((nx, ny), (x, y))
                        self.success = True
                        return
                    nxt_node.visited_by = CTARGET
                    nxt_node.h = node.h + DDIST
                    nxt_node.parent = (x, y)
                    heappush(self.queue_target, (nxt_node.h, (nx, ny)))
                    if rec != None:
                        rec.append(('OPEN', (nx, ny)))
                        rec.append(('VALUE', ('h', (nx, ny), nxt_node.h)))
                        rec.append(('PARENT', ((nx, ny), (x, y))))
    def _expand_source(self, rec):
        """Searches from the source. Until it meets a node which 
        has been visited by the other tree.
        """
        # take the first node from the source queue
        v, (x, y) = heappop(self.queue_source)
        node = self.nodes[y][x]

        diagonal_can = [] # stores the diagonal positions that can be accessed

        if rec != None:
            rec.append(('CLOSE', (x, y)))

        # inspect horizontally and vertically adjacent nodes
        for i in xrange(len(XOFFSET)):
            nx = x + XOFFSET[i]
            ny = y + YOFFSET[i]
            if is_walkable(nx, ny, self.n_row, self.n_col, 
                    self.graph):
                # if this node can be accessed, then then correponding
                # diagonal node can be accessed.
                diagonal_can.append(i)

                nxt_node = self.nodes[ny][nx]
                # if this node has been visited by source queue before,
                # then there's no need to inspect it again.
                if nxt_node.visited_by == CSOURCE:
                    continue
                
                # if this node has been visited by *target* queue.
                # Then a path from source to target exists.
                # Reconstructs the path and return.
                if nxt_node.visited_by == CTARGET:
                    if rec:
                        rec.append(('CLOSE', (nx, ny)))
                    self._retrace((x, y), (nx, ny))
                    self.success = True
                    return 
                
                # mark this node and update its info, then push the node
                # into the source queue
                nxt_node.visited_by = CSOURCE
                nxt_node.g = node.g + DIST
                nxt_node.parent = (x, y)
                heappush(self.queue_source, (nxt_node.g, (nx, ny)))

                if rec != None:
                    rec.append(('OPEN', (nx, ny)))
                    rec.append(('VALUE', ('g', (nx, ny), nxt_node.g)))
                    rec.append(('PARENT', ((nx, ny), (x, y))))

        # further investigate the diagonal nodes, the procedure is identical
        # with above
        for i in diagonal_can:
            nx1 = x + DAXOFFSET[i]
            ny1 = y + DAYOFFSET[i]
            nx2 = x + DBXOFFSET[i]
            ny2 = y + DBYOFFSET[i]
            npos = ((nx1, ny1), (nx2, ny2))
            for nx, ny in npos:
                if is_walkable(nx, ny, self.n_row, self.n_col,
                     self.graph) and \
                     self.nodes[ny][nx].visited_by != CSOURCE:
                    nxt_node = self.nodes[ny][nx]
                    if nxt_node.visited_by == CTARGET:
                        if rec:
                            rec.append(('CLOSE', (nx, ny)))
                        self._retrace((x, y), (nx, ny))
                        self.success = True
                        return 
                    nxt_node.visited_by = CSOURCE
                    nxt_node.g = node.g + DDIST
                    nxt_node.parent = (x, y)
                    heappush(self.queue_source, (nxt_node.g, (nx, ny)))
                    if rec != None:
                        rec.append(('OPEN', (nx, ny)))
                        rec.append(('VALUE', ('g', (nx, ny), 
                            nxt_node.g)))
                        rec.append(('PARENT', ((nx, ny), (x, y))))
Beispiel #6
0
    def _expand_source(self, rec):
        """Searches from the source. Until it meets a node which 
        has been visited by the other tree.
        """
        # take the first node from the source queue
        v, (x, y) = heappop(self.queue_source)
        node = self.nodes[y][x]

        diagonal_can = []  # stores the diagonal positions that can be accessed

        if rec != None:
            rec.append(('CLOSE', (x, y)))

        # inspect horizontally and vertically adjacent nodes
        for i in xrange(len(XOFFSET)):
            nx = x + XOFFSET[i]
            ny = y + YOFFSET[i]
            if is_walkable(nx, ny, self.n_row, self.n_col, self.graph):
                # if this node can be accessed, then then correponding
                # diagonal node can be accessed.
                diagonal_can.append(i)

                nxt_node = self.nodes[ny][nx]
                # if this node has been visited by source queue before,
                # then there's no need to inspect it again.
                if nxt_node.visited_by == CSOURCE:
                    continue

                # if this node has been visited by *target* queue.
                # Then a path from source to target exists.
                # Reconstructs the path and return.
                if nxt_node.visited_by == CTARGET:
                    if rec:
                        rec.append(('CLOSE', (nx, ny)))
                    self._retrace((x, y), (nx, ny))
                    self.success = True
                    return

                # mark this node and update its info, then push the node
                # into the source queue
                nxt_node.visited_by = CSOURCE
                nxt_node.g = node.g + DIST
                nxt_node.parent = (x, y)
                heappush(self.queue_source, (nxt_node.g, (nx, ny)))

                if rec != None:
                    rec.append(('OPEN', (nx, ny)))
                    rec.append(('VALUE', ('g', (nx, ny), nxt_node.g)))
                    rec.append(('PARENT', ((nx, ny), (x, y))))

        # further investigate the diagonal nodes, the procedure is identical
        # with above
        for i in diagonal_can:
            nx1 = x + DAXOFFSET[i]
            ny1 = y + DAYOFFSET[i]
            nx2 = x + DBXOFFSET[i]
            ny2 = y + DBYOFFSET[i]
            npos = ((nx1, ny1), (nx2, ny2))
            for nx, ny in npos:
                if is_walkable(nx, ny, self.n_row, self.n_col,
                     self.graph) and \
                     self.nodes[ny][nx].visited_by != CSOURCE:
                    nxt_node = self.nodes[ny][nx]
                    if nxt_node.visited_by == CTARGET:
                        if rec:
                            rec.append(('CLOSE', (nx, ny)))
                        self._retrace((x, y), (nx, ny))
                        self.success = True
                        return
                    nxt_node.visited_by = CSOURCE
                    nxt_node.g = node.g + DDIST
                    nxt_node.parent = (x, y)
                    heappush(self.queue_source, (nxt_node.g, (nx, ny)))
                    if rec != None:
                        rec.append(('OPEN', (nx, ny)))
                        rec.append(('VALUE', ('g', (nx, ny), nxt_node.g)))
                        rec.append(('PARENT', ((nx, ny), (x, y))))