Esempio n. 1
0
    def __init__(self, rndgen, config):
        """
        Create a new tasks generator.
        :param rndgen: (object) the multi-stream rnd number generator.
        :param config: (dict) the arrival rates configuration.
        """
        # Arrival rates
        self.rates = {
            tsk: 1.0 / config[tsk]["parameters"]["m"]
            for tsk in TaskScope.concrete()
        }

        # Randomization
        self.rndgen = rndgen
        self.stream = {
            tsk: EventType.of(ActionScope.ARRIVAL, SystemScope.SYSTEM,
                              tsk).value
            for tsk in TaskScope
        }
        self.lambda_tot = sum(self.rates[tsk] for tsk in TaskScope.concrete())
        self.p_1 = self.rates[TaskScope.TASK_1] / self.lambda_tot

        # Events
        self.event_types = {
            tsk: EventType.of(ActionScope.ARRIVAL, SystemScope.SYSTEM, tsk)
            for tsk in TaskScope.concrete()
        }

        # State
        self.generated = {tsk: 0 for tsk in TaskScope.concrete()}
Esempio n. 2
0
    def __init__(self, config):
        """
        Creates a new analytical solver.
        :param config: (Configuration) the system configuration.
        """

        self.config = config
        self.markov_chain = None
        self.states_probabilities = None
        self.routing_probabilities = None
        self.solution = None

        self.__validate_markovianity()

        self.clt_n_servers = self.config["system"]["cloudlet"]["n_servers"]
        self.clt_controller_algorithm = ControllerAlgorithm[
            self.config["system"]["cloudlet"]["controller_algorithm"]]
        self.clt_threshold = (self.config["system"]["cloudlet"]["threshold"]
                              if self.clt_controller_algorithm is
                              ControllerAlgorithm.ALGORITHM_2 else None)

        self.arrival_rates = {
            tsk: self.config["arrival"][tsk.name]["parameters"]["r"]
            for tsk in TaskScope.concrete()
        }
        self.service_rates = {
            sys: {
                tsk: self.config["system"][sys.name.lower()]["service"][
                    tsk.name]["parameters"]["r"]
                for tsk in TaskScope.concrete()
            }
            for sys in SystemScope.subsystems()
        }
        self.t_setup = self.config["system"]["cloud"]["setup"][
            TaskScope.TASK_2.name]["parameters"]["m"]
Esempio n. 3
0
    def __init__(self, rndservice, idx):
        """
        Create a new Server.
        :param rndservice: (RandomComponent) rnd component for the service process.
        :param idx: (int) the server index.
        """
        # Server Index (used in randomization)
        self.idx = idx

        # Randomization
        self.rndservice = deepcopy(rndservice)
        for tsk in self.rndservice.str:
            self.rndservice.str[tsk] += self.idx  # decoupling of each server randomness

        # State and important variables
        self.state = ServerState.IDLE  # the state of the server (ServerState)
        self.task_type = None  # the type of the task being served (TaskType)
        self.t_arrival = 0.0  # the last arrival time (float) (s)
        self.t_service = 0.0  # the last service time (float) (s)
        self.t_completion = 0.0  # the last completion time (float) (s)
        self.t_interruption = 0.0  # the last interruption time (float) (s)

        # Statistics (used by server selection rules)
        self.arrived = {tsk: 0 for tsk in TaskScope.concrete()}  # total number of arrived tasks, by task type
        self.completed = {tsk: 0 for tsk in TaskScope.concrete()}  # total number of completed tasks, by task type
        self.switched = {tsk: 0 for tsk in TaskScope.concrete()}  # total number of interrupted tasks, by task type
        self.service = {tsk: 0 for tsk in TaskScope.concrete()}  # total service time, by task type
        self.t_idle = 0.0  # the total idle time (float) (s)
