This chapter had some example from the SimPy web site and equivalent examples in the simulation collection.
| #!/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) | 
The output from the program follows.
|   #lang scheme/base | 
|    | 
|    | 
|   (require (planet williams/simulation/simulation)) | 
|   (require (planet williams/science/random-distributions)) | 
|    | 
|    | 
|    | 
|   (define Nchannels 4) | 
|   (define maxN 1000) | 
|   (define lam 1.0) | 
|   (define mu 0.6667) | 
|   (define meanLifeTime (/ 1.0 mu)) | 
|   (define Nhours 10) | 
|   (define interv 60.0) | 
|   (define gap 15.0) | 
|    | 
|    | 
|    | 
|   (define Nfree Nchannels) | 
|   (define totalBusyVisits 0) | 
|   (define totalBusyTime 0.0) | 
|   (define busyStartTime 0.0) | 
|   (define busyEndTime 0.0) | 
|    | 
|    | 
|    | 
|    | 
|   (define m #f) | 
|   (define bn #f) | 
|    | 
|   (define-process (generator n) | 
|     (do ((i 0 (+ i 1))) | 
|         ((= i n) (void)) | 
|       (schedule now (job i)) | 
|       (wait (random-exponential (/ 1.0 lam))))) | 
|    | 
|   (define-process (job i) | 
|     (when (> Nfree 0) | 
|       (set! Nfree (- Nfree 1)) | 
|       (when (= Nfree 0) | 
|          | 
|         (set! busyStartTime (current-simulation-time)) | 
|         (set! totalBusyVisits (+ totalBusyVisits 1))) | 
|       (work (random-exponential (/ 1.0 mu))) | 
|       (when (= Nfree 0) | 
|          | 
|         (set! busyEndTime (current-simulation-time)) | 
|         (set! totalBusyTime (+ totalBusyTime | 
|                                (- (current-simulation-time) | 
|                                   busyStartTime)))) | 
|       (set! Nfree (+ Nfree 1)))) | 
|    | 
|   (define-process (statistician) | 
|     (do ((i 0 (+ i 1))) | 
|         ((= i Nhours) (void)) | 
|        | 
|       (wait gap) | 
|        | 
|       (set! totalBusyTime 0.0) | 
|       (set! totalBusyVisits 0) | 
|       (when (= Nfree 0) | 
|         (set! busyStartTime (current-simulation-time))) | 
|        | 
|       (wait interv) | 
|        | 
|       (when (= Nfree 0) | 
|         (set! totalBusyTime (+ totalBusyTime | 
|                                (- (current-simulation-time) | 
|                                   busyStartTime)))) | 
|       (printf "~a: busy time = ~a; busy visits = ~a~n" | 
|               (current-simulation-time) totalBusyTime totalBusyVisits) | 
|        | 
|       (set-variable-value! m totalBusyTime) | 
|       (set-variable-value! bn totalBusyVisits)) | 
|      | 
|     (printf "Busy time:   mean = ~a, variance = ~a~n" | 
|             (variable-mean m) (variable-variance m)) | 
|     (printf "Busy number: mean = ~a, variance = ~a~n" | 
|             (variable-mean bn) (variable-variance bn))) | 
|    | 
|   (define (run-simulation) | 
|     (with-new-simulation-environment | 
|       | 
|      (printf "lambda = ~a~n" lam) | 
|      (printf "mu     = ~a~n" mu) | 
|      (printf "s      = ~a~n" Nchannels) | 
|      (printf "Nhours = ~a~n" Nhours) | 
|      (printf "interv = ~a~n" interv) | 
|      (printf "gap    = ~a~n" gap) | 
|       | 
|      (set! Nfree Nchannels) | 
|      (set! totalBusyVisits 0) | 
|      (set! totalBusyTime 0.0) | 
|      (set! busyEndTime 0.0) | 
|       | 
|      (set! m (make-variable)) | 
|      (tally (variable-statistics m)) | 
|      (set! bn (make-variable)) | 
|      (tally (variable-statistics bn)) | 
|       | 
|      (schedule (at 0.0) (generator maxN)) | 
|      (schedule (at 0.0) (statistician)) | 
|      (schedule (at 10000.0) (stop-simulation)) | 
|      (start-simulation))) | 
|    | 
|   (run-simulation) | 
The output from the program follows.
| #!/usr/bin/env python | 
| """ | 
|   Simulation of a jackson queue network | 
 | 
| """ | 
| from __future__ import generators  # not needed in Python 2.3+ | 
| from SimPy.Simulation import * | 
| from random import Random,expovariate,uniform | 
 | 
| def sum(P): | 
|     """ Sum of the real vector P """ | 
|     sumP = 0.0 | 
|     for i in range(len(P)): sumP += P[i] | 
|     return (sumP) | 
 | 
 | 
 | 
| def choose2dA(i,P,g): | 
|     """  return a random choice from a set j = 0..n-1 | 
|        with probs held in list of lists P[j] (n by n) | 
|        using row i | 
|        g = random variable | 
|        call:  next = choose2d(i,P,g) | 
|     """ | 
|     U = g.random() | 
|     sumP = 0.0 | 
|     for j in range(len(P[i])):  # j = 0..n-1 | 
|         sumP +=  P[i][j] | 
|         if U < sumP: break | 
|     return(j) | 
 | 
| ## ----------------------------------------------- | 
| class Msg(Process): | 
|     """a message""" | 
|     def __init__(self,i,node): | 
|         Process.__init__(self) | 
|         self.i = i | 
|         self.node = node | 
 | 
|     def execute(self): | 
|         """ executing a message """ | 
|         global noInSystem | 
|         startTime = now() | 
|         noInSystem += 1 | 
|         ##print "DEBUG noInSystm = ",noInSystem | 
|         NoInSystem.accum(noInSystem) | 
|         self.trace("Arrived node  %d"%(self.node,)) | 
|         while self.node <> 3: | 
|             yield request,self,processor[self.node] | 
|             self.trace("Got processor %d"%(self.node,)) | 
|             st = Mrv.expovariate(1.0/mean[self.node]) | 
|             Stime.observe(st) | 
|             yield hold,self,st | 
|             yield release,self,processor[self.node] | 
|             self.trace("Finished with %d"%(self.node,)) | 
|             self.node = choose2dA(self.node,P,Mrv) | 
|             self.trace("Transfer to   %d"%(self.node,)) | 
|         TimeInSystem.observe(now()-startTime) | 
|         self.trace(    "leaving       %d"%(self.node,),noInSystem) | 
|         noInSystem -= 1 | 
|         NoInSystem.accum(noInSystem) | 
 | 
|     def trace(self,message,nn=0): | 
|         if MTRACING: print "%7.4f %3d %10s %3d"%(now(),self.i, message,nn) | 
 | 
 | 
| ## ----------------------------------------------- | 
| class Generator(Process): | 
|  """ generates a sequence of msgs """ | 
|  def __init__(self, rate,maxT,maxN): | 
|      Process.__init__(self) | 
|      self.name = "Generator" | 
|      self.rate = rate | 
|      self.maxN = maxN | 
|      self.maxT = maxT | 
|      self.g = Random(11335577) | 
|      self.i = 0 | 
 | 
|  def execute(self): | 
|      while (now() < self.maxT)  & (self.i < self.maxN): | 
|          self.i+=1 | 
|          p = Msg(self.i,startNode) | 
|          activate(p,p.execute()) | 
|          ## self.trace("starting "+p.name) | 
|          yield hold,self,self.g.expovariate(self.rate) | 
|      self.trace("generator finished with "+`self.i`+" ========") | 
|      self.stopSim() | 
 | 
|  def trace(self,message): | 
|      if GTRACING: print "%7.4f \t%s"%(now(), message) | 
 | 
| ## ----------------------------------------------- | 
| # generator: | 
| GTRACING = 0 | 
| # messages: | 
| rate = 0.5 | 
| noInSystem = 0 | 
| MTRACING = 0 | 
| startNode = 0 | 
| maxNumber = 10000 | 
| maxTime = 100000.0 | 
| Mrv = Random(77777) | 
| TimeInSystem=Monitor() | 
| NoInSystem= Monitor() | 
| Stime = Monitor() | 
 | 
| processor = [Resource(1),Resource(1),Resource(1)] | 
| mean=[1.0, 2.0, 1.0] | 
| P = [[0, 0.5, 0.5, 0],[0,0,0.8,0.2], [0.2,0,0,0.8]] | 
 | 
| initialize() | 
| g = Generator(rate,maxTime,maxNumber) | 
| activate(g,g.execute()) | 
| simulate(until=100.0) | 
 | 
| print "Mean numberm= %8.4f"%(NoInSystem.timeAverage(),) | 
| print "Mean delay  = %8.4f"%(TimeInSystem.mean(),) | 
| print "Mean stime  = %8.4f"%(Stime.mean(),) | 
| print "Total jobs  = %8d"%(TimeInSystem.count(),) | 
| print "Total time  = %8.4f"%(now(),) | 
| print "Mean rate   = %8.4f"%(TimeInSystem.count()/now(),) | 
The following is the output from the program.
|   #lang scheme/base | 
|    | 
|    | 
|   (require (planet williams/simulation/simulation-with-graphics)) | 
|   (require (planet williams/science/random-distributions)) | 
|    | 
|    | 
|    | 
|   (define n 3) | 
|   (define m #(1.0 2.0 1.0)) | 
|   (define p (vector | 
|              (make-discrete #(0.0 0.5 0.5 0.0)) | 
|              (make-discrete #(0.0 0.0 0.8 0.2)) | 
|              (make-discrete #(0.2 0.0 0.0 0.8)))) | 
|   (define np '(1 1 1)) | 
|   (define mu (/ 1.0 1.5)) | 
|   (define max-messages 10000) | 
|    | 
|    | 
|    | 
|   (define n-arrivals 0) | 
|   (define n-in-system #f) | 
|   (define time-in-system #f) | 
|   (define processor #f) | 
|    | 
|    | 
|    | 
|   (define-process (message i) | 
|     (let ((arrive-time (current-simulation-time)) | 
|           (work-duration 0.0)) | 
|       (set-variable-value! | 
|        n-in-system (+ (variable-value n-in-system) 1)) | 
|       (let loop ((node 0)) | 
|         (when (< node n) | 
|           (with-resource ((vector-ref processor node)) | 
|             (work (random-exponential (vector-ref m node)))) | 
|           (loop (random-discrete (vector-ref p node))))) | 
|       (set-variable-value! | 
|        n-in-system (- (variable-value n-in-system) 1)) | 
|       (set-variable-value! | 
|        time-in-system (- (current-simulation-time) | 
|                          arrive-time)))) | 
|    | 
|   (define (generator) | 
|     (do ((i 0 (+ i 1))) | 
|         ((= i max-messages) (void)) | 
|       (set! n-arrivals (+ n-arrivals 1)) | 
|       (schedule now (message i)) | 
|       (wait (random-exponential (/ mu))))) | 
|    | 
|   (define (main) | 
|     (with-new-simulation-environment | 
|    | 
|       (set! n-arrivals 0) | 
|       (set! n-in-system (make-variable 0)) | 
|       (accumulate (variable-history n-in-system)) | 
|       (set! time-in-system (make-variable)) | 
|       (tally (variable-statistics time-in-system)) | 
|       (set! processor (list->vector | 
|                        (map make-resource np))) | 
|    | 
|       (schedule (at 0.0) (generator)) | 
|       (schedule (at 5000.0) (stop-simulation)) | 
|       (start-simulation) | 
|       (printf "Mean number in system = ~a~n" (variable-mean n-in-system)) | 
|       (printf "Mean delay in system  = ~a~n" (variable-mean time-in-system)) | 
|       (printf "Total time run        = ~a~n" (current-simulation-time)) | 
|       (printf "Total jobs arrived    = ~a~n" n-arrivals) | 
|       (printf "Total jobs completed  = ~a~n" (variable-n time-in-system)) | 
|       (printf "Average arrival rate  = ~a~n" (/ n-arrivals | 
|                                                 (current-simulation-time))) | 
|       (write-special (history-plot (variable-history n-in-system))) | 
|       (newline))) | 
|    | 
|   (main) | 
The following is the output from the program.