docstr: Return a randomized batch of experiences
  
  # Argument
      batch_size (int): Size of the all batch
      batch_idxs (int): Indexes to extract
  # Returns
      A list of experiences randomly selected
docstr_tok: ["Return","a","randomized","batch","of","experiences","#","Argument","batch_size","(","int",")",":","Size","of","the","all","batch","batch_idxs","(","int",")",":","Indexes","to","extract","#","Returns","A","list","of","experiences","randomly","selected"]
code: def sample(self, batch_size, batch_idxs=None):
      """Return a randomized batch of experiences
  
      # Argument
          batch_size (int): Size of the all batch
          batch_idxs (int): Indexes to extract
      # Returns
          A list of experiences randomly selected
      """
      # It is not possible to tell whether the first state in the memory is terminal, because it
      # would require access to the "terminal" flag associated to the previous state. As a result
      # we will never return this first state (only using `self.terminals[0]` to know whether the
      # second state is terminal).
      # In addition we need enough entries to fill the desired window length.
      assert (
          self.nb_entries >= self.window_length + 2
      ), "not enough entries in the memory"
  
      if batch_idxs is None:
          # Draw random indexes such that we have enough entries before each index to fill the
          # desired window length.
          batch_idxs = sample_batch_indexes(
              self.window_length, self.nb_entries - 1, size=batch_size
          )
      batch_idxs = np.array(batch_idxs) + 1
      assert np.min(batch_idxs) >= self.window_length + 1
      assert np.max(batch_idxs) < self.nb_entries
      assert len(batch_idxs) == batch_size
  
      # Create experiences
      experiences = []
      for idx in batch_idxs:
          terminal0 = self.terminals[idx - 2]
          while terminal0:
              # Skip this transition because the environment was reset here. Select a new, random
              # transition and use this instead. This may cause the batch to contain the same
              # transition twice.
              idx = sample_batch_indexes(
                  self.window_length + 1, self.nb_entries, size=1
              )[0]
              terminal0 = self.terminals[idx - 2]
          assert self.window_length + 1 <= idx < self.nb_entries
  
          # This code is slightly complicated by the fact that subsequent observations might be
          # from different episodes. We ensure that an experience never spans multiple episodes.
          # This is probably not that important in practice but it seems cleaner.
          state0 = [self.observations[idx - 1]]
          for offset in range(0, self.window_length - 1):
              current_idx = idx - 2 - offset
              assert current_idx >= 1
              current_terminal = self.terminals[current_idx - 1]
              if (
                  current_terminal
                  and not self.ignore_episode_boundaries
              ):
                  # The previously handled observation was terminal, don't add the current one.
                  # Otherwise we would leak into a different episode.
                  break
              state0.insert(0, self.observations[current_idx])
          while len(state0) < self.window_length:
              state0.insert(0, zeroed_observation(state0[0]))
          action = self.actions[idx - 1]
          reward = self.rewards[idx - 1]
          terminal1 = self.terminals[idx - 1]
  
          # Okay, now we need to create the follow-up state. This is state0 shifted on timestep
          # to the right. Again, we need to be careful to not include an observation from the next
          # episode if the last state is terminal.
          state1 = [np.copy(x) for x in state0[1:]]
          state1.append(self.observations[idx])
  
          assert len(state0) == self.window_length
          assert len(state1) == len(state0)
          experiences.append(
              Experience(
                  state0=state0,
                  action=action,
                  reward=reward,
                  state1=state1,
                  terminal1=terminal1,
              )
          )
      assert len(experiences) == batch_size
      return experiences
  
imports: from __future__ import absolute_import
  from collections import deque, namedtuple
  import warnings
  import random
  import numpy
label_desc: Use image node_id 2 for calling the SequentialMemory obj's underlying member method code with example usage: obj.sample(batch_size, batch_idxs) and returns: experiences