Esempio n. 4
0
    def __init__(self, rndgen, config, state, metrics):
        """
        Create a new Cloudlet.
        :param rndgen: (object) the multi-stream rnd number generator.
        :param config: (dict) the Cloudlet configuration.
        :param state: (dict) the Cloudlet state.
        :param metrics: (SimulationMetrics) the simulation metrics.
        """
        # Randomization - Service
        self.rndservice = RandomComponent(
            gen=rndgen,
            str={
                tsk: EventType.of(ActionScope.COMPLETION, SystemScope.CLOUDLET, tsk).value
                for tsk in TaskScope.concrete()
            },
            var={tsk: config["service"][tsk]["distribution"] for tsk in TaskScope.concrete()},
            par={tsk: config["service"][tsk]["parameters"] for tsk in TaskScope.concrete()},
        )

        # Servers
        self.n_servers = config["n_servers"]
        self.servers = [Server(self.rndservice, i) for i in range(self.n_servers)]
        self.server_selector = config["server_selection"].selector(self.servers)

        # State
        self.state = state

        # Controller
        controller_algorithm = config["controller_algorithm"]
        if controller_algorithm is ControllerAlgorithm.ALGORITHM_1:
            self.controller = ControllerAlgorithm1(self.state, self.n_servers)
        elif controller_algorithm is ControllerAlgorithm.ALGORITHM_2:
            self.threshold = config["threshold"]
            self.controller = ControllerAlgorithm2(self.state, self.n_servers, self.threshold)
            if not (0 <= self.threshold <= self.n_servers):
                raise ValueError(
                    "Invalid threshold: should be >= 0 and <= n_servers, but threshold is {} and n_servers is {}".format(
                        self.threshold, self.n_servers
                    )
                )
        else:
            raise ValueError("Unrecognized controller algorithm type {}".format(controller_algorithm))

        # Timing
        self.t_last_event = {tsk: 0.0 for tsk in TaskScope.concrete()}

        # Metrics
        self.metrics = metrics
Esempio n. 5
0
    def submit_arrival(self, tsk, t_now):
        """
        Submit the arrival of a task.
        :param tsk: (TaskType) the type of the task.
        :param t_now: (float) the current time.
        :return: (float) the completion time.
        """
        # Check correctness
        assert sum(self.state[tsk] for tsk in TaskScope.concrete()) < self.n_servers

        # Generate completion
        server_idx = self.server_selector.select_idle()
        if server_idx is None:
            raise RuntimeError("Cannot find server for arrival of task {} at time {}".format(tsk, t_now))
        t_completion = self.servers[server_idx].submit_arrival(tsk, t_now)

        # Update metrics
        self.metrics.counters.arrived[SystemScope.CLOUDLET][tsk] += 1
        self.metrics.counters.population_area[SystemScope.CLOUDLET][tsk] += (
            t_now - self.t_last_event[tsk]
        ) * self.state[tsk]

        # Update state
        self.state[tsk] += 1

        # Update timing
        self.t_last_event[tsk] = t_now

        return t_completion
Esempio n. 6
0
    def __init__(self, rndgen, config, metrics):
        """
        Create a new system.
        :param rndgen: (object) the multi-stream rnd number generator.
        :param config: (dictionary) the System configuration.
        :param metrics: (SimulationMetrics) the simulation metrics.
        """
        # State
        self.state = {
            sys: {tsk: 0
                  for tsk in TaskScope.concrete()}
            for sys in SystemScope.subsystems()
        }

        # Metrics
        self.metrics = metrics

        # Subsystem - Cloudlet
        self.cloudlet = Cloudlet(rndgen, config["cloudlet"],
                                 self.state[SystemScope.CLOUDLET],
                                 self.metrics)

        # Subsystem - Cloud
        self.cloud = Cloud(rndgen, config["cloud"],
                           self.state[SystemScope.CLOUD], self.metrics)
