public LaplacianFaceRecognizer(List <Matrix> trainingSet, List <String> labels, int numOfComponents)
        {
            this.numOfComponents = numOfComponents;
            this.imgRows         = trainingSet[0].RowDimension;
            int n = trainingSet.Count; // sample size
            HashSet <String> tempSet = new HashSet <String>(labels);
            int c = tempSet.Count;     // class size

            // process in PCA
            EigenFaceRecognizer pca = new EigenFaceRecognizer(trainingSet, labels, numOfComponents);

            //construct the nearest graph
            Matrix S = constructGraph(pca.getWeights());
            Matrix D = constructD(S);
            Matrix L = D.Subtract(S);

            //reconstruct the trainingSet into required X;
            Matrix X    = constructTrainingMatrix(pca.getWeights());
            Matrix XLXT = X.Multiply(L).Multiply(X.Transpose());
            Matrix XDXT = X.Multiply(D).Multiply(X.Transpose());

            //calculate the eignevalues and eigenvectors of (XDXT)^-1 * (XLXT)
            XDXT.Inverse();
            Matrix targetForEigen           = XDXT.Inverse().Multiply(XLXT);
            EigenvalueDecomposition feature = targetForEigen.Eigen();

            double[] eigenValues = feature.RealEigenvalues;
            int[]    indexOfChosenEigenValues = this.getIndOfHigherEV(eigenValues, eigenValues.Length);//higher eigen values

            Matrix eigenVectors         = feature.GetV();
            Matrix selectedEigenVectors = eigenVectors.GetMatrix(0, eigenVectors.RowDimension - 1, indexOfChosenEigenValues);

            this.weightMatrix = pca.getWeightMatrix().Multiply(selectedEigenVectors);

            //Construct projectedTrainingMatrix
            this.weights = new List <ProjectMatrix>();
            for (int i = 0; i < trainingSet.Count(); i++)
            {
                ProjectMatrix pm = new ProjectMatrix(this.weightMatrix.Transpose().Multiply(trainingSet[i].Subtract(pca.getMeanMatrix())),
                                                     labels[i]);
                this.weights.Add(pm);
            }
            this.meanMatrix = pca.getMeanMatrix();
        }
        public LinearDescriminantAnalysis(List <Matrix> trainingSet, List <String> labels)
        {
            this.trainingSet = trainingSet;
            this.imgRows     = trainingSet[0].RowDimension;
            int n = trainingSet.Count();  // sample size
            HashSet <string> uniqueLabels = new HashSet <string>(labels);
            int c = uniqueLabels.Count(); // class size

            this.numOfComponents = c - 1;

            EigenFaceRecognizer pca = new EigenFaceRecognizer(trainingSet, labels, n - c);

            Matrix meanTotal = new Matrix(n - c, 1);

            Dictionary <string, List <Matrix> > dic = new Dictionary <string, List <Matrix> >();
            List <ProjectMatrix> pcaWeights         = pca.getWeights();

            for (int i = 0; i < pcaWeights.Count(); i++)
            {
                string key = pcaWeights[i].getLabel();
                meanTotal.AddEquals(pcaWeights[i].getImgMat());

                if (!dic.ContainsKey(key))
                {
                    List <Matrix> temp = new List <Matrix>();
                    temp.Add(pcaWeights[i].getImgMat());
                    dic.Add(key, temp);
                }
                else
                {
                    List <Matrix> temp = dic[key];
                    temp.Add(pcaWeights[i].getImgMat());
                    dic[key] = temp;
                }
            }
            meanTotal.Multiply((double)1 / n);

            // calculate Sw, Sb
            Matrix Sw = new Matrix(n - c, n - c);
            Matrix Sb = new Matrix(n - c, n - c);

            uniqueLabels = new HashSet <string>(dic.Keys);
            foreach (string s in uniqueLabels)
            {
                List <Matrix> matrixWithinThatClass = dic[s];
                Matrix        meanOfCurrentClass    = getMean(matrixWithinThatClass);

                for (int i = 0; i < matrixWithinThatClass.Count(); i++)
                {
                    Matrix mat = matrixWithinThatClass[i].Subtract(meanOfCurrentClass);
                    mat = mat.Multiply(mat.Transpose());
                    Sw.AddEquals(mat);
                }
                Matrix temp = meanOfCurrentClass.Subtract(meanTotal);
                temp = temp.Multiply(temp.Transpose()).Multiply(matrixWithinThatClass.Count());
                Sb.AddEquals(temp);
            }

            // calculate the eigenvalues and vectors of Sw^-1 * Sb
            Matrix targetForEigen           = Sw.Inverse().Multiply(Sb);
            EigenvalueDecomposition feature = targetForEigen.Eigen();

            double[] eigenValues = feature.RealEigenvalues;

            int[]  indexOfChosenEigenValues = getIndOfHigherEV(eigenValues, c - 1);
            Matrix eigenVectors             = feature.GetV();
            Matrix selectedEigenVectors     = eigenVectors.GetMatrix(0, eigenVectors.RowDimension - 1, indexOfChosenEigenValues);

            this.weightMatrix = pca.getWeightMatrix().Multiply(selectedEigenVectors);

            // Construct weights
            this.weights = new List <ProjectMatrix>();
            for (int i = 0; i < trainingSet.Count(); i++)
            {
                ProjectMatrix ptm = new ProjectMatrix(this.weightMatrix.Transpose().Multiply(trainingSet[i].Subtract(pca.getMeanMatrix()))
                                                      , labels[i]);
                this.weights.Add(ptm);
            }
            this.meanMatrix = pca.getMeanMatrix();
        }