import torch


def compute_N_L(lambda_L, Gram_L, G_out):
    """Compute N_L using KRR

    Parameters
    ----------
    lambda_L: float
              Last layer regularization parameter

    Gram_L: torch.Tensor of shape (n_samples, n_samples)
            Last layer Gram matrix

    G_out: torch.Tensor of shape (n_samples, n_samples)
           Output Gram matrix

    Returns
    -------
    N_L: torch.Tensor of shape (n_samples, n_samples), default None
         Optimal last layer coefficients' dot products computed thanks to KRR
    """
    n = Gram_L.shape[0]
    M_L = Gram_L + n * lambda_L * torch.eye(n, dtype=torch.float64)
    M_L_1 = torch.inverse(M_L)
    N_L = torch.mm(M_L_1, torch.mm(G_out, M_L_1))

    # Should be independent from previous layers: .data
    return N_L.data