| Author: | G A Vignaux |
|---|---|
| Date: | 2004/02/21 |
This program was used in a research study on cellphone congestion. The objective is to find the number of busy periods observed in one cell of the cellphone system where the number of channels in a cell is limited. Calls arriving when the cell is busy are assumed to be lost.
The main program is a standard simulation of a queue system with blocking. Calls (Jobs) are generated randomly using a Generator process. This is an unfortunate title as it clashes with the Python use of the word Generator but it was chosen in a previous version of the program using Simscript. Jobs will be blocked if the cell is busy, that is, the number of free channels (Nfree) is zero, otherwise it will use the channel for a random time and then release the channel. This model does not use Simpy Resources.
In this version of the program, no external arguments are used; all data is set up in the script itself. The data and appropriate values are:
A list of the basic inputs:
lambda mu s Nhours interv gap
a sequence of Nhours pairs:
a summary giving the overall:
An example of the output from a run of this program is:
lambda mu s Nhours interv gap 1.0000 0.6667 4 10 60.00 15.00 3.274 8 0.444 2 3.649 8 0.652 3 2.277 6 1.372 9 0.411 4 0.067 2 2.910 8 5.073 9 Busy Time: mean = 2.01297 var= 2.55814 Busy Number: mean = 5.90000 var= 7.49000
#!/usr/bin/env python
""" Simulate the operation of a BCC cellphone system using SimPy
"""
from __future__ import generators # not needed for Python 2.3+
from SimPy.Simulation import *
from random import Random,expovariate
class Generator(Process):
""" generates a sequence of calls """
def __init__(self, maxN, lam):
global busyEndTime
Process.__init__(self)
self.name = "generator"
self.maxN = maxN
self.lam = lam
self.iatime = 1.0/lam
self.rv = Random(gSeed)
busyEndTime = now() # simulation start time
def execute(self):
for i in range(self.maxN):
j = Job(i)
activate(j,j.execute())
yield hold,self,self.rv.expovariate(lam)
self.trace("WARNING generator finished -- ran out of jobs")
def trace(self,message):
if GTRACING: print "%7.4f \t%s"%(self.time(), message)
class Job(Process):
""" instances of the Job class represent calls arriving at
random at the chnnels.
"""
def __init__(self,i):
Process.__init__(self)
self.i = i
self.name = "Job"+`i`
def execute(self):
global busyStartTime,totalBusyVisits,totalBusyTime
global Nfree,busyEndTime,Jrv
self.trace("arrived ")
if Nfree == 0: self.trace("blocked and left")
else:
self.trace("got a channel")
Nfree -= 1
if Nfree == 0:
self.trace("start busy period======")
busyStartTime = now()
totalBusyVisits += 1
interIdleTime = now() - busyEndTime
yield hold,self,Jrv.expovariate(mu)
self.trace("finished")
if Nfree == 0:
self.trace("end busy period++++++")
busyEndTime = now()
busy = now() - busyStartTime
self.trace(" busy = %9.4f"%(busy,))
totalBusyTime +=busy
Nfree += 1
def trace(self,message):
if TRACING: print "%7.4f \t%s %s "%(now(), message , self.name)
class Statistician(Process):
""" observes the system at intervals """
def __init__(self,Nhours,interv,gap):
Process.__init__(self)
self.Nhours = Nhours
self.interv = interv
self.gap = gap
self.name="Statistician"
def execute(self):
global busyStartTime,totalBusyTime,totalBusyVisits
global hourBusyTime,hourBusyVisits
for i in range(self.Nhours):
yield hold,self,self.gap
totalBusyTime = 0.0
totalBusyVisits = 0
if Nfree == 0: busyStartTime = now()
yield hold,self,self.interv
if Nfree == 0: totalBusyTime += now()-busyStartTime
if STRACING: print "%7.3f %5d"%(totalBusyTime,totalBusyVisits)
m.tally(totalBusyTime)
bn.tally(totalBusyVisits)
print("Busy Time: mean = %10.5f var= %10.5f"%(m.mean(),m.var()))
print("Busy Number: mean = %10.5f var= %10.5f"%(bn.mean(),bn.var()))
def trace(self,message):
if STRACING: print "%7.4f \t%s"%(self.time(), message)
totalBusyVisits = 0
totalBusyTime = 0.0
NChannels = 4 # number of channels in the cell
Nfree = NChannels
maxN = 1000
gSeed = 11111111
JrvSeed = 3333333
lam = 1.0
mu = 0.6667
meanLifeTime = 1.0/mu
TRACING = 0
GTRACING = 0
STRACING = 1
Nhours = 10
interv = 60.0 # monitor
gap = 15.0 # monitor
print "lambda mu s Nhours interv gap"
print "%7.4f %6.4f %4d %4d %6.2f %6.2f"%(lam,mu,NChannels,Nhours,interv,gap)
m = Monitor()
bn=Monitor()
Jrv = Random(JrvSeed)
s = Statistician(Nhours,interv,gap)
initialize()
g = Generator(maxN, lam)
activate(g,g.execute())
activate(s,s.execute())
simulate(until=10000.0)
This program demonstrates an independent monitoring process (Statistician) to observe the rest of the system. This makes observations of a fixed length (interv) with gaps (gap) between observation periods to decrease the correlation between samples.