Enriching the graph code for discrete-event simulation

For those using a RSS reader, subscribe here: rss.xml

For discrete-event simulation, there is a connection between the event graph and the event handler. It is possible to enrich the description of the graph with the distributions for the scheduling. This has the advantage that the event handler can just call schedule from the current event to the event it wants to schedule, and the corresponding distribution will be looked up in the graph.

An example of this setup is shown here, it models a simple graph that spawns bananas. Each banana event spawns a single apple event which does nothing further. The event graph is visualized using a tikzpicture in LaTeX, so the additional information is added as comments.

\begin{tikzpicture}
  \node[ellipse, draw, minimum width=2.5cm, minimum height=2.5cm, align=center] (B) at (0,0) {Banana}
  \node[ellipse, draw, minimum width=2.5cm, minimum height=2.5cm, align=center] (A) at (4,0) {Apple}
  \draw[->] (B) to (A); % np.random.uniform(0, 10)
  \scheduleEventArrow{B} % Banana; 3; np.random.uniform(0, 80)
\end{tikzpicture}

All distributions should be specified for the graph, otherwise a warning is issued. This example uses standard distributions, drawn from the numpy library. Other types of distributions are also easily made, for example an empirical module can also be exposed besides numpy to support distributions based on the empirical data. That way they can be called the same way, so you would for example write empirical.random_arrival() as a comment.

The remaining event handler to write hooks into the information of the event graph. So when you call schedule_event(), you no longer have to specify the distribution; that was already provided in the event graph as comments.

global event_queue
global statistics

event_queue = []
statistics = []
sources = []
connections = []

with open("event_graph_sample.tex", 'r', encoding="UTF-8") as f:
  (sources, _, connections) = graph.read_event_graph(f.readlines())

def event_handler(event):
  if event['label'] == 'A':
    pass
  if event['label'] == 'B':
    schedule_event(event['label'], 'A', connections)

def update_statistics():
  statistics.append(model['time'])

run_model(lambda: queue_from_sources(sources), event_handler, update_statistics)