import torch import pickle class ExperienceCollector: def __init__(self): self.states = [] self.actions = [] self.rewards = [] self.advantages = [] self._current_episode_states = [] self._current_episode_actions = [] self._current_episode_estimated_values = [] def begin_episode(self): self._current_episode_states = [] self._current_episode_actions = [] self._current_episode_estimated_values = [] def record_decision(self, state, action, estimated_value=0): self._current_episode_states.append(state) self._current_episode_actions.append(action) self._current_episode_estimated_values.append(estimated_value) def complete_episode(self, reward): num_states = len(self._current_episode_states) self.states += self._current_episode_states self.actions += self._current_episode_actions self.rewards += [reward for _ in range(num_states)] for i in range(num_states): advantage = reward - self._current_episode_estimated_values[i] self.advantages.append(advantage) self._current_episode_states = [] self._current_episode_actions = [] self._current_episode_estimated_values = [] class ExperienceBuffer: def __init__(self, states, actions, rewards, advantages): self.states = states self.actions = actions self.rewards = rewards self.advantages = advantages def save(self, file_path): with open(file_path, 'wb') as f: pickle.dump((self.states, self.actions, self.rewards, self.advantages), f) @classmethod def load(cls, file_path): with open(file_path, 'rb') as f: states, actions, rewards, advantages = pickle.load(f) return cls( states=states, actions=actions, rewards=rewards, advantages=advantages) def combine_experience(collectors): combined_states = torch.cat([torch.tensor(c.states) for c in collectors]) combined_actions = torch.cat([torch.tensor(c.actions) for c in collectors]) combined_rewards = torch.cat([torch.tensor(c.rewards) for c in collectors]) combined_advantages = torch.cat([torch.tensor(c.advantages) for c in collectors]) return ExperienceBuffer( combined_states, combined_actions, combined_rewards, combined_advantages)