Package SimPy :: Module SimulationStep

[hide private]
[frames] | no frames]

# Source Code for Module SimPy.SimulationStep

      1  #!/usr / bin / env python
      2  # coding=utf-8
      3  # $Revision: 485 $ $Date: 2010-05-10 09:23:24 +0200 (Mon, 10 May 2010) $ kgm
      4  """SimulationStep 2.1 Supports stepping through SimPy simulation event - by - event.
      5  Based on generators (Python 2.3 and later; not 3.0)
      6
      7  LICENSE:
      8  Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009, 2010  Klaus G. Muller, Tony Vignaux
      9  mailto: kgmuller at xs4all.nl and Tony.Vignaux at vuw.ac.nz
     10
     11      This library is free software; you can redistribute it and / or
     12      modify it under the terms of the GNU Lesser General Public
     13      License as published by the Free Software Foundation; either
     14      version 2.1 of the License, or (at your option) any later version.
     15
     16      This library is distributed in the hope that it will be useful,
     17      but WITHOUT ANY WARRANTY; without even the implied warranty of
     18      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     19      Lesser General Public License for more details.
     20
     21      You should have received a copy of the GNU Lesser General Public
     22      License along with this library; if not, write to the Free Software
     23      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111 - 1307  USA
     24  END OF LICENSE
     25  """
     26  from SimPy.Simulation import *
     27
     28  __TESTING = False
     29  version = __version__ = '2.1 $Revision: 485 $ $Date: 2010-05-10 09:23:24 +0200 (Mon, 10 May 2010) $'
     30  if __TESTING:
     31      print 'SimPy.SimulationStep %s' %__version__,
     32      if __debug__:
     33          print '__debug__ on'
     34      else:
     35          print
     36
     37  _step = False
     38
     39 -class SimulationStep(Simulation):
     40 -    def __init__(self):
     41          Simulation.__init__(self)
     42          self._step = False
     43
     44 -    def initialize(self):
     45          Simulation.initialize(self)
     46          self._step = False
     47
     48 -    def startStepping(self):
     49          """Application function to start stepping through simulation."""
     50          self._step = True
     51
     52 -    def stopStepping(self):
     53          """Application function to stop stepping through simulation."""
     54          self._step = False
     55
     56 -    def step(self):
     57          Simulation.step(self)
     58          if self._step: self.callback()
     59
     60 -    def simulate(self, callback=lambda: None, until=0):
     61          """
     62          Simulates until simulation time reaches ``until``. After processing each
     63          event, ``callback`` will be invoked if stepping has been enabled with
     64          :meth:`~SimPy.SimulationStep.startStepping`.
     65          """
     66          self.callback = callback
     67          return Simulation.simulate(self, until)
     68
     69  # For backward compatibility
     70  Globals.sim = SimulationStep()
     71
     72 -def startStepping():
     73      Globals.sim.startStepping()
     74
     75 -def stopStepping():
     76      Globals.sim.stopStepping()
     77
     78  peek = Globals.sim.peek
     79
     80  step = Globals.sim.step
     81
     82 -def simulate(callback = lambda :None, until = 0):
     83      return Globals.sim.simulate(callback = callback, until = until)
     84
     85  # End backward compatibility
     86
     87
     88  ################### end of Simulation module
     89
     90  if __name__ == '__main__':
     91      print 'SimPy.SimulationStep %s' %__version__
     92      ################### start of test / demo programs
     93
     94 -    def askCancel():
     95          a = raw_input('[Time=%s] End run (e), Continue stepping (s), Run to end (r)'%now())
     96          if a == 'e':
     97              stopSimulation()
     98          elif a == 's':
     99              return
    100          else:
    101              stopStepping()
    102
    103 -    def test_demo():
    104          class Aa(Process):
    105              sequIn = []
    106              sequOut = []
    107              def __init__(self, holdtime, name):
    108                  Process.__init__(self, name)
    109                  self.holdtime = holdtime
    110
    111              def life(self, priority):
    112                  for i in range(1):
    113                      Aa.sequIn.append(self.name)
    114                      print now(),rrr.name, 'waitQ:', len(rrr.waitQ),'activeQ:',\
    115                            len(rrr.activeQ)
    116                      print 'waitQ: ',[(k.name, k._priority[rrr]) for k in rrr.waitQ]
    117                      print 'activeQ: ',[(k.name, k._priority[rrr]) \
    118                                 for k in rrr.activeQ]
    119                      assert rrr.n + len(rrr.activeQ) == rrr.capacity, \
    120                             'Inconsistent resource unit numbers'
    121                      print now(),self.name, 'requests 1 ', rrr.unitName
    122                      yield request, self, rrr, priority
    123                      print now(),self.name, 'has 1 ', rrr.unitName
    124                      print now(),rrr.name, 'waitQ:', len(rrr.waitQ),'activeQ:',\
    125                            len(rrr.activeQ)
    126                      print now(),rrr.name, 'waitQ:', len(rrr.waitQ),'activeQ:',\
    127                            len(rrr.activeQ)
    128                      assert rrr.n + len(rrr.activeQ) == rrr.capacity, \
    129                             'Inconsistent resource unit numbers'
    130                      yield hold, self, self.holdtime
    131                      print now(),self.name, 'gives up 1', rrr.unitName
    132                      yield release, self, rrr
    133                      Aa.sequOut.append(self.name)
    134                      print now(),self.name, 'has released 1 ', rrr.unitName
    135                      print 'waitQ: ',[(k.name, k._priority[rrr]) for k in rrr.waitQ]
    136                      print now(),rrr.name, 'waitQ:', len(rrr.waitQ),'activeQ:',\
    137                            len(rrr.activeQ)
    138                      assert rrr.n + len(rrr.activeQ) == rrr.capacity, \
    139                             'Inconsistent resource unit numbers'
    140
    141          class Destroyer(Process):
    142              def __init__(self):
    143                  Process.__init__(self)
    144
    145              def destroy(self, whichProcesses):
    146                  for i in whichProcesses:
    147                      Process().cancel(i)
    148                  yield hold, self, 0
    149
    150          class Observer(Process):
    151              def __init__(self):
    152                  Process.__init__(self)
    153
    154              def observe(self, step, processes, res):
    155                  while now() < 11:
    156                      for i in processes:
    157                          print ' %s %s: act:%s, pass:%s, term: %s, interr:%s, qu:%s'\
    158                                %(now(),i.name, i.active(),i.passive(),i.terminated()\
    159                              ,i.interrupted(),i.queuing(res))
    160                      print
    161                      yield hold, self, step
    162
    163          class UserControl(Process):
    164              def letUserInteract(self, when):
    165                  yield hold, self, when
    166                  startStepping()
    167
    168          print '****First case == priority queue, resource service not preemptable'
    169          initialize()
    170          rrr = Resource(5, name = 'Parking', unitName = 'space(s)', qType = PriorityQ,
    171                       preemptable = 0)
    172          procs = []
    173          for i in range(10):
    174              z = Aa(holdtime = i, name = 'Car ' + str(i))
    175              procs.append(z)
    176              activate(z, z.life(priority = i))
    177          o = Observer()
    178          activate(o, o.observe(1, procs, rrr))
    179          startStepping()
    180          a = simulate(until = 10000, callback = askCancel)
    181          print 'Input sequence: ', Aa.sequIn
    182          print 'Output sequence: ', Aa.sequOut
    183
    184          print '\n****Second case == priority queue, resource service preemptable'
    185          initialize()
    186          rrr = Resource(5, name = 'Parking', unitName = 'space(s)', qType = PriorityQ,
    187                       preemptable = 1)
    188          procs = []
    189          for i in range(10):
    190              z = Aa(holdtime = i, name = 'Car ' + str(i))
    191              procs.append(z)
    192              activate(z, z.life(priority = i))
    193          o = Observer()
    194          activate(o, o.observe(1, procs, rrr))
    195          u = UserControl()
    196          activate(u, u.letUserInteract(4))
    197          Aa.sequIn = []
    198          Aa.sequOut = []
    199          a = simulate(askCancel, until = 10000)
    200          print a
    201          print 'Input sequence: ', Aa.sequIn
    202          print 'Output sequence: ', Aa.sequOut
    203
    204 -    def test_interrupt():
    205          class Bus(Process):
    206              def __init__(self, name):
    207                  Process.__init__(self, name)
    208
    209              def operate(self, repairduration = 0):
    210                  print now(),'>> %s starts' % (self.name)
    211                  tripleft = 1000
    212                  while tripleft > 0:
    213                      yield hold, self, tripleft
    214                      if self.interrupted():
    215                          print 'interrupted by %s' %self.interruptCause.name
    216                          print '%s: %s breaks down ' %(now(),self.name)
    217                          tripleft = self.interruptLeft
    218                          self.interruptReset()
    219                          print 'tripleft ', tripleft
    220                          reactivate(br, delay = repairduration) # breakdowns only during operation
    221                          yield hold, self, repairduration
    222                          print now(),' repaired'
    223                      else:
    224                          break # no breakdown, ergo bus arrived
    225                  print now(),'<< %s done' % (self.name)
    226
    227          class Breakdown(Process):
    228              def __init__(self, myBus):
    229                  Process.__init__(self, name = 'Breakdown ' + myBus.name)
    230                  self.bus = myBus
    231
    232              def breakBus(self, interval):
    233
    234                  while True:
    235                      yield hold, self, interval
    236                      if self.bus.terminated(): break
    237                      self.interrupt(self.bus)
    238
    239          print'\n\n+++test_interrupt'
    240          initialize()
    241          b = Bus('Bus 1')
    242          activate(b, b.operate(repairduration = 20))
    243          br = Breakdown(b)
    244          activate(br, br.breakBus(200))
    245          startStepping()
    246          simulate(until = 4000)
    247
    248
    249 -    def testSimEvents():
    250          class Waiter(Process):
    251              def waiting(self, theSignal):
    252                  while True:
    253                      yield waitevent, self, theSignal
    254                      print '%s: process \'%s\' continued after waiting for %s' % (now(),self.name, theSignal.name)
    255                      yield queueevent, self, theSignal
    256                      print '%s: process \'%s\' continued after queueing for %s' % (now(),self.name, theSignal.name)
    257
    258          class ORWaiter(Process):
    259              def waiting(self, signals):
    260                  while True:
    261                      yield waitevent, self, signals
    262                      print now(),'one of %s signals occurred' % [x.name for x in signals]
    263                      print '\t%s (fired / param)'%[(x.name, x.signalparam) for x in self.eventsFired]
    264                      yield hold, self, 1
    265
    266          class Caller(Process):
    267              def calling(self):
    268                  while True:
    269                      signal1.signal('wake up!')
    270                      print '%s: signal 1 has occurred'%now()
    271                      yield hold, self, 10
    272                      signal2.signal('and again')
    273                      signal2.signal('sig 2 again')
    274                      print '%s: signal1, signal2 have occurred'%now()
    275                      yield hold, self, 10
    276          print'\n+++testSimEvents output'
    277          initialize()
    278          signal1 = SimEvent('signal 1')
    279          signal2 = SimEvent('signal 2')
    280          signal1.signal('startup1')
    281          signal2.signal('startup2')
    282          w1 = Waiter('waiting for signal 1')
    283          activate(w1, w1.waiting(signal1))
    284          w2 = Waiter('waiting for signal 2')
    285          activate(w2, w2.waiting(signal2))
    286          w3 = Waiter('also waiting for signal 2')
    287          activate(w3, w3.waiting(signal2))
    288          w4 = ORWaiter('waiting for either signal 1 or signal 2')
    289          activate(w4, w4.waiting([signal1, signal2]),prior = True)
    290          c = Caller('Caller')
    291          activate(c, c.calling())
    292          print simulate(until = 100)
    293
    294 -    def testwaituntil():
    295          """
    296          Demo of waitUntil capability.
    297
    298          Scenario:
    299          Three workers require sets of tools to do their jobs. Tools are shared, scarce
    300          resources for which they compete.
    301          """
    302
    303
    304          class Worker(Process):
    305              def __init__(self, name, heNeeds = []):
    306                  Process.__init__(self, name)
    307                  self.heNeeds = heNeeds
    308              def work(self):
    309
    310                  def workerNeeds():
    311                      for item in self.heNeeds:
    312                          if item.n == 0:
    313                              return False
    314                      return True
    315
    316                  while now() < 8 * 60:
    317                      yield waituntil, self, workerNeeds
    318                      for item in self.heNeeds:
    319                          yield request, self, item
    320                      print '%s %s has %s and starts job' % (now(),self.name,
    321                          [x.name for x in self.heNeeds])
    322                      yield hold, self, random.uniform(10, 30)
    323                      for item in self.heNeeds:
    324                          yield release, self, item
    325                      yield hold, self, 2 #rest
    326
    327          print '\n+++ nwaituntil demo output'
    328          initialize()
    329          brush = Resource(capacity = 1, name = 'brush')
    330          ladder = Resource(capacity = 2, name = 'ladder')
    331          hammer = Resource(capacity = 1, name = 'hammer')
    332          saw = Resource(capacity = 1, name = 'saw')
    333          painter = Worker('painter',[brush, ladder])
    334          activate(painter, painter.work())
    335          roofer = Worker('roofer',[hammer, ladder, ladder])
    336          activate(roofer, roofer.work())
    337          treeguy = Worker('treeguy',[saw, ladder])
    338          activate(treeguy, treeguy.work())
    339          for who in (painter, roofer, treeguy):
    340              print '%s needs %s for his job' % (who.name,[x.name for x in who.heNeeds])
    341          print
    342          print simulate(until = 9 * 60)
    343
    344
    345
    346
    347      test_demo()
    348      test_interrupt()
    349      testSimEvents()
    350      testwaituntil()
    351