vlcsim.simulator.Simulator

class vlcsim.simulator.Simulator(x: float, y: float, z: float, nGrids: int, rho: float)[source]

Bases: object

Event-driven discrete-event simulator for VLC systems.

The Simulator class implements a complete discrete-event simulation (DES) engine for VLC communication systems. It manages the event scheduling, random variable generation, connection lifecycle, and statistical data collection.

The simulation follows these key phases:
  1. Initialization: Configure scenario, APs, and simulation parameters

  2. Event Scheduling: Maintain chronologically ordered Future Event List (FEL)

  3. Event Processing: Execute event routines (arrive, pause, resume, depart)

  4. Statistics Collection: Track blocking probability, AP utilization, delays

Key Features:
  • Poisson arrival process (exponential inter-arrival times)

  • Exponential service times

  • Uniform spatial distribution of receivers

  • Customizable allocation algorithms

  • Support for both VLC (VLed) and RF access points

Example

Complete simulation workflow:

# Create simulator
sim = Simulator(x=10.0, y=10.0, z=3.0, nGrids=20, rho=0.8)

# Add access points
vled1 = VLed(2.5, 2.5, 3.0, 2, 2, 20, 60)
vled2 = VLed(7.5, 7.5, 3.0, 2, 2, 20, 60)
sim.scenario.addVLed(vled1)
sim.scenario.addVLed(vled2)

# Configure parameters
sim.lambdaS = 3.0  # 3 arrivals/second
sim.mu = 10.0      # mean service time = 0.1 seconds
sim.goalConnections = 10000
sim.lower_capacity_required = 1e6  # 1 Mbps
sim.upper_capacity_required = 10e6  # 10 Mbps

# Run simulation
sim.init()
sim.run()

# Get results
blocking = sim.get_Blocking_Probability()
print(f"Blocking Probability: {blocking}")

Note

  • Must call init() before run()

  • Seeds control reproducibility of random variables

  • Default values are set automatically if not specified

__init__(x: float, y: float, z: float, nGrids: int, rho: float) None[source]

Initialize a Simulator instance.

Creates a new simulator with the specified scenario dimensions and wall reflection parameters. Initializes all internal state variables and sets default simulation parameters.

Parameters:
  • x – Room length in meters (X-axis dimension)

  • y – Room width in meters (Y-axis dimension)

  • z – Room height in meters (Z-axis dimension, ceiling height)

  • nGrids – Number of grid divisions per meter for wall reflection calculations

  • rho – Wall reflection coefficient (0.0 to 1.0, where 0=no reflection, 1=perfect reflection)

Example:

# Create simulator for 10x10x3m room with 0.8 reflection
sim = Simulator(x=10.0, y=10.0, z=3.0, nGrids=20, rho=0.8)

Methods

__init__(x, y, z, nGrids, rho)

Initialize a Simulator instance.

aggregated_metrics()

Display aggregated simulation metrics.

default_values()

Set default simulation parameters.

event_routine()

Process the next scheduled event from the Future Event List.

get_Blocking_Probability()

Calculate the connection blocking probability.

init()

Initialize the simulation engine and prepare for execution.

print_initial_info()

Print scenario configuration and simulation header.

print_row(event)

Print a formatted row for each simulation event.

run()

Execute the simulation until the goal connection count is reached.

set_allocation_algorithm(alloc_alg)

Set a custom connection allocation algorithm.

time_duration()

Get the total execution time of the simulation.

Attributes

goalConnections

Get the target number of connections for simulation termination.

lambdaS

Get the Poisson arrival rate parameter.

lower_capacity_required

Get the lower bound for required connection capacity.

lower_random_wait

Get the lower bound for random wait time.

mu

Get the exponential service rate parameter.

scenario

Get the simulation scenario object.

seedCapacityRequired

Get the random seed for capacity requirement generation.

seedRandomWait

Get the random seed for random wait time generation.

seedX

Get the random seed for X-coordinate generation.

seedY

Get the random seed for Y-coordinate generation.

seedZ

Get the random seed for Z-coordinate generation.

upper_capacity_required

Get the upper bound for required connection capacity.

upper_random_wait

Get the upper bound for random wait time.

aggregated_metrics()[source]

Display aggregated simulation metrics.

Prints the total number of connections served by each access point (both VLeds and RFs) throughout the simulation. Provides insight into AP utilization and load distribution.

Output:
  • List of each VLed with total connections served

  • List of each RF with total connections served

Example Output:

Number of users connected to each VLed
VLed 0: 342
VLed 1: 289
Number of users connected to each RF
RF 0: 156

Note

Called automatically at the end of run().

default_values()[source]

Set default simulation parameters.

