{ "cells": [ { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Max time waited was 166s average 32.128s\n" ] } ], "source": [ "########################################################################\n", "########################################################################\n", "#\n", "# Queue.py\n", "# Simulate a queue where people arrive randomly with an average time of\n", "# X seconds between people and are dealt with in Y seconds on average\n", "# Use a loop with a 1 second step in the simulation\n", "#\n", "# Print the maximum wait that any one of 1000 simulated people had\n", "# Note this solution uses numpy to generate distrubibutions, you can\n", "# also \"math\" functions and \"random\" functions (import math,random)\n", "#\n", "########################################################################\n", "########################################################################\n", "\n", "X = 10 # starting value, can be adjusted\n", "Y = 7 # starting value, can be adjusted\n", "nPerson = 1000 # number of people to simulate, stop when all dealt with\n", "\n", "import numpy as np\n", "\n", "def timeToNext(beta):\n", " \"\"\"Return time to next person, input is beta = 1/(average arrival rate)\"\"\"\n", " # functional form of time to next person if ac is the average arrival time\n", " # is p(t) = 1/beta * exp(- t / beta )\n", " # where beta = beta\n", " # np.random.exponential uses scale = beta\n", " # https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.random.exponential.html\n", " ranExp = np.random.exponential(scale = beta, size=1)\n", " return int(ranExp) # note forcing integer times here to simplify\n", "\n", "def addAPerson(t,q):\n", " \"\"\" Function to add a person to the queue with average time between people = X\"\"\"\n", " # t = time added\n", " # q = your queue\n", " q.append(t) # write your function here\n", "\n", "def removeAPerson(t,q):\n", " \"\"\"Function to remove a person how has been dealt with, record time they waited\"\"\"\n", " # t = time removed\n", " # q = your queue\n", " return t-q.pop(0) #time waited\n", "\n", "def arriveTimesArray(n,dt):\n", " \"\"\"Return a numpy array of integers, which are the times each person will arrive\"\"\" \n", " # Make an array of the delta time between each person arriving\n", " # call the function timeToNext(dt) n times using the fromiter function in numpy\n", " # see https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.fromiter.html\n", " deltaT = np.fromiter( (timeToNext(dt) for i in range(n)), dtype=int )\n", " # \n", " # Then accumulate the results to get the arrival time of each person\n", " # Sometimes more than one person can arrive in each second interval\n", " # and https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ufunc.accumulate.html\n", " return np.add.accumulate( deltaT )\n", "\n", "def timerLoop(X,Y):\n", " \"\"\"Run a loop to add and remove people as required\"\"\"\n", " arriveTimes = arriveTimesArray(nPerson,X)\n", " # queue\n", " q = []\n", " # waied times\n", " wait = []\n", " # nAdd = number of person already added to queue\n", " nAdd =0\n", " t = 0 # so first time is zero\n", " leaveTime = None # nobody yet in the queue so noone can leave...\n", " while(len(q) > 0 or nAdd < nPerson) : # are there still people to add or people queuing\n", " while ( nAdd < nPerson and t == arriveTimes[nAdd] ): # t = time to add a person\n", " addAPerson(t,q)\n", " nAdd += 1 # move pointer to persons up one\n", " if( leaveTime is None ):\n", " leaveTime = t+timeToNext(Y) # can now start removing people\n", " # if we can should a person and there are people to remove\n", " while( leaveTime is not None and t == leaveTime and len(q) > 0 ):\n", " wait.append(removeAPerson(t,q))\n", " if( len(q) > 0 ):\n", " leaveTime = t+timeToNext(Y)\n", " else:\n", " leaveTime = None # queue is empty again \n", " t += 1 # move to next second\n", " return wait\n", "\n", "wait = timerLoop(X,Y)\n", "print(\"Max time waited was {}s average {}s\".format(np.max(wait),np.mean(wait)))" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Max time waited was 86s average 22.083s\n", "if people arrive every 10s and are processed every 7s on average\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "X=10\n", "Y=7\n", "wait = timerLoop(X,Y)\n", "print(\"Max time waited was {}s average {}s\".format(np.max(wait),np.mean(wait)))\n", "print(\"if people arrive every {}s and are processed every {}s on average\".format(X,Y))\n", "if max(wait) < 20 :\n", " plt.hist(wait,bins=max(wait),normed=True)\n", "else:\n", " plt.hist(wait,bins=20,normed=True)\n", "plt.xlabel(\"Wait in seconds\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "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.5.3" } }, "nbformat": 4, "nbformat_minor": 2 }