Browse Source

Fixed delays

rparedis 2 years ago
parent
commit
8c00dd722b
8 changed files with 105 additions and 40 deletions
  1. 3 3
      config.ini
  2. BIN
      de2/__pycache__/elements.cpython-38.pyc
  3. 47 34
      de2/elements.py
  4. 7 2
      main.py
  5. 0 1
      results-de2/plan.csv
  6. 23 0
      stats.ecological.txt
  7. 23 0
      stats.normal.txt
  8. 2 0
      todo.txt

+ 3 - 3
config.ini

@@ -1,6 +1,6 @@
 [simulation]
 ; Whether to visualize the movement of vessels on the map
-visualization = true
+visualization = false
 
 ; Whether to print internal simulation trace to the terminal
 verbose = false
@@ -14,7 +14,7 @@ statistics = true
 ; When zero or negative, runs the simulator as fast as possible
 ; Note: timescale must be strictly positive when using the
 ;    visualization!
-timescale = 0.002
+timescale = 0
 
 ; The time to end the simulation. When zero, no end time
 ;    is considered.
@@ -26,7 +26,7 @@ schedule_file = results-de2/plan.csv
 
 [movement]
 ; When true, the velocities below are ignored and the ETA is used instead
-use_eta = false
+use_eta = true
 
 ; Both tugging and sailing are sampled from a normal distribution
 ;    with the parameters defined below.

BIN
de2/__pycache__/elements.cpython-38.pyc


+ 47 - 34
de2/elements.py

@@ -71,6 +71,7 @@ class Pool(AtomicDEVS):
 		self.state = {
 			"waiting": {},
 			"should_exit": [],
+			"delayed": [],
 			"time": 0.0
 		}
 
@@ -83,47 +84,49 @@ class Pool(AtomicDEVS):
 			if isinstance(mmsi, str):
 				self.state["waiting"][mmsi] = Vessel(mmsi)
 
+	def request_vessel(self, vessel, request):
+		vessel.footprint.idle_time += self.state["time"] - vessel.footprint.idle_since
+
+		# vessel.time_until_departure = (request["end"] - request["start"]) / 1000
+		# vessel.velocity = request["distance"] / vessel.time_until_departure
+		# vessel.distance_left = request["distance"]
+		# vessel.total_distance = request["distance"]
+		# vessel.source = (request["source_lon"], request["source_lat"])
+		# vessel.target = (request["target_lon"], request["target_lat"])
+		# vessel.location = request["location"]
+
+		vessel.velocity = request["velocity"]
+		if vessel.velocity >= 0:  # requests for idling should be ignored!
+			vessel.distance_left = request["distance"]
+			vessel.total_distance = vessel.distance_left
+			# vessel.time_until_departure = vessel.distance_left / vessel.velocity
+			vessel.source = request["source_lon"], request["source_lat"]
+			vessel.target = request["target_lon"], request["target_lat"]
+			vessel.task = request["task"]
+
+			vessel.name = request["name"]
+			vessel.category = request["category"]
+
+			self.state["should_exit"].append(vessel)
+			if vessel.mmsi in self.state["waiting"]:
+				del self.state["waiting"][vessel.mmsi]
+
 	def extTransition(self, inputs):
 		self.state["time"] += self.elapsed
 		if self.req_in in inputs:
 			for request in inputs[self.req_in]:
 				if request["mmsi"] in self.state["waiting"]:
 					vessel = self.state["waiting"][request["mmsi"]]
+					self.request_vessel(vessel, request)
 				else:
