def test_add_and_discard(self): numbers = OrderedSet([1, 2, 3]) numbers.add(3) self.assertEqual(len(numbers), 3) numbers.add(4) self.assertEqual(len(numbers), 4) numbers.discard(4) self.assertEqual(len(numbers), 3) numbers.discard(4) self.assertEqual(len(numbers), 3) # Make sure the add method is efficient too! setup = "numbers = OrderedSet([])" time = partial(timeit, setup=setup, globals=globals(), number=100) small_set_time = time( dedent(""" add = numbers.add for n in [9999 for _ in range(1000)]: add(n) """)) large_set_time = time( dedent(""" add = numbers.add for n in [9999 + i for i in range(1000)]: add(n) """)) self.assertGreater(small_set_time * 30, large_set_time)
def test_add_and_discard(self): numbers = OrderedSet([1, 2, 3]) numbers.add(3) self.assertEqual(len(numbers), 3) numbers.add(4) self.assertEqual(len(numbers), 4) numbers.discard(4) self.assertEqual(len(numbers), 3) numbers.discard(4) self.assertEqual(len(numbers), 3)
class __TransactionSet: def __init__(self): """Initialize transaction store.""" self.store = OrderedSet() def add(self, transaction): self.store.add(transaction) def add_multiple(self, transaction_list): """Add multiple transactions to the set. Since the transactions are re-added to the set (they were in it once), we add them at the front of the existing set. """ transaction_list = OrderedSet(transaction_list) self.store = transaction_list.union(self.store) def contains(self, transaction): return self.store.__contains__(transaction) def pop(self): """Remove and return a transaction from the set.""" try: return self.store.pop(0) # Catch KeyError if set is empty except KeyError: return None def discard(self, transaction): """Remove the transaction if it was present in the set.""" self.store.discard(transaction) def discard_multiple(self, transaction_list): """Remove multiple transactions from the set.""" [self.discard(tx) for tx in transaction_list] def clear(self): """Remove all transactions from the set.""" self.store.clear() def __len__(self): return len(self.store) def __iter__(self): yield from self.store def __repr__(self): return self.store.__repr__()
def test_add_and_discard(self): numbers = OrderedSet([1, 2, 3]) numbers.add(3) self.assertEqual(len(numbers), 3) numbers.add(4) self.assertEqual(len(numbers), 4) numbers.discard(4) self.assertEqual(len(numbers), 3) numbers.discard(4) self.assertEqual(len(numbers), 3) # Make sure the add method is efficient too! with Timer() as small_set_timer: numbers = OrderedSet([]) for n in [9999 for _ in range(2000)]: numbers.add(n) with Timer() as large_set_timer: numbers2 = OrderedSet([]) for n in [9999 + i for i in range(2000)]: numbers2.add(n)
class Simulation: """Agent-based simulation.""" time: Timestamp agents: Set[TrafficDynamicAgent] active: Set[TrafficDynamicAgent] ready_buffer: int _queue: Deque[Tuple[Callable, Tuple]] _listeners = List[Listener] def __init__(self): self.time = 0 self.agents = OrderedSet() self.active = OrderedSet() self.ready_buffer = 0 self._queue = deque() self._listeners = [] @property def target_buffer(self) -> int: """Get index of current target buffer.""" return (self.ready_buffer + 1) % 2 def add(self, agent: TrafficDynamicAgent): """Add agent to the simulation.""" self.agents.add(agent) self.update_active_set(agent) self.raise_event('new_agent') def update(self, dt: Duration): """Update the simulation with time step of `dt`.""" ready = self.ready_buffer target = (ready + 1) % 2 for agent in self.active: agent.update(dt, ready, target) while self._queue: callable_, args = self._queue.popleft() callable_(*args) old_time = self.time self.time += dt self.flip_buffer() self.raise_event('simulation_step', dt) self._check_time_events(old_time) def _check_time_events(self, old_time: Timestamp): """Raise time events when appropriate.""" old_time, time = floor(old_time), floor(self.time) if old_time == time: return self.raise_event('passed_second') for timespan, event in TIME_EVENTS: if old_time // timespan == time // timespan: return self.raise_event(event) def flip_buffer(self): """Flip ready buffer index.""" self.ready_buffer = self.target_buffer def update_active_set(self, agent: TrafficDynamicAgent): """Activate or deactivate agent according to its `active` attribute. When an agent is activated or deactivated during update, this should be called instead of adding or removing directly from the active set, because the set is being iterated and cannot change during iteration. """ def _update_active_set(): if agent.active: self.active.add(agent) else: self.active.discard(agent) self.enqueue(_update_active_set) self.raise_event('active_set_updated') def remove(self, agent: TrafficDynamicAgent): """Remove agent from simulation.""" if agent in self.agents: self.agents.remove(agent) self.raise_event('removed_agent', agent) def enqueue(self, callable_: Callable, args: Tuple = ()): """Enqueue function to be called after update loop ends.""" self._queue.append((callable_, args)) def register_listener(self, listener: Listener): """Register listener to receive raised events.""" if listener not in self._listeners: self._listeners.append(listener) def raise_event(self, name: str, *args): """Raise event to all registered listeners.""" for listener in self._listeners: listener(name, *args)
class GraphBase(object): __metaclass__ = ABCMeta def __init__(self, name, master, namespace): assert isinstance(name, str) assert isinstance(master, Master) assert isinstance(namespace, GraphNamespaceMixin) self.name = "g"+name self.master = master self.namespace = namespace self.start_nodes = OrderedSet() self.end_nodes = OrderedSet() self.nodes = OrderedSet() self.edges = OrderedSet() def __repr_marks__(self): return "" def __repr__(self): return ("<%s#%s: %d(%d,%d) nodes, %d edges, in %s%s>" % (self.__class__.__name__, self.name, len(self.nodes), len(self.start_nodes), len(self.end_nodes), len(self.edges), self.namespace.ns_name, self.__repr_marks__())) def __str_parsenode__(self, node, included, ret_str): assert isinstance(node, NodeBase) assert isinstance(included, set) assert isinstance(ret_str, str) if node in included: return ret_str assert node.graph is self included.add(node) # print node blank = [" ", " "] if node.is_start: blank[0] = "+" if node.is_end: blank[1] = "-" ret_str += "\n%s%s" %("".join(blank), node.__repr_graph__()) # print edge for edge in node.edges: assert edge.graph is self ret_str += "\n %s" % edge.__repr_graph__() # recursive for edge in node.edges: ret_str = self.__str_parsenode__(edge.node, included, ret_str) return ret_str def __str__(self): ret_str = "%r:" % self included = set() for sn in self.start_nodes: ret_str = self.__str_parsenode__(sn, included, ret_str) if included-self.nodes: ret_str += "\nERROR EXTRA NODES: " +\ ",".join(n.name for n in included-self.nodes) if self.nodes-included: ret_str += "\nERROR UNSEEN NODES: " +\ ",".join(n.name for n in self.nodes-included) return ret_str @abstractmethod def _create_node_override(self, id_): pass @abstractmethod def _create_edge_override(self, to_node, payload): pass def create_edge_withnode(self, to_node, payload): assert isinstance(to_node, NodeBase) assert to_node.graph is self edge = self._create_edge_override(to_node, payload) self.edges.add(edge) return edge def create_edge_withnid(self, tonode_id, payload): to_node = self._create_node_override(tonode_id) self.nodes.add(to_node) edge = self.create_edge_withnode(to_node, payload) self.end_nodes.add(to_node) return edge, to_node def register_edge(self, from_node, edge): assert from_node in self.nodes assert edge in self.edges self.namespace._ns_register_edge(from_node, edge) self.end_nodes.discard(from_node)