pacai.core.features

 1import typing
 2
 3import pacai.core.action
 4import pacai.core.agent
 5import pacai.core.gamestate
 6
 7FeatureDict: typing.TypeAlias = dict[str, float]
 8"""
 9A collection of features where each feature is keyed by a string.
10This is a companion to WeightDict.
11
12This is a simple alias for a Python dict with string keys and float values.
13"""
14
15WeightDict: typing.TypeAlias = dict[str, float]
16"""
17A collection of weights where each weight is keyed by a string.
18This is a companion to FeatureDict.
19
20This is a simple alias for a Python dict with string keys and float values.
21"""
22
23@typing.runtime_checkable
24class FeatureExtractor(typing.Protocol):
25    """
26    A function that can be used to extract features from a game state and action pair.
27    """
28
29    def __call__(self,
30            state: pacai.core.gamestate.GameState,
31            action: pacai.core.action.Action,
32            agent: pacai.core.agent.Agent | None = None,
33            **kwargs: typing.Any) -> FeatureDict:
34        """
35        Extract the features for the given state/action pair.
36
37        It is very important to note that we are not evaluating the current state,
38        we are evaluating the state/action pair.
39        A very common thing for extractors to do is to call generate_successor() on the state using the action,
40        and then evaluate the successor state.
41        This is a perfectly fine thing to do.
42        The state and action are provided here as separate values for performance reasons.
43        Extractors may be able to avoid copying states if they do not require a full successor.
44
45        The optional agent may be used as a means of passing persistent state
46        (like pre-computed distances) from the agent to this function.
47        """
48
49def score_feature_extractor(
50        state: pacai.core.gamestate.GameState,
51        action: pacai.core.action.Action,
52        agent: pacai.core.agent.Agent | None = None,
53        **kwargs: typing.Any) -> FeatureDict:
54    """
55    The most basic feature extractor, which just uses the state's current score.
56
57    Features:
58     - 'score' -- The current score of the game.
59    """
60
61    rng = None
62    if (agent is not None):
63        rng = agent.rng
64
65    successor = state.generate_successor(action, rng = rng)
66
67    features = FeatureDict()
68    features['score'] = successor.score
69
70    return features
71
72def board_feature_extractor(
73        state: pacai.core.gamestate.GameState,
74        action: pacai.core.action.Action,
75        agent: pacai.core.agent.Agent | None = None,
76        **kwargs: typing.Any) -> FeatureDict:
77    """
78    A feature extractor that just creates a key unique to the board/action pair and assigns it a value of 1.0.
79    It accomplishes this by generating a JSON string for all the non-wall objects in the board.
80    This will be slow, and should generally not be used outside of learning applications.
81
82    Features:
83     - '<action::board>' -- A key unique to each action/board pair. The value is always 1.0.
84    """
85
86    key = f"{action}::{state.board.get_nonwall_string()}"
87
88    features = FeatureDict()
89    features[key] = 1.0
90
91    return features
FeatureDict: TypeAlias = dict[str, float]

A collection of features where each feature is keyed by a string. This is a companion to WeightDict.

This is a simple alias for a Python dict with string keys and float values.

WeightDict: TypeAlias = dict[str, float]

A collection of weights where each weight is keyed by a string. This is a companion to FeatureDict.

This is a simple alias for a Python dict with string keys and float values.

@typing.runtime_checkable
class FeatureExtractor(typing.Protocol):
24@typing.runtime_checkable
25class FeatureExtractor(typing.Protocol):
26    """
27    A function that can be used to extract features from a game state and action pair.
28    """
29
30    def __call__(self,
31            state: pacai.core.gamestate.GameState,
32            action: pacai.core.action.Action,
33            agent: pacai.core.agent.Agent | None = None,
34            **kwargs: typing.Any) -> FeatureDict:
35        """
36        Extract the features for the given state/action pair.
37
38        It is very important to note that we are not evaluating the current state,
39        we are evaluating the state/action pair.
40        A very common thing for extractors to do is to call generate_successor() on the state using the action,
41        and then evaluate the successor state.
42        This is a perfectly fine thing to do.
43        The state and action are provided here as separate values for performance reasons.
44        Extractors may be able to avoid copying states if they do not require a full successor.
45
46        The optional agent may be used as a means of passing persistent state
47        (like pre-computed distances) from the agent to this function.
48        """

A function that can be used to extract features from a game state and action pair.

FeatureExtractor(*args, **kwargs)
1953def _no_init_or_replace_init(self, *args, **kwargs):
1954    cls = type(self)
1955
1956    if cls._is_protocol:
1957        raise TypeError('Protocols cannot be instantiated')
1958
1959    # Already using a custom `__init__`. No need to calculate correct
1960    # `__init__` to call. This can lead to RecursionError. See bpo-45121.
1961    if cls.__init__ is not _no_init_or_replace_init:
1962        return
1963
1964    # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`.
1965    # The first instantiation of the subclass will call `_no_init_or_replace_init` which
1966    # searches for a proper new `__init__` in the MRO. The new `__init__`
1967    # replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent
1968    # instantiation of the protocol subclass will thus use the new
1969    # `__init__` and no longer call `_no_init_or_replace_init`.
1970    for base in cls.__mro__:
1971        init = base.__dict__.get('__init__', _no_init_or_replace_init)
1972        if init is not _no_init_or_replace_init:
1973            cls.__init__ = init
1974            break
1975    else:
1976        # should not happen
1977        cls.__init__ = object.__init__
1978
1979    cls.__init__(self, *args, **kwargs)
def score_feature_extractor( state: pacai.core.gamestate.GameState, action: pacai.core.action.Action, agent: pacai.core.agent.Agent | None = None, **kwargs: Any) -> dict[str, float]:
50def score_feature_extractor(
51        state: pacai.core.gamestate.GameState,
52        action: pacai.core.action.Action,
53        agent: pacai.core.agent.Agent | None = None,
54        **kwargs: typing.Any) -> FeatureDict:
55    """
56    The most basic feature extractor, which just uses the state's current score.
57
58    Features:
59     - 'score' -- The current score of the game.
60    """
61
62    rng = None
63    if (agent is not None):
64        rng = agent.rng
65
66    successor = state.generate_successor(action, rng = rng)
67
68    features = FeatureDict()
69    features['score'] = successor.score
70
71    return features

The most basic feature extractor, which just uses the state's current score.

Features:

  • 'score' -- The current score of the game.
def board_feature_extractor( state: pacai.core.gamestate.GameState, action: pacai.core.action.Action, agent: pacai.core.agent.Agent | None = None, **kwargs: Any) -> dict[str, float]:
73def board_feature_extractor(
74        state: pacai.core.gamestate.GameState,
75        action: pacai.core.action.Action,
76        agent: pacai.core.agent.Agent | None = None,
77        **kwargs: typing.Any) -> FeatureDict:
78    """
79    A feature extractor that just creates a key unique to the board/action pair and assigns it a value of 1.0.
80    It accomplishes this by generating a JSON string for all the non-wall objects in the board.
81    This will be slow, and should generally not be used outside of learning applications.
82
83    Features:
84     - '<action::board>' -- A key unique to each action/board pair. The value is always 1.0.
85    """
86
87    key = f"{action}::{state.board.get_nonwall_string()}"
88
89    features = FeatureDict()
90    features[key] = 1.0
91
92    return features

A feature extractor that just creates a key unique to the board/action pair and assigns it a value of 1.0. It accomplishes this by generating a JSON string for all the non-wall objects in the board. This will be slow, and should generally not be used outside of learning applications.

Features:

  • '' -- A key unique to each action/board pair. The value is always 1.0.