Source code for simulator.core.DtnCore

import abc
from collections import defaultdict
import numpy as np

[docs]class Simulable(object): """ Base class for all simulable objects. It stores the simulation environment, registers this class, and provides utility methods such as accessing the simulation time, epoch, and configuration. It also provides the ``disp`` that displays a message if the logger is not active, or logs it otherwise. """ def __init__(self, env): # Set simulation environment and logger self.env = env self.log = env.do_log # If the environment has a logger, use it self.logger = hasattr(env, 'logger') @property def t(self): """ Return current simulation time """ return self.env.now @t.setter def t(self, value): """ Block settings this property's """ raise RuntimeError('Cannot set the "t" parameter. It contains the simulation time') @property def is_alive(self): return True if self.env.until is None else (self.t <= self.env.until) @is_alive.setter def is_alive(self, value): """ Block settings this property's """ raise RuntimeError('Cannot set the "is_alive" parameter.') @property def epoch(self): """ Return current simulation epoch """ return self.env.epoch @epoch.setter def epoch(self, value): """ Block settings this property's """ raise RuntimeError('Cannot set the "epoch" parameter. It contains the simulation epoch') @property def config(self): """ Return the configuration structure """ return self.env.config @config.setter def config(self, value): """ Block settings this property's """ raise RuntimeError('Cannot set the "config" parameter. It contains the structure' 'of global settings for the simulation.')
[docs] def disp(self, msg, *args): """ Display a message in the log or sys.out """ # If not logging is needed, return if self.log == False: return # If the logger is available in the environment, use it if self.logger: self.env.log(msg, *args); return # Format logging message header = 't={:.3f}:\t'.format(self.env.now) msg = msg.format(*args) # Log by simply printing print(header + msg.format(*args))
def __str__(self): return '<{}>'.format(self.__class__.__name__) def __repr__(self): return self.__str__()
class Message(object, metaclass=abc.ABCMeta): def __init__(self): # Total propagation delay suffered by this Message # during transmission self.prop_delay = 0.0 # True/False self.has_errors = False @property @abc.abstractmethod def mid(self): pass @property @abc.abstractmethod def num_bits(self): pass def __str__(self): return '<Message>' def __repr__(self): return self.__str__()
[docs]class TimeCounter(dict): """ Essentially equivalent to ``defaultdict(int)``. Re-implemented to provide extra functionality """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self[0] = 0 def inc(self, t): if t in self: self[t] += 1 else: self[t] = 1 def dec(self, t): if t in self: self[t] -= 1 else: self[t] = -1 def to_timeseries(self): t = np.array(list(self.keys())) v = np.cumsum(list(self.values())) return t, v
[docs]class LoadMonitor(dict): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Last arrival time logged self.last_t = 0.0 # Second to last arrival logged self.prior_to_last = 0.0 def log(self, t, bundle): # If t equals 0, then skip, you can't measure the rate yet if t < 0.0: return # If t < last_t, error if t < self.last_t: raise RuntimeError('t is < than last_t') # If t is greater than last arrival if t > self.last_t: self[t] = bundle.data_vol/(t-self.last_t) self.prior_to_last = self.last_t self.last_t = t return # If t == last_t, then just add the bps to the last measurement self[t] += bundle.data_vol/(t-self.prior_to_last) def to_timeseries(self): t = np.array(list(self.keys())) v = np.array(list(self.values())) return t, v