cellphone: A cellphone system

Author: G A Vignaux
Date: 2004/02/21

Description

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.

Input

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:

  • NChannels The number of channels used (4)
  • gSeed - RV seed for the call arrival generator (11111111)
  • JrvSeed RV seed for the call length ( 3333333)
  • lam call arrival rate (calls per time-unit) (1.0) time unit assumed to be, say, a minute
  • mu - service rate = 1/(mean service time) per time unit. This must be less than lam (0.6667)
  • Nhours length of the simulation in periods (10)
  • interv - period: interval to gather statistics (60.0 time units)
  • gap - gap left after a period when no statistics are gathered. This is to reduce autocorrelation between periods (15.0)

Output

  • A list of the basic inputs:

    lambda    mu      s  Nhours interv  gap
    
  • a sequence of Nhours pairs:

    • the mean busy time in the period
    • the total number of busy intervals
  • a summary giving the overall:

    • Busy time mean and variance
    • Busy number mean and variance.

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

Code

#!/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)

Comments

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.