<commit_before>"""A framework for generic state machines."""
from enum import Enum

import pandas as pd
import numpy as np


def _next_state(index, transition_set, population_view):
    """Moves a population between different states using information from a `TransitionSet`.

    Parameters
    ----------
    index : iterable of ints
        An iterable of integer labels for the simulants.
    transition_set : `TransitionSet`
        A set of potential transitions available to the simulants.
    population_view : `pandas.DataFrame`
        A view of the internal state of the simulation.
    """

    if len(transition_set) == 0:
        return

    outputs, decisions = transition_set.choose_new_state(index)
    groups = _groupby_new_state(index, outputs, decisions)

    if groups:
        for output, affected_index in sorted(groups, key=lambda x: str(x[0])):
            if output == 'null_transition':
                pass
            elif isinstance(output, TransientState):
                output.transition_effect(affected_index, population_view)
                output.next_state(affected_index, population_view)
            elif isinstance(output, State):
                output.transition_effect(affected_index, population_view)
            else:
                raise ValueError('Invalid transition output: {}'.format(output))


def _groupby_new_state(index, outputs, decisions):
    """Groups the simulants in the index by their new output state.

    Parameters
    ----------
    index : iterable of ints
        An iterable of integer labels for the simulants.
    outputs : iterable
        A list of possible output states.<commit_msg>Bugfix in state machine to deal with potentially empty indices.<commit_after>"""A framework for generic state machines."""
from enum import Enum

import pandas as pd
import numpy as np


def _next_state(index, transition_set, population_view):
    """Moves a population between different states using information from a `TransitionSet`.

    Parameters
    ----------
    index : iterable of ints
        An iterable of integer labels for the simulants.
    transition_set : `TransitionSet`
        A set of potential transitions available to the simulants.
    population_view : `pandas.DataFrame`
        A view of the internal state of the simulation.
    """

    if len(transition_set) == 0 or index.empty:
        return

    outputs, decisions = transition_set.choose_new_state(index)
    groups = _groupby_new_state(index, outputs, decisions)

    if groups:
        for output, affected_index in sorted(groups, key=lambda x: str(x[0])):
            if output == 'null_transition':
                pass
            elif isinstance(output, TransientState):
                output.transition_effect(affected_index, population_view)
                output.next_state(affected_index, population_view)
            elif isinstance(output, State):
                output.transition_effect(affected_index, population_view)
            else:
                raise ValueError('Invalid transition output: {}'.format(output))


def _groupby_new_state(index, outputs, decisions):
    """Groups the simulants in the index by their new output state.

    Parameters
    ----------
    index : iterable of ints
        An iterable of integer labels for the simulants.
    outputs : iterable
        A list of possible output states.
{'fraction_non_alphanumeric': 0.07803724504877328, 'fraction_numerical': 0.0011823825007389892, 'mean_word_length': 2.702407002188184, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4128094', 'n_tokens_mistral': 875, 'n_tokens_neox': 833, 'n_words': 304}