vlcSim 0.6.2__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vlcSim
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: Python Package of Event-Oriented Simulation for visible light communication
5
5
  License: MIT
6
6
  License-File: LICENSE.md
@@ -318,6 +318,36 @@ sim.print_initial_info() # Display scenario configuration
318
318
  - `get_Allocated_Connections()`: Connections assigned to an AP
319
319
  - `get_Waiting_Connections()`: Connections currently waiting for retry
320
320
  - `get_Blocked_Connections()`: Connections rejected with `NOT_ALLOCATED`
321
+ - `get_Response_Time()`: Per-connection time from arrival to first service
322
+ - `get_Average_Response_Time()`: Mean response time for completed connections
323
+ - `get_Turnaround_Time()`: Per-connection time from arrival to completion
324
+ - `get_Average_Turnaround_Time()`: Mean turnaround time for completed connections
325
+ - `get_Waiting_Time()`: Per-connection total waiting time, including TDM gaps between slots
326
+ - `get_Average_Waiting_Time()`: Mean total waiting time for completed connections
327
+
328
+ **Time Metrics:**
329
+
330
+ VLCSim reports time metrics for completed connections only:
331
+
332
+ ```python
333
+ response_time = first_service_time - arrival_time
334
+ turnaround_time = finish_time - arrival_time
335
+ waiting_time = turnaround_time - active_service_time
336
+ ```
337
+
338
+ `first_service_time` is the first `RESUME` event for a connection.
339
+ `active_service_time` is the effective transmission time accumulated by the receiver.
340
+ In TDM simulations, waiting time includes the initial delay before first service
341
+ and the idle gaps between assigned slots or frames, so it can be larger than
342
+ response time.
343
+
344
+ ```python
345
+ sim.run()
346
+
347
+ avg_response_time = sim.get_Average_Response_Time()
348
+ avg_turnaround_time = sim.get_Average_Turnaround_Time()
349
+ avg_waiting_time = sim.get_Average_Waiting_Time()
350
+ ```
321
351
 
322
352
  ### Scenario Class
323
353
 
@@ -294,6 +294,36 @@ sim.print_initial_info() # Display scenario configuration
294
294
  - `get_Allocated_Connections()`: Connections assigned to an AP
295
295
  - `get_Waiting_Connections()`: Connections currently waiting for retry
296
296
  - `get_Blocked_Connections()`: Connections rejected with `NOT_ALLOCATED`
297
+ - `get_Response_Time()`: Per-connection time from arrival to first service
298
+ - `get_Average_Response_Time()`: Mean response time for completed connections
299
+ - `get_Turnaround_Time()`: Per-connection time from arrival to completion
300
+ - `get_Average_Turnaround_Time()`: Mean turnaround time for completed connections
301
+ - `get_Waiting_Time()`: Per-connection total waiting time, including TDM gaps between slots
302
+ - `get_Average_Waiting_Time()`: Mean total waiting time for completed connections
303
+
304
+ **Time Metrics:**
305
+
306
+ VLCSim reports time metrics for completed connections only:
307
+
308
+ ```python
309
+ response_time = first_service_time - arrival_time
310
+ turnaround_time = finish_time - arrival_time
311
+ waiting_time = turnaround_time - active_service_time
312
+ ```
313
+
314
+ `first_service_time` is the first `RESUME` event for a connection.
315
+ `active_service_time` is the effective transmission time accumulated by the receiver.
316
+ In TDM simulations, waiting time includes the initial delay before first service
317
+ and the idle gaps between assigned slots or frames, so it can be larger than
318
+ response time.
319
+
320
+ ```python
321
+ sim.run()
322
+
323
+ avg_response_time = sim.get_Average_Response_Time()
324
+ avg_turnaround_time = sim.get_Average_Turnaround_Time()
325
+ avg_waiting_time = sim.get_Average_Waiting_Time()
326
+ ```
297
327
 
298
328
  ### Scenario Class
