def METHOD_NAME(self, model, sample, reduce=True):
    """Compute ranking loss for the given sample.
    Returns a tuple with three elements:
    1) the loss
    2) the sample size, which is used as the denominator for the gradient
    3) logging outputs to display while training
    """
    assert (
        hasattr(model, "classification_heads")
        and self.ranking_head_name in model.classification_heads
    ), "model must provide sentence ranking head for --criterion=sentence_ranking"
    scores = []
    for idx in range(self.num_classes):
        score, _ = model(
            **sample["net_input{idx}".format(idx=idx + 1)],
            classification_head_name=self.ranking_head_name,
        )
        scores.append(score)
    logits = torch.cat(scores, dim=1)
    sample_size = logits.size(0)
    if "target" in sample:
        targets = model.get_targets(sample, [logits]).view(-1)
        lprobs = F.log_softmax(logits, dim=-1, dtype=torch.float32)
        loss = F.nll_loss(lprobs, targets, reduction="sum")
    else:
        targets = None
        loss = torch.tensor(0.0, requires_grad=True)
    if self.prediction_h is not None:
        preds = logits.argmax(dim=1)
        for i, (id, pred) in enumerate(zip(sample["id"].tolist(), preds.tolist())):
            if targets is not None:
                label = targets[i].item()
                print("{}\t{}\t{}".format(id, pred, label), file=self.prediction_h)
            else:
                print("{}\t{}".format(id, pred), file=self.prediction_h)
    logging_output = {
        "loss": loss.data,
        "ntokens": sample["ntokens"],
        "nsentences": sample_size,
        "sample_size": sample_size,
    }
    if targets is not None:
        logging_output["ncorrect"] = (logits.argmax(dim=1) == targets).sum()
    return loss, sample_size, logging_output