Example #1
0
 def _n_nearest_items(self, n: int, point: _Point) -> _Iterator[_Item]:
     queue = [(0, 0, self._root)]
     while n and queue:
         _, _, node = _heappop(queue)
         for child in node.children:
             _heappush(queue,
                       (child.distance_to_point(point), -child.index -
                        1 if child.is_leaf else child.index, child))
         while n and queue and queue[0][1] < 0:
             _, _, node = _heappop(queue)
             yield node.item
             n -= 1
Example #2
0
def pythagorean_triples(n=None):
    """Generate n Pythagorean triples ordered by the value of c ascending. If n
    is None or not given, generate infinitly. Default is None.
    Examples:
    >>> list(pythagorean_triples(5))
    [(3, 4, 5), (5, 12, 13), (15, 8, 17), (7, 24, 25), (21, 20, 29)]
    """
    iterator = _count() if n is None else range(n)
    iterator = iter(iterator)

    base_mat = ((1, 2, 2),
            (2, 1, 2),
            (2, 2, 3))
    multiplier = ((1, -1, 1), (1, 1, 1), (-1, 1, 1))
    matrices = []
    for multip in multiplier:
        mat = []
        for row, elem in zip(base_mat, multip):
            mat.append(tuple(map(lambda e: e * elem, row)))
        matrices.append(tuple(mat))
    matrices = tuple(matrices)

    heap = [(5, (3, 4, 5))]
    for i in iterator:
        _, triple = _heappop(heap)
        yield triple
        for matrix in matrices:
            next_triple = tuple(map(lambda col: sum(_starmap(_mul,
                zip(triple, col))), zip(*matrix)))
            _heappush(heap, (next_triple[2], next_triple))
Example #3
0
    def nearest_item(self, point: _Point) -> _Item:
        """
        Searches for index with box in the tree
        the nearest to the given point.

        Time complexity:
            ``O(max_children * log size)``
        Memory complexity:
            ``O(max_children * log size)``

        where ``size = len(self.boxes)``,
        ``max_children = self.max_children``.

        :param point: input point.
        :returns:
            index with box in the tree the nearest to the input point.

        >>> from ground.base import get_context
        >>> context = get_context()
        >>> Box, Point = context.box_cls, context.point_cls
        >>> boxes = [Box(-index, index, 0, index) for index in range(1, 11)]
        >>> tree = Tree(boxes)
        >>> tree.nearest_item(Point(0, 0)) == (9, Box(-10, 10, 0, 10))
        True
        >>> tree.nearest_item(Point(-10, 0)) == (9, Box(-10, 10, 0, 10))
        True
        >>> tree.nearest_item(Point(-10, 10)) == (9, Box(-10, 10, 0, 10))
        True
        >>> tree.nearest_item(Point(10, 0)) == (9, Box(-10, 10, 0, 10))
        True
        >>> tree.nearest_item(Point(10, 10)) == (9, Box(-10, 10, 0, 10))
        True
        """
        queue = [(0, 0, self._root)]
        while queue:
            _, _, node = _heappop(queue)
            for child in node.children:
                _heappush(queue,
                          (child.distance_to_point(point), -child.index -
                           1 if child.is_leaf else child.index, child))
            if queue and queue[0][1] < 0:
                _, _, node = _heappop(queue)
                return node.item
Example #4
0
    def nearest_to_point_item(self, point: _Point) -> _Item:
        """
        Searches for index with segment in the tree
        the nearest to the given point.

        Time complexity:
            ``O(max_children * log size)``
        Memory complexity:
            ``O(max_children * log size)``

        where ``size = len(self.segments)``,
        ``max_children = self.max_children``.

        :param point: input point.
        :returns:
            index with segment in the tree the nearest to the input point.

        >>> from ground.base import get_context
        >>> context = get_context()
        >>> Point, Segment = context.point_cls, context.segment_cls
        >>> segments = [Segment(Point(0, index), Point(index, index))
        ...             for index in range(1, 11)]
        >>> tree = Tree(segments)
        >>> (tree.nearest_to_point_item(Point(0, 0))
        ...  == (0, Segment(Point(0, 1), Point(1, 1))))
        True
        """
        queue = [(0, 0, self._root)]
        while queue:
            _, _, node = _heappop(queue)
            for child in node.children:
                _heappush(queue,
                          (child.distance_to_point(point),
                           child.index if child.is_leaf else -child.index - 1,
                           child))
            if queue and queue[0][1] >= 0:
                _, _, node = _heappop(queue)
                return node.item
Example #5
0
 def _get(self):
     return _heappop(self.queue)
Example #6
0
    def call_scheduled_functions(self, dt):
        """Call scheduled functions that elapsed on the last `update_time`.

        .. versionadded:: 1.2

        :Parameters:
            dt : float
                The elapsed time since the last update to pass to each
                scheduled function.  This is *not* used to calculate which
                functions have elapsed.

        :rtype: bool
        :return: True if any functions were called, otherwise False.
        """
        now = self.last_ts
        result = False  # flag indicates if any function was called

        # handle items scheduled for every tick
        if self._schedule_items:
            result = True
            # duplicate list in case event unschedules itself
            for item in list(self._schedule_items):
                item.func(dt, *item.args, **item.kwargs)

        # check the next scheduled item that is not called each tick
        # if it is scheduled in the future, then exit
        interval_items = self._schedule_interval_items
        try:
            if interval_items[0].next_ts > now:
                return result

        # raised when the interval_items list is empty
        except IndexError:
            return result

        # NOTE: there is no special handling required to manage things
        #       that are scheduled during this loop, due to the heap
        self._current_interval_item = item = None
        get_soft_next_ts = self._get_soft_next_ts
        while interval_items:

            # the scheduler will hold onto a reference to an item in
            # case it needs to be rescheduled.  it is more efficient
            # to push and pop the heap at once rather than two operations
            if item is None:
                item = _heappop(interval_items)
            else:
                item = _heappushpop(interval_items, item)

            # a scheduled function may try and unschedule itself
            # so we need to keep a reference to the current
            # item no longer on heap to be able to check
            self._current_interval_item = item

            # if next item is scheduled in the future then break
            if item.next_ts > now:
                break

            # execute the callback
            try:
                item.func(now - item.last_ts, *item.args, **item.kwargs)
            except ReferenceError:
                pass  # weakly-referenced object no longer exists.

            if item.interval:

                # Try to keep timing regular, even if overslept this time;
                # but don't schedule in the past (which could lead to
                # infinitely-worsening error).
                item.next_ts = item.last_ts + item.interval
                item.last_ts = now

                # test the schedule for the next execution
                if item.next_ts <= now:
                    # the scheduled time of this item has already passed
                    # so it must be rescheduled
                    if now - item.next_ts < 0.05:
                        # missed execution time by 'reasonable' amount, so
                        # reschedule at normal interval
                        item.next_ts = now + item.interval
                    else:
                        # missed by significant amount, now many events have
                        # likely missed execution. do a soft reschedule to
                        # avoid lumping many events together.
                        # in this case, the next dt will not be accurate
                        item.next_ts = get_soft_next_ts(now, item.interval)
                        item.last_ts = item.next_ts - item.interval
            else:
                # not an interval, so this item will not be rescheduled
                self._current_interval_item = item = None

        if item is not None:
            _heappush(interval_items, item)

        return True
Example #7
0
 def _get(self):
     return _heappop(self.queue)