<commit_before># -*- coding: utf-8 -*-
"""This module coordinates the software components that make up the integration
framework.

"""
import logging
from collections import defaultdict

import networkx
import numpy as np
from enum import Enum
from smif import StateData
from smif.convert.area import get_register as get_region_register
from smif.convert.interval import get_register as get_interval_register
from smif.decision import Planning
from smif.intervention import Intervention, InterventionRegister
from smif.metadata import MetadataSet
from smif.model.composite import Model
from smif.model.scenario_model import ScenarioModel
from smif.model.sector_model import SectorModel, SectorModelBuilder

__author__ = "<NAME>, <NAME>"
__copyright__ = "<NAME>, <NAME>"
__license__ = "mit"


class SosModel(Model):
    """Consists of the collection of models joined via dependencies

    This class is populated at runtime by the :class:`SosModelBuilder` and
    called from :func:`smif.cli.run_model`.  SosModel inherits from
    :class:`smif.composite.Model`.

    """
    def __init__(self, name):
        # housekeeping
        super().__init__(name)
        self.logger = logging.getLogger(__name__)
        self.max_iterations = 25
        self.convergence_relative_tolerance = 1e-05
        self.convergence_absolute_tolerance = 1e-08

        # models - includes types of SectorModel and ScenarioModel
        self.models = {}
        self.dependency_graph = networkx.DiGraph()

        # systems, interventions and (system) state
        self.timesteps = []
        self.interventions = InterventionRegister()
        self.initial_conditions = []
        self.planning = Planning([])
        self._state = defaultdict(dict)

        # scenario data and results
        self._results = defaultdict(dict)

    @property
    def free_inputs(self):
        """Returns the free inputs not linked to a dependency at this layer and all contained layers

        Free inputs are passed up to higher layers for deferred linkages to
        dependencies.

        Returns
        -------
        smif.metadata.MetadataSet
        """
        # free inputs of all contained models
        free_inputs = []
        for model in self.models.values():
            free_inputs.extend(model.free_inputs)

        # free inputs of current layer
        my_free_inputs = super().free_inputs
        free_inputs.extend(my_free_inputs)

        # compose a new MetadataSet containing the free inputs
        metadataset = MetadataSet([])
        for meta in free_inputs:
            metadataset.add_metadata_object(meta)

        return metadataset

    def add_model(self, model):
        """Adds a sector model to the system-of-systems model

        Parameters
        ----------
        model : :class:`smif.sector_model.SectorModel`
            A sector model wrapper

        """
        assert isinstance(model, Model)
        self.logger.info("Loading model: %s", model.name)
        self.models[model.name] = model

    @property
    def results(self):
        """Get nested dict of model results

        Returns
        -------
        dict
            Nested dictionary in the format
            results[int:year][str:model][str:parameter] => list of
            SpaceTimeValues
        """
        # convert from defaultdict to plain dict
        return dict(self._results)

    def simulate(self, timestep, data=None):
        """Run the SosModel

        """
        self.check_dependencies()
        run_order = self._get_model_sets_in_run_order()
        self.logger.info("Determined run order as %s", run_order)
        results = {}
        for model in run_order:
            sim_data = {}
            for input_, dep in model.deps.items():
                if input_ in self.free_inputs:
                    # pick external dependencies from data
                    param_data = data[dep.source_model.name][dep.source.name]
                else:
                    # pick internal dependencies from results
                    param_data = results[dep.source_model.name][dep.source.name]
                param_data_converted = dep.convert(param_data, input_)
                sim_data[input_.name] = param_data_converted
            sim_results = model.simulate(timestep, sim_data)
            for model_name, model_results in sim_results.items():
                results[model_name] = model_results
        return results

    def check_dependencies(self):
        """For each contained model, compare dependency list against
        list of available models
        """
        if self.free_inputs.names:
            msg = "A SosModel must have all inputs linked to dependencies." \
                  "Define dependencies for %s"
            raise NotImplementedError(msg, ", ".join(self.free_inputs.names))

        for model in self.models.values():

            if isinstance(model, SosModel):
                msg = "Nesting of SosModels not yet supported"
                raise NotImplementedError(msg)
            else:
                self.dependency_graph.add_node(model,
                                               name=model.name)

                for sink, dependency in model.deps.items():<commit_msg>Look up model input when getting dep data<commit_after># -*- coding: utf-8 -*-
"""This module coordinates the software components that make up the integration
framework.

"""
import logging
from collections import defaultdict

