Bank Queue Simulation with SimPy: The Classic Example
<p>The bank queue is the "Hello World" of simulation. It's simple enough to understand, complex enough to be interesting, and applicable to dozens of other scenarios.</p> <h2 id="the-basic-bank-model">The Basic Bank Model</h2> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy</span> <span class="kn">import</span><span class="w"> </span><span class="nn">random</span> <span class="k">def</span><span class="w"> </span><span class="nf">customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">tellers</span><span class="p">,</span> <span class="n">stats</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Customer arrives, waits for teller, completes transaction."""</span> <span class="n">arrival</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="k">with</span> <span class="n">tellers</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="k">yield</span> <span class="n">req</span> <span class="n">wait</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">arrival</span> <span class="n">stats</span><span class="p">[</span><span class="s1">'waits'</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">wait</span><span class="p">)</span> <span class="c1"># Transaction time</span> <span class="n">transaction</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">5</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">transaction</span><span class="p">)</span> <span class="n">stats</span><span class="p">[</span><span class="s1">'transactions'</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">transaction</span><span class="p">)</span> <span class="n">stats</span><span class="p">[</span><span class="s1">'departures'</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">tellers</span><span class="p">,</span> <span class="n">stats</span><span class="p">,</span> <span class="n">arrival_rate</span><span class="p">):</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="n">arrival_rate</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"Customer </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">tellers</span><span class="p">,</span> <span class="n">stats</span><span class="p">))</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="c1"># Run simulation</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="n">tellers</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span> <span class="n">stats</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'waits'</span><span class="p">:</span> <span class="p">[],</span> <span class="s1">'transactions'</span><span class="p">:</span> <span class="p">[],</span> <span class="s1">'departures'</span><span class="p">:</span> <span class="p">[]}</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">tellers</span><span class="p">,</span> <span class="n">stats</span><span class="p">,</span> <span class="n">arrival_rate</span><span class="o">=</span><span class="mi">1</span><span class="o">/</span><span class="mi">2</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">480</span><span class="p">)</span> <span class="c1"># 8 hours</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Customers served: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">stats</span><span class="p">[</span><span class="s1">'waits'</span><span class="p">])</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Average wait: </span><span class="si">{</span><span class="nb">sum</span><span class="p">(</span><span class="n">stats</span><span class="p">[</span><span class="s1">'waits'</span><span class="p">])</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">stats</span><span class="p">[</span><span class="s1">'waits'</span><span class="p">])</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> minutes"</span><span class="p">)</span> </code></pre></div> <h2 id="multiple-transaction-types">Multiple Transaction Types</h2> <p>Different services take different times:</p> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">Bank</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">num_tellers</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">num_tellers</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span><span class="w"> </span><span class="nf">customer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">customer_id</span><span class="p">,</span> <span class="n">transaction_type</span><span class="p">):</span> <span class="n">arrival</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="n">transaction_times</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">'deposit'</span><span class="p">:</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="s1">'withdrawal'</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="s1">'loan_inquiry'</span><span class="p">:</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">),</span> <span class="s1">'account_opening'</span><span class="p">:</span> <span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span> <span class="p">}</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="k">yield</span> <span class="n">req</span> <span class="n">wait</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">arrival</span> <span class="n">min_t</span><span class="p">,</span> <span class="n">max_t</span> <span class="o">=</span> <span class="n">transaction_times</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">transaction_type</span><span class="p">,</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">))</span> <span class="n">service</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">uniform</span><span class="p">(</span><span class="n">min_t</span><span class="p">,</span> <span class="n">max_t</span><span class="p">)</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">service</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="o">.</span><span class="n">append</span><span class="p">({</span> <span class="s1">'customer'</span><span class="p">:</span> <span class="n">customer_id</span><span class="p">,</span> <span class="s1">'type'</span><span class="p">:</span> <span class="n">transaction_type</span><span class="p">,</span> <span class="s1">'wait'</span><span class="p">:</span> <span class="n">wait</span><span class="p">,</span> <span class="s1">'service'</span><span class="p">:</span> <span class="n">service</span> <span class="p">})</span> <span class="k">def</span><span class="w"> </span><span class="nf">arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">bank</span><span class="p">):</span> <span class="n">customer_id</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">types</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'deposit'</span><span class="p">,</span> <span class="s1">'withdrawal'</span><span class="p">,</span> <span class="s1">'loan_inquiry'</span><span class="p">,</span> <span class="s1">'account_opening'</span><span class="p">]</span> <span class="n">probs</span> <span class="o">=</span> <span class="p">[</span><span class="mf">0.4</span><span class="p">,</span> <span class="mf">0.35</span><span class="p">,</span> <span class="mf">0.15</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">]</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">3</span><span class="p">))</span> <span class="n">transaction_type</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">choices</span><span class="p">(</span><span class="n">types</span><span class="p">,</span> <span class="n">weights</span><span class="o">=</span><span class="n">probs</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">bank</span><span class="o">.</span><span class="n">customer</span><span class="p">(</span><span class="n">customer_id</span><span class="p">,</span> <span class="n">transaction_type</span><span class="p">))</span> <span class="n">customer_id</span> <span class="o">+=</span> <span class="mi">1</span> </code></pre></div> <h2 id="express-lane">Express Lane</h2> <p>Separate queue for quick transactions:</p> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">BankWithExpressLane</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">regular_tellers</span><span class="p">,</span> <span class="n">express_tellers</span><span class="p">,</span> <span class="n">express_threshold</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">regular</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">regular_tellers</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">express</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">express_tellers</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">express_threshold</span> <span class="o">=</span> <span class="n">express_threshold</span> <span class="c1"># Max service time for express</span> <span class="k">def</span><span class="w"> </span><span class="nf">customer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">customer_id</span><span class="p">,</span> <span class="n">expected_service</span><span class="p">):</span> <span class="n">arrival</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="c1"># Choose lane</span> <span class="k">if</span> <span class="n">expected_service</span> <span class="o"><=</span> <span class="bp">self</span><span class="o">.</span><span class="n">express_threshold</span><span class="p">:</span> <span class="n">teller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">express</span> <span class="n">lane</span> <span class="o">=</span> <span class="s2">"express"</span> <span class="k">else</span><span class="p">:</span> <span class="n">teller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">regular</span> <span class="n">lane</span> <span class="o">=</span> <span class="s2">"regular"</span> <span class="k">with</span> <span class="n">teller</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="k">yield</span> <span class="n">req</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">expected_service</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Customer </span><span class="si">{</span><span class="n">customer_id</span><span class="si">}</span><span class="s2"> served at </span><span class="si">{</span><span class="n">lane</span><span class="si">}</span><span class="s2"> lane, waited </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">arrival</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">expected_service</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> </code></pre></div> <h2 id="balking-and-reneging">Balking and Reneging</h2> <p>Customers who leave:</p> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">impatient_customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">tellers</span><span class="p">,</span> <span class="n">max_queue</span><span class="p">,</span> <span class="n">patience</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Customer may balk or renege."""</span> <span class="n">arrival</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="c1"># Balking: refuse to join long queue</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">tellers</span><span class="o">.</span><span class="n">queue</span><span class="p">)</span> <span class="o">>=</span> <span class="n">max_queue</span><span class="p">:</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> balked at </span><span class="si">{</span><span class="n">arrival</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2"> (queue too long)"</span><span class="p">)</span> <span class="k">return</span> <span class="s2">"balked"</span> <span class="k">with</span> <span class="n">tellers</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="c1"># Reneging: leave after waiting too long</span> <span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">req</span> <span class="o">|</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">patience</span><span class="p">)</span> <span class="k">if</span> <span class="n">req</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> <span class="c1"># Got served</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">5</span><span class="p">))</span> <span class="k">return</span> <span class="s2">"served"</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># Ran out of patience</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> reneged at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2"> (waited too long)"</span><span class="p">)</span> <span class="k">return</span> <span class="s2">"reneged"</span> </code></pre></div> <h2 id="vip-customers">VIP Customers</h2> <p>Priority service for special customers:</p> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">bank_with_vip</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">tellers</span><span class="p">):</span> <span class="k">def</span><span class="w"> </span><span class="nf">vip_customer</span><span class="p">(</span><span class="n">customer_id</span><span class="p">):</span> <span class="k">with</span> <span class="n">tellers</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="n">priority</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="c1"># High priority</span> <span class="k">yield</span> <span class="n">req</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">uniform</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"VIP </span><span class="si">{</span><span class="n">customer_id</span><span class="si">}</span><span class="s2"> served at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">regular_customer</span><span class="p">(</span><span class="n">customer_id</span><span class="p">):</span> <span class="k">with</span> <span class="n">tellers</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="n">priority</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="c1"># Lower priority</span> <span class="k">yield</span> <span class="n">req</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">uniform</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Regular </span><span class="si">{</span><span class="n">customer_id</span><span class="si">}</span><span class="s2"> served at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="c1"># VIP customers jump the queue</span> <span class="n">tellers</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">PriorityResource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span> </code></pre></div> <h2 id="peak-hours-modelling">Peak Hours Modelling</h2> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">time_varying_arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">bank</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Arrival rate varies by time of day."""</span> <span class="n">customer_id</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">hour</span> <span class="o">=</span> <span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">/</span> <span class="mi">60</span><span class="p">)</span> <span class="o">%</span> <span class="mi">24</span> <span class="c1"># Peak hours</span> <span class="k">if</span> <span class="mi">12</span> <span class="o"><=</span> <span class="n">hour</span> <span class="o"><=</span> <span class="mi">14</span><span class="p">:</span> <span class="c1"># Lunch rush</span> <span class="n">rate</span> <span class="o">=</span> <span class="mi">1</span><span class="o">/</span><span class="mi">1</span> <span class="c1"># 1 per minute</span> <span class="k">elif</span> <span class="mi">9</span> <span class="o"><=</span> <span class="n">hour</span> <span class="o"><=</span> <span class="mi">11</span> <span class="ow">or</span> <span class="mi">15</span> <span class="o"><=</span> <span class="n">hour</span> <span class="o"><=</span> <span class="mi">17</span><span class="p">:</span> <span class="n">rate</span> <span class="o">=</span> <span class="mi">1</span><span class="o">/</span><span class="mi">2</span> <span class="k">else</span><span class="p">:</span> <span class="n">rate</span> <span class="o">=</span> <span class="mi">1</span><span class="o">/</span><span class="mi">5</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="n">rate</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">bank</span><span class="o">.</span><span class="n">customer</span><span class="p">(</span><span class="n">customer_id</span><span class="p">))</span> <span class="n">customer_id</span> <span class="o">+=</span> <span class="mi">1</span> </code></pre></div> <h2 id="queue-display-board">Queue Display Board</h2> <p>Track and display queue status:</p> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">QueueDisplay</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">tellers</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span> <span class="o">=</span> <span class="n">tellers</span> <span class="bp">self</span><span class="o">.</span><span class="n">log</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span><span class="w"> </span><span class="nf">monitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">append</span><span class="p">({</span> <span class="s1">'time'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="p">,</span> <span class="s1">'waiting'</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">queue</span><span class="p">),</span> <span class="s1">'serving'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">count</span><span class="p">,</span> <span class="s1">'available'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">capacity</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">count</span> <span class="p">})</span> <span class="c1"># Estimate wait time</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">count</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">capacity</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">queue</span><span class="p">:</span> <span class="n">estimated_wait</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">queue</span><span class="p">)</span> <span class="o">*</span> <span class="mi">5</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">capacity</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"[</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">:</span><span class="s2">.0f</span><span class="si">}</span><span class="s2">] Queue: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">queue</span><span class="p">)</span><span class="si">}</span><span class="s2">, Est. wait: </span><span class="si">{</span><span class="n">estimated_wait</span><span class="si">:</span><span class="s2">.0f</span><span class="si">}</span><span class="s2"> min"</span><span class="p">)</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span> </code></pre></div> <h2 id="complete-bank-simulation">Complete Bank Simulation</h2> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy</span> <span class="kn">import</span><span class="w"> </span><span class="nn">random</span> <span class="kn">import</span><span class="w"> </span><span class="nn">numpy</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">np</span> <span class="kn">import</span><span class="w"> </span><span class="nn">pandas</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">pd</span> <span class="k">class</span><span class="w"> </span><span class="nc">BankSimulation</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">config</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span> <span class="o">=</span> <span class="n">config</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">config</span><span class="p">[</span><span class="s1">'tellers'</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">customer_records</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span><span class="w"> </span><span class="nf">customer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">customer_id</span><span class="p">,</span> <span class="n">transaction_type</span><span class="p">):</span> <span class="n">arrival</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="n">record</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">'id'</span><span class="p">:</span> <span class="n">customer_id</span><span class="p">,</span> <span class="s1">'type'</span><span class="p">:</span> <span class="n">transaction_type</span><span class="p">,</span> <span class="s1">'arrival'</span><span class="p">:</span> <span class="n">arrival</span> <span class="p">}</span> <span class="c1"># Balking check</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">queue</span><span class="p">)</span> <span class="o">></span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'max_queue'</span><span class="p">]:</span> <span class="n">record</span><span class="p">[</span><span class="s1">'outcome'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'balked'</span> <span class="bp">self</span><span class="o">.</span><span class="n">customer_records</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">record</span><span class="p">)</span> <span class="k">return</span> <span class="n">patience</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'mean_patience'</span><span class="p">])</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">tellers</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">req</span> <span class="o">|</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">patience</span><span class="p">)</span> <span class="k">if</span> <span class="n">req</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> <span class="n">record</span><span class="p">[</span><span class="s1">'wait'</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">arrival</span> <span class="c1"># Service time by type</span> <span class="n">service_params</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'service_times'</span><span class="p">][</span><span class="n">transaction_type</span><span class="p">]</span> <span class="n">service</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">uniform</span><span class="p">(</span><span class="o">*</span><span class="n">service_params</span><span class="p">)</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">service</span><span class="p">)</span> <span class="n">record</span><span class="p">[</span><span class="s1">'service'</span><span class="p">]</span> <span class="o">=</span> <span class="n">service</span> <span class="n">record</span><span class="p">[</span><span class="s1">'outcome'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'served'</span> <span class="n">record</span><span class="p">[</span><span class="s1">'departure'</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="k">else</span><span class="p">:</span> <span class="n">record</span><span class="p">[</span><span class="s1">'wait'</span><span class="p">]</span> <span class="o">=</span> <span class="n">patience</span> <span class="n">record</span><span class="p">[</span><span class="s1">'outcome'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'reneged'</span> <span class="bp">self</span><span class="o">.</span><span class="n">customer_records</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">record</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">arrivals</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">customer_id</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">types</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'service_times'</span><span class="p">]</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span> <span class="n">probs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'type_probabilities'</span><span class="p">]</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="c1"># Time-varying rate</span> <span class="n">hour</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">/</span> <span class="mi">60</span><span class="p">)</span> <span class="o">%</span> <span class="mi">24</span> <span class="n">rate</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_arrival_rate</span><span class="p">(</span><span class="n">hour</span><span class="p">)</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="n">rate</span><span class="p">))</span> <span class="n">transaction_type</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">choices</span><span class="p">(</span><span class="n">types</span><span class="p">,</span> <span class="n">weights</span><span class="o">=</span><span class="n">probs</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">customer</span><span class="p">(</span><span class="n">customer_id</span><span class="p">,</span> <span class="n">transaction_type</span><span class="p">))</span> <span class="n">customer_id</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_arrival_rate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">hour</span><span class="p">):</span> <span class="k">if</span> <span class="mi">12</span> <span class="o"><=</span> <span class="n">hour</span> <span class="o"><=</span> <span class="mi">14</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'peak_rate'</span><span class="p">]</span> <span class="k">elif</span> <span class="mi">9</span> <span class="o"><=</span> <span class="n">hour</span> <span class="o"><=</span> <span class="mi">17</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'normal_rate'</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">'off_peak_rate'</span><span class="p">]</span> <span class="k">def</span><span class="w"> </span><span class="nf">monitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">duration</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">arrivals</span><span class="p">())</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">monitor</span><span class="p">())</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="n">duration</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">report</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">customer_records</span><span class="p">)</span> <span class="n">served</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="n">df</span><span class="p">[</span><span class="s1">'outcome'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'served'</span><span class="p">]</span> <span class="n">balked</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="n">df</span><span class="p">[</span><span class="s1">'outcome'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'balked'</span><span class="p">]</span> <span class="n">reneged</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="n">df</span><span class="p">[</span><span class="s1">'outcome'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'reneged'</span><span class="p">]</span> <span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">=== Bank Simulation Report ==="</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Total arrivals: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">df</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Served: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">served</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">served</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">df</span><span class="p">)</span><span class="si">:</span><span class="s2">.1%</span><span class="si">}</span><span class="s2">)"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Balked: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">balked</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">balked</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">df</span><span class="p">)</span><span class="si">:</span><span class="s2">.1%</span><span class="si">}</span><span class="s2">)"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Reneged: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">reneged</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">reneged</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">df</span><span class="p">)</span><span class="si">:</span><span class="s2">.1%</span><span class="si">}</span><span class="s2">)"</span><span class="p">)</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">served</span><span class="p">)</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="s2">Wait time (served customers):"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">" Mean: </span><span class="si">{</span><span class="n">served</span><span class="p">[</span><span class="s1">'wait'</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">()</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> min"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">" Max: </span><span class="si">{</span><span class="n">served</span><span class="p">[</span><span class="s1">'wait'</span><span class="p">]</span><span class="o">.</span><span class="n">max</span><span class="p">()</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> min"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">" 90th pct: </span><span class="si">{</span><span class="n">served</span><span class="p">[</span><span class="s1">'wait'</span><span class="p">]</span><span class="o">.</span><span class="n">quantile</span><span class="p">(</span><span class="mf">0.9</span><span class="p">)</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> min"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="s2">By transaction type:"</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="n">served</span><span class="o">.</span><span class="n">groupby</span><span class="p">(</span><span class="s1">'type'</span><span class="p">)[</span><span class="s1">'wait'</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">())</span> <span class="k">return</span> <span class="n">df</span> <span class="c1"># Configuration</span> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">'tellers'</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="s1">'max_queue'</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'mean_patience'</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span> <span class="s1">'peak_rate'</span><span class="p">:</span> <span class="mf">1.0</span><span class="p">,</span> <span class="s1">'normal_rate'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span> <span class="s1">'off_peak_rate'</span><span class="p">:</span> <span class="mf">0.2</span><span class="p">,</span> <span class="s1">'service_times'</span><span class="p">:</span> <span class="p">{</span> <span class="s1">'deposit'</span><span class="p">:</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="s1">'withdrawal'</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="s1">'inquiry'</span><span class="p">:</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span> <span class="s1">'complex'</span><span class="p">:</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span> <span class="p">},</span> <span class="s1">'type_probabilities'</span><span class="p">:</span> <span class="p">[</span><span class="mf">0.35</span><span class="p">,</span> <span class="mf">0.35</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">]</span> <span class="p">}</span> <span class="c1"># Run</span> <span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="n">bank</span> <span class="o">=</span> <span class="n">BankSimulation</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">config</span><span class="p">)</span> <span class="n">bank</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">duration</span><span class="o">=</span><span class="mi">480</span><span class="p">)</span> <span class="c1"># 8 hours</span> <span class="n">results</span> <span class="o">=</span> <span class="n">bank</span><span class="o">.</span><span class="n">report</span><span class="p">()</span> </code></pre></div> <h2 id="summary">Summary</h2> <p>The bank queue teaches: - Basic queue dynamics - Multiple service types - Customer behaviour (balking, reneging) - Priority handling - Time-varying demand</p> <p>Master the bank. Model anything.</p> <h2 id="next-steps">Next Steps</h2> <ul> <li><a href="/blog_posts/simpy-queue-model.html">Queue Modelling</a></li> <li><a href="/blog_posts/simpy-call-center-simulation.html">Call Centre Simulation</a></li> <li><a href="/blog_posts/simpy-restaurant-simulation.html">Restaurant Simulation</a></li> </ul>Build Professional Simulations
Break free from commercial software and learn how to build powerful, industry-standard simulations in Python. The Complete Simulation in Python with SimPy Bootcamp gives you everything you need.
Explore the Bootcamp