Skip to content

Decisions

Decision class of actor.

Source code in abses/decision.py
def __init__(self, agent: Optional[Actor] = None) -> None:
    self._agent: Optional[Actor] = agent
    self._strategy: Any = self._setup()

name classmethod property

name

Get the name of the decision. By default, this will be a snake name of class name. Users can custom it by assigning a class attribute name_as.

Example
class TestDecision(Decision):
    pass
>>> decision = TestDecision()
>>> decision.name
>>> 'test_decision'

class TestDecision(Decision):
    name_as: str = 'decision'
>>> decision = TestDecision()
>>> decision.name
>>> 'decision'

strategies property

strategies

Get all strategies.

agent property

agent

Decision-maker.

now property

now

The strategy now.

validate_strategies classmethod

validate_strategies(strategies)

Check if the strategies valid.

Source code in abses/decision.py
@classmethod
def validate_strategies(cls, strategies: Strategy):
    """Check if the strategies valid."""
    if not isinstance(strategies, Dict):
        raise TypeError(
            f"So far, only discrete strategies are supported, you should set '__strategies__' class attribute with a dictionary of strategies when subclassing 'Decision', got {type(strategies)} instead."
        )

set_strategies classmethod

set_strategies(strategies)

Parsing strategies and save into properties.

Source code in abses/decision.py
@classmethod
def set_strategies(cls, strategies: Dict[str, Strategy]) -> None:
    """Parsing strategies and save into properties."""
    cls._strategies = strategies

making classmethod

making(method)

A decorator makes this decision.

Source code in abses/decision.py
@classmethod
def making(cls, method: Callable) -> Callable:
    """A decorator makes this decision."""

    @wraps(method)
    def decorated(self: Actor, *args, **kwargs):
        cls.validate_decision_maker(self)
        result = method(self, *args, **kwargs)
        cls.validate_strategy(result)
        return result

    setattr(decorated, "__making__", cls)
    return decorated

response classmethod

response(strategy)

Change the decorated function into a response methods.

Source code in abses/decision.py
@classmethod
def response(cls, strategy: Strategy) -> Callable:
    """Change the decorated function into a response methods."""

    def decorator(func) -> Callable:
        @wraps(func)
        def wrapper(self: Actor, *args, **kwargs):
            if not hasattr(self, "decisions"):
                raise AttributeError(
                    f"{self.breed} doesn't have an attribute 'decisions'"
                )
            if not isinstance(
                getattr(self, "decisions"), _DecisionFactory
            ):
                raise TypeError("Type of a decision must be decision.")
            decision_obj = self.decisions.get(cast(str, cls.name))
            if not decision_obj.has_strategy(strategy):
                raise TypeError(
                    f"Decision '{cls.name}' doesn't have strategy {strategy}."
                )
            return func(self, *args, **kwargs)

        setattr(wrapper, "__response__", cls)
        setattr(wrapper, "__expected__", strategy)
        return wrapper

    # decorator.__response__ = cls
    return decorator

validate_decision_maker classmethod

validate_decision_maker(agent)

Validate maker of this decision.

Source code in abses/decision.py
@classmethod
def validate_decision_maker(cls, agent: Actor):
    """Validate maker of this decision."""
    from abses.actor import Actor

    if not isinstance(agent, Actor):
        raise TypeError(
            f"Decision maker should be an instance of 'Actor' class, got {type(agent)} instead."
        )

validate_strategy classmethod

validate_strategy(strategy)

Validate a strategy choice.

Parameters:

Name Type Description Default
strategy Strategy

The strategy to validate.

required

Raises:

Type Description
KeyError

If the strategy is not a valid choice.

Source code in abses/decision.py
@classmethod
def validate_strategy(cls, strategy: Strategy) -> None:
    """Validate a strategy choice.

    Parameters:
        strategy:
            The strategy to validate.

    Raises:
        KeyError:
            If the strategy is not a valid choice.
    """
    if not cls.has_strategy(strategy=strategy):
        raise KeyError(
            f"Decision '{cls.__name__}' doesn't have a valid strategy {strategy}."
        )

has_strategy classmethod

has_strategy(strategy)

Is a specific strategy existing in this decision?

Parameters:

Name Type Description Default
strategy Strategy

The strategy to validate.

required

Returns:

Type Description
bool

If the strategy exists, return True, otherwise returns False.

Source code in abses/decision.py
@classmethod
def has_strategy(cls, strategy: Strategy) -> bool:
    """Is a specific strategy existing in this decision?

    Parameters:
        strategy:
            The strategy to validate.

    Returns:
        If the strategy exists, return True, otherwise returns False.
    """
    return strategy in cls._strategies.keys()

setup

setup()

Overwrite to setup an initial strategy for this decision.

Source code in abses/decision.py
def setup(self) -> None:
    """Overwrite to setup an initial strategy for this decision."""

make

make()

Overwrite this method to do something else after make decision.

Source code in abses/decision.py
def make(self) -> None:
    """Overwrite this method to do something else after make decision."""

Creating and containing decisions of an agent.

Source code in abses/decision.py
def __init__(
    self,
    agent: Actor,
    decisions: Optional[Iterable[Type[Decision]]] = None,
) -> None:
    self.agent: Actor = agent
    self._decisions: Dict[str, Decision] = {}
    if decisions is None:
        decisions = []
    self.parse_decisions(decisions)

agent property writable

agent

Decision-maker, who has these decisions.

parse_decisions

parse_decisions(decisions)

Parse decisions and save into the container.

Parameters:

Name Type Description Default
decisions Iterable[Type[Decision]]

Iterable Decision class.

required

Raises:

Type Description
TypeError

If the input decision is not a subclass of Decision.

Source code in abses/decision.py
def parse_decisions(self, decisions: Iterable[Type[Decision]]):
    """Parse decisions and save into the container.

    Parameters:
        decisions:
            Iterable `Decision` class.

    Raises:
        TypeError:
            If the input decision is not a subclass of `Decision`.
    """
    for d in decisions:
        if not issubclass(d, Decision):
            raise TypeError(
                f"Decision must be an subclass of 'Decision' class, got {type(d)} instead."
            )
        obj = d(agent=self.agent)
        self._decisions[obj.name] = obj

keys

keys()

Get all decision names.

Source code in abses/decision.py
def keys(self) -> List[str]:
    """Get all decision names."""
    return list(self._decisions.keys())

get

get(name)

Get a decision by its name.

Source code in abses/decision.py
def get(self, name: str) -> Decision:
    """Get a decision by its name."""
    if name not in self._decisions:
        raise KeyError(
            f"Decision '{name}' doesn't exist in {self.keys()}."
        )
    return self._decisions[name]

making

making()

Making decisions.

Source code in abses/decision.py
def making(self) -> None:
    """Making decisions."""
    for d in self._decisions.values():
        d._make()