import networkx
import numpy as np
from enum import Enum
from smif import StateData
from smif.convert.area import get_register as get_region_register
from smif.convert.interval import get_register as get_interval_register
from smif.decision import Planning
from smif.intervention import Intervention, InterventionRegister
from smif.metadata import MetadataSet
from smif.model.composite import Model
from smif.model.scenario_model import ScenarioModel
from smif.model.sector_model import SectorModel, SectorModelBuilder

__author__ = "<NAME>, <NAME>"
__copyright__ = "<NAME>, <NAME>"
__license__ = "mit"


class SosModel(Model):
    """Consists of the collection of models joined via dependencies

    This class is populated at runtime by the :class:`SosModelBuilder` and
    called from :func:`smif.cli.run_model`.  SosModel inherits from
    :class:`smif.composite.Model`.

    """
    def __init__(self, name):
        # housekeeping
        super().__init__(name)
        self.logger = logging.getLogger(__name__)
        self.max_iterations = 25
        self.convergence_relative_tolerance = 1e-05
        self.convergence_absolute_tolerance = 1e-08

        # models - includes types of SectorModel and ScenarioModel
        self.models = {}
        self.dependency_graph = networkx.DiGraph()

        # systems, interventions and (system) state
        self.timesteps = []
        self.interventions = InterventionRegister()
        self.initial_conditions = []
        self.planning = Planning([])
        self._state = defaultdict(dict)

        # scenario data and results
        self._results = defaultdict(dict)

    @property
    def free_inputs(self):
        """Returns the free inputs not linked to a dependency at this layer and all contained layers

        Free inputs are passed up to higher layers for deferred linkages to
        dependencies.

        Returns
        -------
        smif.metadata.MetadataSet
        """
        # free inputs of all contained models
        free_inputs = []
        for model in self.models.values():
            free_inputs.extend(model.free_inputs)

        # free inputs of current layer
        my_free_inputs = super().free_inputs
        free_inputs.extend(my_free_inputs)

        # compose a new MetadataSet containing the free inputs
        metadataset = MetadataSet([])
        for meta in free_inputs:
            metadataset.add_metadata_object(meta)

        return metadataset

    def add_model(self, model):
        """Adds a sector model to the system-of-systems model

        Parameters
        ----------
        model : :class:`smif.sector_model.SectorModel`
            A sector model wrapper

        """
        assert isinstance(model, Model)
        self.logger.info("Loading model: %s", model.name)
        self.models[model.name] = model

    @property
    def results(self):
        """Get nested dict of model results

        Returns
        -------
        dict
            Nested dictionary in the format
            results[int:year][str:model][str:parameter] => list of
            SpaceTimeValues
        """
        # convert from defaultdict to plain dict
        return dict(self._results)

    def simulate(self, timestep, data=None):
        """Run the SosModel

        """
        self.check_dependencies()
        run_order = self._get_model_sets_in_run_order()
        self.logger.info("Determined run order as %s", run_order)
        results = {}
        for model in run_order:
            # get data for model
            sim_data = {}
            for input_name, dep in model.deps.items():
                input_ = model.model_inputs[input_name]
                if input_ in self.free_inputs:
                    # pick external dependencies from data
                    param_data = data[dep.source_model.name][dep.source.name]
                else:
                    # pick internal dependencies from results
                    param_data = results[dep.source_model.name][dep.source.name]
                param_data_converted = dep.convert(param_data, input_)
                sim_data[input_.name] = param_data_converted

            sim_results = model.simulate(timestep, sim_data)
            for model_name, model_results in sim_results.items():
                results[model_name] = model_results
        return results

    def check_dependencies(self):
        """For each contained model, compare dependency list against
        list of available models
        """
        if self.free_inputs.names:
            msg = "A SosModel must have all inputs linked to dependencies." \
                  "Define dependencies for %s"
            raise NotImplementedError(msg, ", ".join(self.free_inputs.names))

        for model in self.models.values():

            if isinstance(model, SosModel):
                msg = "Nesting of SosModels not yet supported"
                raise NotImplementedError(msg)
            else:
                self.dependency_graph.add_node(model,
                                               name=model.name)

                for sink, dependency in model.deps.items():
{'fraction_non_alphanumeric': 0.07991299413656137, 'fraction_numerical': 0.0017022886324947987, 'mean_word_length': 2.2339449541284404, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3479699', 'n_tokens_mistral': 2792, 'n_tokens_neox': 2655, 'n_words': 806}