Airport Simulation with SimPy: From Check-In to Takeoff
<p>Airports are complex systems under constant pressure. Passengers flow through multiple touchpoints. Delays cascade. Simulation helps you see where things go wrong before they do.</p> <h2 id="the-airport-model">The Airport Model</h2> <p>Components: - <strong>Passengers</strong> - Arrive for flights - <strong>Check-in</strong> - Desks and kiosks - <strong>Security</strong> - Screening queues - <strong>Gates</strong> - Boarding areas - <strong>Aircraft</strong> - Arrivals and departures</p> <h2 id="basic-passenger-flow">Basic Passenger Flow</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">class</span><span class="w"> </span><span class="nc">Airport</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">check_in_desks</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">'check_in_desks'</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">security_lanes</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">'security_lanes'</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">gates</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">'gates'</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">passenger</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">passenger_id</span><span class="p">,</span> <span class="n">flight_time</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">passenger_id</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="s1">'flight'</span><span class="p">:</span> <span class="n">flight_time</span><span class="p">}</span> <span class="c1"># Check-in</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">check_in_desks</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">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">5</span><span class="p">))</span> <span class="n">record</span><span class="p">[</span><span class="s1">'checked_in'</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="c1"># Security</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">security_lanes</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">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">10</span><span class="p">))</span> <span class="n">record</span><span class="p">[</span><span class="s1">'cleared_security'</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="c1"># Wait at gate (until boarding)</span> <span class="n">boarding_time</span> <span class="o">=</span> <span class="n">flight_time</span> <span class="o">-</span> <span class="mi">30</span> <span class="c1"># Board 30 mins before</span> <span class="k">if</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">boarding_time</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">boarding_time</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="p">)</span> <span class="c1"># Board</span> <span class="n">record</span><span class="p">[</span><span class="s1">'boarded'</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="n">record</span><span class="p">[</span><span class="s1">'made_flight'</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">flight_time</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="n">record</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">passenger_arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">airport</span><span class="p">,</span> <span class="n">flight_schedule</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Generate passengers for scheduled flights."""</span> <span class="n">passenger_id</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">flight_time</span><span class="p">,</span> <span class="n">num_passengers</span> <span class="ow">in</span> <span class="n">flight_schedule</span><span class="p">:</span> <span class="c1"># Passengers arrive 1-3 hours before flight</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_passengers</span><span class="p">):</span> <span class="n">arrival_offset</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="mi">60</span><span class="p">,</span> <span class="mi">180</span><span class="p">)</span> <span class="n">arrival_time</span> <span class="o">=</span> <span class="n">flight_time</span> <span class="o">-</span> <span class="n">arrival_offset</span> <span class="k">if</span> <span class="n">arrival_time</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="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">arrival_time</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="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">airport</span><span class="o">.</span><span class="n">passenger</span><span class="p">(</span><span class="n">passenger_id</span><span class="p">,</span> <span class="n">flight_time</span><span class="p">))</span> <span class="n">passenger_id</span> <span class="o">+=</span> <span class="mi">1</span> <span class="c1"># Run</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">airport</span> <span class="o">=</span> <span class="n">Airport</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="p">{</span><span class="s1">'check_in_desks'</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'security_lanes'</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="s1">'gates'</span><span class="p">:</span> <span class="mi">20</span><span class="p">})</span> <span class="c1"># Flight schedule: (departure_time, passengers)</span> <span class="n">flights</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">60</span><span class="p">,</span> <span class="mi">150</span><span class="p">),</span> <span class="p">(</span><span class="mi">120</span><span class="p">,</span> <span class="mi">200</span><span class="p">),</span> <span class="p">(</span><span class="mi">180</span><span class="p">,</span> <span class="mi">180</span><span class="p">),</span> <span class="p">(</span><span class="mi">240</span><span class="p">,</span> <span class="mi">220</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">passenger_arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">airport</span><span class="p">,</span> <span class="n">flights</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">300</span><span class="p">)</span> </code></pre></div> <h2 id="security-with-different-lanes">Security with Different Lanes</h2> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">SecurityCheckpoint</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_lanes</span><span class="p">,</span> <span class="n">priority_lanes</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_lanes</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">priority</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">priority_lanes</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">screen_passenger</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">passenger_type</span><span class="p">):</span> <span class="k">if</span> <span class="n">passenger_type</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'business'</span><span class="p">,</span> <span class="s1">'frequent_flyer'</span><span class="p">]:</span> <span class="n">lane</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">priority</span> <span class="n">process_time</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="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">lane</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">regular</span> <span class="n">process_time</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="mi">4</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span> <span class="k">with</span> <span class="n">lane</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">process_time</span><span class="p">)</span> </code></pre></div> <h2 id="aircraft-turnaround">Aircraft Turnaround</h2> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">Aircraft</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">flight_id</span><span class="p">,</span> <span class="n">aircraft_type</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">flight_id</span> <span class="o">=</span> <span class="n">flight_id</span> <span class="bp">self</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">aircraft_type</span> <span class="k">def</span><span class="w"> </span><span class="nf">turnaround</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">gate</span><span class="p">,</span> <span class="n">ground_crew</span><span class="p">,</span> <span class="n">fuel_truck</span><span class="p">,</span> <span class="n">catering</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Complete turnaround between arrival and departure."""</span> <span class="c1"># Request gate</span> <span class="k">with</span> <span class="n">gate</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">gate_req</span><span class="p">:</span> <span class="k">yield</span> <span class="n">gate_req</span> <span class="c1"># Parallel activities</span> <span class="n">disembark</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">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">disembark</span><span class="p">())</span> <span class="n">clean</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">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">clean</span><span class="p">())</span> <span class="k">yield</span> <span class="n">disembark</span> <span class="k">yield</span> <span class="n">clean</span> <span class="c1"># Sequential activities requiring resources</span> <span class="k">with</span> <span class="n">ground_crew</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">crew</span><span class="p">:</span> <span class="k">yield</span> <span class="n">crew</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">uniform</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="c1"># Baggage</span> <span class="k">with</span> <span class="n">fuel_truck</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">fuel</span><span class="p">:</span> <span class="k">yield</span> <span class="n">fuel</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">uniform</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">25</span><span class="p">))</span> <span class="k">with</span> <span class="n">catering</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">cater</span><span class="p">:</span> <span class="k">yield</span> <span class="n">cater</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">uniform</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">15</span><span class="p">))</span> <span class="c1"># Board</span> <span class="k">yield from</span> <span class="bp">self</span><span class="o">.</span><span class="n">board</span><span class="p">()</span> <span class="k">def</span><span class="w"> </span><span class="nf">disembark</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">passengers</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">180</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">passengers</span> <span class="o">*</span> <span class="mf">0.1</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">clean</span><span class="p">(</span><span class="bp">self</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">uniform</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">25</span><span class="p">))</span> <span class="k">def</span><span class="w"> </span><span class="nf">board</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">passengers</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">180</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">passengers</span> <span class="o">*</span> <span class="mf">0.15</span><span class="p">)</span> </code></pre></div> <h2 id="baggage-handling">Baggage Handling</h2> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">BaggageSystem</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_carousels</span><span class="p">,</span> <span class="n">num_handlers</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">carousels</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_carousels</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">handlers</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_handlers</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">bags_processed</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">def</span><span class="w"> </span><span class="nf">process_flight_bags</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">flight_id</span><span class="p">,</span> <span class="n">num_bags</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Process bags from check-in to aircraft."""</span> <span class="n">bags_loaded</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">carousels</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">carousel</span><span class="p">:</span> <span class="k">yield</span> <span class="n">carousel</span> <span class="k">while</span> <span class="n">bags_loaded</span> <span class="o"><</span> <span class="n">num_bags</span><span class="p">:</span> <span class="c1"># Handler picks up bags</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">handlers</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">handler</span><span class="p">:</span> <span class="k">yield</span> <span class="n">handler</span> <span class="n">batch</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="n">num_bags</span> <span class="o">-</span> <span class="n">bags_loaded</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">batch</span> <span class="o">*</span> <span class="mf">0.5</span><span class="p">)</span> <span class="n">bags_loaded</span> <span class="o">+=</span> <span class="n">batch</span> <span class="bp">self</span><span class="o">.</span><span class="n">bags_processed</span> <span class="o">+=</span> <span class="n">num_bags</span> </code></pre></div> <h2 id="complete-airport-simulation">Complete Airport 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="k">class</span><span class="w"> </span><span class="nc">AirportSimulation</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="c1"># Resources</span> <span class="bp">self</span><span class="o">.</span><span class="n">check_in</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">'check_in_desks'</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">kiosks</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">'kiosks'</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">bag_drop</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">'bag_drops'</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">security</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">'security_lanes'</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">passport_control</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">'passport_booths'</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">gates</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">'gates'</span><span class="p">])</span> <span class="c1"># Stats</span> <span class="bp">self</span><span class="o">.</span><span class="n">passenger_stats</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">missed_flights</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">def</span><span class="w"> </span><span class="nf">passenger</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pax_id</span><span class="p">,</span> <span class="n">flight_time</span><span class="p">,</span> <span class="n">has_bags</span><span class="p">,</span> <span class="n">is_international</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">pax_id</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="s1">'flight_time'</span><span class="p">:</span> <span class="n">flight_time</span> <span class="p">}</span> <span class="c1"># Check-in (desk or kiosk)</span> <span class="k">if</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span> <span class="o"><</span> <span class="mf">0.7</span><span class="p">:</span> <span class="c1"># 70% use kiosk</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">kiosks</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">random</span><span class="o">.</span><span class="n">uniform</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="k">else</span><span class="p">:</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">check_in</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">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">7</span><span class="p">))</span> <span class="c1"># Bag drop if needed</span> <span class="k">if</span> <span class="n">has_bags</span><span class="p">:</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">bag_drop</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">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">5</span><span class="p">))</span> <span class="n">record</span><span class="p">[</span><span class="s1">'check_in_complete'</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="c1"># Security</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">security</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">random</span><span class="o">.</span><span class="n">triangular</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span> <span class="n">record</span><span class="p">[</span><span class="s1">'security_complete'</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="c1"># Passport control for international</span> <span class="k">if</span> <span class="n">is_international</span><span class="p">:</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">passport_control</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">random</span><span class="o">.</span><span class="n">uniform</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="n">record</span><span class="p">[</span><span class="s1">'airside'</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="c1"># Check if made it in time for boarding</span> <span class="n">boarding_time</span> <span class="o">=</span> <span class="n">flight_time</span> <span class="o">-</span> <span class="mi">30</span> <span class="k">if</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">boarding_time</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">missed_flights</span> <span class="o">+=</span> <span class="mi">1</span> <span class="n">record</span><span class="p">[</span><span class="s1">'made_flight'</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span> <span class="k">else</span><span class="p">:</span> <span class="n">record</span><span class="p">[</span><span class="s1">'made_flight'</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span> <span class="c1"># Wait for boarding</span> <span class="k">if</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">boarding_time</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">boarding_time</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="p">)</span> <span class="n">record</span><span class="p">[</span><span class="s1">'total_time'</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="bp">self</span><span class="o">.</span><span class="n">passenger_stats</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">flight_passengers</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">flight_time</span><span class="p">,</span> <span class="n">num_pax</span><span class="p">,</span> <span class="n">is_international</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Generate passengers for a flight."""</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_pax</span><span class="p">):</span> <span class="c1"># Arrival distribution: 60-180 mins before flight</span> <span class="n">advance</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">triangular</span><span class="p">(</span><span class="mi">60</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="mi">120</span><span class="p">)</span> <span class="n">arrival_time</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">flight_time</span> <span class="o">-</span> <span class="n">advance</span><span class="p">)</span> <span class="c1"># Wait until arrival time</span> <span class="k">if</span> <span class="n">arrival_time</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="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">arrival_time</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="p">)</span> <span class="n">has_bags</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span> <span class="o"><</span> <span class="mf">0.7</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">passenger</span><span class="p">(</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">flight_time</span><span class="si">}</span><span class="s2">_</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">flight_time</span><span class="p">,</span> <span class="n">has_bags</span><span class="p">,</span> <span class="n">is_international</span> <span class="p">))</span> <span class="c1"># Small gap between passenger arrivals</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">uniform</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.5</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">flight_schedule</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Run simulation with flight schedule."""</span> <span class="k">for</span> <span class="n">flight_time</span><span class="p">,</span> <span class="n">num_pax</span><span class="p">,</span> <span class="n">is_intl</span> <span class="ow">in</span> <span class="n">flight_schedule</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">flight_passengers</span><span class="p">(</span><span class="n">flight_time</span><span class="p">,</span> <span class="n">num_pax</span><span class="p">,</span> <span class="n">is_intl</span><span class="p">))</span> <span class="c1"># Run until last flight + buffer</span> <span class="n">last_flight</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">f</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">flight_schedule</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">last_flight</span> <span class="o">+</span> <span class="mi">60</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">pax</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">passenger_stats</span> <span class="n">made_it</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">pax</span> <span class="k">if</span> <span class="n">p</span><span class="p">[</span><span class="s1">'made_flight'</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">=== Airport 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 passengers: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">pax</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">"Made flight: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">made_it</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">made_it</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">pax</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">"Missed flight: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">missed_flights</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="k">if</span> <span class="n">made_it</span><span class="p">:</span> <span class="n">total_times</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span><span class="p">[</span><span class="s1">'total_time'</span><span class="p">]</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">made_it</span><span class="p">]</span> <span class="n">security_times</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span><span class="p">[</span><span class="s1">'security_complete'</span><span class="p">]</span> <span class="o">-</span> <span class="n">p</span><span class="p">[</span><span class="s1">'check_in_complete'</span><span class="p">]</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">made_it</span> <span class="k">if</span> <span class="s1">'security_complete'</span> <span class="ow">in</span> <span class="n">p</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">Total journey time (check-in to gate):"</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">np</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">total_times</span><span class="p">)</span><span class="si">:</span><span class="s2">.1f</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">np</span><span class="o">.</span><span class="n">percentile</span><span class="p">(</span><span class="n">total_times</span><span class="p">,</span><span class="w"> </span><span class="mi">90</span><span class="p">)</span><span class="si">:</span><span class="s2">.1f</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">Security wait + process:"</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">np</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">security_times</span><span class="p">)</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2"> min"</span><span class="p">)</span> <span class="c1"># Config</span> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">'check_in_desks'</span><span class="p">:</span> <span class="mi">15</span><span class="p">,</span> <span class="s1">'kiosks'</span><span class="p">:</span> <span class="mi">20</span><span class="p">,</span> <span class="s1">'bag_drops'</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'security_lanes'</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span> <span class="s1">'passport_booths'</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span> <span class="s1">'gates'</span><span class="p">:</span> <span class="mi">30</span> <span class="p">}</span> <span class="c1"># Flight schedule: (departure_time, passengers, is_international)</span> <span class="n">schedule</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="mi">60</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="p">(</span><span class="mi">90</span><span class="p">,</span> <span class="mi">150</span><span class="p">,</span> <span class="kc">False</span><span class="p">),</span> <span class="p">(</span><span class="mi">120</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="p">(</span><span class="mi">150</span><span class="p">,</span> <span class="mi">160</span><span class="p">,</span> <span class="kc">False</span><span class="p">),</span> <span class="p">(</span><span class="mi">180</span><span class="p">,</span> <span class="mi">220</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="p">(</span><span class="mi">210</span><span class="p">,</span> <span class="mi">190</span><span class="p">,</span> <span class="kc">False</span><span class="p">),</span> <span class="p">(</span><span class="mi">240</span><span class="p">,</span> <span class="mi">175</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="p">]</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">sim</span> <span class="o">=</span> <span class="n">AirportSimulation</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">sim</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">schedule</span><span class="p">)</span> <span class="n">sim</span><span class="o">.</span><span class="n">report</span><span class="p">()</span> </code></pre></div> <h2 id="summary">Summary</h2> <p>Airport simulation captures: - Multi-stage passenger journey - Parallel and sequential processes - Time-critical deadlines - Resource contention at bottlenecks - Flight schedule dependencies</p> <p>Every airport is a system. Simulate to optimise.</p> <h2 id="next-steps">Next Steps</h2> <ul> <li><a href="/blog_posts/simpy-hospital-simulation.html">Hospital Simulation</a></li> <li><a href="/blog_posts/simpy-call-center-simulation.html">Call Centre Simulation</a></li> <li><a href="/blog_posts/simpy-queue-model.html">Queue Modelling</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