atomic.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import copy
  2. from pypdevs.DEVS import AtomicDEVS
  3. from pypdevs.infinity import INFINITY
  4. from events import Request
  5. import numpy as np
  6. class Pool(AtomicDEVS):
  7. def __init__(self, name):
  8. super(Pool, self).__init__(name)
  9. self.state = {
  10. "ships": {},
  11. "requests": [],
  12. "delta": 0.,
  13. "time": 0.
  14. }
  15. self.req_in = self.addInPort("req_in")
  16. self.ship_in = self.addInPort("ship_in")
  17. self.ship_out_sail = self.addOutPort("ship_out_sail")
  18. self.ship_out_tug = self.addOutPort("ship_out_tug")
  19. def timeAdvance(self):
  20. if len(self.state["requests"]) > 0:
  21. return self.state["delta"]
  22. return INFINITY
  23. def extTransition(self, inputs):
  24. self.state["time"] += self.elapsed
  25. if self.req_in in inputs:
  26. self.state["requests"].append(inputs[self.req_in])
  27. if self.ship_in in inputs:
  28. ship = inputs[self.ship_in]
  29. if ship.id in self.state["ships"]:
  30. raise ValueError("Impossible entry to pool.")
  31. self.state["ships"][ship.id] = ship
  32. return self.state
  33. def intTransition(self):
  34. self.state["time"] += self.timeAdvance()
  35. if len(self.state["requests"]) > 0:
  36. if self.state["requests"][0].ship in self.state["ships"]:
  37. req = self.state["requests"].pop(0)
  38. del self.state["ships"][req.ship]
  39. self.state["delta"] = 0
  40. else:
  41. self.state["delta"] = 0.001
  42. return self.state
  43. def outputFnc(self):
  44. if len(self.state["requests"]) > 0:
  45. request = self.state["requests"][0]
  46. if request.ship not in self.state["ships"]:
  47. print("Cannot find free ship", request.ship)
  48. return {}
  49. ship = self.state["ships"][request.ship]
  50. if ship.position != request.source:
  51. print("[%s] Ship %s is not at position %s, but at %s" % (self.state["time"], request.ship, request.source, ship.position))
  52. ship.x = request.distance
  53. ship.v = request.speed
  54. ship.position = request.destination
  55. if request.tugging:
  56. return {
  57. self.ship_out_tug: ship
  58. }
  59. return {
  60. self.ship_out_sail: ship
  61. }
  62. return {}
  63. class Sailer(AtomicDEVS):
  64. def __init__(self, name, alpha, beta):
  65. super(Sailer, self).__init__(name)
  66. self.alpha = alpha
  67. self.beta = beta
  68. self.state = {
  69. "time": 0,
  70. "ships": []
  71. }
  72. self.ship_in = self.addInPort("ship_in")
  73. self.ship_out = self.addOutPort("ship_out")
  74. def timeAdvance(self):
  75. if len(self.state["ships"]) > 0:
  76. return self.state["ships"][0].time_until_departure
  77. return INFINITY
  78. def update_ships(self, elapsed):
  79. for ship in self.state["ships"]:
  80. ship.x -= ship.v * elapsed
  81. ship.total_distance += ship.v * elapsed
  82. ship.time_until_departure = round(ship.time_until_departure - elapsed, 6)
  83. ship.time_used += elapsed
  84. def extTransition(self, inputs):
  85. self.state["time"] += self.elapsed
  86. self.update_ships(self.elapsed)
  87. if self.ship_in in inputs:
  88. ship = inputs[self.ship_in]
  89. # ship.v = np.random.gamma(self.alpha, self.beta)
  90. ship.time_start = self.state["time"]
  91. ship.time_until_departure = round(ship.x / ship.v, 6)
  92. self.state["ships"].append(ship)
  93. self.state["ships"] = sorted(self.state["ships"], key=lambda s: s.time_until_departure)
  94. return self.state
  95. def intTransition(self):
  96. elapsed = self.timeAdvance()
  97. self.state["time"] += elapsed
  98. self.state["ships"].pop(0)
  99. self.update_ships(elapsed)
  100. self.state["ships"] = sorted(self.state["ships"], key=lambda s: s.time_until_departure)
  101. return self.state
  102. def outputFnc(self):
  103. if len(self.state["ships"]) > 0:
  104. elapsed = self.timeAdvance()
  105. ship = copy.deepcopy(self.state["ships"][0])
  106. ship.total_distance += ship.v * elapsed
  107. ship.time_until_departure -= elapsed
  108. ship.time_used += elapsed
  109. return {
  110. self.ship_out: ship
  111. }
  112. return {}
  113. class Planner(AtomicDEVS):
  114. def __init__(self, name, plan, layer=None):
  115. super(Planner, self).__init__(name)
  116. self.plan = plan
  117. self.state = {
  118. "time": 0,
  119. "delta": 0,
  120. "index": 0,
  121. "layer": layer
  122. }
  123. self.reqs = self.addOutPort("reqs")
  124. def timeAdvance(self):
  125. if self.state["index"] > len(self.plan):
  126. return INFINITY
  127. return self.state["delta"]
  128. def intTransition(self):
  129. self.state["time"] += self.timeAdvance()
  130. self.state["layer"].paths = [p for p in self.state["layer"].paths if p["time_end"] < self.state["time"]]
  131. record = self.plan.iloc[self.state["index"]]
  132. if self.state["layer"] is not None:
  133. self.state["layer"].paths.append(record)
  134. self.state["index"] += 1
  135. self.state["delta"] = self.plan.iloc[self.state["index"]]["time"] - self.state["time"]
  136. return self.state
  137. def outputFnc(self):
  138. record = self.plan.iloc[self.state["index"]]
  139. # TODO: fix location check
  140. speed = record["distance"] / (record["time_end"] - record["time"])
  141. req = Request(round(self.state["time"] + self.timeAdvance(), 6), record["Sleepboot"], record["distance"], record["tugging"], record["Locatie van"], record["Locatie naar"], speed)
  142. return {
  143. self.reqs: req
  144. }