Initializes all simulation parameters to sensible default values. These can be overridden before calling init() if different values are needed.

Default Values:
  • lambdaS = 3 (arrival rate: 3 connections/second)

  • mu = 10 (service rate: mean time = 0.1 seconds)

  • seedArrive = 12345 (arrival process seed)

  • seedDeparture = 1234 (departure process seed)

  • seedX = 1235 (X position seed)

  • seedY = 1245 (Y position seed)

  • seedZ = 1345 (Z position seed)

  • seedRandomWait = 1345 (random wait seed)

  • seedCapacityRequired = 1345 (capacity requirement seed)

  • goalConnections = 10000 (simulation stopping criterion)

  • lower_random_wait = 5 (minimum wait time in seconds)

  • upper_random_wait = 15 (maximum wait time in seconds)

  • lower_capacity_required = 1e5 (minimum capacity: 100 Kbps)

  • upper_capacity_required = 5e5 (maximum capacity: 500 Kbps)

  • allocator = Controller.default_alloc (default allocation algorithm)

Note

This method is called automatically by __init__().

event_routine()[source]

Process the next scheduled event from the Future Event List.

This is the core simulation routine that selects and executes the appropriate handler for each event type. It updates the simulation clock, generates new events, and manages the event list chronologically.

Event Handling:
  • ARRIVE: Generate next arrival, create connection, attempt allocation

  • NEXT_CONNECTION_TRY: Retry allocation after random wait

  • PAUSE: Temporarily pause connection transmission

  • RESUME: Resume connection transmission or transition to departure

  • DEPARTURE: Complete connection and deallocate resources

The method maintains the Future Event List (FEL) in chronological order and ensures proper state transitions for all connections.

Returns:

Allocation routine return value (typically None)

Return type:

Any

Note

  • Called repeatedly by run() until simulation termination

  • Updates self.__clock to current event time

  • Manages connection lifecycle state transitions

get_Blocking_Probability() float[source]

Calculate the connection blocking probability.

Blocking probability is the fraction of connections that were NOT successfully allocated. It represents the percentage of connection requests that were denied due to insufficient resources.

Returns:

Blocking probability (0.0 to 1.0, rounded to 2 decimals)

Return type:

float

Formula:

Blocking Probability = 1 - (allocated_connections / total_connections)

Example:

sim.run()
blocking = sim.get_Blocking_Probability()
print(f"Blocking rate: {blocking * 100:.1f}%")  # e.g., "Blocking rate: 5.2%"
property goalConnections: int | None

Get the target number of connections for simulation termination.

The simulation continues until this many connections have been generated. This serves as the stopping criterion for the simulation.

Returns:

Target connection count, or None if not set

Return type:

int or None

init()[source]

Initialize the simulation engine and prepare for execution.

This method must be called after all configuration parameters have been set and before calling run(). It initializes:

Initialization Steps:

1. Set initReady flag to prevent further parameter changes 2. Initialize random number generators with configured seeds 3. Create first arrival event 4. Initialize controller and AP structures 5. Set up connection tracking lists

Raises:

ValueError – If scenario has no VLeds or RFs configured

Example:

sim = Simulator(10.0, 10.0, 3.0, 20, 0.8)
sim.scenario.addVLed(vled1)
sim.lambdaS = 3.0
sim.mu = 10.0
sim.init()  # Initialize before running
sim.run()

Note

After calling init(), simulation parameters cannot be modified.

property lambdaS: float | None

Get the Poisson arrival rate parameter.

Lambda (λ) controls the arrival rate of connections. With exponential inter-arrival times, the mean time between arrivals is 1/λ seconds.

Returns:

Arrival rate in connections per second, or None if not set

Return type:

float or None

Example:

sim.lambdaS = 3.0  # Average of 3 arrivals per second
                   # Mean inter-arrival time = 1/3 = 0.333 seconds
property lower_capacity_required: float | None

Get the lower bound for required connection capacity.

Returns:

Minimum capacity requirement in bps, or None if not set

Return type:

float or None

property lower_random_wait: float | None

Get the lower bound for random wait time.

When a connection cannot be allocated, it waits a random time uniformly distributed between [lower_random_wait, upper_random_wait] before retrying.

Returns:

Minimum wait time in seconds, or None if not set

Return type:

float or None

property mu: float | None

Get the exponential service rate parameter.

Mu (μ) controls the service time distribution. With exponential service times, the mean service time is 1/μ seconds.

Returns:

Service rate in 1/seconds, or None if not set

Return type:

float or None

Example:

sim.mu = 10.0  # Mean service time = 1/10 = 0.1 seconds
print_initial_info()[source]

Print scenario configuration and simulation header.

Displays initial scenario information including dimensions, number and positions of VLeds and RFs, and prepares the formatted table header for simulation event logging.

