import torch
import torch.nn as nn
import torch.nn.functional as F

BATCH_SIZE = 16384
NUM_ITEMS = 1024
SHAPE = (BATCH_SIZE, NUM_ITEMS)

class BPRLoss(nn.Module):
    def __init__(self, reduction='mean'):
        super(BPRLoss, self).__init__()
        self.reduction = reduction

    def forward(self, pos_scores: torch.Tensor, neg_scores: torch.Tensor) -> torch.Tensor:
        diff = pos_scores - neg_scores

        loss = -F.logsigmoid(diff)
        
        if self.reduction == 'mean':
            return loss.mean()
        elif self.reduction == 'sum':
            return loss.sum()
        return loss

class Model(nn.Module):
    def __init__(self, reduction='none'):
        super(Model, self).__init__()
        self.loss_fn = BPRLoss(reduction=reduction)
    
    def forward(self, pos, neg):
        return self.loss_fn(pos, neg)

def get_inputs():
    pos_scores = torch.randn(SHAPE, dtype=torch.float32)
    neg_scores = torch.randn(SHAPE, dtype=torch.float32)
    return [pos_scores.contiguous(), neg_scores.contiguous()]

def get_init_inputs():
    return ['none']