def optimize_policy_model(self):
    '\n        performs a single step of optimization for the policy model\n        :return:\n        '
    if (self.memory.length() < self.config.batch_size):
        return
    transitions = self.memory.sample_batch(self.config.batch_size)
    one_batch = Transition(*zip(*transitions))
    non_final_mask = torch.tensor(tuple(map((lambda s: (s is not None)), one_batch.next_state)), device=self.device, dtype=torch.uint8)
    non_final_next_states = torch.cat([s for s in one_batch.next_state if (s is not None)])
    state_batch = torch.cat(one_batch.state)
    action_batch = torch.cat(one_batch.action)
    reward_batch = torch.cat(one_batch.reward)
    state_batch = state_batch.to(self.device)
    non_final_next_states = non_final_next_states.to(self.device)
    curr_state_values = self.policy_model(state_batch)
    curr_state_action_values = curr_state_values.gather(1, action_batch)
    next_state_values = torch.zeros(self.config.batch_size, device=self.device)
    next_state_values[non_final_mask] = self.target_model(non_final_next_states).max(1)[0].detach()
    expected_state_action_values = ((next_state_values * self.config.gamma) + reward_batch)
    loss = self.loss(curr_state_action_values, expected_state_action_values.unsqueeze(1))
    self.optim.zero_grad()
    loss.backward()
    for param in self.policy_model.parameters():
        param.grad.data.clamp_((- 1), 1)
    self.optim.step()
    return loss
performs a single step of optimization for the policy model
:return:
def optimize_policy_model(self):
    '\n        performs a single step of optimization for the policy model\n        :return:\n        '
    if (self.memory.length() < self.config.batch_size):
        return
    transitions = self.memory.sample_batch(self.config.batch_size)
    one_batch = Transition(*zip(*transitions))
    non_final_mask = torch.tensor(tuple(map((lambda s: (s is not None)), one_batch.next_state)), device=self.device, dtype=torch.uint8)
    non_final_next_states = torch.cat([s for s in one_batch.next_state if (s is not None)])
    state_batch = torch.cat(one_batch.state)
    action_batch = torch.cat(one_batch.action)
    reward_batch = torch.cat(one_batch.reward)
    state_batch = state_batch.to(self.device)
    non_final_next_states = non_final_next_states.to(self.device)
    curr_state_values = self.policy_model(state_batch)
    curr_state_action_values = curr_state_values.gather(1, action_batch)
    next_state_values = torch.zeros(self.config.batch_size, device=self.device)
    next_state_values[non_final_mask] = self.target_model(non_final_next_states).max(1)[0].detach()
    expected_state_action_values = ((next_state_values * self.config.gamma) + reward_batch)
    loss = self.loss(curr_state_action_values, expected_state_action_values.unsqueeze(1))
    self.optim.zero_grad()
    loss.backward()
    for param in self.policy_model.parameters():
        param.grad.data.clamp_((- 1), 1)
    self.optim.step()
    return loss