movingcircle.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import random
  2. import sys
  3. sys.path.append("../../src/")
  4. from DEVS import AtomicDEVS, CoupledDEVS
  5. from mpi4py import MPI
  6. class CircleNodeState(object):
  7. def __init__(self):
  8. self.event = None
  9. self.queue = []
  10. self.nr = 0
  11. self.generated = 0
  12. def copy(self):
  13. a = CircleNodeState()
  14. a.event = self.event
  15. a.queue = list(self.queue)
  16. a.nr = self.nr
  17. a.generated = self.generated
  18. return a
  19. def __hash__(self):
  20. return self.event + sum(self.queue)
  21. def __eq__(self, other):
  22. # For memoization
  23. if self.event == other.event and self.queue == other.queue and self.nr == other.nr and self.generated == other.generated:
  24. return True
  25. else:
  26. return False
  27. def __str__(self):
  28. return "%s (%s)" % (self.event, self.queue)
  29. class CircleNode(AtomicDEVS):
  30. def __init__(self, nr, count, multiplier):
  31. AtomicDEVS.__init__(self, "CircleNode" + str(nr))
  32. self.inport = self.addInPort("input")
  33. self.outport = self.addOutPort("output")
  34. self.state = CircleNodeState()
  35. #self.state.event = random.randint(2, 100)
  36. self.state.nr = nr
  37. self.state.generated = 0
  38. self.state.event = nr
  39. self.count = count
  40. self.multiplier = multiplier
  41. def intTransition(self):
  42. if 0.6 * self.count < self.state.nr < 0.7 * self.count:
  43. for _ in xrange(self.state.nr*self.multiplier):
  44. pass
  45. if self.state.queue:
  46. self.state.event = self.state.queue.pop()
  47. else:
  48. self.state.event = None
  49. self.state.generated += 1
  50. if self.state.generated == 10:
  51. self.state.nr = (self.state.nr + 1) % self.count
  52. self.state.generated = 0
  53. return self.state
  54. def extTransition(self, inputs):
  55. if self.state.event is None:
  56. self.state.event = inputs[self.inport][0]
  57. else:
  58. self.state.queue.append(inputs[self.inport][0])
  59. return self.state
  60. def timeAdvance(self):
  61. if self.state.event is None:
  62. return float('inf')
  63. else:
  64. #return self.state.event
  65. return 1.0
  66. def outputFnc(self):
  67. return {self.outport: [self.state.event]}
  68. class MovingCircle(CoupledDEVS):
  69. def __init__(self, count, multiplier):
  70. import math
  71. CoupledDEVS.__init__(self, "Circle")
  72. nodes = []
  73. try:
  74. from mpi4py import MPI
  75. pernode = float(count) / MPI.COMM_WORLD.Get_size()
  76. except ImportError:
  77. pernode = float(count)
  78. for i in range(count):
  79. nodes.append(self.addSubModel(CircleNode(i, count, multiplier), math.floor(i/pernode)))
  80. for index in range(len(nodes)):
  81. self.connectPorts(nodes[index-1].outport, nodes[index].inport)
  82. if __name__ == "__main__":
  83. random.seed(1)
  84. from simulator import Simulator
  85. model = MovingCircle(int(sys.argv[1]), int(sys.argv[2]))
  86. sim = Simulator(model)
  87. sim.setTerminationTime(int(sys.argv[3]))
  88. #sim.setVerbose(True)
  89. sim.setMessageCopy('none')
  90. sim.setStateSaving('custom')
  91. sim.setGVTInterval(1 if int(argv[1]) < 500 else 5)
  92. from allocator import MyAllocator
  93. sim.setInitialAllocator(MyAllocator())
  94. #sim.setDrawModel(True, 'model.dot', True)
  95. if sys.argv[4] == "True":
  96. sim.setActivityRelocatorBasicBoundary(1.1)
  97. sim.setMemoization(True)
  98. sim.setSchedulerSortedList()
  99. #sim.setActivityTracking(True)
  100. #sim.setShowProgress()
  101. sim.simulate()