Esempio n. 7
0
    def __init__(self, config, name="SIMULATION-CLOUD-CLOUDLET"):
        """
        Create a new simulation.
        :param config: the configuration for the simulation.
        :param name: the name of the simulation.
        """
        self.name = name

        # Configuration - General
        config_general = config["general"]
        self.mode = config_general["mode"]

        # Configuration - Transient Analysis
        if self.mode is SimulationMode.TRANSIENT_ANALYSIS:
            self.t_stop = config_general["t_stop"]
            # self.t_tran = 0
            self.batches = INFINITE
            self.batchdim = 1
            self.closed_door_condition = lambda: self.closed_door_condition_transient_analysis(
            )
            self.print_progress = lambda: print_progress(
                self.calendar.get_clock(),
                self.t_stop,
                message="Clock: %d" % (self.calendar.get_clock()))
            # self.should_discard_transient_data = False

        # Configuration - Performance Analysis
        elif self.mode is SimulationMode.PERFORMANCE_ANALYSIS:
            self.t_stop = INFINITE
            # self.t_tran = config_general["t_tran"]
            self.batches = config_general["batches"]
            self.batchdim = config_general["batchdim"]
            self.closed_door_condition = lambda: self.closed_door_condition_performance_analysis(
            )
            self.print_progress = lambda: print_progress(
                self.metrics.n_batches,
                self.batches,
                message="Clock: %d | Batches: %d | CurrentBatchSamples: %d" %
                (self.calendar.get_clock(), self.metrics.n_batches, self.
                 metrics.curr_batchdim),
            )
            # self.should_discard_transient_data = self.t_tran > 0.0

        else:
            raise RuntimeError(
                "The current version supports only TRANSIENT_ANALYSIS and PERFORMANCE_ANALYSIS"
            )

        # Configuration - Randomization
        self.rndgen = getattr(rndgen, config_general["random"]["generator"])(
            config_general["random"]["seed"])

        # The simulation metrics
        self.metrics = SimulationMetrics(self.batchdim)
        self.confidence = config_general["confidence"]

        # Configuration - Tasks
        # Checks that the arrival process is Markovian (currently, the only one supported)
        if not all(variate is Variate.EXPONENTIAL for variate in [
                config["arrival"][tsk]["distribution"]
                for tsk in TaskScope.concrete()
        ]):
            raise NotImplementedError(
                "The current version supports only exponential arrivals")
        self.taskgen = Taskgen(rndgen=self.rndgen, config=config["arrival"])

        # Configuration - System (Cloudlet and Cloud)
        config_system = config["system"]
        self.system = System(rndgen=self.rndgen,
                             config=config_system,
                             metrics=self.metrics)

        # Configuration - Calendar
        # Notice that the calendar internally manages:
        # (i) event sorting, by occurrence time.
        # (ii) scheduling of only possible events, that are:
        #   (ii.i) possible arrivals, i.e. arrivals with occurrence time lower than stop time.
        #   (ii.ii) departures of possible arrivals.
        # (iii) unscheduling of events to ignore, e.g. completion in Cloudlet of interrupted tasks.
        self.calendar = Calendar(t_clock=0.0)

        # Sampling management
        self.sampling_file = None

        # Simulation management
        self.closed_door = False