-					print("VESSEL %s DOES NOT EXIST IN POOL" % str(request["mmsi"]))
-					# print("\t", request)
-					vessel = Vessel(request["mmsi"])
-
-				vessel.footprint.idle_time += self.state["time"] - vessel.footprint.idle_since
-
-				# vessel.time_until_departure = (request["end"] - request["start"]) / 1000
-				# vessel.velocity = request["distance"] / vessel.time_until_departure
-				# vessel.distance_left = request["distance"]
-				# vessel.total_distance = request["distance"]
-				# vessel.source = (request["source_lon"], request["source_lat"])
-				# vessel.target = (request["target_lon"], request["target_lat"])
-				# vessel.location = request["location"]
-
-				vessel.velocity = request["velocity"]
-				if vessel.velocity > 0: # requests for idling should be ignored!
-					vessel.distance_left = request["distance"]
-					vessel.total_distance = vessel.distance_left
-					# vessel.time_until_departure = vessel.distance_left / vessel.velocity
-					vessel.source = request["source_lon"], request["source_lat"]
-					vessel.target = request["target_lon"], request["target_lat"]
-					vessel.task = request["task"]
-
-					vessel.name = request["name"]
-					vessel.category = request["category"]
-
-					self.state["should_exit"].append(vessel)
-					if vessel.mmsi in self.state["waiting"]:
-						del self.state["waiting"][vessel.mmsi]
+					print("[WARN] %4.4f Vessel %s does not exist in pool - delaying request" % (self.state["time"], str(request["mmsi"])))
+					self.state["delayed"].append(request)
+
 		if self.vessel_in in inputs:
 			for vessel in inputs[self.vessel_in]:
 				if vessel.mmsi in self.state["waiting"]:
-					raise ValueError("Cannot create duplicate vessels (loc = %s; mmsi = %s; d = %f)" %
-					                 (str(vessel.location), str(vessel.mmsi), vessel.total_distance))
+					raise ValueError("[WARN] %4.4f Cannot create duplicate vessels (mmsi = %s; d = %f)" %
+					                 (self.state["time"], str(vessel.mmsi), vessel.total_distance))
 				else:
 					vessel.source = vessel.target
 					vessel.target = None
@@ -141,6 +144,13 @@ class Pool(AtomicDEVS):
 					vessel.footprint.idle_since = self.state["time"]
 
 					self.state["waiting"][vessel.mmsi] = vessel
+
+					for ix, r in enumerate(self.state["delayed"]):
+						if r["mmsi"] == vessel.mmsi:
+							self.request_vessel(vessel, r)
+							self.state["delayed"].pop(ix)
+							print("[INFO] %4.4f Delay for vessel %s cleared" % (self.state["time"], r["mmsi"]))
+							break
 		return self.state
 
 	def timeAdvance(self):
@@ -192,7 +202,10 @@ class Sailer(AtomicDEVS):
 					vessel.velocity = -1
 					while vessel.velocity <= 0 or vessel.velocity > self.v_max:
 						vessel.velocity = random.normalvariate(*self.v_sailing)
-				vessel.time_until_departure = vessel.distance_left / vessel.velocity
+				if vessel.distance_left == 0.0:
+					vessel.time_until_departure = 0.0
+				else:
+					vessel.time_until_departure = vessel.distance_left / vessel.velocity
 				self.state["vessels"].append(vessel)
 		self.state["vessels"].sort(key=lambda v: v.time_until_departure)
 		return self.state
@@ -344,7 +357,6 @@ class Port(CoupledDEVS):
 	def __init__(self, name, ivef, v_tugging=None, v_sailing=None, v_max=None):
 		super(Port, self).__init__(name)
 
-		self.clock = self.addSubModel(Clock("clock"))
 		self.scheduler = self.addSubModel(Scheduler("scheduler", ivef))
 		self.planner = self.addSubModel(RoutePlanner("planner"))
 		# self.tracer = self.addSubModel(Tracer("tracer", ivef))
@@ -357,7 +369,8 @@ class Port(CoupledDEVS):
 		self.connectPorts(self.pool.vessel_out, self.sailer.vessel_in)
 		self.connectPorts(self.sailer.vessel_out, self.pool.vessel_in)
 
-		self.connectPorts(self.clock.outp, self.sailer.update)
+		# self.clock = self.addSubModel(Clock("clock"))
+		# self.connectPorts(self.clock.outp, self.sailer.update)
 
 	def select(self, imm_children):
 		for child in imm_children:

