Skip to content

States module

AdaptiveProbabilisticState

Special probabilistic state that allows modifaction of weights.

modifiers: List[float] property readonly

The weight modifiers assigned to the transitions.

name: str inherited property readonly

The name (including the prefix) of the state instance

Names must be unique within a state machine.

name_only: str inherited property readonly

The name of the state instance (names must be uniq within a state machine).

name_prefix: Optional[str] inherited property readonly

The name prefix of the state instance.

probabilities: List[float] property readonly

The propabilities based on the weights and modifiers

transitions: List[cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

transitions_map: Dict[str, cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

weights: Sequence[float] inherited property readonly

The weight assigned to the transitions.

__init__(self, name, transitions, weights, modifiers=None, name_prefix=None) special

Parameters:

Name Type Description Default
name str

The name of the state

required
transitions List[cr_kyoushi.simulation.transitions.Transition]

The list of transitions

required
weights Sequence[float]

The list of weights to assign to the transitions in propability notation

required
modifiers Optional[Sequence[float]]

List of multiplicative modifiers for each weight. Will default to all 1 if not set.

None
name_prefix Optional[str]

A prefix for the state name

None
Source code in simulation/states.py
def __init__(
    self,
    name: str,
    transitions: List[Transition],
    weights: Sequence[float],
    modifiers: Optional[Sequence[float]] = None,
    name_prefix: Optional[str] = None,
):
    """
    Args:
        name: The name of the state
        transitions: The list of transitions
        weights: The list of weights to assign to the transitions in propability notation
        modifiers: List of multiplicative modifiers for each weight.
                   Will default to all 1 if not set.
        name_prefix: A prefix for the state name
    """
    super().__init__(name, transitions, weights, name_prefix)
    if modifiers is None:
        modifiers = [1.0] * len(self.weights)

    self._modifiers = dict(zip(transitions, list(modifiers)))

    self.__modifiers_org: Tuple[float, ...] = tuple(self.modifiers)

adapt_after(self, log, context, selected)

Hook to update the weight modifiers after the transition selection.

Parameters:

Name Type Description Default
log BoundLogger

The logger for the sm context

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

The state machine context

required
selected Optional[cr_kyoushi.simulation.transitions.Transition]

The transition selected in this next call

required
Source code in simulation/states.py
def adapt_after(
    self,
    log: BoundLogger,
    context: Context,
    selected: Optional[Transition],
):
    """Hook to update the weight modifiers after the transition selection.

    Args:
        log: The logger for the sm context
        context: The state machine context
        selected: The transition selected in this next call
    """

adapt_before(self, log, context)

Hook to update the weight modifiers before the transition selection.

Parameters:

Name Type Description Default
log BoundLogger

The logger for the sm context

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

The state machine context

required
Source code in simulation/states.py
def adapt_before(self, log: BoundLogger, context: Context):
    """Hook to update the weight modifiers before the transition selection.

    Args:
        log: The logger for the sm context
        context: The state machine context
    """

next(self, log, context)

Selects the next state transition.

The selection logic depends on the state implementation. It might rely on the state machine context and/or execution environment information to select transitions based on complex conditions.

Parameters:

Name Type Description Default
log BoundLogger

The bound logger initialized with transition specific information

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

State machine context which can be used for complex selection logic

required

Returns:

Type Description
Optional[cr_kyoushi.simulation.transitions.Transition]

The selected Transition or None if no transition is available.

Source code in simulation/states.py
def next(self, log: BoundLogger, context: Context) -> Optional[Transition]:
    if len(self.transitions) > 0:
        self.adapt_before(log, context)
        selected = np.random.choice(
            a=np.array(self.transitions), p=self.probabilities
        )
        self.adapt_after(log, context, selected)
        return selected
    return None

reset(self)

Resets the modifiers to their original state

Source code in simulation/states.py
def reset(self):
    """Resets the modifiers to their original state"""
    self._modifiers = dict(zip(self.transitions, self.__modifiers_org))

ChoiceState

Simple boolean choice state decides between two transitions

name: str inherited property readonly

The name (including the prefix) of the state instance

Names must be unique within a state machine.

name_only: str inherited property readonly

The name of the state instance (names must be uniq within a state machine).

name_prefix: Optional[str] inherited property readonly

The name prefix of the state instance.

no: Transition property readonly

The transition that is returned when the decision function returns False

transitions: List[cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

transitions_map: Dict[str, cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

yes: Transition property readonly

The transition that is returned when the decision function returns True

__init__(self, name, decision_function, yes, no, name_prefix=None) special

Parameters:

Name Type Description Default
name str

The state name

required
decision_function Callable[[structlog.stdlib.BoundLogger, Union[pydantic.main.BaseModel, Dict[str, Any]]], bool]

Context function that decides a yes/no question.

required
yes Transition

The transition to return when the decision function returns True

required
no Transition

The transition to return when the decision function returns False

required
name_prefix Optional[str]

A prefix for the state name

None
Source code in simulation/states.py
def __init__(
    self,
    name: str,
    decision_function: Callable[[BoundLogger, Context], bool],
    yes: Transition,
    no: Transition,
    name_prefix: Optional[str] = None,
):
    """
    Args:
        name: The state name
        decision_function: Context function that decides a yes/no question.
        yes: The transition to return when the decision function returns `True`
        no: The transition to return when the decision function returns `False`
        name_prefix: A prefix for the state name
    """
    super().__init__(name, [yes, no], name_prefix)
    self.__decision_function: Callable[
        [BoundLogger, Context], bool
    ] = decision_function

next(self, log, context)

Selects the next state transition.

The selection logic depends on the state implementation. It might rely on the state machine context and/or execution environment information to select transitions based on complex conditions.

Parameters:

Name Type Description Default
log BoundLogger

The bound logger initialized with transition specific information

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

State machine context which can be used for complex selection logic

required

Returns:

Type Description
Optional[cr_kyoushi.simulation.transitions.Transition]

The selected Transition or None if no transition is available.

Source code in simulation/states.py
def next(self, log: BoundLogger, context: Context) -> Optional[Transition]:
    return self.yes if self.__decision_function(log, context) else self.no

EquallyRandomState

Special type of probabilistic state using an equal random distribution for all transitions

name: str inherited property readonly

The name (including the prefix) of the state instance

Names must be unique within a state machine.

name_only: str inherited property readonly

The name of the state instance (names must be uniq within a state machine).

name_prefix: Optional[str] inherited property readonly

The name prefix of the state instance.

transitions: List[cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

transitions_map: Dict[str, cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

weights: Sequence[float] inherited property readonly

The weight assigned to the transitions.

__init__(self, name, transitions, name_prefix=None) special

Parameters:

Name Type Description Default
name str

The state name

required
transitions List[cr_kyoushi.simulation.transitions.Transition]

The list of transitions

required
name_prefix Optional[str]

A prefix for the state name

None

Exceptions:

Type Description
ValueError

If there are transitions with duplicate names

Source code in simulation/states.py
def __init__(
    self,
    name: str,
    transitions: List[Transition],
    name_prefix: Optional[str] = None,
):
    """
    Args:
        name: The state name
        transitions: The list of transitions
        name_prefix: A prefix for the state name

    Raises:
        ValueError: If there are transitions with duplicate names
    """
    # create even random distribution
    probability = 1.0 / len(transitions)
    weights = [probability for i in range(0, len(transitions))]
    # initialize using super
    super().__init__(name, transitions, weights, name_prefix)

next(self, log, context) inherited

Selects the next state transition.

The selection logic depends on the state implementation. It might rely on the state machine context and/or execution environment information to select transitions based on complex conditions.

Parameters:

Name Type Description Default
log BoundLogger

The bound logger initialized with transition specific information

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

State machine context which can be used for complex selection logic

required

Returns:

Type Description
Optional[cr_kyoushi.simulation.transitions.Transition]

The selected Transition or None if no transition is available.

Source code in simulation/states.py
def next(self, log: BoundLogger, context: Context) -> Optional[Transition]:
    if len(self.transitions) > 0:
        return np.random.choice(a=np.array(self.transitions), p=self.weights)
    return None

FinalState

State with not further transitions which can be used as final state of a state machine

name: str inherited property readonly

The name (including the prefix) of the state instance

Names must be unique within a state machine.

name_only: str inherited property readonly

The name of the state instance (names must be uniq within a state machine).

name_prefix: Optional[str] inherited property readonly

The name prefix of the state instance.

transitions: List[cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

transitions_map: Dict[str, cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

__init__(self, name, name_prefix=None) special

Parameters:

Name Type Description Default
name str

The state name

required
name_prefix Optional[str]

A prefix for the state name

None
Source code in simulation/states.py
def __init__(self, name: str, name_prefix: Optional[str] = None):
    """
    Args:
        name: The state name
        name_prefix: A prefix for the state name
    """
    super().__init__(name, [], name_prefix)

next(self, log, context)

Selects the next state transition.

The selection logic depends on the state implementation. It might rely on the state machine context and/or execution environment information to select transitions based on complex conditions.

Parameters:

Name Type Description Default
log BoundLogger

The bound logger initialized with transition specific information

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

State machine context which can be used for complex selection logic

required

Returns:

Type Description
Optional[cr_kyoushi.simulation.transitions.Transition]

The selected Transition or None if no transition is available.

Source code in simulation/states.py
def next(self, log: BoundLogger, context: Context) -> Optional[Transition]:
    return None

ProbabilisticState

A state that uses a propability table to select its successor

name: str inherited property readonly

The name (including the prefix) of the state instance

Names must be unique within a state machine.

name_only: str inherited property readonly

The name of the state instance (names must be uniq within a state machine).

name_prefix: Optional[str] inherited property readonly

The name prefix of the state instance.

transitions: List[cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

transitions_map: Dict[str, cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

weights: Sequence[float] property readonly

The weight assigned to the transitions.

__init__(self, name, transitions, weights, name_prefix=None) special

Parameters:

Name Type Description Default
name str

The state name

required
transitions List[cr_kyoushi.simulation.transitions.Transition]

The list of transitions

required
weights Sequence[float]

The list of weights to assign to the transitions in probability notation.

required
name_prefix Optional[str]

A prefix for the state name

None

Exceptions:

Type Description
ValueError

If there are transitions with duplicate names

ValueError

If the weights and transitions list lengths do not match

ValueError

If the given weights do not sum up to 1

Source code in simulation/states.py
def __init__(
    self,
    name: str,
    transitions: List[Transition],
    weights: Sequence[float],
    name_prefix: Optional[str] = None,
):
    """
    Args:
        name: The state name
        transitions: The list of transitions
        weights: The list of weights to assign to the transitions in probability notation.
        name_prefix: A prefix for the state name

    Raises:
        ValueError: If there are transitions with duplicate names
        ValueError: If the weights and transitions list lengths do not match
        ValueError: If the given weights do not sum up to 1
    """
    # initial base properties
    super().__init__(name, transitions, name_prefix)

    # convert weights to cumulative weights
    self.__weights = weights

    # verify that given weights and transitions are sound
    self.__verify_weights()

next(self, log, context)

Selects the next state transition.

The selection logic depends on the state implementation. It might rely on the state machine context and/or execution environment information to select transitions based on complex conditions.

Parameters:

Name Type Description Default
log BoundLogger

The bound logger initialized with transition specific information

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

State machine context which can be used for complex selection logic

required

Returns:

Type Description
Optional[cr_kyoushi.simulation.transitions.Transition]

The selected Transition or None if no transition is available.

Source code in simulation/states.py
def next(self, log: BoundLogger, context: Context) -> Optional[Transition]:
    if len(self.transitions) > 0:
        return np.random.choice(a=np.array(self.transitions), p=self.weights)
    return None

RoundRobinState

name: str inherited property readonly

The name (including the prefix) of the state instance

Names must be unique within a state machine.

name_only: str inherited property readonly

The name of the state instance (names must be uniq within a state machine).

name_prefix: Optional[str] inherited property readonly

The name prefix of the state instance.

transitions: List[cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

transitions_map: Dict[str, cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

__init__(self, name, transitions, name_prefix=None) special

Parameters:

Name Type Description Default
name str

The state name

required
transitions List[cr_kyoushi.simulation.transitions.Transition]

List of transitions to cycle through

required
name_prefix Optional[str]

A prefix for the state name

None

Exceptions:

Type Description
ValueError

If there are transitions with duplicate names

Source code in simulation/states.py
def __init__(
    self,
    name: str,
    transitions: List[Transition],
    name_prefix: Optional[str] = None,
):
    """
    Args:
        name (str): The state name
        transitions (List[Transition]): List of transitions to cycle through
        name_prefix: A prefix for the state name

    Raises:
        ValueError: If there are transitions with duplicate names
    """
    super().__init__(name, transitions, name_prefix)
    self.transition_cycle = cycle(transitions)

next(self, log, context)

Selects the next state transition.

The selection logic depends on the state implementation. It might rely on the state machine context and/or execution environment information to select transitions based on complex conditions.

Parameters:

Name Type Description Default
log BoundLogger

The bound logger initialized with transition specific information

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

State machine context which can be used for complex selection logic

required

Returns:

Type Description
Optional[cr_kyoushi.simulation.transitions.Transition]

The selected Transition or None if no transition is available.

Source code in simulation/states.py
def next(self, log: BoundLogger, context: Context) -> Optional[Transition]:
    try:
        return next(self.transition_cycle)
    except StopIteration:
        return None

SequentialState

Simple sequential state only having one possible transition

name: str inherited property readonly

The name (including the prefix) of the state instance

Names must be unique within a state machine.

name_only: str inherited property readonly

The name of the state instance (names must be uniq within a state machine).

name_prefix: Optional[str] inherited property readonly

The name prefix of the state instance.

transitions: List[cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

transitions_map: Dict[str, cr_kyoushi.simulation.transitions.Transition] inherited property readonly

List of all possible transitions originating from this state

__init__(self, name, transition, name_prefix=None) special

Parameters:

Name Type Description Default
name str

The state name

required
transition Transition

The target transition

required
name_prefix Optional[str]

A prefix for the state name

None

Exceptions:

Type Description
ValueError

If transition is None

Source code in simulation/states.py
def __init__(
    self,
    name: str,
    transition: Transition,
    name_prefix: Optional[str] = None,
):
    """
    Args:
        name: The state name
        transition: The target transition
        name_prefix: A prefix for the state name

    Raises:
        ValueError: If transition is None
    """
    if transition is None:
        raise ValueError("Transition must not be None")

    super().__init__(name, [transition], name_prefix)
    self.__transition = transition

next(self, log, context)

Selects the next state transition.

The selection logic depends on the state implementation. It might rely on the state machine context and/or execution environment information to select transitions based on complex conditions.

Parameters:

Name Type Description Default
log BoundLogger

The bound logger initialized with transition specific information

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

State machine context which can be used for complex selection logic

required

Returns:

Type Description
Optional[cr_kyoushi.simulation.transitions.Transition]

The selected Transition or None if no transition is available.

Source code in simulation/states.py
def next(self, log: BoundLogger, context: Context) -> Optional[Transition]:
    return self.__transition

State

A State contains various transitions to other states

name: str property readonly

The name (including the prefix) of the state instance

Names must be unique within a state machine.

name_only: str property readonly

The name of the state instance (names must be uniq within a state machine).

name_prefix: Optional[str] property readonly

The name prefix of the state instance.

transitions: List[cr_kyoushi.simulation.transitions.Transition] property readonly

List of all possible transitions originating from this state

transitions_map: Dict[str, cr_kyoushi.simulation.transitions.Transition] property readonly

List of all possible transitions originating from this state

__init__(self, name, transitions, name_prefix=None) special

Parameters:

Name Type Description Default
name str

The state name

required
transitions List[cr_kyoushi.simulation.transitions.Transition]

List of possible transitions

required
name_prefix Optional[str]

A prefix for the state name

None

Exceptions:

Type Description
ValueError

If there are transitions with duplicate names

Source code in simulation/states.py
def __init__(
    self,
    name: str,
    transitions: List[Transition],
    name_prefix: Optional[str] = None,
):
    """
    Args:
        name: The state name
        transitions: List of possible transitions
        name_prefix: A prefix for the state name

    Raises:
        ValueError: If there are transitions with duplicate names
    """
    self._name = name
    self._transitions = {t.name: t for t in transitions}
    self._name_prefix: Optional[str] = name_prefix

    if len(self._transitions) < len(transitions):
        raise ValueError("Transition names must be unique")

next(self, log, context)

Selects the next state transition.

The selection logic depends on the state implementation. It might rely on the state machine context and/or execution environment information to select transitions based on complex conditions.

Parameters:

Name Type Description Default
log BoundLogger

The bound logger initialized with transition specific information

required
context Union[pydantic.main.BaseModel, Dict[str, Any]]

State machine context which can be used for complex selection logic

required

Returns:

Type Description
Optional[cr_kyoushi.simulation.transitions.Transition]

The selected Transition or None if no transition is available.

Source code in simulation/states.py
@abstractmethod
def next(self, log: BoundLogger, context: Context) -> Optional[Transition]:
    """Selects the next state transition.

       The selection logic depends on the state implementation. It might
       rely on the [`state machine context`][cr_kyoushi.simulation.sm.Statemachine.context]
       and/or execution environment information to select transitions based on complex conditions.

    Args:
        log: The bound logger initialized with transition specific information
        context (Context): State machine context which can be used for complex selection logic

    Returns:
        The selected [`Transition`][cr_kyoushi.simulation.transitions.Transition]
        or None if no transition is available.

    """
    ...