def calculate_gradient(self, batch_info, device, model, rollout):
evaluator = model.evaluate(rollout)<EOL>dones_tensor = evaluator.get('<STR_LIT>')<EOL>rewards_tensor = evaluator.get('<STR_LIT>')<EOL>assert dones_tensor.dtype == torch.float32<EOL>with torch.no_grad():<EOL><INDENT>target_evaluator = self.target_model.evaluate(rollout)<EOL>if self.double_dqn:<EOL><INDENT>target_q = target_evaluator.get('<STR_LIT>')<EOL>model_q = evaluator.get('<STR_LIT>')<EOL>values = target_q.gather(<NUM_LIT:1>, model_q.argmax(dim=<NUM_LIT:1>, keepdim=True)).squeeze(<NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>values = target_evaluator.get('<STR_LIT>').max(dim=<NUM_LIT:1>)[<NUM_LIT:0>]<EOL><DEDENT>forward_steps = rollout.extra_data.get('<STR_LIT>', <NUM_LIT:1>)<EOL>estimated_return = rewards_tensor + (self.discount_factor ** forward_steps) * values * (<NUM_LIT:1> - dones_tensor)<EOL><DEDENT>q_selected = evaluator.get('<STR_LIT>')<EOL>if evaluator.is_provided('<STR_LIT>'):<EOL><INDENT>weights = evaluator.get('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>weights = torch.ones_like(rewards_tensor)<EOL><DEDENT>original_losses = F.smooth_l1_loss(q_selected, estimated_return, reduction='<STR_LIT:none>')<EOL>loss_value = torch.mean(weights * original_losses)<EOL>loss_value.backward()<EOL>return {<EOL>'<STR_LIT>': loss_value.item(),<EOL>'<STR_LIT>': original_losses.detach().cpu().numpy(),<EOL>'<STR_LIT>': torch.mean(q_selected).item(),<EOL>'<STR_LIT>': torch.mean(estimated_return).item()<EOL>}<EOL>
Calculate loss of the supplied rollout