Output includes:
  • Scenario dimensions (X x Y x Z)

  • Number of VLeds with ID and position table

  • Number of RFs with ID and position table

  • Event logging table header

Note

This method is called automatically by run() before starting simulation.

print_row(event: Event) None[source]

Print a formatted row for each simulation event.

Displays detailed information about the current event in tabular format, including event type, connection details, receiver position, assigned AP, timing information, SNR, and capacity requirements.

Parameters:

event – The Event object to print information for

Output Columns:
  • Time: Simulation clock time

  • Event: Event type (ARRIVE, PAUSE, RESUME, DEPARTURE, RETRYING)

  • Receiver: Connection ID

  • X, Y, Z: Receiver position coordinates

  • Access Point: Assigned AP (VLed/RF) with active connection count

  • Goal time: Target transmission time

  • Elapsed time: Actual time spent transmitting

  • SNR: Signal-to-Noise Ratio

  • Req. Cap.: Required capacity in bps

Note

Called automatically by the event loop for each processed event.

run()[source]

Execute the simulation until the goal connection count is reached.

Runs the main simulation loop, processing events chronologically from the Future Event List (FEL) until the number of generated connections reaches or exceeds goalConnections.

The simulation workflow:
  1. Print initial scenario information and table header

  2. Process events sequentially from FEL

  3. Print each event’s details

  4. Continue until goalConnections reached

  5. Display aggregated metrics

Output:
  • Prints formatted table of all simulation events

  • Shows connection arrivals, allocations, transmissions, departures

  • Displays final aggregated metrics (AP utilization)

Raises:

RuntimeError – If init() has not been called first

Example:

sim.init()
sim.run()  # Executes until goalConnections reached

Note

Simulation time advances based on event timestamps, not real time.

property scenario

Get the simulation scenario object.

Provides access to the underlying Scenario object which contains all physical infrastructure (VLeds, RFs, room dimensions, etc.).

Returns:

The simulation scenario with all access points and configuration

Return type:

Scenario

Example:

# Add VLeds to scenario
vled = VLed(5.0, 5.0, 3.0, 2, 2, 20, 60)
sim.scenario.addVLed(vled)

# Query scenario properties
print(f"Room: {sim.scenario.length} x {sim.scenario.width} m")
property seedCapacityRequired: int | None

Get the random seed for capacity requirement generation.

Returns:

Random number generator seed for capacity distribution

Return type:

int or None

property seedRandomWait: int | None

Get the random seed for random wait time generation.

Returns:

Random number generator seed for wait time distribution

Return type:

int or None

property seedX: int | None

Get the random seed for X-coordinate generation.

Returns:

Random number generator seed for receiver X positions

Return type:

int or None

property seedY: int | None

Get the random seed for Y-coordinate generation.

Returns:

Random number generator seed for receiver Y positions

Return type:

int or None

property seedZ: int | None

Get the random seed for Z-coordinate generation.

Returns:

Random number generator seed for receiver Z positions (height)

Return type:

int or None

set_allocation_algorithm(alloc_alg: Callable[[Receiver, Connection, Any, Controller], tuple[Any, Connection]]) None[source]

Set a custom connection allocation algorithm.

Replaces the default allocation algorithm with a user-defined function. The custom allocator must follow the required signature and return format.

Parameters:

alloc_alg

Allocation algorithm function with signature:

def custom_alloc(
    receiver: Receiver,
    connection: Connection,
    scenario: Scenario,
    controller: Controller
) -> tuple[Controller.status, Connection]:
    # Allocation logic here
    return Controller.status.ALLOCATED, connection

Example:

def my_allocator(receiver, connection, scenario, controller):
    # Custom allocation logic
    vleds = scenario.vleds
    best_vled = max(vleds, key=lambda v: scenario.snrVled(receiver, v))
    connection.AP = best_vled
    return Controller.status.ALLOCATED, connection

sim.set_allocation_algorithm(my_allocator)

Note

Must be called before init() for the algorithm to take effect.

time_duration() float[source]

Get the total execution time of the simulation.

Returns:

Execution time in seconds (0.0 if not available)

Return type:

float

Note

This measures the real wall-clock time taken to run the simulation, not the simulated time. The measurement starts when init() is called and ends when run() completes.

property upper_capacity_required: float | None

Get the upper bound for required connection capacity.

Returns:

Maximum capacity requirement in bps, or None if not set

Return type:

float or None

property upper_random_wait: float | None

Get the upper bound for random wait time.

When a connection cannot be allocated, it waits a random time uniformly distributed between [lower_random_wait, upper_random_wait] before retrying.

Returns:

Maximum wait time in seconds, or None if not set

Return type:

float or None