generator.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. from pypdevs.DEVS import AtomicDEVS
  2. from job import Job
  3. import random
  4. # Define the state of the generator as a structured object
  5. class GeneratorState:
  6. def __init__(self, gen_num, seed=0):
  7. # Current simulation time (statistics)
  8. self.current_time = 0.0
  9. # Remaining time until generation of new event
  10. self.remaining = 0.0
  11. # Counter on how many events to generate still
  12. self.to_generate = gen_num
  13. # Next job to output
  14. self.next_job = None
  15. # State of our random number generator
  16. self.random = random.Random(seed)
  17. class Generator(AtomicDEVS):
  18. def __init__(self, gen_param, size_param, gen_num):
  19. AtomicDEVS.__init__(self, "Generator")
  20. # Output port for the event
  21. self.out_event = self.addOutPort("out_event")
  22. # Parameters defining the generator's behaviour
  23. self.gen_param = gen_param
  24. self.size_param = size_param
  25. # Init state
  26. self.state = GeneratorState(gen_num)
  27. self.__nextJob() # already schedule the first job to generate
  28. def __nextJob(self):
  29. # Determine size of the event to generate
  30. size = max(1, int(self.state.random.gauss(self.size_param, 5)))
  31. # Calculate current time (note the addition!)
  32. creation = self.state.current_time + self.state.remaining
  33. # Update state
  34. self.state.next_job = Job(size, creation)
  35. self.state.remaining = self.state.random.expovariate(self.gen_param)
  36. def intTransition(self):
  37. # Update simulation time
  38. self.state.current_time += self.timeAdvance()
  39. # Update number of generated events
  40. self.state.to_generate -= 1
  41. if self.state.to_generate == 0:
  42. # Already generated enough events, so stop
  43. self.state.remaining = float('inf')
  44. self.state.next_job = None
  45. else:
  46. # Still have to generate events, so sample for new duration
  47. self.__nextJob()
  48. return self.state
  49. def timeAdvance(self):
  50. # Return remaining time; infinity when generated enough
  51. return self.state.remaining
  52. def outputFnc(self):
  53. # Output the new event on the output port
  54. return {self.out_event: self.state.next_job}