Source code for queueing_tool.queues.agents

from numpy import infty
from numpy.random import uniform

from queueing_tool.queues.choice import _choice, _argmin


[docs]class Agent(object): """The base class for an agent. ``Agents`` are the objects that move throughout the network. ``Agents`` are instantiated by a queue, and once serviced the ``Agent`` moves on to another queue in the network. Each ``Agent`` *decides* where in the network it wants to arrive at next but choosing amongst its options randomly. The probabilities are specified in :class:`QueueNetwork's<.QueueNetwork>` transition matrix. See :meth:`.set_transitions` for changing the routing probabilities. Parameters ---------- agent_id : tuple (optional, default: ``(0, 0)``) A unique identifier for an agent. Is set automatically by the :class:`.QueueServer` that instantiates the ``Agent``. The first slot is the :class:`QueueServer's<.QueueServer>` edge index and the second slot is the ``Agent's`` instantiation number for that queue. **kwargs : Unused. Attributes ---------- agent_id : tuple A unique identifier for an agent. blocked : int Specifies how many times an agent has been blocked by a finite capacity queue. """ def __init__(self, agent_id=(0, 0), **kwargs): self.agent_id = agent_id self.blocked = 0 self._time = 0 # The agents arrival or departure time def __repr__(self): return "Agent; agent_id:{0}. time: {1}".format(self.agent_id, round(self._time, 3)) def __lt__(self, b): return self._time < b._time def __gt__(self, b): return self._time > b._time def __eq__(self, b): return self._time == b._time def __le__(self, b): return self._time <= b._time def __ge__(self, b): return self._time >= b._time
[docs] def add_loss(self, *args, **kwargs): """Adds one to the number of times the agent has been blocked from entering a queue. """ self.blocked += 1
[docs] def desired_destination(self, network, edge): """Returns the agents next destination given their current location on the network. An ``Agent`` chooses one of the out edges at random. The probability that the ``Agent`` will travel along a specific edge is specified in the :class:`QueueNetwork's<.QueueNetwork>` transition matrix. Parameters ---------- network : :class:`.QueueNetwork` The :class:`.QueueNetwork` where the Agent resides. edge : tuple A 4-tuple indicating which edge this agent is located at. The first two slots indicate the current edge's source and target vertices, while the third slot indicates this edges ``edge_index``. The last slot indicates the edge type of that edge Returns ------- out : int Returns an the edge index corresponding to the agents next edge to visit in the network. See Also -------- :meth:`.transitions` : :class:`QueueNetwork's<.QueueNetwork>` method that returns the transition probabilities for each edge in the graph. """ n = len(network.out_edges[edge[1]]) if n <= 1: return network.out_edges[edge[1]][0] u = uniform() pr = network._route_probs[edge[1]] k = _choice(pr, u, n) # _choice returns an integer between 0 and n-1 where the # probability of k being selected is equal to pr[k]. return network.out_edges[edge[1]][k]
[docs] def queue_action(self, queue, *args, **kwargs): """A method that acts on the queue the Agent is at. This method is called when the Agent arrives at the queue (where ``args[0] == 0``), when service starts for the Agent (where ``args[0] == 1``), and when the Agent departs from the queue (where ``args[0] == 2``). By default, this method does nothing to the queue, but is here if the Agent class is extended and this method is overwritten. """ pass
[docs]class GreedyAgent(Agent): """An agent that chooses the queue with the shortest line as their next destination. Notes ----- If there are any ties, the ``GreedyAgent`` chooses the first queue with the shortest line (where the ordering is given by :class:`QueueNetwork's<.QueueNetwork>` ``out_edges`` attribute). """ def __init__(self, agent_id=(0, 0)): Agent.__init__(self, agent_id) def __repr__(self): msg = "GreedyAgent; agent_id:{0}. time: {1}" return msg.format(self.agent_id, round(self._time, 3))
[docs] def desired_destination(self, network, edge): """Returns the agents next destination given their current location on the network. ``GreedyAgents`` choose their next destination with-in the network by picking the adjacent queue with the fewest number of :class:`Agents<.Agent>` in the queue. Parameters ---------- network : :class:`.QueueNetwork` The :class:`.QueueNetwork` where the Agent resides. edge : tuple A 4-tuple indicating which edge this agent is located at. The first two slots indicate the current edge's source and target vertices, while the third slot indicates this edges ``edge_index``. The last slot indicates the edges edge type. Returns ------- out : int Returns an the edge index corresponding to the agents next edge to visit in the network. """ adjacent_edges = network.out_edges[edge[1]] d = _argmin([network.edge2queue[d].number_queued() for d in adjacent_edges]) return adjacent_edges[d]
class InftyAgent(object): """An special agent that only operates within the :class:`.QueueServer` class. This agent never interacts with the :class:`.QueueNetwork`. """ def __init__(self): self._time = infty def __repr__(self): return "InftyAgent" def __lt__(self, b): return self._time < b._time def __gt__(self, b): return self._time > b._time def __eq__(self, b): return self._time == b._time