Esempio n. 8
0
    def generate_report(self):
        """
        Generate the simulation report.
        :return: (SimpleReport) the simulation report.
        """
        r = Report(self.name)

        alpha = 1.0 - self.confidence

        # Report - General
        r.add("general", "mode", self.mode.name)
        if self.mode is SimulationMode.TRANSIENT_ANALYSIS:
            r.add("general", "t_stop", self.t_stop)
        elif self.mode is SimulationMode.PERFORMANCE_ANALYSIS:
            r.add("general", "batches", self.batches)
            r.add("general", "batchdim", self.batchdim)
        else:
            raise RuntimeError(
                "The current version supports only TRANSIENT_ANALYSIS and PERFORMANCE_ANALYSIS"
            )
        r.add("general", "confidence", self.confidence)

        # Report - Randomization
        r.add("randomization", "generator", self.rndgen.__class__.__name__)
        r.add("randomization", "iseed", self.rndgen.get_initial_seed())
        r.add("randomization", "modulus", self.rndgen.get_modulus())
        r.add("randomization", "multiplier", self.rndgen.get_multiplier())
        r.add("randomization", "streams", self.rndgen.get_nstreams())

        # Report - Arrivals
        for tsk in TaskScope.concrete():
            r.add("arrival", "arrival_{}_dist".format(tsk.name.lower()),
                  Variate.EXPONENTIAL.name)
            r.add("arrival", "arrival_{}_rate".format(tsk.name.lower()),
                  self.taskgen.rates[tsk])
        for tsk in TaskScope.concrete():
            r.add("arrival", "generated_{}".format(tsk.name.lower()),
                  self.taskgen.generated[tsk])

        # Report - System/Cloudlet
        r.add("system/cloudlet", "n_servers", self.system.cloudlet.n_servers)
        r.add("system/cloudlet", "controller_algorithm",
              self.system.cloudlet.controller.controller_algorithm.name)
        if self.system.cloudlet.controller.controller_algorithm is ControllerAlgorithm.ALGORITHM_2:
            r.add("system/cloudlet", "threshold",
                  self.system.cloudlet.threshold)
        for tsk in TaskScope.concrete():
            r.add(
                "system/cloudlet",
                "service_{}_dist".format(tsk.name.lower()),
                self.system.cloudlet.rndservice.var[tsk].name,
            )
            if self.system.cloudlet.rndservice.var[tsk] is Variate.EXPONENTIAL:
                r.add(
                    "system/cloudlet",
                    "service_{}_rate".format(tsk.name.lower()),
                    1.0 / self.system.cloudlet.rndservice.par[tsk]["m"],
                )
            else:
                for p in self.system.cloudlet.rndservice.par[tsk]:
                    r.add(
                        "system/cloudlet",
                        "service_{}_param_{}".format(tsk.name.lower(), p),
                        self.system.cloudlet.rndservice.par[tsk][p],
                    )

        # Report - System/Cloud
        for tsk in TaskScope.concrete():
            r.add("system/cloud", "service_{}_dist".format(tsk.name.lower()),
                  self.system.cloud.rndservice.var[tsk].name)
            if self.system.cloud.rndservice.var[tsk] is Variate.EXPONENTIAL:
                r.add(
                    "system/cloud",
                    "service_{}_rate".format(tsk.name.lower()),
                    1.0 / self.system.cloud.rndservice.par[tsk]["m"],
                )
            else:
                for p in self.system.cloud.rndservice.par[tsk]:
                    r.add(
                        "system/cloud",
                        "service_{}_param_{}".format(tsk.name.lower(), p),
                        self.system.cloud.rndservice.par[tsk][p],
                    )

        for tsk in TaskScope.concrete():
            r.add("system/cloud", "setup_{}_dist".format(tsk.name.lower()),
                  self.system.cloud.rndsetup.var[tsk].name)
            for p in self.system.cloud.rndsetup.par[tsk]:
                r.add(
                    "system/cloud",
                    "service_{}_param_{}".format(tsk.name.lower(), p),
                    self.system.cloud.rndsetup.par[tsk][p],
                )

        # Report - Execution
        r.add("execution", "clock", self.calendar.get_clock())
        r.add("execution", "collected_samples", self.metrics.n_samples)
        r.add("execution", "collected_batches", self.metrics.n_batches)

        # Report - State
        for sys in sorted(self.system.state, key=lambda x: x.name):
            for tsk in sorted(self.system.state[sys], key=lambda x: x.name):
                r.add("state", "{}_{}".format(sys.name.lower(),
                                              tsk.name.lower()),
                      self.system.state[sys][tsk])

        # Report - Statistics
        for metric in sorted(self.metrics.performance_metrics.__dict__):
            for sys in sorted(SystemScope, key=lambda x: x.name):
                for tsk in sorted(TaskScope, key=lambda x: x.name):
                    r.add(
                        "statistics",
                        "{}_{}_{}_mean".format(metric, sys.name.lower(),
                                               tsk.name.lower()),
                        getattr(self.metrics.performance_metrics,
                                metric)[sys][tsk].mean(),
                    )
                    r.add(
                        "statistics",
                        "{}_{}_{}_sdev".format(metric, sys.name.lower(),
                                               tsk.name.lower()),
                        getattr(self.metrics.performance_metrics,
                                metric)[sys][tsk].sdev(),
                    )
                    r.add(
                        "statistics",
                        "{}_{}_{}_cint".format(metric, sys.name.lower(),
                                               tsk.name.lower()),
                        getattr(self.metrics.performance_metrics,
                                metric)[sys][tsk].cint(alpha),
                    )

        return r
Esempio n. 9
0
                for tsk in TaskScope:
                    header.append("{}_{}_{}".format(counter, sys.name.lower(), tsk.name.lower()))
                    sample.append(getattr(self.counters, counter)[sys][tsk])

        for performance_metric in sorted(self.performance_metrics.__dict__):
            for sys in SystemScope:
                for tsk in TaskScope:
                    header.append("{}_{}_{}".format(performance_metric, sys.name.lower(), tsk.name.lower()))
                    sample.append(getattr(self.performance_metrics, performance_metric)[sys][tsk])

        data = [sample]

        save_csv(filename, header, data, append, skip_header)


