{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from heapq import heappush, heappop\n", "import random\n", "from scipy.special import factorial" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "class Stats:\n", " def __init__(self, sim):\n", " self.sim = sim\n", " self.waiting_time = 0.0\n", " self.servicing_time = 0.0\n", " \n", " def avg_wait_time(self):\n", " return self.waiting_time / self.sim.t\n", " \n", " def avg_service_time(self):\n", " return self.servicing_time / self.sim.t\n", " \n", " def avg_system_time(self):\n", " return (self.waiting_time + self.servicing_time) / self.sim.t\n", " \n", " def prb_empty(self):\n", " c = self.sim.servers\n", " rho = self.sim.arrival_rate / self.sim.service_rate\n", " if self.sim.servers == 1:\n", " return 1.0 - rho\n", " return 1 / (sum(rho**n/factorial(n) for n in range(0, c)) +\n", " rho**c/factorial(c) * 1/(1-rho/c))\n", " \n", " def exp_wait_time(self):\n", " c = self.sim.servers\n", " if c == 1:\n", " return self.exp_system_time() - self.exp_service_time()\n", " rho = self.sim.arrival_rate / self.sim.service_rate\n", " return self.prb_empty()*rho**(c+1) / (factorial(c-1)*(c-rho)**2)\n", " \n", " def exp_service_time(self):\n", " c = self.sim.servers\n", " rho = self.sim.arrival_rate / self.sim.service_rate\n", " if c == 1:\n", " return rho\n", " return self.exp_system_time() - self.exp_wait_time()\n", " \n", " def exp_system_time(self):\n", " c = self.sim.servers\n", " rho = self.sim.arrival_rate / self.sim.service_rate\n", " if c == 1:\n", " return rho / (1 - rho)\n", " return self.exp_wait_time() + rho\n", " \n", " def show(self):\n", " summaries = [\n", " 'avg_wait_time',\n", " 'exp_wait_time',\n", " 'avg_service_time',\n", " 'exp_service_time',\n", " 'avg_system_time',\n", " 'exp_system_time',\n", " ]\n", " for s in summaries:\n", " print('{} {:.2f}'.format(s, getattr(self, s)()))\n", "\n", "class Sim:\n", " def __init__(self, arrival_rate, service_rate, servers, debug=False):\n", " self.arrival_rate = arrival_rate\n", " self.service_rate = service_rate\n", " self.servers = servers\n", " self.debug = debug\n", " \n", " self.t = 0.0\n", " self.events = []\n", " self.waiting = 0\n", " self.servicing = 0\n", " \n", " self.stats = Stats(self)\n", " \n", " def schedule_arrival(self):\n", " delay = random.expovariate(self.arrival_rate)\n", " heappush(self.events, (self.t + delay, 'arrival'))\n", " \n", " def service(self):\n", " assert self.waiting > 0\n", " self.waiting -= 1\n", " self.servicing += 1\n", " delay = random.expovariate(self.service_rate)\n", " heappush(self.events, (self.t + delay, 'serviced'))\n", " \n", " def process_event(self):\n", " t, event = heappop(self.events)\n", " if self.debug:\n", " print(t, event)\n", " self.stats.waiting_time += (t - self.t) * self.waiting\n", " self.stats.servicing_time += (t - self.t) * self.servicing\n", " self.t = t\n", " if event == 'arrival':\n", " self.waiting += 1\n", " self.schedule_arrival()\n", " if self.servicing < self.servers:\n", " self.service()\n", " elif event == 'serviced':\n", " assert self.servicing > 0\n", " self.servicing -= 1\n", " if self.waiting > 0:\n", " self.service()\n", " \n", " def simulate(self, duration):\n", " self.schedule_arrival()\n", " while self.t < duration:\n", " self.process_event()\n", " return self.stats" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "avg_wait_time 0.90\n", "exp_wait_time 0.90\n", "avg_service_time 0.60\n", "exp_service_time 0.60\n", "avg_system_time 1.50\n", "exp_system_time 1.50\n" ] } ], "source": [ "Sim(arrival_rate=0.6, service_rate=1.0, servers=1).simulate(1e6).show()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "avg_wait_time 0.09\n", "exp_wait_time 0.09\n", "avg_service_time 1.20\n", "exp_service_time 1.20\n", "avg_system_time 1.29\n", "exp_system_time 1.29\n" ] } ], "source": [ "Sim(arrival_rate=0.6, service_rate=0.5, servers=3).simulate(1e6).show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.2" } }, "nbformat": 4, "nbformat_minor": 2 }