299
329
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "vlcSim"
3
- version = "0.6.2" # Placeholder, will be replaced by dynamic versioning
3
+ version = "0.7.0" # Placeholder, will be replaced by dynamic versioning
4
4
  description = "Python Package of Event-Oriented Simulation for visible light communication"
5
5
  authors = ["Danilo Bórquez-Paredes <danilo.borquez.p@uai.cl>"]
6
6
  license = "MIT"
@@ -30,7 +30,7 @@ See Also:
30
30
  For detailed documentation, visit the project repository or build the Sphinx docs.
31
31
  """
32
32
 
33
- __version__ = "0.6.2" # placeholder for poetry-dynamic-versioning
33
+ __version__ = "0.7.0" # placeholder for poetry-dynamic-versioning
34
34
 
35
35
  from .scene import *
36
36
  from .controller import *
@@ -360,7 +360,7 @@ class Controller:
360
360
  raise ValueError(
361
361
  "Receiver must have goalTime set before resuming connection."
362
362
  )
363
- if receiver.goalTime < receiver.timeActive + connection.AP.sliceTime:
363
+ if receiver.goalTime <= receiver.timeActive + connection.AP.sliceTime:
364
364
  return (
365
365
  Controller.nextStatus.FINISH,
366
366
  time + receiver.goalTime - receiver.timeActive,
@@ -253,6 +253,10 @@ class Simulator:
253
253
  self.__allocatedConnectionIds: set[int] = set()
254
254
  self.__blockedConnectionIds: set[int] = set()
255
255
  self.__waitingConnectionIds: set[int] = set()
256
+ self.__firstServiceTimes: dict[int, float] = {}
257
+ self.__responseTimes: List[float] = []
258
+ self.__turnaroundTimes: List[float] = []
259
+ self.__waitingTimes: List[float] = []
256
260
  # time
257
261
  self.__clock: float = 0.0
258
262
  self.__time_duration: Optional[float] = None
@@ -900,9 +904,6 @@ class Simulator:
900
904
  next_status == Controller.nextStatus.RESUME
901
905
  or next_status == Controller.nextStatus.PAUSE
902
906
  ):
903
- connection.receiver.goalTime = self.__departure_variable.exponential(
904
- self.__mu
905
- )
906
907
  connection.allocated = True
907
908
  if next_status == Controller.nextStatus.RESUME:
908
909
  for pos in range(len(self.__events) - 1, -1, -1):
@@ -953,6 +954,7 @@ class Simulator:
953
954
  elif self.__current_event.type == Event.event.RESUME:
954
955
  if not self.__current_event.connection:
955
956
  return
957
+ self.__record_first_service_time(self.__current_event.connection)
956
958
  next_status, time, connection = self.__controller.resumeConnection(
957
959
  self.__current_event.connection, self.__clock
958
960
  )
@@ -977,9 +979,11 @@ class Simulator:
977
979
  elif self.__current_event.type == Event.event.DEPARTURE:
978
980
  if not self.__current_event.connection:
979
981
  return
982
+ completed_connection = self.__current_event.connection
980
983
  next_status, time, connection = self.__controller.unassignConnection(
981
- self.__current_event.connection, self.__clock
984
+ completed_connection, self.__clock
982
985
  )
986
+ self.__record_completed_connection_time_metrics(completed_connection)
983
987
  # if next_status == Controller.nextStatus.RESUME:
984
988
  # for pos in range(len(self.__events) - 1, -1, -1):
985
989
  # if self.__events[pos].time <= time:
@@ -1017,6 +1021,33 @@ class Simulator:
1017
1021
  if connection_id not in self.__allocatedConnectionIds:
1018
1022
  self.__blockedConnectionIds.add(connection_id)
1019
1023
 
1024
+ def __record_first_service_time(self, connection: Connection) -> None:
1025
+ connection_id = connection.id
1026
+ if connection_id not in self.__firstServiceTimes:
1027
+ self.__firstServiceTimes[connection_id] = self.__clock
1028
+
1029
+ def __record_completed_connection_time_metrics(
1030
+ self, connection: Connection
1031
+ ) -> None:
1032
+ first_service_time = self.__firstServiceTimes.get(connection.id)
1033
+ finish_time = connection.receiver.timeFinished
1034
+ if first_service_time is None or finish_time is None:
1035
+ return
1036
+
1037
+ response_time = first_service_time - connection.time
1038
+ turnaround_time = finish_time - connection.time
1039
+ waiting_time = max(0.0, turnaround_time - connection.receiver.timeActive)
1040
+
1041
+ self.__responseTimes.append(response_time)
1042
+ self.__turnaroundTimes.append(turnaround_time)
1043
+ self.__waitingTimes.append(waiting_time)
1044
+
1045
+ @staticmethod
1046
+ def __average(values: List[float]) -> float:
1047
+ if len(values) == 0:
1048
+ return 0.0
1049
+ return sum(values) / len(values)
1050
+
1020
1051
  def init(self):
1021
1052
  """Initialize the simulation engine and prepare for execution.