if __name__ == "__main__":
    s = Sample(0)

    s.counters.arrived[SystemScope.CLOUDLET][TaskScope.TASK_1] = 1
    s.counters.arrived[SystemScope.CLOUDLET][TaskScope.TASK_2] = 2
    s.counters.arrived[SystemScope.CLOUD][TaskScope.TASK_1] = 3
    s.counters.arrived[SystemScope.CLOUD][TaskScope.TASK_2] = 4

    for tsk in TaskScope.concrete():
        s.counters.arrived[SystemScope.SYSTEM][tsk] = sum(
            s.counters.arrived[sys][tsk] for sys in SystemScope.subsystems()
        )

    for tsk in TaskScope.concrete():
        print(s.counters.arrived[SystemScope.SYSTEM][tsk])
Esempio n. 10
0
    def generate_report(self):
        """
        Generate the solver report.
        :return: (SimpleReport) the solver report.
        """
        r = Report("ANALYTICAL-SOLUTION")

        # Report - Arrivals
        for tsk in TaskScope.concrete():
            r.add("arrival", "arrival_{}_dist".format(tsk.name.lower()),
                  Variate.EXPONENTIAL.name)
            r.add("arrival", "arrival_{}_rate".format(tsk.name.lower()),
                  self.arrival_rates[tsk])

        # Report - System/Cloudlet
        r.add("system/cloudlet", "n_servers", self.clt_n_servers)
        r.add("system/cloudlet", "controller_algorithm",
              self.clt_controller_algorithm.name)
        if self.clt_controller_algorithm is ControllerAlgorithm.ALGORITHM_2:
            r.add("system/cloudlet", "threshold", self.clt_threshold)
        for tsk in TaskScope.concrete():
            r.add("system/cloudlet",
                  "service_{}_dist".format(tsk.name.lower()),
                  Variate.EXPONENTIAL.name)
            r.add(
                "system/cloudlet",
                "service_{}_rate".format(tsk.name.lower()),
                self.service_rates[SystemScope.CLOUDLET][tsk],
            )

        # Report - System/Cloud
        for tsk in TaskScope.concrete():
            r.add("system/cloud", "service_{}_dist".format(tsk.name.lower()),
                  Variate.EXPONENTIAL.name)
            r.add("system/cloud", "service_{}_rate".format(tsk.name.lower()),
                  self.service_rates[SystemScope.CLOUD][tsk])

        r.add("system/cloud",
              "setup_{}_dist".format(TaskScope.TASK_2.name.lower()),
              Variate.EXPONENTIAL.name)
        r.add("system/cloud",
              "service_{}_param_m".format(TaskScope.TASK_2.name.lower()),
              self.t_setup)

        # Report - Statistics
        for performance_metric in sorted(
                self.solution.performance_metrics.__dict__):
            for sys in sorted(SystemScope, key=lambda x: x.name):
                for tsk in sorted(TaskScope, key=lambda x: x.name):
                    r.add(
                        "statistics",
                        "{}_{}_{}_mean".format(performance_metric,
                                               sys.name.lower(),
                                               tsk.name.lower()),
                        getattr(self.solution.performance_metrics,
                                performance_metric)[sys][tsk],
                    )

        # Report - States Probability
        for state in sorted(self.states_probabilities):
            r.add("states probability", state,
                  self.states_probabilities[state])

        # Report - Routing Probability
        for probability, value in self.routing_probabilities.items():
            r.add("routing probability", probability, value)

        return r
Esempio n. 11
0
from pydes.core.rnd.rndgen import MarcianiMultiStream
from pydes.core.rnd.rndvar import Variate
from pydes.core.simulation.model.scope import TaskScope

rndgen = MarcianiMultiStream()

rndparams = {
    TaskScope.TASK_1: {"distribution": "EXPONENTIAL", "distribution_params": {"m": 0.5}},
    TaskScope.TASK_2: {"distribution": "EXPONENTIAL", "distribution_params": {"m": 0.8}},
}

variates = {
    tsk: lambda u: Variate[rndparams[tsk]["distribution"]].vargen.generate(u=u, **rndparams[tsk]["distribution_params"])
    for tsk in TaskScope.concrete()
}


def get_service_time(tsk):
    return variates[tsk](u=rndgen)


if __name__ == "__main__":

    values = {tsk: [] for tsk in TaskScope.concrete()}

    for tsk in TaskScope.concrete():
        for i in range(10):
            t = get_service_time(tsk)
            values[tsk].append(t)
