How does a computer store, sort and process the events during a simulation implemented with with Simpy? -


i'm facing synchronization problem in simpy. that, mean events not processed computer in order to. have been looking lot more information in simpy documentation how events queued, sorted , processed computer. found everywhere sorted respect time have triggered at. before reading remaining, have links or document advise me?

more specifically, trying model , simulate real world systems (an instance of poolsystem class), pool of subsystems can either further broken down sub-subsystems or capable of failing (this last category of system called atomicsystem). sum up, poolsystem made of subsystems can either poolsystem or atomicsystem.

for instance, car instance of poolsystem class, engine subsystem. engine can broken down several other subsystems such piston or sparking plug, can fail. in case, engine defined poolsystem instance , piston , sparking plug atomicsystem instances.

the atomicsystem , poolsystem classes based on same standard model. both have:

  • a "critical" boolean attribute "true" if failure of given subsystem induces failure of whole system (which means other subsystems must interrupted)
  • an "update_order" event acts signal system communicate subsystems (if any)
  • a "dysfunction_signal" event signal subsystems tell system have failed
  • a "interrupted" event triggered whenever given system cannot work or whenever has been interrupted higher level system
  • an "update_end" event acts signal subsystem tell higher level system has finished update
  • a "lifecycle" attribute process simulates operational service of given system

i hope following schema can understanding read: the breakdown of car defined pool system

on schema, car defined poolsystem instance subsystems engine , tyre. tyre can firect cause of failure car defined atomicsystem instance. engine defined poolsystem subsystems piston , sparking plug, can fail defined atomicsystem instances.

the class atomicsystem can found below:

class atomicsystem(object): def __init__(self, env, mtbd, backlog, user_defined_critical=true, ids=none):     self.env = env                                       # environment()         self.mtbd = mtbd                                     # mean time between dysfunction     self.critical = user_defined_critical                # boolean     self.ids = ids                                       # list of strings     self.ttd = self.time_to_dysfunction()                # time before dysfunction     self.update_order = self.env.event()                      self.dysfunction_signal = self.env.event()                self.interrupted = self.env.event()     self.update_end = self.env.event()     self.lifecycle = self.env.process(self.run(backlog))  def time_to_dysfunction(self):     return self.mtbd  def run(self, backlog):     # atomic system starts service when update_order event triggered     yield self.update_order     print("t = " + str(self.env.now) + " : " + self.ids[-1] + " starts service.")     self.update_order = self.env.event()      # atomic system specifies higher level system has started service     self.update_end.succeed()     self.update_end = self.env.event()      try:         # long atomic system remains in while loop, said in service.         while true:             start = self.env.now             time_out = self.env.timeout(self.ttd)              # wait dysfunction (time_out) or interruption (interrupted) or update higher level system (update_order)             result = yield time_out | self.interrupted | self.update_order              if time_out in result:                 print("t = " + str(self.env.now) + " : " + self.ids[-1] + " fails.")                  # if atomic system fails, trigger dysfunction_signal event destined detected higher level system                 self.dysfunction_signal.succeed()                 # when atomic system fails, interrupted event automatically triggered                  self.interrupted.succeed()                 if self.ttd > 0:                     backlog.append({"dysfunction time": self.env.now, "ids": self.ids})                 self.ttd = 0              if self.interrupted.triggered:                 print("t = " + str(self.env.now) + " : " + self.ids[-1] + " interrupts service.")                 if self.ttd > 0:                     operation_duration = self.env.now - start                     self.ttd -= operation_duration                  # atomic system waits update_order trigger when has been interrupted                 yield self.update_order               if self.update_order.triggered:             # here, atomic system returns service                 print("t = " + str(self.env.now) + " : " + self.ids[-1] + " updated.")                 if self.ttd > 0:                     operation_duration = self.env.now - start                     self.ttd -= operation_duration                 self.update_end.succeed()                 self.update_order = self.env.event()                 self.dysfunction_signal = self.env.event()                 self.interrupted = self.env.event()                 self.update_end = self.env.event()      except:     # here atomic system terminated (end of service)         print("t = " + str(self.env.now) + " : " + self.ids[-1] + " terminated.")         self.env.exit() 