1022
1053
 
@@ -1055,6 +1086,10 @@ class Simulator:
1055
1086
  self.__allocatedConnectionIds = set()
1056
1087
  self.__blockedConnectionIds = set()
1057
1088
  self.__waitingConnectionIds = set()
1089
+ self.__firstServiceTimes = {}
1090
+ self.__responseTimes = []
1091
+ self.__turnaroundTimes = []
1092
+ self.__waitingTimes = []
1058
1093
  self.__users_by_vlc = []
1059
1094
  self.__users_by_rf = []
1060
1095
  self.__current_event = None
@@ -1185,6 +1220,64 @@ class Simulator:
1185
1220
  """
1186
1221
  return len(self.__blockedConnectionIds)
1187
1222
 
1223
+ def get_Response_Time(self) -> List[float]:
1224
+ """Get response times for completed connections.
1225
+
1226
+ Response time is the elapsed simulation time from connection arrival to
1227
+ the first RESUME event, when the connection first receives service.
1228
+
1229
+ Returns:
1230
+ list[float]: Response time for each completed connection in seconds
1231
+ """
1232
+ return list(self.__responseTimes)
1233
+
1234
+ def get_Average_Response_Time(self) -> float:
1235
+ """Get the average response time for completed connections.
1236
+
1237
+ Returns:
1238
+ float: Mean response time in seconds, or 0.0 if no connection finished
1239
+ """
1240
+ return self.__average(self.__responseTimes)
1241
+
1242
+ def get_Turnaround_Time(self) -> List[float]:
1243
+ """Get turnaround times for completed connections.
1244
+
1245
+ Turnaround time is the elapsed simulation time from connection arrival
1246
+ to departure.
1247
+
1248
+ Returns:
1249
+ list[float]: Turnaround time for each completed connection in seconds
1250
+ """
1251
+ return list(self.__turnaroundTimes)
1252
+
1253
+ def get_Average_Turnaround_Time(self) -> float:
1254
+ """Get the average turnaround time for completed connections.
1255
+
1256
+ Returns:
1257
+ float: Mean turnaround time in seconds, or 0.0 if no connection finished
1258
+ """
1259
+ return self.__average(self.__turnaroundTimes)
1260
+
1261
+ def get_Waiting_Time(self) -> List[float]:
1262
+ """Get total waiting times for completed connections.
1263
+
1264
+ Waiting time is turnaround time minus active service time. In TDM
1265
+ simulations, this includes the initial delay before first service and
1266
+ the idle gaps between assigned slots or frames.
1267
+
1268
+ Returns:
1269
+ list[float]: Waiting time for each completed connection in seconds
1270
+ """
1271
+ return list(self.__waitingTimes)
1272
+
1273
+ def get_Average_Waiting_Time(self) -> float:
1274
+ """Get the average total waiting time for completed connections.
1275
+
1276
+ Returns:
1277
+ float: Mean waiting time in seconds, or 0.0 if no connection finished
1278
+ """
1279
+ return self.__average(self.__waitingTimes)
1280
+
1188
1281
  def get_Waiting_Probability(self) -> float:
1189
1282
  """Calculate the fraction of attempted connections currently waiting.
1190
1283
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes