Source code for sierra.plugins.engine.argos.variables.population_variable_density

# Copyright 2021 John Harwell, All rights reserved.
#
#  SPDX-License-Identifier: MIT
#
"""Classes for the variable population density batch criteria.

See :ref:`plugins/engine/argos/bc/population-variable-density` for usage
documentation.

"""

# Core packages
import typing as tp
import logging
import pathlib

# 3rd party packages

# Project packages
from sierra.core.variables import variable_density as vd
from sierra.core.vector import Vector3D
from sierra.core.experiment import definition
from sierra.core import types, utils
from sierra.core.graphs import bcbridge


[docs] class PopulationVariableDensity(vd.VariableDensity, bcbridge.IGraphable): """Defines XML changes for variable population density within a single arena. This class is a base class which should (almost) never be used on its own. Instead, the ``factory()`` function should be used to dynamically create derived classes expressing the user's desired density ranges. """ def __init__(self, *args, **kwargs) -> None: vd.VariableDensity.__init__(self, *args, **kwargs) self.already_added = False self.logger = logging.getLogger(__name__)
[docs] def gen_attr_changelist(self) -> list[definition.AttrChangeSet]: """Generate XML modifications to achieve the desired population densities. Robots are approximated as point masses. """ if not self.already_added: for density in self.densities: # ARGoS won't start if there are 0 robots, so you always # need to put at least 1. n_agents = int(self.extent.area() * (density / 100.0)) if n_agents == 0: n_agents = 1 self.logger.warning( "n_agents set to 1 even though \ calculated as 0 for area=%d,density=%s", self.extent.area(), density, ) changeset = definition.AttrChangeSet( definition.AttrChange( ".//arena/distribute/entity", "quantity", str(n_agents) ) ) self.attr_changes.append(changeset) self.logger.debug( "Calculated swarm size=%d for extent=%s,density=%s", n_agents, str(self.extent), density, ) self.already_added = True return self.attr_changes
[docs] def graph_info( self, cmdopts: types.Cmdopts, batch_output_root: tp.Optional[pathlib.Path] = None, exp_names: tp.Optional[list[str]] = None, ) -> bcbridge.GraphInfo: info = bcbridge.GraphInfo( cmdopts, batch_output_root, exp_names if exp_names else self.gen_exp_names(), ) info.xticks = [ p / self.extent.area() for p in self.populations(info.cmdopts, info.exp_names) ] info.xticklabels = [str(round(x, 4)) for x in info.xticks] info.xlabel = "Population Density" return info
def n_agents(self, exp_num: int) -> int: return int(self.extent.area() * self.densities[exp_num] / 100.0)
def factory( cli_arg: str, main_config: types.YAMLDict, cmdopts: types.Cmdopts, batch_input_root: pathlib.Path, **kwargs, ) -> PopulationVariableDensity: """ Create a :class:`PopulationVariableDensity` derived class. """ densities = vd.parse(cli_arg) kw = utils.gen_scenario_spec(cmdopts, **kwargs) extent = utils.ArenaExtent(Vector3D(kw["arena_x"], kw["arena_y"], kw["arena_z"])) return PopulationVariableDensity( cli_arg, main_config, batch_input_root, densities, extent ) __all__ = ["PopulationVariableDensity"]