the class poolsystem can found below:

class poolsystem(object): def __init__(self, env, id, init_subsystems, user_defined_critical=true):     self.env = env     self.id = id     self.subsystems = init_subsystems     self.working_subsystems = [self.subsystems[key] key in self.subsystems.keys()]     self.critical = user_defined_critical     self.update_order = self.env.event()     self.dysfunction_signal = simpy.anyof(self.env, [syst.dysfunction_signal syst in self.working_subsystems])     self.interrupted = self.env.event()     self.update_end = self.env.event()     self.lifecycle = self.env.process(self.run())  def start_subsystems(self):     key in self.subsystems.keys():         self.subsystems[key].update_order.succeed()  def run(self):     user_defined_critical = self.critical      # pool system started here when update_order event triggered     yield self.update_order     print("t = " + str(self.env.now) + " : " + self.id + " starts service.")     self.update_order = self.env.event()      # here, pool system starts of subsystems (which can atomic and/or pool systems)     self.start_subsystems()      # here, update_end triggered if update_end events of subsystems have been triggered     self.update_end = simpy.allof(self.env, [self.subsystems[key].update_end key in self.subsystems.keys()])     yield self.update_end     try:         while true:              # wait dysfunction (dysfunction_signal), interruption (interrupted) or update higher level system (update_order)             yield self.dysfunction_signal | self.interrupted | self.update_order               if self.dysfunction_signal.triggered:                 crit = []                 syst in self.working_subsystems:                     if syst.dysfunction_signal.triggered:                         crit.append(syst.critical)                 if true in crit: # if 1 of failed subsystems critical (critical = true), trigger interrupted event()                     print("t = " + str(self.env.now) + " : " + self.id + " fails completely.")                     # pool system interrupted                     self.critical = user_defined_critical                     self.interrupted.succeed()                 else:                     # no critical subsystem has failed yet pool system can continue working (no interruption here)                     self.critical = false                     self.working_subsystems = [self.subsystems[key] key in self.subsystems.keys() if                                                not self.subsystems[key].interrupted.triggered]                     if len(self.working_subsystems) not 0:                         print("t = " + str(self.env.now) + " : " + self.id + " fails partially.")                         self.dysfunction_signal = simpy.anyof(self.env, [syst.dysfunction_signal syst in                                                                          self.working_subsystems])                     else:                     # pool system interrupted if of subsystems have failed                         print("t = " + str(self.env.now) + " : " + self.id + " fails (no working eus).")                         self.interrupted.succeed()              if self.interrupted.triggered:                 print("t = " + str(self.env.now) + " : " + self.id + " interrupts service.")                 # interrupt subsystems                 key in self.subsystems.keys():                     if not self.subsystems[key].interrupted.triggered:                         self.subsystems[key].interrupted.succeed()                  # waits update_order higher level system                 yield self.update_order              if self.update_order.triggered:                 print("t = " + str(self.env.now) + " : " + self.id + " updated.")                 # update_order has been troggered higher level system                                     self.update_order = self.env.event()                 self.start_subsystems()                 self.update_end = simpy.allof(self.env,                                               [self.subsystems[key].update_end key in self.subsystems.keys()])                 # wait end of update of subsystems                 yield self.update_end                 print("t = " + str(self.env.now) + " : " + self.id + " receives update-end signal.")                 self.working_subsystems = [self.subsystems[key] key in self.subsystems.keys()]                 self.dysfunction_signal = simpy.anyof(self.env,                                                       [syst.dysfunction_signal syst in self.working_subsystems])                 self.interrupted = self.env.event()       except simpy.interrupt:     # here pool system terminated, leaves service.         key in self.subsystems.keys():             self.subsystems[key].lifecycle.interrupt()         self.env.exit() 