+ 7 - 2
main.py

@@ -1,5 +1,5 @@
 import configparser
-from de2.elements import Port
+from de2.elements import Port, Clock
 from pypdevs.simulator import Simulator
 
 config = configparser.ConfigParser()
@@ -10,9 +10,15 @@ sailing = config.getfloat('movement', 'velocity_mean_sailing'), config.getfloat(
 vel_max = config.getfloat('movement', 'velocity_max')
 if config.getboolean('movement', 'use_eta'):
 	tugging = sailing = vel_max = None
+timescale = config.getfloat('simulation', 'timescale')
 
 port = Port("PoAB", config.get('simulation', 'schedule_file'), tugging, sailing, vel_max)
 
+if config.getboolean('simulation', 'visualization') and timescale > 0:
+	port.clock = port.addSubModel(Clock("clock"))
+	port.connectPorts(port.clock.outp, port.sailer.update)
+
+
 sim = Simulator(port)
 if config.getboolean('simulation', 'verbose'):
 	sim.setVerbose(None)
@@ -22,7 +28,6 @@ if end_time > 0:
 else:
 	sim.setTerminationCondition(lambda _, m: m.scheduler.state["index"] >= len(m.scheduler.ivef))
 
-timescale = config.getfloat('simulation', 'timescale')
 if timescale > 0:
 	sim.setRealTime(scale=timescale)
 

+ 0 - 1
results-de2/plan.csv

@@ -391,4 +391,3 @@ mmsi,start,ETA,source,target,task
 205257290,1643642917825,1643643517824,"(4.351315757000066, 51.26427078800003)","(4.349825623000072, 51.265297763000035)",tugging
 205257290,1643643517824,1643673577824,"(4.349825623000072, 51.265297763000035)","(4.34999, 51.26505)",tugging
 205203390,1643647324324,1643673541824,"(4.320220451000068, 51.31285972400008)","(4.37787, 51.25886)",tugging
-,,,,,

+ 23 - 0
stats.ecological.txt

@@ -0,0 +1,23 @@
+[WARN] 562081.5000 Vessel 205203390 does not exist in pool - delaying request
+[INFO] 562423.7333 Delay for vessel 205203390 cleared
+
+category: strong
+OVERALL COST: 1451752.045145 euros
+Travelling: 4090.183750 euros
+Tugging: 6932.010150 euros
+Waiting: 696729.851245 euros
+Fixed: 744000.000000 euros
+
+category: average
+OVERALL COST: 808656.960514 euros
+Travelling: 2548.513118 euros
+Tugging: 6329.274946 euros
+Waiting: 396779.172451 euros
+Fixed: 403000.000000 euros
+
+category: weak
+OVERALL COST: 381114.244280 euros
+Travelling: 1041.299246 euros
+Tugging: 2113.526445 euros
+Waiting: 114459.418589 euros
+Fixed: 263500.000000 euros

+ 23 - 0
stats.normal.txt

@@ -0,0 +1,23 @@
+
+
+
+category: strong
+OVERALL COST: 1970302.365236 euros
+Travelling: 561067.833292 euros
+Tugging: 663809.698611 euros
+Waiting: 1424.833333 euros
+Fixed: 744000.000000 euros
+
+category: average
+OVERALL COST: 1200046.515620 euros
+Travelling: 257327.531056 euros
+Tugging: 533688.472572 euros
+Waiting: 6030.511992 euros
+Fixed: 403000.000000 euros
+
+category: weak
+OVERALL COST: 469778.511918 euros
+Travelling: 86482.604653 euros
+Tugging: 119561.052682 euros
+Waiting: 234.854583 euros
+Fixed: 263500.000000 euros

+ 2 - 0
todo.txt

@@ -0,0 +1,2 @@
+difference between ecological and original
+sailing delays -- add a tracer?