-
Notifications
You must be signed in to change notification settings - Fork 1
/
BasicQueueSimulation.py
173 lines (144 loc) · 6.59 KB
/
BasicQueueSimulation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
from SimPy.Simulation import *
import random as rnd
import numpy.random as rnp
import argparse
import matplotlib.pyplot as plt
#global parameters with fixed values for assignment - could easily extend to a more flexible program that takes input from
#user to determine what these quantities should be (for later maybe?)
class Parameters:
arrmin = 1.5
arrmax = 3.5
intmin = 2.5
intmax = 6.5
wM = Monitor()
interarrival_time = 10.0
service_time = 8.0
packageArrivalCounter = 0
x = []
y = []
bankservicetime = 0
seed = 123
#generates Packets with a uniform interarrival rate
class PacketGeneratorU( Process ):
def produce( self, b ):
while True:
c = PacketU( b, Parameters.packageArrivalCounter )
c.start( c.doit() )
Parameters.packageArrivalCounter +=1
yield hold, self, rnp.uniform(Parameters.arrmin, Parameters.arrmax)
#generates a queue where packets that arrive from PacketGeneratorU() are serviced with a uniform service time (or queued)
class PacketU( Process ):
def __init__( self, resource, i ):
Process.__init__( self )
self.i = i
self.banku = resource
def doit( self ):
arrive = now()
print "Time %f : %d arrived and about to join the queue "%(now(), self.i)
yield request, self, self.banku
wait = now() - arrive
Parameters.wM.observe(wait) #monitor waiting times
print "Time %f : %d is about to get its service initiated "%(now(), self.i)
yield hold, self, self.banku.servicetime() #uniform service time
yield release, self, self.banku
print "Time %f : %d service terminated and exits " %(now(), self.i)
#generates a uniform service time unless service time is varying (in which case use property that service time will eventually be constant)
class BankU( Resource ):
def servicetime( self ):
if arg.generateRawResults == False:
return rnp.uniform(Parameters.intmin, Parameters.intmax)
if arg.generateRawResults == True:
return Parameters.service_time
#generate packets with poisson arrival rate (so exponential interarrival time)
class PacketGenerator( Process ):
def produce( self, b ):
while True:
c = Packet( b, Parameters.packageArrivalCounter )
c.start( c.doit() )
Parameters.packageArrivalCounter +=1
yield hold, self, rnd.expovariate(1.0/Parameters.interarrival_time)
#generate queue with an exponential service time
class Packet( Process ):
def __init__( self, resource, i ):
Process.__init__( self )
self.i = i
self.bank = resource
def doit( self ):
arrive = now()
print "Time %f : %d arrived and about to join the queue "%(now(), self.i)
yield request, self, self.bank
wait = now() - arrive
Parameters.wM.observe(wait)
print "Time %f : %d is about to get its service initiated "%(now(), self.i)
yield hold, self, self.bank.servicetime()
yield release, self, self.bank
print "Time %f : %d service terminated and exits " %(now(), self.i)
#generates an exponential service time
class Bank( Resource ):
def servicetime( self ):
return rnd.expovariate(1.0/Parameters.service_time) #service time should vary with specific simulations (see below)
#either we run the simulation once with a specified seed to verify validity of simulation or we run multiple simultaions
#each simulation should repeat 10 times while varying the service time and then plot service time against mean waiting time
def run_simulation(bankservicetime, totaltime, numberofsimulations):
if arg.type == 'UU1':
for r in range(numberofsimulations):
rnp.seed(Parameters.seed)
initialize()
banku = BankU( capacity=1, monitored=True, monitorType=Monitor )
Parameters.wM = Monitor()
src = PacketGeneratorU()
activate( src, src.produce( banku ), at=rnp.uniform(Parameters.arrmin, Parameters.arrmax))
startCollection(when=totaltime/2)
simulate(until=totaltime)
Parameters.x.append(bankservicetime)
Parameters.y.append(banku.waitMon.timeAverage())
print Parameters.y
result = Parameters.wM.count(), Parameters.wM.mean()
Parameters.seed+= 25
print "Average wait for %3d completions was %5.3f seconds."% result
if arg.type == 'MM1':
for r in range(numberofsimulations):
rnp.seed(Parameters.seed)
initialize()
bank = Bank( capacity=1, monitored=True, monitorType=Monitor )
Parameters.wM = Monitor()
src = PacketGenerator()
activate( src, src.produce( bank ), at = rnd.expovariate(1.0/Parameters.interarrival_time))
startCollection(when=totaltime/2)
simulate(until=totaltime)
Parameters.x.append(bankservicetime)
Parameters.y.append(bank.waitMon.timeAverage())
print Parameters.y
result = Parameters.wM.count(), Parameters.wM.mean()
Parameters.seed+= 25
print "Average wait for %3d completions was %5.3f seconds."% result
if arg.type == 'MM2':
for r in range(numberofsimulations):
rnp.seed(Parameters.seed)
initialize()
bank = Bank( capacity=2, monitored=True, monitorType=Monitor )
src = PacketGenerator()
activate( src, src.produce( bank ))
startCollection(when=totaltime/2)
simulate(until=totaltime)
Parameters.x.append(bankservicetime)
Parameters.y.append(bank.waitMon.timeAverage())
print Parameters.y
Parameters.seed+= 25
#use parser to input command line arguments to generate different queues based on input
parser = argparse.ArgumentParser()
parser.add_argument('-generateRawResults', '-generateRawResults', action='store_true', default = False)
parser.add_argument('--type', '--type', required=True)
arg = parser.parse_args()
#how to run simulation based on command line user input
if arg.generateRawResults == True:
Parameters.service_time = 0.5
while Parameters.service_time <= 11.0:
Parameters.service_time +=.5
run_simulation(Parameters.service_time, 120, 10)
print Parameters.x
print Parameters.y
plt.scatter(Parameters.x, Parameters.y) #resulting plot
plt.show()
if arg.generateRawResults == False:
run_simulation(Parameters.service_time, 120, 1)