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
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))
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
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
def _get(self): return _heappop(self.queue)
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