Module spatial_inequality.optimization.holdout
Implements a "holdout queue" data structure, which allows for items to be conditionally held out from the results upon dequeing.
Expand source code
"""
Implements a "holdout queue" data structure, which allows for items to be
conditionally held out from the results upon dequeing.
"""
from queue import Queue
class _HoldoutQueueItemWrapper:
"""
Wrapper class for any item to be added onto HoldoutQueue. All instances of
this class allow storage of both an actual item and an associated (static)
tag.
Attributes:
__item (Object): Stored item.
__tag (Object): Stored tag.
"""
__item = None
__tag = None
def __init__(self, item, tag):
self.__item = item
self.__tag = tag
def get_data(self):
"""
Getter method for the stored (unmodified) item.
Returns:
Object: Unmodified stored item.
"""
return self.__item
def get_tag(self):
"""
Getter method for the stored item's tag.
Returns:
Object: Unmodified stored tag.
"""
return self.__tag
class HoldoutQueue:
"""
This class implements a holdout queue that, in addition to the functionality
of a standard (FIFO) queue, allows for filtering on items upon dequeue. More
specifically, instead of returning the first-most item in the queue, only
the first item that validates a specified filtering condition will be
dequeued. All other items will be held out as if the queue were empty,
preserving their initial order.
Internally, this class operates on top of two independent (FIFO) queues. The
first (i.e., primary queue) is where all items are either enqueued to or
dequeued from. The second queue (i.e., leftover queue) is where all items
dequeued from the former queue get enqueued in case they do not validate the
specified condition. When the primary queue becomes empty, then instances of
this class can be 'recycled', swapping the primary and leftover queues.
Attributes:
__primary_queue (Queue): Underlying primary queue.
__leftover_queue (Queue): Unerlying leftover queue.
__get_item_tag (function): Function to calculate an item's tag.
__is_valid (function): Function to validate an item (based on its tag).
Example:
>>> def is_even(n):
... return n%2 == 0
>>> holdout_queue = HoldoutQueue(is_valid=is_even)
>>> for i in range(5):
... holdout_queue.enqueue(i)
>>> print(holdout_queue.dequeue())
2
>>> print(holdout_queue.dequeue())
4
"""
__primary_queue = None
__leftover_queue = None
__get_item_tag = None
__is_valid = None
def __init__(self, get_item_tag=lambda x:x, is_valid=lambda x:True):
self.__primary_queue = Queue()
self.__leftover_queue = Queue()
self.__get_item_tag = get_item_tag
self.__is_valid = is_valid
def recycle(self):
"""
Recycles the holdout queue, swapping the primary and leftover queues.
"""
self.__primary_queue, self.__leftover_queue = self.__leftover_queue, self.__primary_queue
def enqueue(self, item):
"""
Wraps a new item with _HoldoutQueueItemWrapper and adds it at the end of
the holdout queue.
Args:
item (Object): Item to be added.
"""
item_wrapper = _HoldoutQueueItemWrapper(
item,
self.__get_item_tag(item)
)
self.__primary_queue.put(item_wrapper)
def get_primary_queue(self):
"""
Getter method for the holdout queue's primary queue.
Returns:
Queue: Primary queue.
"""
return self.__primary_queue
def dequeue(self):
"""
Retrieves the first valid _HoldoutQueueItemWrapper from the beginning of
the holdout queue.
Returns:
Object: First valid item from the primary queue, or None if primary
queue is empty.
"""
while True:
if self.__is_empty():
return None
item_wrapper = self.__primary_queue.get()
if self.__is_valid(item_wrapper):
return item_wrapper.get_data()
self.__leftover_queue.put(item_wrapper)
def __is_empty(self):
"""
Checks whether the primary queue is empty.
Returns:
bool: 'true' if primary queue is empty, 'false' otherwise.
"""
return self.__primary_queue.empty()
Classes
class HoldoutQueue (get_item_tag=<function HoldoutQueue.<lambda>>, is_valid=<function HoldoutQueue.<lambda>>)
-
This class implements a holdout queue that, in addition to the functionality of a standard (FIFO) queue, allows for filtering on items upon dequeue. More specifically, instead of returning the first-most item in the queue, only the first item that validates a specified filtering condition will be dequeued. All other items will be held out as if the queue were empty, preserving their initial order.
Internally, this class operates on top of two independent (FIFO) queues. The first (i.e., primary queue) is where all items are either enqueued to or dequeued from. The second queue (i.e., leftover queue) is where all items dequeued from the former queue get enqueued in case they do not validate the specified condition. When the primary queue becomes empty, then instances of this class can be 'recycled', swapping the primary and leftover queues.
Attributes
__primary_queue
:Queue
- Underlying primary queue.
__leftover_queue
:Queue
- Unerlying leftover queue.
__get_item_tag
:function
- Function to calculate an item's tag.
__is_valid
:function
- Function to validate an item (based on its tag).
Example
>>> def is_even(n): ... return n%2 == 0 >>> holdout_queue = HoldoutQueue(is_valid=is_even) >>> for i in range(5): ... holdout_queue.enqueue(i) >>> print(holdout_queue.dequeue()) 2 >>> print(holdout_queue.dequeue()) 4
Expand source code
class HoldoutQueue: """ This class implements a holdout queue that, in addition to the functionality of a standard (FIFO) queue, allows for filtering on items upon dequeue. More specifically, instead of returning the first-most item in the queue, only the first item that validates a specified filtering condition will be dequeued. All other items will be held out as if the queue were empty, preserving their initial order. Internally, this class operates on top of two independent (FIFO) queues. The first (i.e., primary queue) is where all items are either enqueued to or dequeued from. The second queue (i.e., leftover queue) is where all items dequeued from the former queue get enqueued in case they do not validate the specified condition. When the primary queue becomes empty, then instances of this class can be 'recycled', swapping the primary and leftover queues. Attributes: __primary_queue (Queue): Underlying primary queue. __leftover_queue (Queue): Unerlying leftover queue. __get_item_tag (function): Function to calculate an item's tag. __is_valid (function): Function to validate an item (based on its tag). Example: >>> def is_even(n): ... return n%2 == 0 >>> holdout_queue = HoldoutQueue(is_valid=is_even) >>> for i in range(5): ... holdout_queue.enqueue(i) >>> print(holdout_queue.dequeue()) 2 >>> print(holdout_queue.dequeue()) 4 """ __primary_queue = None __leftover_queue = None __get_item_tag = None __is_valid = None def __init__(self, get_item_tag=lambda x:x, is_valid=lambda x:True): self.__primary_queue = Queue() self.__leftover_queue = Queue() self.__get_item_tag = get_item_tag self.__is_valid = is_valid def recycle(self): """ Recycles the holdout queue, swapping the primary and leftover queues. """ self.__primary_queue, self.__leftover_queue = self.__leftover_queue, self.__primary_queue def enqueue(self, item): """ Wraps a new item with _HoldoutQueueItemWrapper and adds it at the end of the holdout queue. Args: item (Object): Item to be added. """ item_wrapper = _HoldoutQueueItemWrapper( item, self.__get_item_tag(item) ) self.__primary_queue.put(item_wrapper) def get_primary_queue(self): """ Getter method for the holdout queue's primary queue. Returns: Queue: Primary queue. """ return self.__primary_queue def dequeue(self): """ Retrieves the first valid _HoldoutQueueItemWrapper from the beginning of the holdout queue. Returns: Object: First valid item from the primary queue, or None if primary queue is empty. """ while True: if self.__is_empty(): return None item_wrapper = self.__primary_queue.get() if self.__is_valid(item_wrapper): return item_wrapper.get_data() self.__leftover_queue.put(item_wrapper) def __is_empty(self): """ Checks whether the primary queue is empty. Returns: bool: 'true' if primary queue is empty, 'false' otherwise. """ return self.__primary_queue.empty()
Methods
def dequeue(self)
-
Retrieves the first valid _HoldoutQueueItemWrapper from the beginning of the holdout queue.
Returns
Object
- First valid item from the primary queue, or None if primary queue is empty.
Expand source code
def dequeue(self): """ Retrieves the first valid _HoldoutQueueItemWrapper from the beginning of the holdout queue. Returns: Object: First valid item from the primary queue, or None if primary queue is empty. """ while True: if self.__is_empty(): return None item_wrapper = self.__primary_queue.get() if self.__is_valid(item_wrapper): return item_wrapper.get_data() self.__leftover_queue.put(item_wrapper)
def enqueue(self, item)
-
Wraps a new item with _HoldoutQueueItemWrapper and adds it at the end of the holdout queue.
Args
item
:Object
- Item to be added.
Expand source code
def enqueue(self, item): """ Wraps a new item with _HoldoutQueueItemWrapper and adds it at the end of the holdout queue. Args: item (Object): Item to be added. """ item_wrapper = _HoldoutQueueItemWrapper( item, self.__get_item_tag(item) ) self.__primary_queue.put(item_wrapper)
def get_primary_queue(self)
-
Getter method for the holdout queue's primary queue.
Returns
Queue
- Primary queue.
Expand source code
def get_primary_queue(self): """ Getter method for the holdout queue's primary queue. Returns: Queue: Primary queue. """ return self.__primary_queue
def recycle(self)
-
Recycles the holdout queue, swapping the primary and leftover queues.
Expand source code
def recycle(self): """ Recycles the holdout queue, swapping the primary and leftover queues. """ self.__primary_queue, self.__leftover_queue = self.__leftover_queue, self.__primary_queue