i have defined 2 other classes, eu (inheriting atomicsystem) , modsat (inheriting poolsystem). basically, i'm building modsat object out of several eu objects (only 2 system levels). have posted code below:

class eu(atomicsystem): def __init__(self, env, identity, mtbd, backlog, critical=true, ids=none):     self.id = identity     ids.append(self.id)     atomicsystem.__init__(self, env, mtbd, backlog, critical, ids)  class modsat(poolsystem): def __init__(self, env, digit_id, eu_mtbds_criticals, backlog, critical=true):     identity = "modsat" + str(digit_id)     self.eus = self.initialize(env, identity, eu_mtbds_criticals, backlog)     poolsystem.__init__(self, env, identity, self.eus, critical)  def initialize(self, env, identity, eu_mtbds_criticals, backlog):     eus = {}     in range(1, len(eu_mtbds_criticals) + 1):         eu_id = "eu" + str(i) + ":" + identity         eu = eu(env, eu_id, eu_mtbds_criticals[i - 1][0], backlog, eu_mtbds_criticals[i - 1][1], [identity])         eus[eu_id] = eu     return eus 

finally, wanted test modsat objects , see if replace 1 of failed subsystems (eu type) of modsat object without affecting behavior of modsat. created simulate function enables me interact modsat objects. ran tests 2 modsat objects defined by:

backlog = [] eu_mtbds_criticals1 = [[5, false], [11, false], [19, false]] eu_mtbds_criticals2 = [[4, false], [27, false], [38, false]] env = simpy.environment() sat1 = modsat(env, 1, eu_mtbds_criticals1, backlog, true) sat2 = modsat(env, 2, eu_mtbds_criticals2, backlog, true) constellation = {'modsat1': sat1, 'modsat2': sat2} env.process(simulate(constellation, env, backlog)) env.run(until=100) 

the first test simple following simulate function:

def simulate(constellation, env, backlog): key in constellation.keys():     # start service of each modsat object included in constellation dictionary,      # triggering update_order event.     constellation[key].update_order.succeed()  # wait while sure modsat objects have been simulated. yield env.timeout(50) 

the output wanted because events seem have been triggered , processed in right order computer:

# 1st update_order event of poolsystem triggered t = 0 : modsat1 starts service. t = 0 : modsat2 starts service. # 1st update_order event of atomicsystem triggered t = 0 : eu1:modsat1 starts service. t = 0 : eu3:modsat1 starts service. t = 0 : eu2:modsat1 starts service. t = 0 : eu2:modsat2 starts service. t = 0 : eu1:modsat2 starts service. t = 0 : eu3:modsat2 starts service. # 1st failure here. since critical attribute of eu1:modsat2 set false modsat2 not interrupted (partial failure) t = 4 : eu1:modsat2 fails. t = 4 : eu1:modsat2 interrupts service. t = 4 : modsat2 fails partially. # 2nd failure here t = 5 : eu1:modsat1 fails. t = 5 : eu1:modsat1 interrupts service. t = 5 : modsat1 fails partially. t = 11 : eu2:modsat1 fails. t = 11 : eu2:modsat1 interrupts service. t = 11 : modsat1 fails partially. # here last failure of modsat1: modsat1 interrupted because has no more working eus t = 19 : eu3:modsat1 fails. t = 19 : eu3:modsat1 interrupts service. t = 19 : modsat1 fails (no working eus). t = 19 : modsat1 interrupts service. t = 27 : eu2:modsat2 fails. t = 27 : eu2:modsat2 interrupts service. t = 27 : modsat2 fails partially. # here last failure of modsat2: modsat2 interrupted because has no more working eus t = 38 : eu3:modsat2 fails. t = 38 : eu3:modsat2 interrupts service. t = 38 : modsat2 fails (no working eus). t = 38 : modsat2 interrupts service. 

now, want test code following simulate function:

