import torch
import torch.nn as nn

class Model(nn.Module):
    """
    Canberra Distance implementation.
    Computes the Canberra distance between two sets of vectors.
    """
    def __init__(self):
        super(Model, self).__init__()
    
    def forward(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        """
        Compute Canberra distance between x and y.

        Args:
            x (torch.Tensor): First set of vectors [batch_size, feature_dim]
            y (torch.Tensor): Second set of vectors [batch_size, feature_dim]

        Returns:
            torch.Tensor: Canberra distances [batch_size]
        """
        # Input validation
        if x.shape != y.shape:
            raise ValueError(f"Input tensors must have the same shape, got {x.shape} and {y.shape}")
        
        if x.dim() != 2:
            raise ValueError(f"Input tensors must be 2D, got {x.dim()}D")
        
        # Compute Canberra distance: Σ(|x_i - y_i| / (|x_i| + |y_i|))
        # Step 1: Compute absolute differences
        diff = torch.abs(x - y)
        
        # Step 2: Compute denominator (sum of absolute values)
        denom = torch.abs(x) + torch.abs(y)
        
        # Step 3: Handle division by zero (where denominator is 0)
        # When both x_i and y_i are 0, the term is defined as 0
        ratio = torch.where(denom > 0, diff / denom, torch.zeros_like(diff))
        
        # Step 4: Sum along feature dimension
        distance = torch.sum(ratio, dim=1)
        
        return distance

batch_size = 256
feature_dim = 1024

def get_inputs():
    # Generate two sets of positive vectors (to avoid sign issues)
    x = torch.abs(torch.randn(batch_size, feature_dim)) + 0.1
    y = torch.abs(torch.randn(batch_size, feature_dim)) + 0.1
    return [x, y]

def get_init_inputs():
    return []  # No special initialization inputs needed
