#2869 - Remove outdated parameters from actionmanager (action map achieves the same result) [skip ci]

This commit is contained in:
Marek Wolan
2025-01-14 13:48:18 +00:00
parent fb5242bd78
commit 40d052141c
42 changed files with 36 additions and 1679 deletions

View File

@@ -13,7 +13,7 @@ agents:
from __future__ import annotations
from typing import Dict, List, Optional, Tuple
from typing import Dict, Optional, Tuple
from gymnasium import spaces
@@ -41,31 +41,12 @@ class DoNothingAction(AbstractAction, identifier="do_nothing"):
class ActionManager:
"""Class which manages the action space for an agent."""
def __init__(
self,
actions: List[Dict], # stores list of actions available to agent
nodes: List[Dict], # extra configuration for each node
act_map: Optional[
Dict[int, Dict]
] = None, # allows restricting set of possible actions - TODO: Refactor to be a list?
*args,
**kwargs,
) -> None:
def __init__(self, act_map: Optional[Dict[int, Dict]] = None) -> None:
"""Init method for ActionManager.
:param game: Reference to the game to which the agent belongs.
:type game: PrimaiteGame
:param actions: List of action specs which should be made available to the agent. The keys of each spec are:
'type' and 'options' for passing any options to the action class's init method
:type actions: List[dict]
:param act_map: Action map which maps integers to actions. Used for restricting the set of possible actions.
:type act_map: Optional[Dict[int, Dict]]
"""
self.actions: Dict[str, AbstractAction] = {}
for act_spec in actions:
act_type = act_spec.get("type")
self.actions[act_type] = AbstractAction._registry[act_type]
self.action_map: Dict[int, Tuple[str, Dict]] = {}
"""
Action mapping that converts an integer to a specific action and parameter choice.
@@ -73,6 +54,7 @@ class ActionManager:
For example :
{0: ("node_service_scan", {node_name:"client_1", service_name:"WebBrowser"})}
"""
# allows restricting set of possible actions - TODO: Refactor to be a list?
if act_map is None:
# raise RuntimeError("Action map must be specified in the config file.")
pass
@@ -100,39 +82,17 @@ class ActionManager:
return spaces.Discrete(len(self.action_map))
@classmethod
def from_config(cls, game: "PrimaiteGame", cfg: Dict) -> "ActionManager": # noqa: F821
def from_config(cls, cfg: Dict) -> "ActionManager":
"""
Construct an ActionManager from a config definition.
Construct an ActionManager from a config dictionary.
The action space config supports the following three sections:
1. ``action_list``
``action_list`` contains a list action components which need to be included in the action space.
Each action component has a ``type`` which maps to a subclass of AbstractAction, and additional options
which will be passed to the action class's __init__ method during initialisation.
2. ``action_map``
Since the agent uses a discrete action space which acts as a flattened version of the component-based
action space, action_map provides a mapping between an integer (chosen by the agent) and a meaningful
action and values of parameters. For example action 0 can correspond to do nothing, action 1 can
correspond to "node_service_scan" with ``node_name="server"`` and
``service_name="WebBrowser"``, action 2 can be "
3. ``options``
``options`` contains a dictionary of options which are passed to the ActionManager's __init__ method.
These options are used to calculate the shape of the action space, and to provide additional information
to the ActionManager which is required to convert the agent's action choice into a CAOS request.
The action space config supports must contain the following key:
``action_map`` - List of actions available to the agent, formatted as a dictionary where the key is the
action number between 0 - N, and the value is the CAOS-formatted action.
:param game: The Primaite Game to which the agent belongs.
:type game: PrimaiteGame
:param cfg: The action space config.
:type cfg: Dict
:return: The constructed ActionManager.
:rtype: ActionManager
"""
obj = cls(
actions=cfg["action_list"],
**cfg["options"],
protocols=game.options.protocols,
ports=game.options.ports,
act_map=cfg.get("action_map"),
)
return obj
return cls(**cfg.get("options", {}), act_map=cfg.get("action_map"))

View File

@@ -93,8 +93,8 @@ class AbstractAgent(BaseModel):
return ValueError(f"Invalid Agent Type: {config['type']}")
obj = cls(
config=cls.ConfigSchema(**config["agent_settings"]),
action_manager=ActionManager.from_config(config["game"], config["action_manager"]),
observation_manager=ObservationManager.from_config(config["observation_manager"]),
action_manager=ActionManager.from_config(config["action_space"]),
observation_manager=ObservationManager.from_config(config["observation_space"]),
reward_function=RewardFunction.from_config(config["reward_function"]),
)
return obj

View File

@@ -534,8 +534,8 @@ class PrimaiteGame:
agent_config = {
"type": agent_type,
"action_manager": action_space_cfg,
"observation_manager": observation_space_cfg,
"action_space": action_space_cfg,
"observation_space": observation_space_cfg,
"reward_function": reward_function_cfg,
"agent_settings": agent_settings,
"game": game,