def simulate(constellation, env, backlog):     key in constellation.keys():     # start service of each modsat object included in constellation dictionary,      # triggering update_order event.         constellation[key].update_order.succeed()       # detect failure     request_signal = simpy.anyof(env, [constellation[key].dysfunction_signal key in constellation.keys()])     yield request_signal      # servicer's backlog updated first item of backlog list     print("t = " + str(env.now) + " : service request detected.")     servicer_backlog = []     servicer_backlog.append(backlog[0])     del backlog[0]      # next line models servicer time of service     yield env.timeout(5)      # servicer gets id of failed eu replace backlog     sat_id = servicer_backlog[0]['ids'][0]     eu_id =  servicer_backlog[0]['ids'][1]     failed_eu = constellation[sat_id].eus[eu_id]     # servicer gives values of attributes of failed eu new eu     new_eu = eu(failed_eu.env, failed_eu.id, failed_eu.mtbd, backlog, failed_eu.critical, failed_eu.ids)     # failed eu terminated (its service ends)     failed_eu.lifecycle.interrupt()     # new eu replaces failed_eu     constellation[sat_id].eus[eu_id] = new_eu     # modsat concerned replacement has update_order event triggered     constellation[sat_id].update_order.succeed()     print("t = " + str(env.now) + " : service provided") 

the simulate function above models replacement of first failed eu new one. output is:

# 1st update_order event of poolsystem triggered t = 0 : modsat1 starts service. t = 0 : modsat2 starts service. # 1st update_order event of atomicsystem triggered t = 0 : eu3:modsat1 starts service. t = 0 : eu2:modsat1 starts service. t = 0 : eu1:modsat1 starts service. t = 0 : eu1:modsat2 starts service. t = 0 : eu2:modsat2 starts service. t = 0 : eu3:modsat2 starts service. t = 0 : modsat1 receives update-end signal. t = 0 : modsat2 receives update-end signal. # first eu of modsat2 fails, , failure detected simulate function t = 4 : eu1:modsat2 fails. t = 4 : eu1:modsat2 interrupts service. t = 4 : service request detected. t = 4 : modsat2 fails partially. # here concern: @ time t = 5, eu1 of modsat1 fails , interrupts service. however, there should line "t = 5 : modsat1 fails partially" not appear...  t = 5 : eu1:modsat1 fails. t = 5 : eu1:modsat1 interrupts service. t = 9 : service provided t = 9 : eu1:modsat2 terminated. t = 9 : modsat2 updated. t = 9 : eu1:modsat2 starts service. t = 9 : eu2:modsat2 updated. t = 9 : eu3:modsat2 updated. t = 9 : modsat2 receives update-end signal. t = 11 : eu2:modsat1 fails. t = 11 : eu2:modsat1 interrupts service. t = 13 : eu1:modsat2 fails. t = 13 : eu1:modsat2 interrupts service. t = 13 : modsat2 fails partially. t = 19 : eu3:modsat1 fails. t = 19 : eu3:modsat1 interrupts service. t = 27 : eu2:modsat2 fails. t = 27 : eu2:modsat2 interrupts service. t = 27 : modsat2 fails partially. t = 38 : eu3:modsat2 fails. t = 38 : eu3:modsat2 interrupts service. t = 38 : modsat2 fails (no working eus). t = 38 : modsat2 interrupts service. 

as indicated above, there should line @ "t = 5 : modsat1 fails partially" after line "t = 5 : eu1:modsat1 interrupts service". instead, computer jumps directly first line after "yield env.timeout(5)" of simulate function.

i don't understand happens here, think that's because of lack of knowledge how defined , sorted queue of events simpy. not find hint online of what's going on here. have not seen question of kind on stackoverflow , other forums. gladly appreciate help.

my code quite long explain hope comments in code posted sufficient :\

thank much!

i (finally) started guide time in simpy. still wip, can follow discussion here.


Comments

Popular posts from this blog

java - SSE Emitter : Manage timeouts and complete() -

jquery - uncaught exception: DataTables Editor - remote hosting of code not allowed -

java - How to resolve error - package com.squareup.okhttp3 doesn't exist? -