Source code for rpasdt.algorithm.diffusion

"""Diffusion models configuration."""
import random
from typing import Dict, List, Optional

from ndlib.models import DiffusionModel
from ndlib.models.epidemics import (
    GeneralisedThresholdModel,
    IndependentCascadesModel,
    KerteszThresholdModel,
    SEIRModel,
    SIModel,
    SIRModel,
    SISModel,
    SWIRModel,
    ThresholdModel,
)
from ndlib.models.ModelConfig import Configuration
from ndlib.models.opinions import (
    MajorityRuleModel,
    QVoterModel,
    SznajdModel,
    VoterModel,
)
from networkx import Graph

from rpasdt.algorithm.taxonomies import (
    DiffusionTypeEnum,
    NodeStatusEnum,
    NodeStatusToValueMapping,
)
from rpasdt.common.utils import eval_if_str

DiffusionTypeToDiffusionModelMap = {
    DiffusionTypeEnum.SI: SIModel,
    DiffusionTypeEnum.SIS: SISModel,
    DiffusionTypeEnum.SIR: SIRModel,
    DiffusionTypeEnum.SEIR: SEIRModel,
    DiffusionTypeEnum.SWIR: SWIRModel,
    DiffusionTypeEnum.THRESHOLD: ThresholdModel,
    DiffusionTypeEnum.KERTESZ_THRESHOLD: KerteszThresholdModel,
    DiffusionTypeEnum.GENERALISED_THRESHOLD: GeneralisedThresholdModel,
    DiffusionTypeEnum.INDEPENDENT_CASCADES: IndependentCascadesModel,
    DiffusionTypeEnum.VOTER: VoterModel,
    DiffusionTypeEnum.Q_VOTER: QVoterModel,
    DiffusionTypeEnum.MAJORITY_RULE: MajorityRuleModel,
    DiffusionTypeEnum.SZNAJD: SznajdModel,
}
# ndlib diffusion model configuration kwargs
NDLIB_MODEL_KWARG = "model"
NDLIB_RANGE_KWARG = "range"
NDLIB_DEFAULT_KWARG = "default"


[docs]def get_diffusion_model_default_params(diffusion_model: DiffusionModel) -> Dict: """Return default configuration for provided diffusion model.""" parameters = diffusion_model.get_model_parameters().get(NDLIB_MODEL_KWARG) result = {} for field, details in parameters.items(): range = eval_if_str(details.get(NDLIB_RANGE_KWARG)) default_val = details.get( NDLIB_DEFAULT_KWARG, random.uniform(range[0], range[1]) if range else 0 ) result[field] = default_val return result
[docs]def get_and_init_diffusion_model( graph: Graph, diffusion_type: DiffusionTypeEnum, source_nodes: List[int], model_params: Optional[Dict] = None, ): """Create and initialize diffusion model based on provided config.""" diffusion_model = DiffusionTypeToDiffusionModelMap[diffusion_type](graph) config = Configuration() model_params = model_params or get_diffusion_model_default_params(diffusion_model) for key, value in model_params.items(): config.add_model_parameter(param_name=key, param_value=value) config.add_model_initial_configuration(NodeStatusEnum.INFECTED, source_nodes) diffusion_model.set_initial_status(config) return diffusion_model, model_params
[docs]def get_nodes_by_diffusion_status( diffusion_model: DiffusionModel = None, node_status: NodeStatusEnum = NodeStatusEnum.INFECTED, ) -> List[int]: """Return nodes with required status.""" return ( [ key for key, value in diffusion_model.status.items() if value == NodeStatusToValueMapping[node_status] ] if diffusion_model else [] )