| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- import copy
- from pypdevs.DEVS import AtomicDEVS
- from pypdevs.infinity import INFINITY
- from events import Request
- import numpy as np
- class Pool(AtomicDEVS):
- def __init__(self, name):
- super(Pool, self).__init__(name)
- self.state = {
- "ships": {},
- "requests": [],
- "delta": 0.,
- "time": 0.
- }
- self.req_in = self.addInPort("req_in")
- self.ship_in = self.addInPort("ship_in")
- self.ship_out_sail = self.addOutPort("ship_out_sail")
- self.ship_out_tug = self.addOutPort("ship_out_tug")
- def timeAdvance(self):
- if len(self.state["requests"]) > 0:
- return self.state["delta"]
- return INFINITY
- def extTransition(self, inputs):
- self.state["time"] += self.elapsed
- if self.req_in in inputs:
- self.state["requests"].append(inputs[self.req_in])
- if self.ship_in in inputs:
- ship = inputs[self.ship_in]
- if ship.id in self.state["ships"]:
- raise ValueError("Impossible entry to pool.")
- self.state["ships"][ship.id] = ship
- return self.state
- def intTransition(self):
- self.state["time"] += self.timeAdvance()
- if len(self.state["requests"]) > 0:
- if self.state["requests"][0].ship in self.state["ships"]:
- req = self.state["requests"].pop(0)
- del self.state["ships"][req.ship]
- self.state["delta"] = 0
- else:
- self.state["delta"] = 0.001
- return self.state
- def outputFnc(self):
- if len(self.state["requests"]) > 0:
- request = self.state["requests"][0]
- if request.ship not in self.state["ships"]:
- print("Cannot find free ship", request.ship)
- return {}
- ship = self.state["ships"][request.ship]
- if ship.position != request.source:
- print("[%s] Ship %s is not at position %s, but at %s" % (self.state["time"], request.ship, request.source, ship.position))
- ship.x = request.distance
- ship.v = request.speed
- ship.position = request.destination
- if request.tugging:
- return {
- self.ship_out_tug: ship
- }
- return {
- self.ship_out_sail: ship
- }
- return {}
- class Sailer(AtomicDEVS):
- def __init__(self, name, alpha, beta):
- super(Sailer, self).__init__(name)
- self.alpha = alpha
- self.beta = beta
- self.state = {
- "time": 0,
- "ships": []
- }
- self.ship_in = self.addInPort("ship_in")
- self.ship_out = self.addOutPort("ship_out")
- def timeAdvance(self):
- if len(self.state["ships"]) > 0:
- return self.state["ships"][0].time_until_departure
- return INFINITY
- def update_ships(self, elapsed):
- for ship in self.state["ships"]:
- ship.x -= ship.v * elapsed
- ship.total_distance += ship.v * elapsed
- ship.time_until_departure = round(ship.time_until_departure - elapsed, 6)
- ship.time_used += elapsed
- def extTransition(self, inputs):
- self.state["time"] += self.elapsed
- self.update_ships(self.elapsed)
- if self.ship_in in inputs:
- ship = inputs[self.ship_in]
- # ship.v = np.random.gamma(self.alpha, self.beta)
- ship.time_start = self.state["time"]
- ship.time_until_departure = round(ship.x / ship.v, 6)
- self.state["ships"].append(ship)
- self.state["ships"] = sorted(self.state["ships"], key=lambda s: s.time_until_departure)
- return self.state
- def intTransition(self):
- elapsed = self.timeAdvance()
- self.state["time"] += elapsed
- self.state["ships"].pop(0)
- self.update_ships(elapsed)
- self.state["ships"] = sorted(self.state["ships"], key=lambda s: s.time_until_departure)
- return self.state
- def outputFnc(self):
- if len(self.state["ships"]) > 0:
- elapsed = self.timeAdvance()
- ship = copy.deepcopy(self.state["ships"][0])
- ship.total_distance += ship.v * elapsed
- ship.time_until_departure -= elapsed
- ship.time_used += elapsed
- return {
- self.ship_out: ship
- }
- return {}
- class Planner(AtomicDEVS):
- def __init__(self, name, plan, layer=None):
- super(Planner, self).__init__(name)
- self.plan = plan
- self.state = {
- "time": 0,
- "delta": 0,
- "index": 0,
- "layer": layer
- }
- self.reqs = self.addOutPort("reqs")
- def timeAdvance(self):
- if self.state["index"] > len(self.plan):
- return INFINITY
- return self.state["delta"]
- def intTransition(self):
- self.state["time"] += self.timeAdvance()
- self.state["layer"].paths = [p for p in self.state["layer"].paths if p["time_end"] < self.state["time"]]
- record = self.plan.iloc[self.state["index"]]
- if self.state["layer"] is not None:
- self.state["layer"].paths.append(record)
- self.state["index"] += 1
- self.state["delta"] = self.plan.iloc[self.state["index"]]["time"] - self.state["time"]
- return self.state
- def outputFnc(self):
- record = self.plan.iloc[self.state["index"]]
- # TODO: fix location check
- speed = record["distance"] / (record["time_end"] - record["time"])
- req = Request(round(self.state["time"] + self.timeAdvance(), 6), record["Sleepboot"], record["distance"], record["tugging"], record["Locatie van"], record["Locatie naar"], speed)
- return {
- self.reqs: req
- }
|