Source code for slotted_aloha_simulator.geometric

import numpy as np
from numba import njit


[docs] @njit def core_aloha_run(p0=1/8, alpha=1/2, n=64, c_max=60, t_sim=20): """ Core Aloha simulator. Parameters ---------- p0: :class:`float`, optional Default emission probability. alpha: :class:`float`, optional Back-off ratio. n: :class:`int`, optional Number of stations. c_max: :class:`int`, optional Upper bound on state value. t_sim: :class:`int`, optional Time range (exponential). Returns ------- states: :class:`~numpy.ndarray` States (counter, not normalized) occupancy: :class:`~numpy.ndarray` Busy slots (counter, not normalized) goodput: :class:`~numpy.ndarray` Useful slots (counter, not normalized) emissions: :class:`~numpy.ndarray` Number of emissions (counter, not normalized) """ current_state = np.zeros(n, dtype=np.int64) speeds = p0 * alpha ** np.arange(c_max + 1) states = np.zeros((c_max + 1, t_sim + 1), dtype=np.int64) emissions = np.zeros(t_sim + 1, dtype=np.int64) occupancy = np.zeros(t_sim + 1, dtype=np.int64) goodput = np.zeros(t_sim + 1, dtype=np.int64) for t in range(t_sim + 1): o = 0 g = 0 e = 0 emitter = 0 d_t = np.zeros(c_max + 1, dtype=np.int64) for _ in range(2 ** t): emission = False reception = True for i, s in enumerate(current_state): d_t[s] += 1 if speeds[s] > np.random.rand(): e += 1 if emission: reception = False else: emission = True emitter = i if s < c_max: current_state[i] += 1 if emission: o += 1 if reception: current_state[emitter] = 0 g += 1 occupancy[t] = o emissions[t] = e goodput[t] = g states[:, t] = d_t return states, occupancy, goodput, emissions
[docs] @njit def aloha_run(p0=1/8, alpha=1/2, n=2, t_sim=20, c_max=60, m=10, seed=None): """ Simulation. Parameters ---------- p0: :class:`float`, optional Default emission probability. alpha: :class:`float`, optional Back-off ratio. n: :class:`int`, optional Number of stations. c_max: :class:`int`, optional Upper bound on state value. t_sim: :class:`int`, optional Time range (exponential). m: :class:`int`, optional Minimal number of samples per time bucket (exponential). seed: :class:`int`, optional Seed Returns ------- states: :class:`~numpy.ndarray` State distribution occupancy: :class:`~numpy.ndarray` Proportion of busy slots goodput: :class:`~numpy.ndarray` Proportion of useful slots efficiency: `~numpy.ndarray` Proportion of useful emissions Examples -------- >>> s, o, g, e = aloha_run(n=2, t_sim=10, m=5) >>> s, o, g, e = aloha_run(n=2, t_sim=14, m=10, seed=42) >>> s[:4, :4].round(4) array([[1. , 0.9765, 0.942 , 0.8958], [0. , 0.0235, 0.058 , 0.1022], [0. , 0. , 0. , 0.002 ], [0. , 0. , 0. , 0. ]]) >>> e[:4].round(4) array([0.8504, 0.8697, 0.8799, 0.8807]) >>> s, o, g, e = aloha_run(n=1000, t_sim=14, m=10, seed=42) >>> s[:4, :4].round(4) array([[1. , 0.8207, 0.5545, 0.2581], [0. , 0.1754, 0.3908, 0.511 ], [0. , 0.0039, 0.0528, 0.2057], [0. , 0. , 0.0018, 0.0242]]) >>> e[:4] array([0., 0., 0., 0.]) """ if seed is not None: np.random.seed(seed) # Main run dist, occupancy, goodput, emissions = core_aloha_run(p0=p0, alpha=alpha, n=n, t_sim=t_sim, c_max=c_max) # Extra short runs for i in range(m): for _ in range(2 ** (m - i)): d, o, g, e = core_aloha_run(p0=p0, alpha=alpha, n=n, t_sim=i, c_max=c_max) dist[:, :(i + 1)] += d occupancy[:(i + 1)] += o goodput[:(i + 1)] += g emissions[:(i + 1)] += e # extra runs normalization dist = dist.astype(np.float64) occupancy = occupancy.astype(np.float64) goodput = goodput.astype(np.float64) emissions = emissions.astype(np.float64) for i in range(m): dist[:, i] /= 2 ** (m - i + 1) - 1 occupancy[i] /= 2 ** (m - i + 1) - 1 goodput[i] /= 2 ** (m - i + 1) - 1 emissions[i] /= 2 ** (m - i + 1) - 1 # Counter conversion efficiency = goodput / emissions for i in range(t_sim + 1): occupancy[i] /= 2 ** i goodput[i] /= 2 ** i dist[:, i] = dist[:, i] / n / 2 ** i return dist, occupancy, goodput, efficiency