Files
CSC110/10-simulation/05-simulation.html
T
Hykilpikonna 6fffdf686a deploy
2021-12-07 22:28:01 -05:00

277 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>10.5 Creating a Discrete-Event Simulation</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<link rel="stylesheet" href="../tufte.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<div style="display:none">
\(
\newcommand{\NOT}{\neg}
\newcommand{\AND}{\wedge}
\newcommand{\OR}{\vee}
\newcommand{\XOR}{\oplus}
\newcommand{\IMP}{\Rightarrow}
\newcommand{\IFF}{\Leftrightarrow}
\newcommand{\TRUE}{\text{True}\xspace}
\newcommand{\FALSE}{\text{False}\xspace}
\newcommand{\IN}{\,{\in}\,}
\newcommand{\NOTIN}{\,{\notin}\,}
\newcommand{\TO}{\rightarrow}
\newcommand{\DIV}{\mid}
\newcommand{\NDIV}{\nmid}
\newcommand{\MOD}[1]{\pmod{#1}}
\newcommand{\MODS}[1]{\ (\text{mod}\ #1)}
\newcommand{\N}{\mathbb N}
\newcommand{\Z}{\mathbb Z}
\newcommand{\Q}{\mathbb Q}
\newcommand{\R}{\mathbb R}
\newcommand{\C}{\mathbb C}
\newcommand{\cA}{\mathcal A}
\newcommand{\cB}{\mathcal B}
\newcommand{\cC}{\mathcal C}
\newcommand{\cD}{\mathcal D}
\newcommand{\cE}{\mathcal E}
\newcommand{\cF}{\mathcal F}
\newcommand{\cG}{\mathcal G}
\newcommand{\cH}{\mathcal H}
\newcommand{\cI}{\mathcal I}
\newcommand{\cJ}{\mathcal J}
\newcommand{\cL}{\mathcal L}
\newcommand{\cK}{\mathcal K}
\newcommand{\cN}{\mathcal N}
\newcommand{\cO}{\mathcal O}
\newcommand{\cP}{\mathcal P}
\newcommand{\cQ}{\mathcal Q}
\newcommand{\cS}{\mathcal S}
\newcommand{\cT}{\mathcal T}
\newcommand{\cV}{\mathcal V}
\newcommand{\cW}{\mathcal W}
\newcommand{\cZ}{\mathcal Z}
\newcommand{\emp}{\emptyset}
\newcommand{\bs}{\backslash}
\newcommand{\floor}[1]{\left \lfloor #1 \right \rfloor}
\newcommand{\ceil}[1]{\left \lceil #1 \right \rceil}
\newcommand{\abs}[1]{\left | #1 \right |}
\newcommand{\xspace}{}
\newcommand{\proofheader}[1]{\underline{\textbf{#1}}}
\)
</div>
<header id="title-block-header">
<h1 class="title">10.5 Creating a Discrete-Event Simulation</h1>
</header>
<section>
<p>Lets put together all of the classes weve designed over the course of this chapter to create a full simulation our of food delivery system. In this section, well first learn about how the main simulation loop works. Then, well turn our attention to the possible ways a simulation can be configured, and how to incorporate these configuration options as part of the public interface of a class.</p>
<h2 id="the-main-simulation-loop">The main simulation loop</h2>
<p>Before we get to creating a full simulation class, well discuss how our simulation works. The type of simulation were learning about is called a <strong>discrete-event simulation</strong>, because it is driven by individual events occurring at specified periods of time.</p>
<p>A discrete-event simulation runs as follows:</p>
<ol type="1">
<li>It keeps track of a collection of events, which begins with some initial events. The collection is a <em>priority queue</em>, where an events priority is its timestamp (earlier timestamps mean higher priority).</li>
<li>The highest-priority event (i.e., the one with the earliest timestamp) is removed and processed. Any new events it generates are added to the priority queue.</li>
<li>Step 2 repeats until there are no events left.</li>
</ol>
<p>The algorithm is remarkably simple, though it does rely on a slightly modified version of our <em>priority queue</em> implementation from <a href="" title="../09-abstraction/07-priority-queues.html">Section 9.7</a>.<label for="sn-0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0" class="margin-toggle"/><span class="sidenote">In that section, we used <code>int</code>s to represent priority, while here were using <code>datetime.datetime</code> values.</span> Assuming we have such an implementation called <code>EventQueueList</code>, here is how we could write a simple function that runs this simulation loop:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">def</span> run_simulation(initial_events: <span class="bu">list</span>[Event], system: FoodDeliverySystem) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb1-2"><a href="#cb1-2"></a> events <span class="op">=</span> EventQueueList() <span class="co"># Initialize an empty priority queue of events</span></span>
<span id="cb1-3"><a href="#cb1-3"></a> <span class="cf">for</span> event <span class="kw">in</span> initial_events:</span>
<span id="cb1-4"><a href="#cb1-4"></a> events.enqueue(event)</span>
<span id="cb1-5"><a href="#cb1-5"></a></span>
<span id="cb1-6"><a href="#cb1-6"></a> <span class="co"># Repeatedly remove and process the next event</span></span>
<span id="cb1-7"><a href="#cb1-7"></a> <span class="cf">while</span> <span class="kw">not</span> events.is_empty():</span>
<span id="cb1-8"><a href="#cb1-8"></a> event <span class="op">=</span> events.dequeue()</span>
<span id="cb1-9"><a href="#cb1-9"></a></span>
<span id="cb1-10"><a href="#cb1-10"></a> new_events <span class="op">=</span> event.handle_event(system)</span>
<span id="cb1-11"><a href="#cb1-11"></a> <span class="cf">for</span> new_event <span class="kw">in</span> new_events:</span>
<span id="cb1-12"><a href="#cb1-12"></a> events.enqueue(new_event)</span></code></pre></div>
<p>The main reason for this implementations simplicity is abstraction. Remember that <code>Event</code> is an abstract class; the complex behaviour of how different events are handled is deferred to its concrete subclasses via our calls to <code>event.handle_event</code>. Our <code>run_simulation</code> function is <em>polymorphic</em>: it works regardless of what <code>Event</code> instances its given in its <code>initial_events</code> parameter, or what new events are generated and stored in <code>new_events</code>. The only thing our function needs to be able to do is call the <code>handle_event</code> method on each event object, which we can assume is present because it is defined in the <code>Event</code> public interface.</p>
<h2 id="a-simulation-class">A simulation class</h2>
<p>Next, we will take our <code>run_simulation</code> in the previous section and “wrap” it inside a new class. This isnt necessary to the running of the simulation, but is a standard practice in an object-oriented design, and makes it easier to both configure the simulation parameters and report results after the simulation is complete.</p>
<p>Were going to begin with a sketch of a class to represent our simulation:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">class</span> FoodDeliverySimulation:</span>
<span id="cb2-2"><a href="#cb2-2"></a> <span class="co">&quot;&quot;&quot;A simulation of the food delivery system.</span></span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-4"><a href="#cb2-4"></a> <span class="co"># Private Instance Attributes:</span></span>
<span id="cb2-5"><a href="#cb2-5"></a> <span class="co"># - _system: The FoodDeliverySystem instance that this simulation uses.</span></span>
<span id="cb2-6"><a href="#cb2-6"></a> <span class="co"># - _events: A collection of the events to process during the simulation.</span></span>
<span id="cb2-7"><a href="#cb2-7"></a> _system: FoodDeliverySystem</span>
<span id="cb2-8"><a href="#cb2-8"></a> _events: EventQueue</span>
<span id="cb2-9"><a href="#cb2-9"></a></span>
<span id="cb2-10"><a href="#cb2-10"></a> <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>, start_time: datetime.datetime, num_days: <span class="bu">int</span>,</span>
<span id="cb2-11"><a href="#cb2-11"></a> num_couriers: <span class="bu">int</span>, num_customers: <span class="bu">int</span>,</span>
<span id="cb2-12"><a href="#cb2-12"></a> num_restaurants: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-13"><a href="#cb2-13"></a> <span class="co">&quot;&quot;&quot;Initialize a new simulation with the given simulation parameters.</span></span>
<span id="cb2-14"><a href="#cb2-14"></a></span>
<span id="cb2-15"><a href="#cb2-15"></a><span class="co"> start_time: the starting time of the simulation</span></span>
<span id="cb2-16"><a href="#cb2-16"></a><span class="co"> num_days: the number of days that the simulation runs</span></span>
<span id="cb2-17"><a href="#cb2-17"></a><span class="co"> num_couriers: the number of couriers in the system</span></span>
<span id="cb2-18"><a href="#cb2-18"></a><span class="co"> num_customers: the number of customers in the system</span></span>
<span id="cb2-19"><a href="#cb2-19"></a><span class="co"> num_restaurants: the number of restaurants in the system</span></span>
<span id="cb2-20"><a href="#cb2-20"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-21"><a href="#cb2-21"></a> <span class="va">self</span>._events <span class="op">=</span> EventQueueList()</span>
<span id="cb2-22"><a href="#cb2-22"></a> <span class="va">self</span>._system <span class="op">=</span> FoodDeliverySystem()</span>
<span id="cb2-23"><a href="#cb2-23"></a></span>
<span id="cb2-24"><a href="#cb2-24"></a> <span class="va">self</span>._populate_initial_events(start_time, num_days)</span>
<span id="cb2-25"><a href="#cb2-25"></a> <span class="va">self</span>._generate_system(num_couriers, num_customers, num_restaurants)</span>
<span id="cb2-26"><a href="#cb2-26"></a></span>
<span id="cb2-27"><a href="#cb2-27"></a> <span class="kw">def</span> _populate_initial_events(<span class="va">self</span>, start_time: datetime.datetime, num_days: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-28"><a href="#cb2-28"></a> <span class="co">&quot;&quot;&quot;Populate this simulation&#39;s Event priority queue with GenerateOrdersEvents.</span></span>
<span id="cb2-29"><a href="#cb2-29"></a></span>
<span id="cb2-30"><a href="#cb2-30"></a><span class="co"> One new GenerateOrderEvent is generated per day, starting with start_time and</span></span>
<span id="cb2-31"><a href="#cb2-31"></a><span class="co"> repeating num_days times.</span></span>
<span id="cb2-32"><a href="#cb2-32"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-33"><a href="#cb2-33"></a></span>
<span id="cb2-34"><a href="#cb2-34"></a> <span class="kw">def</span> _generate_system(<span class="va">self</span>, num_couriers: <span class="bu">int</span>, num_customers: <span class="bu">int</span>, num_restaurants: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-35"><a href="#cb2-35"></a> <span class="co">&quot;&quot;&quot;Populate this simulation&#39;s FoodDeliverySystem with the specified number of entities.</span></span>
<span id="cb2-36"><a href="#cb2-36"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-37"><a href="#cb2-37"></a></span>
<span id="cb2-38"><a href="#cb2-38"></a> <span class="kw">def</span> run(<span class="va">self</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb2-39"><a href="#cb2-39"></a> <span class="co">&quot;&quot;&quot;Run this simulation.</span></span>
<span id="cb2-40"><a href="#cb2-40"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb2-41"><a href="#cb2-41"></a> <span class="cf">while</span> <span class="kw">not</span> <span class="va">self</span>._events.is_empty():</span>
<span id="cb2-42"><a href="#cb2-42"></a> event <span class="op">=</span> <span class="va">self</span>._events.dequeue()</span>
<span id="cb2-43"><a href="#cb2-43"></a></span>
<span id="cb2-44"><a href="#cb2-44"></a> new_events <span class="op">=</span> event.handle_event(<span class="va">self</span>._system)</span>
<span id="cb2-45"><a href="#cb2-45"></a> <span class="cf">for</span> new_event <span class="kw">in</span> new_events:</span>
<span id="cb2-46"><a href="#cb2-46"></a> <span class="va">self</span>._events.enqueue(new_event)</span></code></pre></div>
<p>There are a few key items to note in this (incomplete) implementation:</p>
<ol type="1">
<li><p>The <code>run_simulation</code> method has been renamed to simply <code>run</code>, since its a method in the <code>FoodDeliverySimulation</code> class.</p></li>
<li><p>The local variable <code>events</code> and parameter <code>system</code> from the function are now instance attributes for the <code>FoodDeliverySimulation</code> class, and have been moved out of the <code>run</code> method entirely. Its the job of <code>FoodDeliverySimulation.__init__</code> to initialize these objects.</p></li>
<li><p>The initializer takes in several parameters representing <em>configuration values</em> for the simulation. It then uses these values in two helper methods to initialize the <code>_system</code> and <code>_events</code> objects. These methods are marked private (named with a leading underscore) because theyre only meant to be called by the initializer, and not code outside of the class.</p>
<p>Here is how we could use the <code>FoodDeliverySimulation</code> class:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1"></a><span class="op">&gt;&gt;&gt;</span> simulation <span class="op">=</span> FoodDeliverySimulation(datetime.datetime(<span class="dv">2020</span>, <span class="dv">11</span>, <span class="dv">30</span>), <span class="dv">7</span>, <span class="dv">4</span>, <span class="dv">100</span>, <span class="dv">50</span>)</span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="op">&gt;&gt;&gt;</span> simulation.run()</span></code></pre></div></li>
</ol>
<p>Next, well briefly discuss one way to implement each of the two key helper methods for the initializer, <code>_populate_initial_events</code> and <code>_generate_system</code>.</p>
<h3 id="populating-initial-events">Populating initial events</h3>
<p>The key idea for our first helper method is that given a start time and a number of days, our initial events will be a series of <code>GenerateOrderEvents</code> that will generate <code>NewOrderEvents</code> when they are processed. Here is the basic skeleton, which will be leave as an exercise for you to complete:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1"></a> <span class="kw">def</span> _populate_initial_events(<span class="va">self</span>, start_time: datetime.datetime, num_days: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb4-2"><a href="#cb4-2"></a> <span class="co">&quot;&quot;&quot;Populate this simulation&#39;s Event priority queue with GenerateOrdersEvents.</span></span>
<span id="cb4-3"><a href="#cb4-3"></a></span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="co"> One new GenerateOrderEvent is generated per day, starting with start_time and</span></span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="co"> repeating num_days times.</span></span>
<span id="cb4-6"><a href="#cb4-6"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb4-7"><a href="#cb4-7"></a> <span class="cf">for</span> day <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, num_days):</span>
<span id="cb4-8"><a href="#cb4-8"></a> <span class="co"># 1. Create a GenerateOrderEvent for the given day after the start time.</span></span>
<span id="cb4-9"><a href="#cb4-9"></a></span>
<span id="cb4-10"><a href="#cb4-10"></a> <span class="co"># 2. Enqueue the new event.</span></span></code></pre></div>
<h3 id="populating-the-system-entities">Populating the system entities</h3>
<p>The way that our simulation is currently set up, our <code>FoodDeliverySystem</code> instance will contain all restaurants, customers, and couriers before the events start being processed. That is, we assume that only <em>orders</em> are dynamic in our system; the restaurants, customers, and couriers do not change over time.</p>
<p>The easiest way to populate these three entity types is to randomly generate new instances of each of these classes. Weve shown an example with <code>Customer</code>s below.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1"></a> <span class="kw">def</span> _generate_system(<span class="va">self</span>, num_couriers: <span class="bu">int</span>, num_customers: <span class="bu">int</span>, num_restaurants: <span class="bu">int</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb5-2"><a href="#cb5-2"></a> <span class="co">&quot;&quot;&quot;Populate this simulation&#39;s FoodDeliverySystem with the specified number of entities.</span></span>
<span id="cb5-3"><a href="#cb5-3"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-4"><a href="#cb5-4"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">0</span>, num_customers):</span>
<span id="cb5-5"><a href="#cb5-5"></a> location <span class="op">=</span> _generate_location()</span>
<span id="cb5-6"><a href="#cb5-6"></a> customer <span class="op">=</span> Customer(<span class="ss">f&#39;Customer </span><span class="sc">{i}</span><span class="ss">&#39;</span>, location)</span>
<span id="cb5-7"><a href="#cb5-7"></a> <span class="va">self</span>._system.add_customer(customer)</span>
<span id="cb5-8"><a href="#cb5-8"></a></span>
<span id="cb5-9"><a href="#cb5-9"></a> <span class="co"># Couriers and Restaurants are similar</span></span>
<span id="cb5-10"><a href="#cb5-10"></a> ...</span>
<span id="cb5-11"><a href="#cb5-11"></a></span>
<span id="cb5-12"><a href="#cb5-12"></a></span>
<span id="cb5-13"><a href="#cb5-13"></a><span class="co"># Outside the class: helper for generating random locations in Toronto</span></span>
<span id="cb5-14"><a href="#cb5-14"></a>TORONTO_COORDS <span class="op">=</span> (<span class="fl">43.747743</span>, <span class="fl">43.691170</span>, <span class="op">-</span><span class="fl">79.633951</span>, <span class="op">-</span><span class="fl">79.176646</span>)</span>
<span id="cb5-15"><a href="#cb5-15"></a></span>
<span id="cb5-16"><a href="#cb5-16"></a></span>
<span id="cb5-17"><a href="#cb5-17"></a><span class="kw">def</span> _generate_location() <span class="op">-&gt;</span> <span class="bu">tuple</span>[<span class="bu">float</span>, <span class="bu">float</span>]:</span>
<span id="cb5-18"><a href="#cb5-18"></a> <span class="co">&quot;&quot;&quot;Return a randomly-generated location (latitude, longitude) within the Toronto bounds.</span></span>
<span id="cb5-19"><a href="#cb5-19"></a><span class="co"> &quot;&quot;&quot;</span></span>
<span id="cb5-20"><a href="#cb5-20"></a> <span class="cf">return</span> (random.uniform(TORONTO_COORDS[<span class="dv">0</span>], TORONTO_COORDS[<span class="dv">1</span>]),</span>
<span id="cb5-21"><a href="#cb5-21"></a> random.uniform(TORONTO_COORDS[<span class="dv">2</span>], TORONTO_COORDS[<span class="dv">3</span>]))</span></code></pre></div>
<h2 id="putting-it-all-together">Putting it all together</h2>
<p>After completing the implementation of these two helper methods, you are ready to run the simulation! Try doing the following in the Python console:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1"></a><span class="op">&gt;&gt;&gt;</span> simulation <span class="op">=</span> FoodDeliverySimulation(datetime.datetime(<span class="dv">2020</span>, <span class="dv">11</span>, <span class="dv">30</span>), <span class="dv">7</span>, <span class="dv">4</span>, <span class="dv">100</span>, <span class="dv">50</span>)</span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="op">&gt;&gt;&gt;</span> simulation.run()</span></code></pre></div>
<p>Of course, we arent printing anything out, and the <code>FoodDeliverySimualtion.run</code> method doesnt actually return anything. You are free to insert some <code>print</code> calls to see whether events are actually being processed, but thats not the only way to see the results of the simulation.</p>
<p>Once the simulation is complete, <code>self._system</code> will have accumulated several completed orders, as a <code>list[Order]</code>. We can access these values and perform any kind of computation on them we want, just like we did all the way back in Chapter 4!</p>
<p>For example, we might ask:</p>
<ul>
<li>How many orders were delivered in total?</li>
<li>What was the average number of orders delivered per courier?</li>
<li>For a given restaurant, which menu items were most popular?</li>
<li><em>What else can you come up with?</em></li>
</ul>
</section>
<footer>
<a href="https://www.teach.cs.toronto.edu/~csc110y/fall/notes/">CSC110 Course Notes Home</a>
</footer>
</body>
</html>