## Maximum-entropy Linear Discriminant Analysis
## Input:
## x: a matrix containing the samples in the rows
## LABEL: vector containing the labels (1 or 2)
## Output:
## class: object containing the means of class 1 (class$m1) and 2 (class$m2), and the hyperplane (class$mlda)

MLDA <- function(x,LABEL) {
    #x is the predictors matrix (Nsamples x Nfeatures)
   
    x <- t(x) 
    INDEX <- sort(as.numeric(LABEL),index.return=T)$ix
    x <- x[,INDEX]
    LABEL <- LABEL[INDEX]

    x1 <- x[,1:as.numeric(table(LABEL)[1])]
    x2 <- x[,(as.numeric(table(LABEL)[1])+1):(as.numeric(table(LABEL)[1])+as.numeric(table(LABEL)[2]))]
    numGenes <- nrow(x1)
    numSample1 <- ncol(x1)
    numSample2 <- ncol(x2)

    xMean <- matrix(0,numGenes,1)
    x1Mean <- matrix(0,numGenes,1)
    x2Mean <- matrix(0,numGenes,1)


    x <- matrix(0,numGenes,numSample1+numSample2)
    x[,1:numSample1] <- x1
    x[,(numSample1+1):(numSample1+numSample2)] <- x2

    x1 <- x[,1:numSample1]   
    x2 <- x[,(numSample1+1):(numSample1+numSample2)]   

    for (i in 1:numGenes) {
        x1Mean[i,1] <- mean(x1[i,])
        x2Mean[i,1] <- mean(x2[i,])
        xMean[i,1] <- (sum(x1[i,]) + sum(x2[i,]))/(numSample1+numSample2)
    }

    Sb <- ( numSample1 * (x1Mean[,1] - xMean[,1]) %*% t((x1Mean[,1] - xMean[,1]))) + ( numSample2 * (x2Mean[,1] - xMean[,1]) %*% t((x2Mean[,1] - xMean[,1])))

    Sw <- matrix(0, numGenes, numGenes)
    for (i in 1:numSample1) {
        Sw <- Sw + (x1[,i] - x1Mean[,1]) %*% (t(x1[,i] - x1Mean[,1]))
    }
    for (i in 1:numSample2) {
        Sw <- Sw + (x2[,i] - x2Mean[,1]) %*% (t(x2[,i] - x2Mean[,1]))
    }

    Sp <- Sw/(numSample1+numSample2-2)

    Eigen <- eigen(Sp)

    lambdaMean <- sum(diag(Sp))/(numSample1+numSample2)

    SpEigenValueNew <- matrix(0,numGenes,numGenes)

    for(i in 1:numGenes) {
        SpEigenValueNew[i,i] <- max(Eigen$values[i], lambdaMean)
    }
   
    SwNew <- (Eigen$vectors %*% SpEigenValueNew %*% t(Eigen$vectors)) * (numSample1+numSample2-2)

    SwNew_1 <- qr.solve(SwNew)
    Z=eigen(SwNew_1%*%Sb)
    pMLDA <- Z$vectors
   
    x1Trans <- pMLDA[,1]%*%x1
    x2Trans <- pMLDA[,1]%*%x2

    meanx1Trans <- mean(x1Trans)
    meanx2Trans <- mean(x2Trans)

    pMLDA[,1]=pMLDA[,1]*sign(as.real(meanx1Trans))
    x1Trans <- pMLDA[,1]%*%x1
    x2Trans <- pMLDA[,1]%*%x2

    meanx1Trans <- mean(x1Trans)
    meanx2Trans <- mean(x2Trans)


    class <- list()
    class$mlda <- pMLDA[,1]
    class$m1=meanx1Trans
    class$m2=meanx2Trans
    return(class)
}


## Input:
## MODEL: object returned by function MLDA
## x: matrix containg the samples in the rows
## Output:
## label: array containing the labels marked by MLDA
predict.MLDA <- function(MODEL,x) {
    #x is a matrix not an array (Nsamples x Npredictors)
    x <- t(x)
    xTrans <- MODEL$mlda%*%x
    numSample <- length(xTrans)
    label <- array(0,numSample)
    for (i in 1:numSample) {
        if(abs(xTrans[i]-MODEL$m1) < abs(xTrans[i]-MODEL$m2)) {
            label[i] <- 1
        }
        else {
            label[i] <- 2
        }
    }
    return(label)
}