Esempio n. 12
0
 def is_idle(self):
     """
     Check weather the Cloudlet is idle or not.
     :return: True, if the Cloudlet is idle; False, otherwise.
     """
     return sum(self.state[tsk] for tsk in TaskScope.concrete()) == 0
Esempio n. 13
0
    def _compute_global_counters(self, t_now):
        """
        Updates aggregated counters (e.g. system global counters) using task-scoped and subsystem-scoped counters
        (e.g. counter for task 1 in Cloudlet).
        :param t_now (float) the current time,
        :return: None
        """
        # Compute counters for each task class in system
        #   * arrived_system = arrived_cloudlet + arrived_cloud
        #   * completed_system = completed_cloudlet + completed_cloud
        #   * service_system = service_cloudlet + service_cloud
        #   * switched_system = switched_cloudlet
        #   * switched_completed_system = switched_completed_cloud
        #   * switched_service_system = switched_service_cloudlet + switched_service_cloud
        #   * switched_service_lost_system = switched_service_lost_cloudlet + switched_service_lost_cloud
        #   * population_area_system = population_area_cloudlet + population_area_lost_cloud
        for tsk in TaskScope.concrete():
            self.counters.arrived[SystemScope.SYSTEM][tsk] = sum(
                self.counters.arrived[sys][tsk]
                for sys in SystemScope.subsystems())
            self.counters.completed[SystemScope.SYSTEM][tsk] = sum(
                self.counters.completed[sys][tsk]
                for sys in SystemScope.subsystems())
            self.counters.service[SystemScope.SYSTEM][tsk] = sum(
                self.counters.service[sys][tsk]
                for sys in SystemScope.subsystems())
            self.counters.switched[SystemScope.SYSTEM][
                tsk] = self.counters.switched[SystemScope.CLOUDLET][tsk]
            self.counters.switched_completed[SystemScope.SYSTEM][
                tsk] = self.counters.switched_completed[SystemScope.CLOUD][tsk]
            self.counters.switched_service[SystemScope.SYSTEM][tsk] = sum(
                self.counters.switched_service[sys][tsk]
                for sys in SystemScope.subsystems())
            self.counters.switched_service_lost[SystemScope.SYSTEM][tsk] = sum(
                self.counters.switched_service_lost[sys][tsk]
                for sys in SystemScope.subsystems())
            self.counters.population_area[SystemScope.SYSTEM][tsk] = sum(
                self.counters.population_area[sys][tsk]
                for sys in SystemScope.subsystems())

        # Compute counters for global tasks
        #   * arrived_global = arrived_task_1 + arrived_task_2
        #   * completed_global = completed_task_1 + completed_task_2
        #   * service_global = service_task_1 + service_task_2
        #   * switched_global = switched_task_1 + switched_task_2
        #   * switched_completed_global = switched_completed_task_1 + switched_completed_task_2
        #   * switched_service_global = switched_service_task_1 + switched_service_task_2
        #   * switched_service_lost_global = switched_service_lost_task_1 + switched_service_lost_task_2
        #   * population_area_global = population_area_task_1 + population_area_task_2
        for sys in SystemScope:
            self.counters.arrived[sys][TaskScope.GLOBAL] = sum(
                self.counters.arrived[sys][tsk]
                for tsk in TaskScope.concrete())
            self.counters.completed[sys][TaskScope.GLOBAL] = sum(
                self.counters.completed[sys][tsk]
                for tsk in TaskScope.concrete())
            self.counters.service[sys][TaskScope.GLOBAL] = sum(
                self.counters.service[sys][tsk]
                for tsk in TaskScope.concrete())
            self.counters.switched[sys][TaskScope.GLOBAL] = sum(
                self.counters.switched[sys][tsk]
                for tsk in TaskScope.concrete())
            self.counters.switched_completed[sys][TaskScope.GLOBAL] = sum(
                self.counters.switched_completed[sys][tsk]
                for tsk in TaskScope.concrete())
            self.counters.switched_service[sys][TaskScope.GLOBAL] = sum(
                self.counters.switched_service[sys][tsk]
                for tsk in TaskScope.concrete())
            self.counters.switched_service_lost[sys][TaskScope.GLOBAL] = sum(
                self.counters.switched_service_lost[sys][tsk]
                for tsk in TaskScope.concrete())
            self.counters.population_area[sys][TaskScope.GLOBAL] = sum(
                self.counters.population_area[sys][tsk]
                for tsk in TaskScope.concrete())