Source code for pettingzoo.utils.wrappers.flatten

from __future__ import annotations

from typing import Any

import gymnasium.spaces
from gymnasium.spaces.utils import flatten, flatten_space
from typing_extensions import override

from pettingzoo.utils.env import ActionType, AECEnv, AgentID, ObsType, ParallelEnv
from pettingzoo.utils.wrappers.base import BaseWrapper
from pettingzoo.utils.wrappers.base_parallel import BaseParallelWrapper


[docs] class FlattenObservationV1(BaseWrapper[AgentID, Any, ActionType]): """Flattens each agent's observation into a 1D array. :param env: The AEC environment to wrap. """ def __init__(self, env: AECEnv[AgentID, ObsType, ActionType]): assert isinstance(env, AECEnv), ( "FlattenObservationV1 is only compatible with AEC environments, " "use FlattenObservationParallelV1 instead." ) super().__init__(env) self._obs_spaces: dict[AgentID, gymnasium.spaces.Space[Any]] = {} @override def observation_space(self, agent: AgentID) -> gymnasium.spaces.Space[Any]: if agent not in self._obs_spaces: self._obs_spaces[agent] = flatten_space(self.env.observation_space(agent)) return self._obs_spaces[agent] @override def observe(self, agent: AgentID) -> Any: obs = self.env.observe(agent) if obs is None: return None return flatten(self.env.observation_space(agent), obs) @override def __str__(self) -> str: return f"FlattenObservationV1<{self.env!s}>"
[docs] class FlattenObservationParallelV1(BaseParallelWrapper[AgentID, Any, ActionType]): """Flattens each agent's observation into a 1D array. :param env: The parallel environment to wrap. """ def __init__(self, env: ParallelEnv[AgentID, ObsType, ActionType]): super().__init__(env) self._obs_spaces: dict[AgentID, gymnasium.spaces.Space[Any]] = {} @override def observation_space(self, agent: AgentID) -> gymnasium.spaces.Space[Any]: if agent not in self._obs_spaces: self._obs_spaces[agent] = flatten_space(self.env.observation_space(agent)) return self._obs_spaces[agent] def _flatten(self, observations: dict[AgentID, Any]) -> dict[AgentID, Any]: return { agent: flatten(self.env.observation_space(agent), obs) for agent, obs in observations.items() } @override def reset( self, seed: int | None = None, options: dict[str, Any] | None = None ) -> tuple[dict[AgentID, Any], dict[AgentID, dict[str, Any]]]: observations, infos = self.env.reset(seed=seed, options=options) return self._flatten(observations), infos @override def step( self, actions: dict[AgentID, ActionType] ) -> tuple[ dict[AgentID, Any], dict[AgentID, float], dict[AgentID, bool], dict[AgentID, bool], dict[AgentID, dict[str, Any]], ]: observations, rewards, terminations, truncations, infos = self.env.step(actions) return self._flatten(observations), rewards, terminations, truncations, infos @override def __str__(self) -> str: return f"FlattenObservationParallelV1<{self.env!s}>"