def set_attr(self, name, values): """ Parameters ---------- name : string Name of the property to be set in each individual environment. values : list, tuple, or object Values of the property to be set to. If `values` is a list or tuple, then it corresponds to the values for each individual environment, otherwise a single value is set for all environments. """ self._assert_is_running() if not isinstance(values, (list, tuple)): values = [values for _ in range(self.num_envs)] if len(values) != self.num_envs: raise ValueError( "Values must be a list or tuple with length equal to the " f"number of environments. Got `{len(values)}` values for " f"{self.num_envs} environments.") if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError( "Calling `set_attr` while waiting " f"for a pending call to `{self._state.value}` to complete.", self._state.value, ) for pipe, value in zip(self.parent_pipes, values): pipe.send(("_setattr", (name, value))) _, successes = zip(*[pipe.recv() for pipe in self.parent_pipes]) self._raise_if_errors(successes)
def seed(self, seeds=None): """ Parameters ---------- seeds : list of int, or int, optional Random seed for each individual environment. If `seeds` is a list of length `num_envs`, then the items of the list are chosen as random seeds. If `seeds` is an int, then each environment uses the random seed `seeds + n`, where `n` is the index of the environment (between `0` and `num_envs - 1`). """ self._assert_is_running() if seeds is None: seeds = [None for _ in range(self.num_envs)] if isinstance(seeds, int): seeds = [seeds + i for i in range(self.num_envs)] assert len(seeds) == self.num_envs if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError('Calling `seed` while waiting ' 'for a pending call to `{0}` to complete.'.format( self._state.value), self._state.value) for pipe, seed in zip(self.parent_pipes, seeds): pipe.send(('seed', seed)) _, successes = zip(*[pipe.recv() for pipe in self.parent_pipes]) self._raise_if_errors(successes)
def seed(self, seed=None): """Seeds the vector environments. Args: seed: The seeds use with the environments Raises: AlreadyPendingCallError: Calling `seed` while waiting for a pending call to complete """ super().seed(seed=seed) self._assert_is_running() if seed is None: seed = [None for _ in range(self.num_envs)] if isinstance(seed, int): seed = [seed + i for i in range(self.num_envs)] assert len(seed) == self.num_envs if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError( f"Calling `seed` while waiting for a pending call to `{self._state.value}` to complete.", self._state.value, ) for pipe, seed in zip(self.parent_pipes, seed): pipe.send(("seed", seed)) _, successes = zip(*[pipe.recv() for pipe in self.parent_pipes]) self._raise_if_errors(successes)
def step_async(self, actions): """Send the calls to :obj:`step` to each sub-environment. Parameters ---------- actions : element of :attr:`~VectorEnv.action_space` Batch of actions. Raises ------ ClosedEnvironmentError If the environment was closed (if :meth:`close` was previously called). AlreadyPendingCallError If the environment is already waiting for a pending call to another method (e.g. :meth:`reset_async`). This can be caused by two consecutive calls to :meth:`step_async`, with no call to :meth:`step_wait` in between. """ self._assert_is_running() if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError( f"Calling `step_async` while waiting for a pending call to `{self._state.value}` to complete.", self._state.value, ) actions = iterate(self.action_space, actions) for pipe, action in zip(self.parent_pipes, actions): pipe.send(("step", action)) self._state = AsyncState.WAITING_STEP
def reset_async(self): self._assert_is_running() if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError('Calling `reset_async` while waiting ' 'for a pending call to `{0}` to complete'.format( self._state.value), self._state.value) for pipe in self.parent_pipes: pipe.send(('reset', None)) self._state = AsyncState.WAITING_RESET
def render_async(self): self._assert_is_running() if self._state.value != AsyncState.DEFAULT.value: raise AlreadyPendingCallError( 'Calling `render_async` while waiting ' 'for a pending call to `{0}` to complete.'.format( self._state.value), self._state.value) else: self.default_state = self._state self.parent_pipes[0].send(('render', None)) self._state = AsyncState.WAITING_RENDER
def step_async(self, actions): """ Parameters ---------- actions : iterable of samples from `action_space` List of actions. """ self._assert_is_running() if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError('Calling `step_async` while waiting ' 'for a pending call to `{0}` to complete.'.format( self._state.value), self._state.value) for pipe, action in zip(self.parent_pipes, actions): pipe.send(('step', action)) self._state = AsyncState.WAITING_STEP
def reset_async( self, seed: Optional[Union[int, list[int]]] = None, return_info: bool = False, options: Optional[dict] = None, ): """Send calls to the :obj:`reset` methods of the sub-environments. To get the results of these calls, you may invoke :meth:`reset_wait`. Args: seed: List of seeds for each environment return_info: If to return information options: The reset option Raises: ClosedEnvironmentError: If the environment was closed (if :meth:`close` was previously called). AlreadyPendingCallError: If the environment is already waiting for a pending call to another method (e.g. :meth:`step_async`). This can be caused by two consecutive calls to :meth:`reset_async`, with no call to :meth:`reset_wait` in between. """ self._assert_is_running() if seed is None: seed = [None for _ in range(self.num_envs)] if isinstance(seed, int): seed = [seed + i for i in range(self.num_envs)] assert len(seed) == self.num_envs if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError( f"Calling `reset_async` while waiting for a pending call to `{self._state.value}` to complete", self._state.value, ) for pipe, single_seed in zip(self.parent_pipes, seed): single_kwargs = {} if single_seed is not None: single_kwargs["seed"] = single_seed if return_info: single_kwargs["return_info"] = return_info if options is not None: single_kwargs["options"] = options pipe.send(("reset", single_kwargs)) self._state = AsyncState.WAITING_RESET
def seed(self, seeds=None): self._assert_is_running() if seeds is None: seeds = [None for _ in range(self.num_envs)] if isinstance(seeds, int): seeds = [seeds + i for i in range(self.num_envs)] assert len(seeds) == self.num_envs if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError('Calling `seed` while waiting ' 'for a pending call to `{0}` to complete.'.format( self._state.value), self._state.value) for pipe, seed in zip(self.parent_pipes, seeds): pipe.send(('seed', seed)) _, successes = zip(*[pipe.recv() for pipe in self.parent_pipes]) self._raise_if_errors(successes)
def call_async(self, name: str, *args, **kwargs): """Calls the method with name asynchronously and apply args and kwargs to the method. Args: name: Name of the method or property to call. *args: Arguments to apply to the method call. **kwargs: Keyword arguments to apply to the method call. """ self._assert_is_running() if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError( "Calling `call_async` while waiting " f"for a pending call to `{self._state.value}` to complete.", self._state.value, ) for pipe in self.parent_pipes: pipe.send(("_call", (name, args, kwargs))) self._state = AsyncState.WAITING_CALL
def reset_async(self): """Send the calls to :obj:`reset` to each sub-environment. Raises ------ ClosedEnvironmentError If the environment was closed (if :meth:`close` was previously called). AlreadyPendingCallError If the environment is already waiting for a pending call to another method (e.g. :meth:`step_async`). This can be caused by two consecutive calls to :meth:`reset_async`, with no call to :meth:`reset_wait` in between. """ self._assert_is_running() if self._state != AsyncState.DEFAULT: raise AlreadyPendingCallError( f"Calling `reset_async` while waiting for a pending call to `{self._state.value}` to complete", self._state.value, ) for pipe in self.parent_pipes: pipe.send(("reset", None)) self._state = AsyncState.WAITING_RESET