generator.py 2.4 KB

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