|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
class ActionTuple(NamedTuple): |
|
|
|
class ActionTuple: |
|
|
|
A NamedTuple whose fields correspond to actions of different types. |
|
|
|
Continuous and discrete actions are numpy arrays. |
|
|
|
An object whose fields correspond to actions of different types. |
|
|
|
Continuous and discrete actions are numpy arrays of type float32 and |
|
|
|
int32, respectively and are type checked on construction. |
|
|
|
Dimensions are of (n_agents, continuous_size) and (n_agents, discrete_size), |
|
|
|
respectively. |
|
|
|
continuous: np.ndarray # dims (n_agents, continuous_size) |
|
|
|
discrete: np.ndarray # dims (n_agents, discrete_size) |
|
|
|
def __init__(self, continuous: np.ndarray, discrete: np.ndarray): |
|
|
|
if continuous.dtype != np.float32: |
|
|
|
continuous = continuous.astype(np.float32, copy=False) |
|
|
|
self._continuous = continuous |
|
|
|
if discrete.dtype != np.int32: |
|
|
|
discrete = discrete.astype(np.int32, copy=False) |
|
|
|
self._discrete = discrete |
|
|
|
|
|
|
|
@property |
|
|
|
def continuous(self) -> np.ndarray: |
|
|
|
return self._continuous |
|
|
|
|
|
|
|
@property |
|
|
|
def discrete(self) -> np.ndarray: |
|
|
|
return self._discrete |
|
|
|
|
|
|
|
|
|
|
|
class ActionSpec(NamedTuple): |
|
|
|
|
|
|
for a number of agents. |
|
|
|
:param n_agents: The number of agents that will have actions generated |
|
|
|
""" |
|
|
|
continuous: np.ndarray = None |
|
|
|
discrete: np.ndarray = None |
|
|
|
if self.continuous_size > 0: |
|
|
|
continuous = np.zeros((n_agents, self.continuous_size), dtype=np.float32) |
|
|
|
|
|
|
|
if self.discrete_size > 0: |
|
|
|
discrete = np.zeros((n_agents, self.discrete_size), dtype=np.int32) |
|
|
|
continuous = np.zeros((n_agents, self.continuous_size), dtype=np.float32) |
|
|
|
discrete = np.zeros((n_agents, self.discrete_size), dtype=np.int32) |
|
|
|
return ActionTuple(continuous, discrete) |
|
|
|
|
|
|
|
def random_action(self, n_agents: int) -> ActionTuple: |
|
|
|
|
|
|
:param n_agents: The number of agents that will have actions generated |
|
|
|
""" |
|
|
|
continuous: np.ndarray = None |
|
|
|
discrete: np.ndarray = None |
|
|
|
if self.continuous_size > 0: |
|
|
|
continuous = np.random.uniform( |
|
|
|
low=-1.0, high=1.0, size=(n_agents, self.continuous_size) |
|
|
|
).astype(np.float32) |
|
|
|
|
|
|
|
continuous = np.random.uniform( |
|
|
|
low=-1.0, high=1.0, size=(n_agents, self.continuous_size) |
|
|
|
) |
|
|
|
discrete = np.array([]) |
|
|
|
if self.discrete_size > 0: |
|
|
|
discrete = np.column_stack( |
|
|
|
[ |
|
|
|
|
|
|
for the correct number of agents and ensures the type. |
|
|
|
""" |
|
|
|
_expected_shape = (n_agents, self.continuous_size) |
|
|
|
if self.continuous_size > 0 and actions.continuous.shape != _expected_shape: |
|
|
|
if actions.continuous.shape != _expected_shape: |
|
|
|
if actions.continuous.dtype != np.float32: |
|
|
|
actions.continuous = actions.continuous.astype(np.float32) |
|
|
|
|
|
|
|
if self.discrete_size > 0 and actions.discrete.shape != _expected_shape: |
|
|
|
if actions.discrete.shape != _expected_shape: |
|
|
|
if actions.discrete.dtype != np.int32: |
|
|
|
actions.discrete = actions.discrete.astype(np.int32) |
|
|
|
return actions |
|
|
|
|
|
|
|
@staticmethod |
|
|
|